Полная версия
Активные данные. Философское программирование
Можно даже попробовать вообразить этого Создателя – Великого Программиста, который сотворил ДНК и Рибосому, загрузил их внутрь первичной самовоспроизводящейся клетки, запустил механизм размножения, и в результате последующих итераций появились и мы, и всё живое, что нас окружает. Хотя вполне вероятно, что всё было решительно иначе, никакого Великого Программиста изначально не было, и вся эта красота получилась из случайного соединения молекул. Но что бы ни произошло тогда на Земле, есть некоторые основания утверждать, что жизнь есть следствие глобального биологического программирования. Система биологических программ, которая имеется в каждой клетке и в каждом вирусе, в процессе фантастически огромного количества компиляций и интерпретаций, под воздействием различных мутирующих факторов, породила всё многообразие живых организмов, которые продолжают эволюционировать, с каждой очередной интерпретацией копии программы ДНК на Рибосоме. А когда пришло время, то и Человек, в свою очередь, сотворил и компьютер, и программирование, которые являются естественным продолжением своих биологических прототипов. И чем закончится эволюция компьютеров – кто знает?
Грезят на подобные темы не только программисты. Странные картины мира привычны также и физикам, например у Р. Фейнмана, вселенная – это «атомы с сознанием, материя с любопытством.». А если уж продолжить фантазировать вместе с физиками совсем по-настоящему, то можно представить себе модель рекуррентного Создателя. Ведь когда один Создатель породил итеративный процесс, который привел к появлению другого Создателя, и тот, в свою очередь, породил следующий итеративный процесс, который… А что, если был Создатель, который придумал язык, в котором алфавит состоит из атомов (см. таблицу Менделеева), а слова-молекулы образуются путем многомерной конкатенации букв этого алфавита. Затем, с помощью первоначальной загрузки (Большой Взрыв), он запустил универсальный процесс, и в результате из физического алфавита и слов, образуются молекулярные предложения, из которых и получается ВСЁ, что с точки зрения конструктивного программиста, вполне логичная система рекуррентных отношений. И вернувшись к своей программе, конструктивный программист добавил к ней ещё одну строчку, ещё одну маленькую итерацию к процессу Великой Эволюции, и кто знает, может быть, когда-то нечто подобное делал другой Программист? – «Но довольно…»
Последние два слова – пример того, как глубоко различны все мы в восприятии и понимании! Этими словами заканчивается знаменитый монолог Гамлета в переводе Б. Пастернака и у того, кто читал и помнит эту версию, они определённо вызовут какую-нибудь, возможно, что и весьма глубокую, ассоциацию. Но для того, кто не читал или не помнит, реакция после прочтения этих двух слов будет совсем другой. Слово всё в начале этой главы, вместе со словом ВСЁ в конце, объединяют не логика, а принципиально иные по своей природе, глубокие ассоциативные связи, о которых и пойдет речь в этой книге.
Книга о программировании без примеров программ, так же неполна, как и книга о математике без математических формул. Можно много фантазировать и интересно рассуждать о знаниях, программах и компьютерах, но практическая цель этой книги будет достигнута только тогда, когда программисты смогут применить результаты этих рассуждений в своих работах, и чтобы помочь в этом, все демонстрационные примеры, приведенные в этой книге, включая библиотеки подпрограмм и объектов, доступны в GitHub:
https://github.com/stolkachev
От слов к делу
В самом начале была Буква,
затем появилось Слово,
и уже потом Дело.
Формальные грамматики
Мы живем в мире машин, которые постоянно что-то делают: перевозят, разогревают, фрезеруют – или, если сформулировать более точно, выполняют определенные действия, которые можно измерить и описать в физических терминах: работа, мощность, КПД, энергия и пр. Здесь разносторонний программист обязательно должен добавить: «Класс машин, помимо энергетических, должен включать подкласс информационных машин, которые тоже умеют кое-что делать». Эх, как было бы удобно всё формализовать в виде классов, методов и отношений, если бы объектно-ориентированный подход приняли в качестве основы для рассуждений все остальные непрограммисты! Мечты…
Из повседневного опыта известно, что слова могут быть декларативными или императивными, и они могут определять или инициировать действия. Например, набор слов: «Чтобы разогреть воду, включи плиту» будет понятен любому современному человеку, и даже компьютеру, хотя несколько столетий назад, эта фраза вызвала бы недоумение – ведь в то время для того, чтобы разогреть воду, нужно было разжечь огонь. Естественно, что один и тот же результат может быть получен в итоге различных последовательностей действий. А слова, как виртуальный мостик, связывают исполнительные механизмы, способные к конкретным действиям, с одной стороны, с процедурами или знаниями, задающими эти последовательности, с другой. Но и суть программирования заключается в формулировании чего бы то ни было – словами! Будь то математическая формула или экономическая модель, программист обязан передать их описание компьютеру при помощи комбинации слов. Желательно только не забывать при этом, о чем на основании своего опыта предупреждают известные мастера слов – математики: «Слова – орудия опасные» (Герман Вейль).
Мы употребляем подобные слова повсеместно и никаких сомнений не возникает, пока мы не зададимся вопросом, а что, собственно, есть действие, и чем знание отличается от данных и информации? Рассуждая над смыслом слов, нужно быть готовым к тому, что, как бы глубоко и формально мы не старались уточнить их определения, всё равно, согласно К. Гёделю и В. Гейзенбергу, они будут недостаточно точными, неполными или противоречивыми. Общепринятый подход к получению более «точных определений» основан на использовании более строгих математических формализаций. Мы же, напротив, будем рассчитывать на неформальное и интуитивное понимание, основанное на «глубоком многослойном обучении». Сравнительно недавно появилась новая теория – «Intelligent Learning» и один из её авторов, Владимир Вапник, высказал предположение, что если фактические знания передаются в сочетании с ассоциативно связанными «посторонними» идеями, то обучение происходит более эффективно, модификация знаний о предметной области не разрушает модель, а адаптация к новому происходит быстрее и легче.
Слово делать относится как раз к такой категории интуитивно понятных, и положительный ответ на вопрос «Может ли машина делать?», особенно если речь идет о физических действиях, не должен вызвать каких-либо сомнений (разве что филологических). Но и у программистов не видно серьезных оснований для возражений по поводу способности информационных машин – ведь стоит загрузить программу в компьютер, как в нем начинаются действия. Как в физике, так и в информатике, действие всегда приводит к изменению состояния, и это изменение в энергетической машине может быть измерено в джоулях, а в информационной – в битах. Мы не будем здесь углубляться в сравнение свойств физических и информационных систем, например закона сохранения энергии с его информационным аналогом, или определения работы в физических и информационных системах. Однако если эта тема заинтересует любопытного читателя, то можно быть уверенным, что его ждут интересные и неожиданные открытия.
Но ведь и человек способен к делу, равно как и множество живых существ, которые тоже совершают самые разнообразные осмысленные, и не очень, действия. Почему бы не расширить класс машин, добавив к нему биологические системы? При этом у нас появляется возможность изучить связи между информационными действиями и соответствующими физиологическими реакциями, на целом спектре разнообразных организмов, поскольку биологическая эволюция предоставила нам последовательный ряд: от примитивного червяка-нематоды C. еlegans, до человека разумного, в которых связи между информационными и физическими органами уже достаточно хорошо изучены и описаны.
Если сравнить рефлекторные реакции в ответ на возбуждения в простейших организмах, с тем, как анализирует вопросы и генерирует ответы человек в процессе диалога, то можно проследить, как видоизменяются биологические системы, созданные с применением одного и того же базового конструктивного элемента – нейрона. Правда, проводить измерения внутри живых организмов дело тонкое и вряд ли в скором времени мы сможем создать универсальную структурно-функциональную модель, в которой для каждого органа будут получены энерго-информационные характеристики в джоулях и битах. Но характерные особенности и отличия в структурах различных по сложности организмов, могут дать хорошую пищу для рассуждений.
А «Может ли машина мыслить?» – с этого вопроса начинается, одна из самых популярных в истории вычислительной техники, статья А. Тьюринга «Вычислительные машины и разум». Этот вопрос вызвал бесконечное количество дискуссий и безусловно до сих пор, он является одним из самых интересных теоретических вызовов для многих программистов, и не только. Но если сформулировать его несколько иначе – «Как машина может помочь человеку мыслить?», то из области сложных формальных проблем, с которыми столкнулся Тьюринг и его последователи, мы переходим к инженерным системам и техническим определениям, где результат должен быть конкретен и может быть измерен понятным способом, например, как КПД физической машины, заменяющей ручной труд человека.
На первый взгляд, такая игра словами может показаться простой забавой для ума, однако, когда Тьюринг попытался найти формальный подход к ответу на свой вопрос, он тоже решил переформулировать его в других, менее двусмысленных терминах, и назвал эту проблему – «игра в имитацию». В результате появился хрестоматийный «тест Тьюринга», который пытаются пройти поколения программистов. Если бы только Тьюринг смог предвидеть, что слово имитация в будущем, будет многими воспринято буквально и безотносительно к слову игра, то кто знает, возможно он попробовал бы подобрать ещё более аккуратные термины, и тогда, мы бы имели больше полезных функциональных чат-ботов, вместо множества «имитаторов», способных поддерживать лишь разговоры на общие темы.
Знаменитый вопрос Тьюринга можно рассматривать как продолжение его другой, не менее знаменитой, концепции универсальной вычислительной машины, которую он предложил в 1936 году. Для математиков машина Тьюринга, это несомненно прорыв, поскольку, согласно А. Черчу, Тьюринг – первый, кто ввел физическое действие в математическое понятие вычисления. В математике, с момента её возникновения, существует разрыв между «строго формальной» абстрактной теорией, и интерпретатором этой теории, которым всегда выступает другой математик. И каким бы строгим не было доказательство, в конце концов, проверяет его человек. У математиков нет компилятора, который является обыденным инструментом для программистов, а Тьюринг, если уж совсем упрощенно, предложил и обосновал возможность такого математического компилятора, по крайней мере, для вычислительных задач. Впрочем, при всей важности машины Тьюринга для фундаментальных исследований, программируют на ней лишь редкие математики и студенты курса «Теоретическое программирование», и вряд ли на всей Земле можно найти программиста, который использует её для решения своих практических задач.
Но есть в биологии чрезвычайно распространённый процесс, на который очень похожа универсальная модель вычислений Тьюринга! Если поместить рядом и сравнить две схемы – синтез протеина рибосомой и машину Тьюринга, то сходство основных функциональных блоков, логики работы и методов кодирования, становится наглядным. Рибосома считывает последовательности кодов, записанных на ленте информационной РНК, и на выходе конструирует структуру из соответствующих молекул. В машине Тьюринга, управляющее устройство считывает с ленты символы и следуя программе, выполняет ограниченный набор действий – перемещает головку, записывает новое значение на ленту и т. п. И в рибосоме, и в машине Тьюринга, исполнение программ приводит к определенному результату. Обе программы – это линейные последовательности кодов, которые задаются простыми алфавитами. Обе машины получают программы извне и интерпретируют эти программы, превращая информацию команд в физические действия. Однако принципиальное отличие между двумя машинами всё-таки есть. Рибосома – это узко специализированная машина для производства органов и организмов, состоящих из разнообразных клеток, включая миоциты (мышечные клетки), нейроны и нервы, а машина Тьюринга – универсальная модель, попытка построить нечто, способное на всё. Если бы только Тьюринг мог предвидеть, что его машина окажется так поразительно похожа на рибосому и ДНК, может быть, вместо гипотетической модели универсального вычислителя, сегодня мы бы имели простой, но работающий генетический интерпретатор?
Биологические машины представляют собой симбиоз энерго-информационных подсистем, и все действия в них инициируются внутренними механизмами управления. В отличие от биологических, физические и информационные машины создавались как инструменты, предназначенные для повышения производительности сначала физического, а затем умственного труда, и соответственно, в их основе лежит принцип руководства человеком, иными словами, программа управления всегда разрабатывается извне этих машин.
Энерго-информационные процессы в живых организмах, можно разделить на два типа: репродуктивные – когда при создании новой клетки, рибосома конструирует протеины под управлением программы ДНК/РНК, и рефлекторные – когда действия осуществляются моторными нейронами на основании состояния нервной системы. Репродуктивный и рефлекторный механизмы управления имеют четкое функциональное назначение: первый предназначен для создания исполнительных механизмов, а второй – для их эксплуатации. Если перед самым умным программистом на Земле поставить задачу спроектировать систему, в которой компоненты должны эволюционировать, приспосабливаться к внешней среде и самообучаться, то скорее всего, обладая всеми доступными знаниями, он пришел бы к очень похожему решению. Для программирования репродуктивных систем подходят алгоритмические методы, а вот для рефлекторных, нужны принципиально новые инструменты и платформы, такие как интегрированные методы искусственного интеллекта и нейронное программирование.
Теория управления физическими машинами традиционно относилась к разделам математики и механики, вплоть до появления в 1948 году книги Н. Винера «Кибернетика, или управление и связь в животном и машине», которая внесла некоторый сумбур в эту область знаний. Новая наука предполагает, что существуют общие законы управления, которые можно описать в виде формальных математических уравнений, позволяющих рассчитать значения параметров воздействия на механические, биологические, социальные или экономические объекты, для достижения определённых целей. Так же, как и классическая механика Ньютона, которая решает множество задач известного типа, так и кибернетика с успехом применяется в широком спектре разнообразных систем. Но всякая «правильная» теория должна иметь область ограничения, и при достижении определенного уровня сложности, нужны новые теории и новые методы решения, и как никому другому, это хорошо известно всем прикладным программистам.
Современные системы управления используют искусственный интеллект в сочетании с алгоритмическими методами и имеют развитый интерфейс к разнообразным аналого-цифровым преобразователям. В результате мы наблюдаем, как быстро прогрессируют, обучаются, становятся автономными и независимыми от непосредственного вмешательства человека самые разнообразные роботы и автоматизированные системы. «Обучение машин», «передача знаний», «принятие решений компьютером» – термины, которые из профессионального жаргона постепенно переходят в повседневный оборот. Если сравнительно недавно программирование было уделом избранных, то сегодня это массовая профессия, и в скором времени, это будет уже не только профессия, но и общедоступный элемент культуры, такой же, как умение писать и читать. И чтобы понять, как это произойдет, попробуем, используя математическую терминологию, экстраполировать процесс.
«Ученые изучают то, что уже есть, инженеры создают то, чего никогда не было». В этой цитате, авторство которой Интернет приписывает А. Эйнштейну, очень доходчиво показано различие между теоретическими исследованиями ученых и практической деятельностью инженеров. Ученым требуется время для наблюдений и размышлений. Научная деятельность, со времен Аристотеля – это процесс получения знаний, состоящий из определенной последовательности шагов. С момента появления гипотезы, её проверки и публикации, до подтверждения теории научным сообществом, может пройти много времени, однако от этого зависит и качество науки и, соответственно, образования. В классических науках, времени всегда хватало – история механики насчитывает более двух тысяч лет, пятьсот лет развивается теория электричества, а вот в программировании глубокие изменения происходят в такие короткие промежутки, что наука просто не успевает за темпами развития компьютерных технологий. Наверное, поэтому и возник разрыв между теоретическими исследованиями в области программирования и полноценным профессиональным обучением, позволяющим инженерам рационально применять научные результаты в практике.
Современное программирование появилось в середине 50-х годов, как система из трех взаимодополняющих элементов – программист, программа и компьютер. Компьютеры тогда были, пусть и внушительных размеров, но всё же понятные вычислительные машины с известной логикой и состояниями. Практически все программисты имели либо математическое, либо специальное инженерное образование. Системные программисты разрабатывали операционные системы, компиляторы и специальные утилиты для ЭВМ, а программисты-математики создавали прикладные программы, которые представляли собой реализации различных алгоритмов решения численных задач. Такая модель программирования напоминала геоцентрическую систему Птолемея и многие надеялись, что рано или поздно, будет создана универсальная теория языков и верификации программ, что сделает их похожими на «вечные» математические конструкции.
Но компьютеры развиваются стремительно, и за сравнительно небольшой период времени, прошедший с момента появления первых ЭВМ, мы наблюдаем уже несколько эволюций, которые принципиально изменили мир информационных технологий. Если в самом начале программирование было ориентированно на численные методы, где основным объектом вычислений является число, то на следующем этапе, наравне с числами, в программах появляются данные и, как сформулировал в 1976 году Н. Вирт:
Программа = Алгоритм + Структуры Данных
В эти же годы появляются серверы и персональные компьютеры, объединенные в простейшие сети, а наряду с прикладными математиками, в информатику приходит всё больше и больше инженеров, специализирующихся на решении задач обмена и организации данных. Тогда же появилась принципиально новая форма программирования – электронные таблицы, которые позволяют «непрограммистам» создавать сложные модели из данных, связанных друг с другом функциональными отношениями в многомерном виртуальном пространстве.
Это принципиально новое решение соответствует естественному для человека способу пространственного мышления и позволяет, используя простую систему координат, не только систематизировать структуры и отношения между различными данными, но и передавать изменения непосредственно от точки, в которых они происходят, ко всем взаимосвязанным объектам. В электронных таблицах действия инициируются данными, и это принципиально отличает их от алгоритмических систем, в которых данные изменяются в результате интерпретации последовательности команд в программе.
Программист-зануда здесь справедливо возразит, что «за всем этим стоит простая система ссылок и таблиц значений, которые пересчитываются в ответ на событие, возникающее при изменении координат указателя мышки». Но любопытный программист сможет представить стоящие за этим рисунком реальные физические процессы, в связанных между собой исполнительных элементах, очень похожих на сеть биологических нейронов или на вычислительную модель в аналогово-цифровых комплексах, которую можно получить, соединив кибернетику Н. Винера с машиной фон Неймана. Ещё раз заметим, что в своих моделях и Винер, в аналоговой, и фон Нейман, в цифровой, ссылаются на нейрон в качестве прототипа вычислительного элемента.
Сегодня аналогово-цифровые преобразователи используются повсеместно: от сенсоров, переключателей и микрофонов в «умном доме», до промышленных роботов и медицинских имплантатов, соединенных различными видами как проводной, так и беспроводной связи. На смену серверам пришли сервисы, и компьютер, как целостная вычислительная машина, трансформировался в набор фактически неограниченных ресурсов в облаках. Числа, с которыми имеют дело программисты при решении алгоритмических задач, составляют очень небольшой процент от постоянно увеличивающихся по объёму, как структурированных, так и неструктурированных данных, распределённых в глобальных и локальных сетях Интернет. А одно из новых ключевых направлений в программировании 2020, это интерактивность и поддержка прямого взаимодействия между бизнесом и потребителями.
В 1968 году вышел первый том монографии Д. Кнута «Искусство программирования». В то время, количество программистов в мире исчислялось десятками тысяч, а профессионалом мог считаться лишь тот, кто сумел бы решить большинство из приведенных в этой книге упражнений. На обучение этому у среднего студента уходило несколько лет, и трудно было представить тогда программиста без специального инженерного или математического образования. В 2020 году программированием занималось уже более двадцати миллионов человек, и эта профессия превратилась в одну из самых массовых и доступных. Многие из современных программистов ничего не слышали о книге Д. Кнута, что, впрочем, не мешает им создавать полезные прикладные решения. Изменилась природа приложений, и соответственно появились новые технологии и инструменты. Если первоначально программирование было предназначено для автоматизации работы вычислительных машин и реализации алгоритмов специально подготовленными профессионалами, то сегодня, это в первую очередь инструмент для накопления и передачи знаний, а основы программирования и информатики включены школьную программу для начальных классов.
За эти годы в мире информатики было решено множество проблем. Но чем шире горизонт – тем больше открывается неизвестного, и вместе с этим появляются новые задачи, среди которых, в первую очередь нужно выделить обработку знаний. До сих пор, основным объектом программирования являлись данные. Знания – это значительно более сложная система, в которой данные соединяются с процедурами, а обмен знаниями, это контекстно-зависимый процесс. В процессе обмена могут участвовать группы, где каждый участник имеет своё уникальное состояние.
Данные, информация и знания – три основополагающие категории, как в биологических, так и в компьютерных системах. Термин данные относится к неопределимым аксиоматическим понятиям, которые, чаще всего объясняют, используя косвенную рекурсию. Например, согласно Википедии, данные – это факты или события, а статистик и специалист по машинному обучению определит их как числа или вектор чисел. Но если продолжить уточнение: а что есть факты или числа, то круг очень быстро замкнется. Однако если мы зададим разумные области ограничений, то оказывается, что этот термин поддается конструктивному определению.