Объектно-ориентированное программирование в разработке экспертных систем
За последние 20 лет было разработано довольно много языков для представления знаний, причем большинство из них можно отнести к классу объектно-ориентированных. Как и в случае с использованием концепции фреймов, основная идея состоит в том, чтобы заключить данные и связанные с ними процедуры в некие структуры, объединенные механизмом наследования.
Одним из предшественников современных программных средств является система KRL (Knowledge Representation Language - язык представления знаний).
Язык представления знаний - KRL
В языке KRL впервые была сделана попытка собрать воедино результаты выполненных ранее исследований о структурировании элементов знаний и реализовать их в виде единой системы. Создание системы преследовало не только теоретические цели, но и имело достаточно четкую практическую направленность. В качестве «строительных блоков» системы использованы так называемые «концептуальные объекты», которые сходны с фреймами, предложенными Минским, в том, что представляют прототипы и связанные с ними свойства.
Такая ориентация повлекла за собой создание декларативного языка, основанного на описаниях, в которых концептуальные объекты рассматриваются не изолированно, а в совокупности с другими объектами-прототипами. Фундаментальное предположение состояло в следующем: что какие свойства некоторого объекта знаний оказываются существенными, представляющими интерес и т. д. - зависит от точки зрения на объект и цели решаемой задачи.
При этом описание новой сущности можно рассматривать как процесс сравнения ее с ранее описанными: нужно указать, на какие из известных объектов похож новый и чем именно, а в чем от них отличается.
В основе процедурных свойств языка KRL также лежат наиболее распространенные программные методы, предполагающие подключение процедур общего вида к классам объектов данных.
Разработчики языка предположили, что наследование процедур позволит программировать в терминах родовых операций, детали реализации которых конкретизируются по-разному для объектов разных классов. Так же, как абстрактные типы данных позволяют программисту забыть о деталях хранения конкретных данных в машине, родовые операции позволяют на определенной стадии не принимать во внимание детали реализации однотипных операций в каждом конкретном случае.
Таким образом, идея, которая стоит за объектно-центрической организацией процедур, состоит в том, чтобы попытаться программно воспроизвести тот естественный стиль выработки суждений, который реализуется в мозге человека. В частности, предполагается, что управление логическим выводом реализуется на локальном уровне, в отличие от глобальных задач, ассоциирующихся, например, с автоматическим доказательством теорем. Другими словами, зная, как реализовать родовые операции, классы объектов будут обладать знаниями и о том, когда активизировать те многочисленные процедуры, к которым они имеют доступ.
Языки LOOPS и FLA VORS
Объектно-ориентированный стиль программирования более всего подходит для решения проблем, требующих детального представления объектов реального мира и динамических отношений между ними.
Классическим примером применения данного подхода являются задачи моделирования. В таких программах компоненты сложной системы представляются структурами, инкапсулирующими и данные, и функции, моделирующие поведение соответствующих компонентов. Первым языком, в котором была реализована такая идея, стал SmallTalk.
Для задач искусственного интеллекта были разработаны языки LOOPS и FLAVORS, причем оба представляют собой объектноориентированные расширения языка Лисп. Хотя в настоящее время эти языки практически не используются, реализованные в них базовые идеи унаследованы множеством языков представления знаний, появившихся позже. В частности, это можно сказать о языках CLOS (Common LISP Object System) и CLIPS.
Языки CLIPS и CLOS
Появление языка Common LISP было связано с попыткой стандартизировать многочисленные диалекты Лисп и создать устраивающую большинство пользователей версию этого языка. Развитие объектно-ориентированного подхода в программировании привело к разработке объектно-ориентированной версии Лисп - CLOS (Common LISP Object System). Разработчики CLOS включили в свою систему поддержку множественного наследования, объединение методов и структуру метаклассов, ранее хорошо себя зарекомендовавших в языках FLAVORS и LOOPS.
Механизм множественного наследования в языках CLIPS и CLOS аналогичен реализованному в языке LOOPS. Порядок, в котором базовые классы перечислены в определении подкласса, задает и порядок приоритетов наследования данных и процедур.
Кроме того, существует правило, в соответствии с которым определение процедуры или свойства, сделанное в классе, всегда имеет приоритет перед унаследованными от суперклассов. Эти соглашения позволяют разрешить проблему неоднозначности при множественном наследовании путем формирования списка предшествования классов.
В языках FLAVORS и LOOPS реализованы разные механизмы комбинирования поведения, унаследованного от разных «родителей». В языке FLAVORS используется механизм вставок, а в языке LOOPS производится дополнительное обращение к альтернативному коду.
В языке CLOS поддерживаются оба варианта. Обычно существует главный метод, который берет на себя основную часть работы по выполнению родовой операции. Как и в языке FLAVORS, предварительные методы используются в целях подготовки данных для тех вычислений, которые должны быть выполнены основным методом, а заключительные методы - для выполнения заключительных операций.
Кроме того, в CLOS имеется возможность применять так называемые методы оболочки, которые образуют своего рода оболочку вокруг ядра. Такая методика предназначена для ситуаций, в которых ядро не позволяет достичь требуемого результата. Например, желательно, чтобы предварительный метод установил локальные переменные, которые должны быть использованы основным методом, или когда нужно заключить предварительный метод в какую-либо управляющую структуру. В ядре предварительные и заключительные методы используются только для того, чтобы сформировать побочные эффекты; возвращается же значение, сформированное primary-методом, причем это значение не ограничивается никакими внешними управляющими структурами.
В языке CLOS классы и метаклассы интегрированы в среду Лисп. Фактически каждый объект Лисп является экземпляром класса.
C++
Так же, как язык CLOS представляет собой объектно-ориентированное расширение языка Лисп, так и язык C++ создан на основе широко известного языка С и сохранил все его возможности, добавив к ним средства объектно-ориентированного программирования. Основное отличие между CLOS и C++ заключается в реализации механизма наследования, в частности множественного наследования.
В языке C++ множественное наследование трактуется иначе. Родовые операции в нем реализуются в виде виртуальных функций. Виртуальная функция, объявленная в классе X, - это функция, которая может быть переопределена в классе, производном от X. При объявлении в классе X виртуальная функция вообще может не иметь тела, т. е. программного кода реализации. В таком случае функция называется чисто виртуальной, а класс, имеющий одну или более чисто виртуальных функций, является абстрактным базовым классом, экземпляры которого создать невозможно.
Методы, вызывающиеся на выполнение, являются невиртуальными членами-функциями, т. е. функциями, имеющими определенный программный код, который не переопределяется в производных классах.
В этом смысле C++ существенно отличается от языка CLOS, в котором практически все функции суперкласса в большей или меньшей степени модифицируются механизмом наложения методов. Поэтому в C++ существует множество синтаксических тонкостей, в которых не нуждается CLOS.
В чисто иерархической структуре классов, когда каждый производный класс имеет единственного «родителя», передача методов по наследству выполняется совершенно очевидным способом. Единственная тонкость реализации этого механизма в C++ состоит в использовании квалификаторов наследования public и private. Если не вдаваться в подробности, то наследование вида public представляет собой отношение «is а» (является), которое используется при фреймовой структуре представления знаний. Наследование вида private ближе к отношению «реализовано в терминах», которое позволяет скрыть определенные детали реализации интерфейсов объектов. Такое полезное разделение отсутствует в языке CLOS, в котором каждое отношение «класс-подкласс» несет семантический смысл.
Язык C++, обладая такими преимуществами, как проверка статических типов, разделение между закрытым и общедоступным наследованием, множество средств защиты данных от случайных изменений может служить базовым программным инструментом для создания экспертных систем.
SmallTalk
SmallTalk - объектно-ориентированный язык программирования, разработанный сотрудниками исследовательской группы фирмы XEROX (США) в 1970 году. Язык был представлен как SmallTalk-80 и с тех пор широко используется при разработке экспертных систем.
Объект в SmallTalk содержит и процедурную, и понятийную части (объект - данные + процедуры), причем для представления понятийной части используется аппарат абстрактных типов данных.
При решении задач на объектно-ориентированном языке используется абстрактная модель обработки данных
«объект - класс - сообщение»
Эта модель носит фундаментальный характер и легко может применяться в любой предметной области.
SmallTalk продолжает активно развиваться. В настоящее время существует две реализации SmallTalk, являющихся прямыми потомками SmallTalk: Squeak и VisualWorks.
Реализация идей объектно-ориентированного программирования в разработке экспертных систем
Представление знаний о реальном мире в терминах взаимодействия объектов и субъектов является достаточно удобной средой для решения большого класса проблем, предполагающих значительный объем моделирования (задачи планирования и составления расписаний).
Методика представления абстрактных данных и процедур позволяет программистам, занятым задачами искусственного интеллекта, на ранних этапах разработки сосредоточиться на выборе подходящих видов объектов и их поведении, не вдаваясь в подробности реализации функций и структур данных.
Сложности внедрения объектно-ориентированного подхода в область задач искусственного интеллекта:
- 1. Объекты, в основном, являются средствами реализации вычислений.
- 2. Идея наследования поведения влечет за собой появление множества проблем при ее реализации (некоторые из появившихся в последнее время объектно-ориентированных схем допускают наследование только интерфейсов).
- 3. Определенные сложности возникают с реализацией наследования при использовании новых технологий многокомпонентных объектов, таких как СОМ.
В идеальном случае желательно так организовать разработку экспертной системы, чтобы добавление новых возможностей сводилось к включению в систему новых модулей программного кода.
Однако это вряд ли возможно даже при использовании объектно-ориентированной среды. Добавление новых модулей знаний обусловливает необходимость включения правил разрешения конфликтов и неопределенностей.
Таким образом, совершенно очевидно, что реализация идей объектно-ориентированного программирования не позволяет решить все проблемы разработки экспертной системы. Но объектно-ориентированная парадигма упрощает принятие определенных видов решений в процессе проектирования системы и облегчает реализацию уже принятых.