Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Сильный искусственный интеллект и объектно-ориентированное программирование синтез парадигм

.pdf
Скачиваний:
0
Добавлен:
08.09.2026
Размер:
2 Мб
Скачать
☆
ществляется через конкретную команду. Конкретная команда связана с инициатором по типу композиции: инициатор создает объект конкретной команды и без инициатора его бы не суще­ствовало. Команда же (базовая команда) связана с получателем по типу композиции, так как она изначально создается «под него» и для работы с ним.
Значимость паттерна в контексте разработки систем
сильного ИИ. Данный поведенческий паттерн актуально ис-
пользовать в контексте разработки систем сильного ИИ вполне логичным образом: для преобразования, упаковки и передачи информации. Однако необходимо, разумеется, абстрагировать суть паттерна. А в абстрактном виде она, как уже постулирова­лось, заключается в наличии буфера между программными ком­понентами, передающими информацию некоторого типа другим программным компонентам для ее последующей обработки и воспроизведения некоторой реакции на эту информацию. В контексте данного паттерна наиболее значимой абстрактной характеристикой является специфика преобразования информа­ции, сама ее идея: информация из, можно так выразиться, неко­торых импульсов преобразуется в качественно иной вид – в нечто очень отдаленно, но все же более подобное субъекту действия, чем просто совокупность однонаправленных импульсов (абстракт­ные запросы, к примеру). Ведь объект – это уже нечто упорядо­ченное, обладающее некой формой, определенным содержанием, специфической идентичностью и т. д. Напомним, что специфи­кой паттерна «Команда» является качественное преобразование информации с ее воплощением в виде упорядоченной информа­ционной структуры с потенциалом использования составляющих блоков информации по усмотрению субъекта (информационной структуры). Если абстрагироваться еще сильнее, то можно бу­дет (примерно как в вышеописанной ситуации о TransferCoin) говорить о некоем аккумулировании в единую информацион­ную структуру разнородных, но по какому-либо критерию все же связанных блоков данных. И, что крайне важно, эта структу­ра должна будет являться по отношению ко всей совокупности данных, ее составляющих, чем-то большим, чем-то качественно
191
новым, т. е. чем-то эмерджентным. Выглядит это, как будто только что существовали просто некоторые блоки данных, а те­перь мы уже имеем дело с вполне определенной сущностью, с новым субъектом инфополя. А это напоминает гипотетический процесс зарождения системы сильного ИИ.
Примеры, напоминающие реализацию подобного механизма, предположительно наличествуют также и в сфере человеческой психики и являются определенными и задокументированными в некоторых психотерапевтических направлениях, в частности в психоанализе. У одного из представителей кляйнианского пси­хоанализа, У. Р. Д. Фейрбейрна, имеется теория формирования психики, основанная на специфических отношениях младенца с окружающим миром. В частности, он упоминает расщепление целостной психики субъекта на три части, одной из которых яв­ляется так им определенный «внутренний диверсант», который представляет собой антилибидную часть «Я» [119]. «Внутренний диверсант» представляет собой активно действующего психи­ческого субъекта, разумеется (в духе психоанализа), неосознава­емого. Так вот, что интересно, это точно так же, как и в слу чае с абстрагированием сути паттерна «Команда»: происходит каче­ственное преобразование изначально разрозненных блоков дан­ных путем их оформления в сущность нового порядка, способ­ную активно действовать в рамках доступного ей контекста. Предполагаемый феномен внутреннего диверсанта приведен просто в качестве примера, иллюстрирующего функционирова­ние механизмов, которые свойственны абстрагированному пат­терну «Команда».
Резюмируя данный паттерн, стоит отметить, что именно за­ложенное в его суть качественное преобразование данных с по­следующим созданием на их основе новой сущности, являющейся чем-то большим, чем все данные вместе взятые, чем-то эмерджент­ным – именно этот аспект «Команды» и стоит отдельно позаим­ствовать для нужд разработки систем сильного ИИ по причине его чрезвычайной значимости в контексте нашего исследования и его самоорганизующей природы.
192
12.6. Поведенческий паттерн «Интерпретатор»
Идентификатор. Интерпретатор (Interpreter). Классические элементы. Абстрактное выражение, терми-
нальное выражение, нетерминальное выражение, контекст.
Назначение. Как указывается в Design patterns, «Интерпре­татор» «для заданного языка определяет представление его грам­матики, а также интерпретатор предложений этого языка» [114, с. 236]. Собственно говоря, определение паттерна «Интерпрета­тор», которое приводится выше, несколько вырвано из контекста. На самом деле имеется в виду практический буквальный кон­структор для анализа данных, дальнейшего их преобразования и синтеза в виде решения некоторой формализованной задачи, основанной на этих данных. Этот конструктор предназначен осуществлять разбор некоторой задачи на составляющие, что позволяет ему «понять» задачу, преобразовать ее в необходи­мый для решения вид и затем непосредственно решить.
Проблема. Классическое определение подходящей для «Ин­терпретатора» проблемы описано в Design patterns и звучит так: «Если некоторая задача встречается достаточно часто, то имеет смысл представить ее конкретные проявления в виде предложе­ний на простом языке» [114, с. 237]. Т. е. у нас имеется некоторая задача, состоящая из определенного конечного количества со­ставляющих – подзадач. Количество возможных подзадач не должно быть большим, иначе данный паттерн не подойдет для применения в контексте. Также мы имеем возможность форма­лизовать задачу, т. е. преобразовать ее в простые формы каких­либо символов (неважно, каких именно: английский алфавит, римские цифры или скаляры алгебры логики), которых также небольшое количество. Смысл преобразования задачи в том, что после трансформации она может быть легко решена, т. е. в про­цессе преобразования мы должны максимально упростить, про­анализировать, разложить на составляющие данную нам задачу. Задачи, которые решать сложно, также вряд ли подойдут для реализации паттерна «Интерпретатор».
Концептуальное решение. В контексте решения вышеопи­санной проблемы подразумевается некоторый, логично будет
193
так сказать, решатель. Этот решатель представляет собой, как уже постулировалось выше, конструктор. Вышеописанные класси­ческие элементы паттерна «Решатель» способны, в зависимости от текущего состояния контекста, выполнять различные задачи. В частности, терминальное выражение являет собой ПК, ответ­ственный за атомарные единицы какого-либо языка, т. е. за те конструкции языка, которые далее уже неразложимы на состав­ляющие (символы, к примеру). Нетерминальное выражение, в свою очередь, представляет собой ПК, который ответственен за правила построения синтаксических конструкций из терми­нальных символов (тех, за которые ответственен предыдущий компонент), т. е. он ответственен за правила конкретного языка. Контекст представляет собой ПК, который ответственен за об­щую информацию о происходящем в процессе интерпретации в каждый конкретный момент. Ну и абстрактное выражение является программным компонентом, который определяет некий общий интерфейс, в частности специфику самого метода интер­претирования. Понятно, что в данном контексте должен исполь­зоваться рекурсивный алгоритм. Конструктором же, в сущ ности, данный паттерн является по той причине, что итогом всего це­лостного процесса интерпретации является абстрактное синтак­сическое дерево. Абстрактное же синтаксическое дерево (AST) представляет собой специфический способ фиксирования и ре­презентации иерархически распределенной информации на ка­ком-либо конкретном языке.
Предполагаемые результаты и преимущества. Предпола­гается, что реализация паттерна «Интерпретатор» позволяет ав­томатизировать интерпретирование грамматических конструкций простого языка. Также будет достаточно несложно при примене­нии паттерна добавить некоторые новые правила или же терми­налы, т. е. мы получим масштабируемость системы в качестве преимущества. Разбор каких-либо задач, сопоставление строк, определение специфики и особенностей выражений на конкрет­ном языке – за все данные операции может быть ответственен паттерн «Интерпретатор».
Гипотетический пример реализации паттерна. Проще всего осмыслить примерную реализацию данного паттерна, как
194
ни странно, на конкретном примере использования возможно­стей функционального программирования. Мы выберем для де­монстрации какой-нибудь эзотерический язык программирования, допустим MiniStringFuck. Данный эзотерический язык програм­мирования, или сокращенно эсоланг, является дочерним языком по отношению к довольно известному эсолангу Brainfuck. Мы выбрали его по причине его наибольшей простоты. Основу грам­матики данного языка составляют всего два символа (попадаю­щие под юрисдикцию терминального выражения, если реализо­вывать паттерн в рамках ООП), но, несмотря на это, на нем можно написать любой текст. В качестве некоего хранилища выступает всего одна ячейка памяти (в данном случае попадающая под юрисдикцию контекста), которую допустимо представить в ви- де переменной с числовым значением 0. Правила синтаксиса (попадающие под юрисдикцию нетерминального выражения) следующие: при попадании на входную ленту или, можно пе­рефразировать, в поле зрения интерпретатора символа плюс (+) значение ячейки памяти увеличивается на 1, а при попадании в поле зрения интерпретатора символа точки (обычная точка) значение выносится на выходную ленту. Контекст следит за тем, чтобы значение ячейки памяти не становилось больше 256. В противном случае он сбрасывает значение ячейки на 0. Аб­страктное выражение в данном случае может быть ответствен­ным за конечное преобразование данных после их попадания на выходную ленту.
Таким образом, простейший интерпретатор будет выглядеть как функция, которая получает на вход строку, состоящую из последовательно расположенных плюсов и точек. В функцио­нальной области видимости определяется переменная и иници­ализируется числовым значением 0. Также определяется некото­рая выходная лента, которая представлена какой-либо удобной структурой данных, например массивом или строкой (разумеет­ся, что строка в данном случае предпочтительнее, но тогда необ­ходимо сразу преобразовывать данные после каждой встречен­ной во входной строке точки). Далее запускается цикл, который последовательно считывает каждое значение входной строки
195
и реализует логику в зависимости от того, представлено оно точкой или плюсом. В случае плюса значение переменной, кото­рая хранит наши данные, увеличивается на 1, а в случае точки значение переменной добавляется на выходную ленту после (воз­можно) предварительного преобразования. Цикл заканчивается тогда, когда закончилась строка. После завершения цикла функ­ция осуществляет возврат значения, которое представлено (как правило) каким-либо текстом. Вот и вся реализация паттерна «Интерпретатор» в стиле функционального программирования.
В контексте же макромира примеры интерпретации текстов
окружают нас уже практически в любой момент.
Осмысление структуры паттерна. В контексте структуры данного паттерна наличествует несколько разновидностей взаи­мосвязи между ПК. Терминальное выражение и нетерминаль- ное выражение связаны с абстрактным выражением отноше- ниями наследования, так как они оба являются его подклассами и абстрактное выражение определяет их общий функционал, в частности (в контексте классической реализации) абстракт­ный метод Interpret. Так как контекст содержит в себе общие данные о ходе интерпретации и является глобальной точкой до­ступа, он не связан напрямую с остальными элементами. Он связан с дополнительным элементом паттерна, который также выделяют в отдельный компонент, а именно – с клиентом. Однако мы, по уже сложившейся в контексте нашего исследования тра­диции, посчитали, что в данном конкретном случае дополни­тельное обособление клиента в отдельный ПК и/или элемент паттерна – операция излишняя, так как какой-либо пользователь всегда подразумевается у любого системного процесса. Мы счи­таем, что целесообразно обособлять клиента в отдельный ком­понент лишь в том случае, если на него в контексте паттерна возложены какие-либо функции (в общем смысле слова) помимо осуществления «заказа».
Значимость паттерна в контексте разработки систем сильного ИИ. В процессе разработки систем сильного ИИ пове-
денческий паттерн, который, по сути, отвечает за целостное вос­приятие (не за ощущения, а именно за восприятие), несомненно,
196
важен. В случае с данным паттерном, если представить его в ви­де некоторой системы ПК, которая ответственна за восприятие, его терминальным выражением будут как раз ощущения и во­обще все блоки воспринимаемой им информации. Они будут представлены в виде определенных полей данных, которые за­тем, в ходе взаимодействия системы со свойственной ей средой, будут упорядочиваться согласно выявленным системой законо­мерностям. Эти закономерности затем будут попадать под юрис­дикцию нетерминального выражения. Контекст же тут будет выступать в качестве некоего критерия успешности процесса интерпретирования данных со стороны системы. Т. е. некото­рые элементы паттерна «Интерпретатор» должны сами реализо­вываться системой в процессе ее развития и совершенствования, потому что только самой системе «виднее», какие именно зако­номерности полей данных важны непосредственно для нее. Та­ким образом, мы полагаем, что из структуры данного паттерна для нужд построения систем сильного ИИ было бы уместно по­заимствовать такое образование, как абстрактное выражение, которое будет определять возможности взаимодействия систе­мы со средой, задавать в целом тот потенциал интерпретирова­ния данных, на который по минимальным параметрам должна быть способна система. Для определения же успешности/неу­спешности интерпретирования данных считаем необходимым позаимствовать принцип функционирования элемента контекст, который будет определять, насколько какая-либо конкретная интерпретация полей данных помогла системе успешно функ­ционировать. Резюмируя паттерн, стоит отдельно заметить, что процессы ощущения и восприятия окружающей среды со сторо­ны сильного ИИ – это одни из немногих составляющих систе­мы, которые придется определить хоть сколько-то конкретно, хотя бы для начала процесса запуска системы.
12.7. Поведенческий паттерн «Стратегия»
Идентификатор. Стратегия (Strategy). Классические элементы. Стратегия, конкретная стратегия,
контекст.
197
Назначение. Как указывается в Design patterns, назначение паттерна «Стратегия» – «инкапсуляция алгоритма в объект. Ос­новными участниками паттерна являются объекты-стратегии, инкапсулирующие различные алгоритмы, и контекст, в котором они работают» [114, с. 56]. Данный паттерн предназначен для эффективного реагирования на динамически изменяющуюся си­туацию путем выбора одного из различных вариантов этого ре­агирования. Изменение образа действия программной системы в runtime вместе с соответствующим ситуации выбором одного из числа многих варианта этого образа действия и составляет предназначение паттерна «Стратегия».
Проблема. По сути, проблема в данном случае определяется двояко, т. е. можно сказать, что мы имеем дело сразу с двумя проблемами, а если копнуть глубже, то окажется, что с целым комплексом. В описании проблемы мы в данном случае допу­стим себе некоторый уровень конкретики, так как речь все же про паттерн «Стратегия», а это про менеджмент алгоритмов. Во-первых, у нас в наличии имеется довольно сложная система, состоящая из большого количества вариантов действий в зави­симости от ситуации. Визуально и в упрощенном виде это легче всего представить, как некоторый большой и запутанный опера­тор ветвления (if/else) с вложенными различными условиями. С такой системой самой по себе очень сложно и трудоемко рабо­тать и довольно неудобно добавлять в нее новую функциональ­ность. Система, что очевидно, является единой в том смысле, что буквально представлена всего одним программным компо­нентом. Сразу становится заметно, что в подобной ситуации происходит нарушение принципа сильной связности и принци­па SOLID – единственной ответственности. Система-компонент представляет собой god-object в чистом виде. И с этим, конечно же, необходимо уже на данном этапе что-то делать, т. е. осу­ществлять глубокий рефакторинг программной системы, а то и просто переделать с нуля. Второй момент: на каждой из ветвей оператора ветвления в рамках нашей системы заложен некото­рый цикл. Пусть это будет, для примера, цикл поиска нужного значения в какой-либо структуре данных. Причем, следуя логике
198
нашего (конечно, утрированного) примера системы, представим, что один и тот же цикл, работающий с различными данными в зависимости от ветви оператора, буквально каждый раз с нуля прописан в каждой ветви. Здесь, помимо откровенной бесполез­ности и неэкономичности подобного решения, также нарушается и один из организационных принципов ООП – DRY, т. е. «Не по­вторяйся». Этот принцип свидетельствует в числе прочего о том, что одну и ту же логику в рамках одной и той же системы нельзя определять дважды, напротив, ее необходимо преобразо­вывать в такой вид, который позволит ее многократно использо­вать (например, вынести в отдельную функцию). И соответствен­но, данный приведенный фактор также существенно затрудняет не только внесение в систему изменений, но и просто ее обслу­живание. Пусть мы попробовали бы все же вынести неэффек­тивно и неудобно повторяющуюся логику в какой-либо отдельный ПК, а затем попробовали бы передать в нее также и контекст. Здесь уже все зависит от конкретной системы. С системой, кото­рая работает со сложными контекстами, такое будет совершен­но неудобно осуществлять по причине слишком большого коли­чества аргументов, необходимых для описания контекста. Мы же хотели бы, в идеале, эффективно функционирующую систему, масштабируемую, реализующую свое поведение в зависимости от контекста, податливую к необходимым изменениям и удоб­ную в обслуживании. И вот тут на помощь приходит паттерн «Стратегия».
Концептуальное решение. С точки зрения функционально­го программирования решение, подразумеваемое «Стратегией», также реализуемо. Однако все же удобнее реализация при помощи методологии ООП. Итак, мы определяем несколько ПК. Стра­тегия (элемент паттерна) будет далее определять некий общий интерфейс для всех конкретных стратегий. Контекст же, так­же представленный отдельным программным компонентом, бу­дет определять специфику актуальной для системы ситуации и хранить у себя ссылки на все доступные конкретные страте­гии. При возникновении какой-либо ситуации в рамках системы ПК, оформленный в виде контекста, определяет специфику
199
этой ситуации и далее делегирует ответственность одной из до­ступных ему конкретных стратегий, представленных ПК, ин­капсулирующими в себе некоторый алгоритм, специально по­добранный для эффективного функционирования именно при контексте, аналогичном актуальному. Соответственно, система разделена на несколько ПК, в каждом из которых инкапсулиро­вана логика, необходимая для осуществления строго конкретной деятельности (логика не будет повторяться, если она одинакова). С подобной системой удобно работать: она легко принимает до­бавления нового функционала (новых конкретных стратегий) путем простого создания подклассов класса стратегия.
Предполагаемые результаты и преимущества. В рамках реализации поведенческого паттерна «Стратегия» за счет ин­капсуляции логики в ПК мы способны избежать применения сложных и запутанных операторов ветвления. Также среди пре­имуществ использования данного паттерна имеются высокая эластичность системы в плане масштабируемости и расширяе­мости, удобство взаимодействия с ней и достаточно легкая ее поддержка.
Гипотетический пример реализации паттерна. Довольно показательным примером, иллюстрирующим практическую зна­чимость данного паттерна, являются различные системы под­борки, коих в наше время великое множество. Для примера: приложение, которое подбирает оптимальную программу тре­нировки в зависимости от актуальных потребностей пользова­теля. Приложение принимает некоторые входные данные, каса­ющиеся антропометрических особенностей пользователя (рост, вес, далее – опционально), его возраст и предпочитаемый им ва­риант тренировок. Вариант можно выбрать из предоставляемых, которых всего наличествует три: тренировка «на массу», трени­ровка «на силу» и тренировка «на сушку». У системы в ее базе данных (к которой, скорее всего, имеет доступ контекст) имеется определенное количество различных упражнений. При введении пользователем всех тех данных, которые запрашивает приложе­ние, и выборе одного из трех вариантов тренировки контекст осуществляет фильтрацию базы данных (в данном случае под
200
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]