Титульный лист
Аннотация
Предисловие
1. Назначение, состав и функционирование экспертной системы
1.2. Язык эксперта
1.3. Блок логического вывода
1.4. Блок пояснений и язык пользователя
1.5. Описание функционирования экспертной системы
2. Реализация экспертной системы на языке Паскаль
2.2. Выбор структур данных
2.3. Реализация языка эксперта
2.4. Реализация логического вывода
2.5. Реализация блока объяснений и языка пользователя
2.6. Основная программа инструментальной экспертной системы
3. Реализация экспертной системы на языке ЛИСП
3.2. Выбор структур данных
3.3. Реализация логического вывода
3.4. Реализация блока объяснений и языка пользователя
3.5. Реализация языка эксперта
3.6. Основная программа инструментальной экспертной системы
4. Реализация экспертной системы на языке Пролог
4.2. Реализация логического вывода
4.3. Реализация блока пояснений и языка пользователя
4.4. Реализация языка эксперта
4.5. Основная программа инструментальной экспертной системы
5. Пути расширения возможностей экспертной системы
5.2. Организация циклов иа языке эксперта
5.3. Автоматизированная обучающая система на базе инструментальной экспертной системы
Приложение 1. Синтаксические диаграммы языка Паскаль
Приложение 2. Программа инструментальной экспертной системы
Список литературы
Оглавление
Текст
                    В.  Э.  Балтрашевич
 РЕАЛИЗАЦИЯ  ИНСТРУМЕНТАЛЬНОЙ
ЭКСПЕРТНОЙ  СИСТЕМЫ
 Санкт-Петербург
 «Политехника»
 1993


ББК 32.973.2-01 Б20 УДК 381.5.2: [681.3.06:519.682] Балтрашевич В. Э. Б20 Реализация инструментальной экспертной систем и,— СПб.: Политехника, 1993.— 237 с.: ил. ISBN 5-7325-0037-5 В книге рассмотрены экспертные системы (ЭС) и примеры их реализации. Приведены варианты реализации основных блоков ЭС: базы знаний, блока логического вывода, блока пояснений, блока вы¬ дачи сообщений, интерфейса между системой и экспертом и интер¬ фейса между ЭС и пользователем. Даны тексты программ на языках программирования Паскаль, ЛИСП, Пролог. Книга предназначена для начинающих и потенциальных пользова¬ телей ЭС. 2404010000-036 Б 045(01)-93 36-92 ББК 32.073.2-01 ISBN 5-7325-0037-5 © В. Э. Балтрашевич, 1993
ПРЕДИСЛОВИЕ В связи с появлением в настоящее время большого числа вычислительных машин различных классов (под вычислитель¬ ной машиной будем понимать совокупность аппаратных и про¬ граммных средств, предназначенных для решения задач) встает вопрос о расширении круга их пользователей. До недавнего времени пользователю было необходимо знание какого-либо языка программирования, а также принципов работы машины. Фактически он должен был решить свою задачу, а затем описать процесс ее решения на алгоритмическом языке программирова¬ ния. С помощью разработанной программы пользователь ука¬ зывал машине, как нужно обработать исходные данные для решения задачи. Все это значительно сокращало число поль¬ зователей, способных решать трудно формализуемые задачи в таких широко распространенных областях человеческой дея¬ тельности, как медицина, ботаника, зоология и т. п. Для того чтобы расширить круг пользователей, необходимо было создать универсальнные средства, во-первых, позволяю¬ щие пользователю описывать задачи из предметной области, и, во-вторых, решающие задачи на основании этого описания. Очевидная перспективность этого пути развития вычислитель¬ ных машин привела к появлению целого класса программных систем, получивших название экспертных, т. е. систем, заме¬ няющих эксперта в какой-либо предметной области при реше¬ нии задач определенного класса. Экспертные системы позволяют специалисту в конкретной предметной области обобщить свои знания и опыт и наиболее полно их продемонстрировать, непрограммисту свободно рабо¬ тать на вычислительных машинах, решать неформализованные задачи, проводить обучение. С помощью экспертных систем можно осуществлять [16] ин¬ терпретацию, т. е. построение описаний ситуаций по наблю¬ даемым данным; прогноз, т. е. вывод вероятных следствий из заданных ситуаций; диагностику, т. е. заключение о нарушениях в системе, исходя из наблюдений; мониторинг, т. е. сравнение наблюдений с критическими точками плана; обучение, т. е. ди¬ агностику, отлаживание и исправление поведения ученика и др. Разработке и использованию экспертных систем посвящено много журнальных статей и ряд книг [13, 15, 16, 18, 22, 23, 27, 28]. Однако в разрозненных журнальных статьях рассматрива¬ ются особенности разработки различных блоков экспертных I* 3
сипом, что зитрудияст получение1 npe;u‘TmwieiiiiH об экспертной системе и целом. С другой стороны, н книгах даются обзоры различных ЭС и некоторые особенности реализации отдельных: блоком. Очень нужны книги, содержащие полное описание ка¬ комлибо (пусть и упрощенной) ЭС |20|. Исходя из литературных данных и из собсгмсннош опыта, можно сделать вывод о том, что понять и оценить достоинства ЭС можно, только работая с ними. Экспериментирование на вычислительных машинах отличается точностью, гак как при. реализации ЭС на машине вскрываются те ошибки и недочеты, которые обычно ускользают от внимания даже самых скрупу¬ лезных исследователей. Часто обнаруживаются такие подвод¬ ные камни, которые не принимались в расчет до начала цикла размышления и экспериментирования. С другой стороны, надо отметить, что построить универ¬ сальную ЭС вряд ли можно. В каждом конкретном случае пользователям придется разрабатывать свои ЭС, пригодные для решения конкретного класса задач в конкретной предметной области. Для этого необходимо иметь какой-либо прототип. В данной книге приводится полное описание конкретной экс¬ пертной системы. Рассматриваемая ЭС предназначена для решения задачи ин¬ терпретации и диагностики, а также для построения автомати¬ зированных обучающих систем и обработки изменяющихся данных. Большое внимание в книге уделено вопросам реали¬ зации инструментальной экспертной системы. Перспективным является создание (реализация) экспертной системы на языках программирования различных классов.. В данной книге дается полное описание инструментальной экспертной системы на различных языках (Паскаль, ЛИСП, Пролог). Выбор именно этих языков объясняется тем, что они яв¬ ляются типичными представителями различных направлений в программировании: язык Паскаль — представитель тради¬ ционного императивного программирования, ЛИСП — функ¬ ционального программирования, Пролог — логического про¬ граммирования. Программы на Паскале, ЛИСПе и Прологе, приведенные в книге, прошли апробацию на машинах СМ ЭВМ. Программа инструментальной ЭС написана на языке TURBO PASCAL и опробована на машине IBM PC. Автор выражает благодарность за помощь и поддержку своим коллегам с кафедры математического обеспечения и при¬ менения ЭВМ ЛЭТИ им. В. И. Ульянова (Ленина).
1. НАЗНАЧЕНИЕ, СОСТАВ И ФУНКЦИОНИРОВАНИЕ ЭКСПЕРТНОЙ СИСТЕМЫ 1.1. НАЗНАЧЕНИЕ, ОСОБЕННОСТИ ФУНКЦИОНИРОВАНИЯ И СТРУКТУРНАЯ СХЕМА ИНСТРУМЕНТАЛЬНОЙ ЭКСПЕРТНОЙ СИСТЕМЫ Реализуемая экспертная система предназначена для реше¬ ния задачи интерпретации или диагностики в различных пред¬ метных областях. Предметной областью обычно называют сово¬ купность взаимосвязанных сведений, необходимых и достаточ¬ ных для решения поставленной задачи или определенной совокупности задач. Знания о предметной области включают описания объектов, явлений, фактов, а также отношений между ними. Задача интерпретации предполагает наличие некоторого объекта исследования, обладающего рядом свойств, по кото¬ рым делается вывод о самом объекте. В качестве примера интерпретации рассмотрим следующую задачу. Имеется ряд языков и ряд предложений на этих язы¬ ках (табл. 1.1). Пользователю ЭС необходимо определить тип конкретного имеющегося у него предложения или тип языка, к которому относится это предложение. Этот пример можно отнести к задаче интерпретации для предметной области — лингвистики. В п. 1.5 будет дан пример аналогичной задачи интерпретации для другой предметной об- Таблица 1.1 № пп Предложение № пп Предложение 1 1 ТО стебель — зеленый 5 # зеленый 2 7 ЕСЛИ стебель — зеленый 6 ? почему ТО тин — травянистые 7 ? как стебель 3 8 ЕСЛИ стебель — древесный И ПОЛОЖЕНИЕ — стелюще¬ еся ТО тин — лианы 8 ПОДСКАЗКА стебель Какой стебель у растения 4 9 ЕСЛИ стебель — древесный И положение — прямостоящее И один-основной-ствол — да ТО тип — деревья 9 ПЕРЕВОД стебель стебель растения 5
ласти — ботаники. Разрабатываемая нами инструментальная ЭС должна решать задачи указанного класса независимо от предметной области. Проанализировав табл. 1.1, можно сделать вывод, что решить задачу интерпретации можно пока только с помощью эксперта или с помощью заменяющей эксперта программной системы, т. е. экспертной системы. Рассмотрим требования, предъявляемые к ЭС и вытекающие из постановки задачи. 1. Поскольку с экспертной системой будут работать не спе¬ циалисты в вычислительной технике и программировании, то об¬ щение с ней должно быть максимально простым, т. е. необхо¬ димо использовать язык общения наиболее близкий специали¬ стам данной предметной области. 2. Экспертная система должна обеспечить решение несколь¬ ких задач, ставящихся перед ней пользователем. Например, оп¬ ределение типа языка или типа предложения при условии, что этих типов может быть несколько. 3. Инструментальная ЭС должна решать задачи интерпре¬ тации в любой предметной области. 4. Поскольку пользователь ЭС не является экспертом в своей предметной области и ему при решении конкретной задачи могут понадобиться консультации эксперта, то ЭС должна иметь средства для объяснения процесса решения за¬ дачи. Вследствие того что с ЭС работают программист, эксперт, пользователь, каждый из них имеет свои функции. Перед тем как решать любую задачу (в нашем случае за¬ дачу разработки инструментальной ЭС) необходимо выяснить, не решена ли уже подобная задача или какие из решенных задач являются наиболее близкими. Для этого осуществляют краткий анализ традиционных программ, заключающийся в сле¬ дующем. 1. В традиционном программировании при иерархической структуре программ программист, сначала определяет что нужно сделать, чтобы решить задачу, а потом решает как это осуществить. Записав последовательность решения на алгорит¬ мическом языке, т. е. создав программу, он передает ее машине, которая решает данную задачу при разных исходных (для за¬ дачи) данных. Поскольку в нашем случае пользователь машин не является программистом, то его деятельность состоит в том, чтобы поставить задачу, а как ее решать определяет машина. Пользователь же, задавая машине вопрос КАК, может поин¬ тересоваться ходом решения задачи. 2. Большая часть существующих программ предназначена для решения одной задачи, и при необходимости решения дру¬ гой задачи или даже модификации первой приходится перепи¬ сывать исходную программу. Как уже отмечалось, в нашем в
случае требуется обслужить много целей без переписывания программы экспертной системы. 3. Для традиционного подхода типична обработка под уп¬ равлением программы и такие программы не могут работать при неизвестной заранее цели решения. Человеком (экспертом) обычно «управляют» данные, и это зачастую оказывается весьма эффективным, если приходится сталкиваться с большим числом ситуаций. Экспертные системы относятся к области искусственного интеллекта, т. е. области, пытающейся с учетом процессов мышления человека провести автоматизацию интел¬ лектуальной деятельности человека. Существует большой класс программ, в которых обработка идет под управлением исходных данных. Это трансляторы с раз¬ личных языков программирования. Разработка трансляторов — это одна из наиболее успешно развивающихся областей искус¬ ственного интеллекта. Их управляющие структуры отличаются от обычных программ и, как будет видно из дальнейшего, имеют много общего с управляющей структурой ЭС. Чтобы полнее отразить их сходство и различие и было выбрано содержание нашего примера (табл. 1.1). Однако трансляторы предназна¬ чены для работы с конкретным языком, т. е. в конкретной пред¬ метной области. Например, транслятор с языка Паскаль пред¬ назначен только для работы с программами (предложениями языка), написанными на языке Паскаль, и не сможет работать с программами, написанными на языке ЛИСП или Пролог. Наша же задача построить инструментальную ЭС, способную работать со знаниями из различных предметных областей. 4. В традиционных программах отсутствует возможность объяснения своих действий. Даже в трансляторах диагностиче¬ ские сообщения констатируют ошибку, но не объясняют, вслед¬ ствие чего она возникла. Из проведенного качественного анализа традиционных про¬ грамм следует вывод о необходимости специальной разработки инструментальной ЭС. Однако необходимо отметить некоторое сходство ЭС с трансляторами, которые позволяют обслуживать несколько целей и управление в которых производится от дан¬ ных. Основным недостатком трансляторов, с точки зрения построения ЭС, является жесткая зависимость от предметной области, т. е. от языка, для которого они предназначены. В основе работы любого транслятора лежит интерпретация команд языка. Простейший аппаратный или программный ин¬ терпретатор (независимо от предметной области) по заданному коду, перебирая последовательно все правила, устанавливающие соответствие между кодом и командой, находит то, которое удовлетворяет заданному коду и активирует команду. Правила, используемые интерпретатором, можно представить в виде ЕСЛИ <условие> ТО <действие>.
Очевидно, что используя интерпретатор, исполняющий по¬ добного вида команды, можно решать задачи из различных предметных областей. Но возникает вопрос, как с его помощью решать задачу, для которой предназначена ЭС? Решение задачи — это процесс, но при работе интерпрета¬ тора процесс не возможен, так как у интерпретатора отсутст¬ вует память. Однако, если с каждым действием интерпретатора связать какое-то понятие (состояние) и к интерпретатору до¬ бавить память состояний, то при выполнении каждого очеред¬ ного правила система (интерпретатор + память) будет перехо¬ дить из одного состояния Таблица 1.2 в другое, т. е. возможен процесс. Чтобы этот процесс приобрел смысл и при¬ вел к решению за¬ дачи из конкретной пред¬ метной области, надо ис¬ пользовать не какие-то правила, а конкретные правила из конкретной предметной области, ко¬ торые может составить только эксперт. Эти очевидные рас¬ суждения приводят к мысли о том, что решать задачи можно с помощью системы, состоящей из интерпретатора, памяти состояний ^и правил предметной области. Поскольку правила предметной области вида ЕСЛИ...ТО получили название пра¬ вил продукций, то и всю систему называют системой продук¬ ций. В работе [13] предлагается использовать более общие на¬ звания составляющих системы продукции: глобальная база дан¬ ных, правила продукций и система управления. Вследствие того что условия в правилах могут быть до¬ вольно сложными, а число правил может быть большим, иногда интерпретатор разделяют на интерпретатор и диспетчер. При этом интерпретатор определяет, каким образом применять пра¬ вила, а диспетчер устанавливает порядок применения этих пра¬ вил [23]. Таким образом, для представления процесса решения задачи интерпретации предложений экспертом можно использовать со¬ стояния, под которыми будем понимать некоторый список фак¬ тов о предложении и тип предложения. 8 Атрибут Смысл атрибута Число Предложение начина¬ ется с числа Слово Предложение начи¬ нается со слова След_ слово Следующая строка предложения начинает¬ ся со слова ТО Имеется строка пред¬ ложения, начинающая¬ ся с ТО 4* Предложение начи¬ нается с символа # ? Предложение начина¬ ется с символа ?
9 Рис. 1.1. Граф представления состояний
Граф представления состояний, построенный экспертом на основании его знаний, приведен на рис. 1.1. Состояния вклю¬ чают атрибуты и их значения. Сами названия атрибутов пока недостаточно ясны и поэтому в табл. 1.2 приведена их семан¬ тика (так называемые переводы). Конечные состояния графа, т. е. состояния из которых нет переходов в другие состояния, могут быть выданы пользова¬ телю как некие шаблоны, сравнивая с которыми имеющееся у него предложение, пользователь определяет его тип. Например, шаблон из состояния Р7 (см. рис. 1.1) после рас¬ крытия атрибутов при- Таблнца 1.3 мет следующий вид: предложение н ачина- ется с числа — ДА предложение начина¬ ется со слова — ЕСЛИ. следующая строка предложения начинается со слова — ТО. Очевидно, что этот ш а бл он соотв етствует второму предложению из табл. 1.1. Таким обра¬ зом, на основании зна¬ ний эксперта, заложен¬ ных в графе, можно сделать вывод о том, что второе предложение из табл. 1.1 относится к типу правило. Результаты анализа предложений (см. табл. 1.1) с помощью графа 1.1 можно представить в виде табл. 1.3, в которой фак¬ тически представлены результаты решения задачи интерпрета¬ ции, а состояние Р12 (см. рис. 1.1) можно рассматривать кок пример решения задачи диагностики. Подробнее задача диаг¬ ностики будет рассмотрена в дальнейшем при реализации трансляторов. Таким образом, имея граф поиска решения нашей задачи, определить тип предложения может даже не специалист. Рассмотренное нами представление задачи является пред¬ ставлением в пространстве состояний. Поиск формы представ¬ ления задачи, удобной для ее машинного решения, является трудно формализуемым творческим процессом. Можно выделить следующие наиболее употребительные формы: представление в пространстве состояний; представление путем сведения задач к подзадачам; представление в виде теорем; комбинированное представление [19]. Представление задач в пространстве состояний. Полное представление задачи в пространстве состояний включает опи¬ Номер пред¬ ложения в табл. 1.1 Номер состояния графа на рис. 1.1 Тип предложе¬ ния ! РЗ Правило 2 Р7 Правило 3, 4 Р11 Правило 5 Р5 Ответ 6 Р13 Вопрос 7 Р14 Вопрос 8 Р15 Подсказка 9 Р16 Перевод 10
сание всех состояний или только начальных, задание операто¬ ров, отображающих одни состояния в другие, и задание целе¬ вого состояния. Возможны различные формы описания состоя¬ ний задачи: списки, матрицы, графы и т. п. Процедура поиска решения в пространстве состояний за¬ ключается в том, чтобы найти последовательность операторов, которая преобразует начальное состояние в целевое, т. е. в со¬ стояние, отвечающее поставленной цели. При описании прост¬ ранства состояний и методов поиска решений в искусственном интеллекте широко используется граф и особенно одна его раз¬ новидность, называемая деревом (см. рис. 1.1). Представление, сводящее задачу к подзадачам. Такое пред¬ ставление предусматривает разбиение исходной задачи на мно¬ жество подзадач, раздельное решение которых дает решение исходной задачи. Каждая из подзадач может в свою очередь быть разбита на подзадачи. Число уровней разбиения теоре¬ тически неограничено. На практике разбиение продолжается до получения на нижнем уровне множества задач (подзадач),, способ решения которых известен. Существуют два типа структур взаимосвязи подзадач: И-структуры и И — ИЛИ-структуры. В структурах типа И для решения основной задачи требуется решить все подзадачи. В структурах И — ИЛИ подзадачи разбиваются на группы, внутри которых они связаны отношением И, а между груп¬ пами— отношением ИЛИ. В этом случае для решения исходной задачи достаточно решить все подзадачи только какой-либо одной группы. Представление в виде теорем. При представлении задачи в виде теоремы определяются или задаются посылки, т. е. мно¬ жество известных истинных утверждений (аксиом). Затем фор¬ мулируется теорема, доказательство которой позволяет полу¬ чить решение исходной задачи. Поиск решения при таком пред¬ ставлении производится следующим образом. Комбинируя по разному две аксиомы или более, выводят утверждения, которые можно получить из посылок. Далее проверяется, не содержит ли полученное множество утверждений теорему или ее отрицание. Если содержит, то теорема доказана или отвергнута. Если тео¬ рема или ее отрицание не содержится, то полученное множе¬ ство утверждений добавляется к посылкам и процедура повто¬ ряется. Способы комбинации аксиом будут рассмотрены вп. 1.3. Комбинированное представление. В общем случае необяза¬ тельно использовать какое-либо одно представление. Более эф¬ фективным при решении отдельных задач может оказаться ком¬ бинированное (смешанное) представление. Например, если за¬ дача имеет явно выраженную иерархическую структуру и легко разбивается на ряд подзадач, то удобно сначала свести задачу к подзадачам, а для представления подзадач использовать раз¬ 11
личные формы описания в пространстве состояний или пред¬ ставление в виде теоремы. В процессе реализации инструментальной ЭС мы рассмот¬ рим различные способы представления задач. Пока же обра¬ тимся к представлению задач в пространстве состояний, при реализации которого наибольшее распространение получили си¬ стемы продукций. Основными элементами системы продукций являются гло¬ бальная база данных, множество правил продукции и система управления. Глобальная база данных — центральная структура данных, используемая системой продукций. В зависимости от конкрет¬ ной задачи эта база данных может быть простой или слож¬ ной. Правила продукций применяются к глобальной базе данных. Для каждого правила имеется предварительное условие, кото¬ рому эта база данных либо удовлетворяет, либо нет. Если пред¬ варительное условие выполняется, то правило может быть при¬ менено. Применение этого правила изменяет базу данных. Система управления выбирает, какое именно применимое правило следует использовать, и прекращает вычисления, когда глобальная база данных удовлетворяет терминальному условию (или условию остановки). Правила вывода и запоминания уже опробованных после¬ довательностей правил и баз данных, порожденных их приме¬ нением, образуют стратегию управления для систем продук¬ ций. Часто информация, доступная стратегии управления, не¬ достаточна для того, чтобы выбрать наиболее подходящее правило. Поэтому работу системы продукций можно охарак¬ теризовать как процесс поиска, в котором правила подвер¬ гаются испытанию до тех пор, пока не обнаружится, что не¬ которая их последовательность порождает базу данных, удов¬ летворяющих терминальному условию. Как уже отмечалось, граф, представленный на рис. 1.1, отражает все возможные варианты решения задачи интерпре¬ тации предложений, представленных в табл. 1.1. Процесс по¬ иска решения задачи фактически сводится к перебору состоя¬ ний этого графа. Граф содержит небольшое число состояний и поэтому порядок перебора его состояний может быть и слу¬ чайным. Однако при решении задачи автоматизации работы с графом обычно предлагается какой-либо путь обхода этого графа, точнее поиска нужного состояния графа. Наиболее часто используются два вида поиска: поиск в глу¬ бину и поиск в ширину [9, 13]. При поиске в ширину вершины графа перебираются в порядке, соответствующем нумерации вершин на рис. 1.1. При поиске в глубину следует двигаться вдоль самой левой ветви дерева до тех пор, пока не будет 12
удовлетворен запрос или не будет достигнут конец ветви. В последнем случае необходимо «отступить» (возвратиться) в предыдущую точку ветвления и с помощью того же метода произвести проверку других ветвей. Для рассматриваемого графа при поиске в глубину вершины будут перебираться в следующем порядке: Ру Р1> РЗУ Р4У Р7, Р8, Р11у Р12у Р2У Р5У Р6У Р9У Р13у Р14У Р10у Р15у Р16. Поиск в глубину и в ширину относится к так называемым методам слепого перебора, достоинствами которых являются, во-первых, простота алгоритмической реализации, во-вторых, обязательность получения решения, если оно существует. Недо¬ статком этих методов является резкое возрастание числа вер¬ шин, которые необходимо обойти в процессе поиска решения, с увеличением размерности задачи. Это зачастую делает эги методы не пригодными для использования при управлении си¬ стемой продукций, поскольку здесь в процессе поиска до на¬ хождения требуемого пути раскрывается слишком много вер¬ шин. Вследствие того что на практике всегда существуют ограничения на время и память, которые выделяются для реа¬ лизации этого процесса, необходимо найти более эффективные альтернативы неинформированному поиску. При методах слепого перебора вершин дерева поиска шаб¬ лон, соответствующий анализируемому предложению, ищется фактически «вслепую»: без учета предыдущих результатов по¬ иска. Перебор можно значительно сократить, если учитывать результаты предыдущего анализа совмещения шаблона и пред¬ ложения, которые могут быть получены от пользователя на ос¬ новании задаваемых ему вопросов. Ответы пользователя будут направлять процесс поиска, т. е. процесс перебора состояний (вершин) дерева поиска. Вопросы должны быть сформулиро¬ ваны так, чтобы их можно было задавать по телефону, т. е. чтобы можно было бы использовать так называемую телефон¬ ную консультацию, которая исключает вопросы связанные с чувствами. Ответы пользователя, так называемые факты, бу¬ дут запоминаться в списке фактов, каждое состояние которого будет определять состояние в пространстве состояний. На рис. 1.2 приведен граф (дерево) поиска типа предло¬ жения с учетом ответов пользователя. Читателю предлагается самостоятельно проследить изменение состояний списка фактов при прохождении состояний графа, предполагая, что элемент списка состоит из атрибута и его значения, и сравнить получен¬ ные состояния списка с шаблонами, приведенным на рис. 1.1. Каждый вопрос на рис. 1.2 соответствует некоторому атрибуту. Это соответствие легко может быть установлено с помощью табл. 1.2. Из приведенного графа видно, что с учетом ответа пользова¬ теля значительно сокращается число перебираемых состояний 13
14 Предложение Предложение Предложение Предложение Предложение Предложение -правило -ошибочное -вопрос -вопрос -подсказка -перевод Рис. 1.2. Граф поиска типа предложения
графа, так как поиск идет в «нужном» направлении. В этом случае при решении любой конкретной задачи фактически про¬ ходится одна ветвь дерева (см. рис. 1.2), тогда как при работе с графом (см. рис. 1.1) в худшем случае приходилось обходить все его вершины. Каждая ветка (путь) дерева, начинающаяся в корне дерева и заканчивающаяся в вершине, определяющей тип предложения, может быть описана с помощью правила продукции. Так, опи¬ сание решения задачи интерпретации предложений со структу¬ рой, соответствующей структуре предложения 2 в табл. 1.1, можно задать в виде ЕСЛИ число — да И слово — если И след_слово — то ТО предложение — правило. Читателю предлагается представить себя на месте эксперта и описать все возможные пути на дереве рис. 1.2, т. е. пути решения всевозможных подзадач задачи интерпретации пред¬ ложений, приведенных в табл. 1.1 с учетом табл. 1.2, в виде правил продукции, по аналогии с вышеприведенным прави¬ лом. Кроме того, полезно явно записать таблицу соответствия атрибутов и вопросов им соответствующих, по аналогии с табл. 1.2. Пример, рассматриваемый нами, очень прост, и граф, ему соответствующий, имеет мало состояний, поэтому мы этот граф смогли построить целиком. В реальных задачах число состояний гораздо больше и, чтобы не загружать память ма¬ шины, полный граф для них заранее не строится, тем более, что при хорошо организованном поиске решения конкретной задачи весь граф и не нужен. Вследствие того что правила продукции описывают отдель¬ ные ветви дерева поиска, перебирая эти правила в соответст¬ вии с некоторой стратегией управления, можно получить лю¬ бой путь на дереве поиска, соответствующий решению конкрет¬ ной задачи. Следует отметить, что поскольку рассматриваемый пример является очень простым, мы смогли с помощью одного правила продукции описать всю ветку графа от начала до конца. Естественно, что в реальных условиях это сделать не удается, и приходится для описания одного пути исполь¬ зовать несколько правил, описывающих отдельные части пол¬ ного пути решения конкретной задачи. Различают два основных типа стратегий управления: без¬ возвратный и пробный. В безвозвратном режиме управления выбирается применимое правило и используется необратимо, т. е. без возможности пересмотра в дальнейшем. Этот тип управле¬ ния будет подробно рассмотрен при построении транслятора языка эксперта в п. 1.2. В пробном режиме управления вы¬ бирается применимое правило (либо произвольно, либо на каком-то разумном основании). Это правило используется, но 15
резервируется возможность впоследствии заново вернуться к этой ситуации, чтобы применить другое правило. Далее различают два типа пробных режимов управления. Первый — так называемый режим с возвращением. В этом слу¬ чае при выборе правила определяется некоторая точка воз¬ врата. Если вычисления приведут к трудностям в построении решения, то процесс вычисления переходит в точку возврата, выбирается другое правило, и процесс продолжается. Второй тип пробного режима управления — управление с по¬ иском на графе. В этом случае предусмотрено запоминание результатов применения одновременно нескольких последова¬ тельностей правил. Здесь используются различные виды гра¬ фовых структур и процедур поиска на графе [13]. Следует подчеркнуть, что и при безвозвратном управлении, и при управлении с возвращением фактически строится граф поиска, точнее необходимые его части. Так, при безвозвратном управлении строится одна ветвь дерева (графа) поиска. При управлении с возвращением строится одна ветвь, если же она не приводит к успеху, то происходит возврат и строится дру¬ гая ветвь, и т. д., пока не будет найдено решение. Управляю¬ щая стратегия с возвращением, не располагающая дополни¬ тельной информацией от пользователя, порождает новые со¬ стояния в порядке, подобном тому, в котором они порождаются процедурой поиска в глубину. Стратегии с возвращением за¬ поминают только один путь к целевой вершине; они не хранят полной записи процесса поиска, как это делают стратегии поиска на графе методом поиска в глубину. Учитывая, что стратегии с возвращением обычно проще ре¬ ализуются и требуют меньшего объема памяти, мы их и выбе¬ рем для реализации ЭС. Кроме деления на поиск в глубину и поиск в ширину ме¬ тоды поиска еще делят на прямые и обратные. При прямых методах поиск идет от начального состояния к целевому, при обратных методах — от целевых состояний к начальному. Хотя между системами продукции, работающими над ре¬ шением задач в прямом и обратном направлениях, нет фор¬ мального различия, часто оказывается удобным ввести его в явном виде [13]. Если в задаче можно выделить четкие (на интуитивном уровне) факты и цели и принято решение поль¬ зоваться описаниями этих фактов как глобальной базой дан¬ ных систем продукций, то эту систему называют прямой си¬ стемой продукций. Правила применяются к описаниям фактов для порождения новых фактов. Если же используются описа¬ ния целей задачи как глобальная база данных, эту систему называют обратной системой продукций. В этом случае пра¬ вила применяются к описаниям целей для порождения описа¬ ния подцелей. 16
Есть случаи, когда при решении задачи одно направление более предпочтительно. Предположим, например, что сущест¬ вует большое число явно заданных целевых состояний и одно* исходное (см. рис. 1.2). Не очень эффективной была бы по¬ пытка решить такую задачу в обратном направлении; априори мы не знаем, какое именно целевое состояние должно быть до¬ стигнуто, и нам пришлось бы начинать полный перебор со¬ стояний. Вообще, наиболее эффективное направление решения: определяется структурой пространства состояний. Зная, что ориентированная на продукцию система вывода может действовать как в прямом, так и в обратном направле¬ нии, трудно решить, что лучше. Ответ зависит от цели, пресле¬ дуемой при выводе, и от формы пространства состояний. Безусловно, если целью является вывод всего, что может быть получено из данного множества фактов, то продукционная си¬ стема должна работать в прямом направлении. С другой стороны, если целью является проверка или опроверже¬ ние некоторого конкретного заключения, то, вероятно,, лучше всего идти в обратном направлении, начиная от этого заключения. Одно из соображений — избегать ненуж¬ ного накопления фактов. В действительности нет необходимо¬ сти рассматривать факты, не относящиеся непосредственно к делу. Система продукций может работать в обратном направ¬ лении (от элементов предпосылок) до тех пор, пока существуют подходящие продукции. Посылка запроса к пользователю для собирания фактов необходима лишь в том случае, когда не под¬ ходит ни одна продукция. Другая необходимость действия в обратном направлении возникает потому, что обычно из начального множества фак¬ тов может последовать большое множество заключений, не имеющих никакого отношения к целевому заключению. Если такие факты предъявлены системе продукций, работающей в прямом направлении, то много усилий может быть потра¬ чено впустую из-за излишней комбинаторики. Из вышесказанного следует, что граф, приведенный на рис. 1.2, следует обходить в прямом направлении, так как ис¬ ходное состояние одно, а целевых, содержащих тип предложе¬ ния,— несколько. На рис. 1.3 приведен граф (дерево) поиска типа языка на основании определенного типа предложения. Очевидно, что- в этом случае лучше двигаться от целей, так как первой целью является ЯЗЫК, для определения типа которого надо предва¬ рительно достигнуть цели ПРЕДЛОЖЕНИЕ. Таким образом, при решении задачи интерпретации целе¬ сообразно использовать двунаправленный поиск, подразуме¬ вающий чередование обратного и прямого поисков. Для хра¬ нения фактов, используемых при прямом выводе решения, и 2 В. Э. Балтрашевич 17"
для хранения целей, используемых при обратном выводе, будем использовать соответственно стек фактов и стек целей. Напом¬ ним, что под стеком понимается список, доступ к элементам ко¬ торого производится с одного конца, т. е. по правилу «послед¬ ним пришел, первым вышел». Использование стека облегчает реализацию стратегии управления с возвращением. Подробно стратегия управления будет изложена в п. 1.3. Имеются некоторые различия между структурой рассмот¬ ренной системы продукций и традиционными программами с иерархической организацией. Глобальная база данных до- Рис. 1.3. Граф поиска типа языка ступна для всех правил продукций, поскольку ни одна ее часть не ориентирована преимущественно на какое-либо из них. Одни правила не «вызывают» другие. Связь между прави¬ лами осуществляется только через глобальную базу данных. Эти свойства систем продукций находятся в согласии с эволю¬ ционным характером разработки больших экспертных систем, предполагающих наличие весьма обширных объемов знаний. Таким образом, мы в общих чертах рассмотрели организа¬ цию процесса решения задачи с точки зрения программиста. Процесс решения задачи, как правило, включает два этапа: представление задачи и поиск (перебор) решения. Теперь рас¬ смотрим представление задачи с точки зрения эксперта. При этом подчеркнем, что эксперту не надо делать никакого описа¬ ния управления, поскольку оно находится в компетенции ин¬ терпретатора правил продукции, реализованного программи¬ стом. Внешнее представление знаний. С внутренним представле¬ нием знаний эксперта работает только программист. На осно¬ вании выбранной структуры внутреннего представления знаний эксперта программист составляет алгоритмы поиска решения 18
задачи. Эксперту должны быть предоставлены средства для: описания его знаний, допускающие минимальные знания об ЭВМ и программировании. С помощью внешнего представления знаний эксперт описы¬ вает задачи определенного класса из предметной области к определяет, что необходимо сделать для решения задач. На ос¬ новании этого программа, разработанная программистом, уже должна определить как решить поставленную пользователем кон етную задачу. >скольку нашей задачей является реализация инструмен¬ тальной ЭС, представление знаний должна как можно меньше зависеть от предметной области и позволять легко пополнять содержимое базы знаний. Этим требованиям как уже отмеча¬ лось, удовлетворяют правила продукций типа ЕСЛИ...ТО. Мы: будем работать с правилами имеющими следующую струк- <номер правила> ЕСЛИ <атрибут> — <значение> И <атрибут> — <значение> ТО <атрибут> — <значение>. Вместо слов, заключенных в угловые скобки, должна быть подставлена конкретная информация, соответствующая пред¬ метной области. Значения некоторых атрибутов определяются в результате использования правил, значения же других атрибутов задаются только пользователем. Чтобы пользователь мог понять, что ЭС. запрашивает у него значение какого-либо атрибута, ему дол¬ жна быть выдана подсказка, текст которой может быть опре¬ делен только экспертом. Таким образом, с некоторыми атрибу¬ тами могут быть связаны тексты подсказок, формализм для представления которых может быть задан в виде ПОДСКАЗКА <атрибут> <текст подсказки>. В состав ЭС должен входить блок объяснений действий си¬ стемы. Так как действия системы основаны на правилах про¬ дукций, то очевидно, что при объяснениях придется распечаты¬ вать правила. Поскольку уровень квалификации пользователей может быть разным, иногда может потребоваться боле подроб¬ ное (развернутое) пояснение самих атрибутов (см. табл. 1.2). Таким образом, с некоторыми атрибутами могут быть связаны так называемые переводы, формализм для представления ко¬ торых может быть задан в виде ПЕРЕВОД <атрибут> Стекст перевода>. Приведенные формализмы (правила, подсказки, переводы) вполне можно рассматривать как формализмы для внешнего представления знаний абстрактного эксперта, составляющие ос¬ нову языка конкретного эксперта. Примеры применения этих туру: 2* 19
-формализмов приведены в табл. 1.1. Транслятор с языка эксперта должен позволять использовать эти формализмы в произвольном порядке. Программа (на языке конкретного эксперта) описания за¬ дачи интерпретации типа предложения и типа языка, соответ¬ ствующая табл. 1.1, 1.2 и рис. 1.2, 1,3, представлена на стр. 21. Нетрудно заметить, что в приведенном примере правила могут быть расположены в любой последовательности (без учета номера), так как каждое правило описывает полный путь на дереве поиска (см. рис. 1.2 или рис. 1.3). Обеспечив подобную тщательность определения правил, мы можем вво¬ дить новые функции в программу просто путем добавления со¬ ответствующих правил. Но сконструировать систему независи¬ мых от порядка записи правил не так просто. Следует заметить, что в целях компактного представления программы на одной строке представлено несколько строк вве¬ денного языка. Очевидно, что если имеется внешнее и внутреннее представ¬ ления знаний, то должен быть блок их взаимного преобразова¬ ния. Таким образом, интерфейс эксперта будет состоять из языка внешнего представления знаний (языка эксперта) и тран¬ слятора с этого языка. Трансляторы с языков могут быть компилирующего и интер¬ претирующего типов [24]. Компиляторы осуществляют перевод целиком всей программы на исходном языке во внутреннее пред¬ ставление, а затем производится выполнение программ. Интер¬ претаторы переводят предложения по одному и сразу выпол¬ няют. Достоинством компилятора является большая скорость выполнения оттранслированной программы, а достоинством ин¬ терпретатора— большая гибкость, обусловившая широкое рас¬ пространение интерпретаторов при реализации диалоговых языков. Встает вопрос, какого типа делать транслятор с языка внеш¬ него представления знаний (языка эксперта)? Компилятор пре¬ образует внешнее представление всех знаний во внутреннее, по¬ мещаемое в оперативную память, и, если база знаний большая, то может не хватить оперативной памяти. Интерпретатор же выбирает предложения языка по одному из какого-нибудь внешнего файла, однако, этот процесс протекает медленнее. Следует иметь в виду, что при введенном формализме правила, подсказки и переводы для атрибутов, входящих в это пра¬ вило, дополняют друг друга и образуют одно целое, что обус¬ ловливает использование компилятора. В данной книге будет рассматриваться реализация инстру¬ ментальной ЭС с транслятором с языка эксперта компилирую¬ щего типа. Подробному изложению реализации языка эксперта отведен п. 1.2. Рассмотрение реализации языка эксперта пред- 20
1 ЕСЛИ ЧИСЛО - ДА И СЛОВО - ТО ТО ПРЕДЛОЖЕНИЕ - ПРАВИЛО 2 ЕСЛИ ЧИСЛО - ДА И СЛОВО - ЕСЛИ И СЛЕД_СЛОВО - ТО ТО ПРЕДЛОЖЕНИЕ - ПРАВИЛО 3 ЕСЛИ ЧИСЛО-ДА И СЛОВО-ЕСЛИ И СЛЕД_СЛОВО-И И ТО-ДА ТО ПРЕДЛОЖЕНИЕ - ПРАВИЛО 4 ЕСЛИ ЧИСЛО - ДА И СЛОВО - ЕСЛИ И СЛЕД_СЛОВО-И И ТО-НЕТ ТО ПРЕДЛОЖЕНИЕ - ОШИБОЧНОЕ_ПРАВИЛО 5 ЕСЛИ ЧИСЛО-НЕТ И #-ДА ТО ПРЕДЛОЖЕНИЕ - ОТВЕТ € ЕСЛИ ЧИСЛО-НЕТ И #-НЕТ И ?-ДА И СЛОВО-ПОЧЕМУ ТО ПРЕДЛОЖЕНИЕ - ВОПРОС 7 ЕСЛИ ЧИСЛО-НЕТ И #-НЕТ И ?-ДА И СЛОВО-КАК ТО ПРЕДЛОЖЕНИЕ - ВОПРОС 8 ЕСЛИ ЧИСЛО-НЕТ И #-НЕТ И ?-НЕТ И СЛОВО-ПЕРЕВОД ТО ПРЕДЛОЖЕНИЕ - ПЕРЕВОД 9 ЕСЛИ ЧИСЛО-НЕТ И #-НЕТ И 7-НЕТ И СЛОВО-ПОДСКАЗКА ТО ПРЕДЛОЖЕНИЕ - ПОДСКАЗКА 10 ЕСЛИ ПРЕДЛОЖЕНИЕ - ПРАВИЛО ТО ЯЗЫК - ЭКСПЕРТА 11 ЕСЛИ ПРЕДЛОЖЕНИЕ - ПЕРЕВОД ТО ЯЗЫК - ЭКСПЕРТА 12 ЕСЛИ ПРЕДЛОЖЕНИЕ - ПОДСКАЗКА ТО ЯЗЫК - ЭКСПЕРТА 13 ЕСЛИ ПРЕДЛОЖЕНИЕ - ОТВЕТ ТО ЯЗЫК - ПОЛЬЗОВАТЕЛЯ 14 ЕСЛИ ПРЕДЛОЖЕНИЕ - ВОПРОС ТО ЯЗЫК - ПОЛЬЗОВАТЕЛЯ ПОДСКАЗКА ЧИСЛО ПРЕДЛОЖЕНИЕ НАЧИНАЕТСЯ С ЧИСЛА?(ДА/НЕТ) ПОДСКАЗКА СЛОВО С КАКОГО СЛОВА НАЧИНАЕТСЯ ПРЕДЛОЖЕНИЕ? ПОДСКАЗКА СЛЕД_СЛОВО С КАКОГО СЛОВА НАЧИНАЕТСЯ СЛЕДУЮЩАЯ СТРОКА? ПОДСКАЗКА ТО ИМЕЕТСЯ СТРОКА НАЧИНАЮЩАЯСЯ С ТО?(ДА/НЕТ) ПОДСКАЗКА # ПРЕДЛОЖЕНИЕ НАЧИНАЕТСЯ С #?(ДА/НЕТ) ПОДСКАЗКА ? ПРЕДЛОЖЕНИЕ НАЧИНАЕТСЯ С ? ?(ДА/НЕТ) ПЕРЕВОД ЧИСЛО ИМЕЕТСЯ ЧИСЛО ПЕРЕВОД СЛЕД_СЛОВО СЛЕДУЮЩАЯ СТРОКА НАЧИНАЕТСЯ СО СЛОВА ПЕРЕВОД # ПРЕДЛОЖЕНИЕ НАЧИНАЕТСЯ С # ПЕРЕВОД СЛОВО СЛОВО ИМЕЕТ ЗНАЧЕНИЕ ПЕРЕВОД ТО ИМЕЕТСЯ СТРОКА НАЧИНАЮЩАЯСЯ С ТО ПЕРЕВОД ? ПРЕДЛОЖЕНИЕ НАЧИНАЕТСЯ С ? ПЕРЕВОД ПРЕДЛОЖЕНИЕ ТИП ПРЕДЛОЖЕНИЯ ПЕРЕВОД ЯЗЫК ТИП ЯЗЫКА
ставляет большой интерес с точки зрения разработки ЭС, так как работа компилятора управляется данными, а не програм¬ мой и язык определяется с помощью правил грамматики, ко¬ торые близки к правилам продукции. Отличие будет состоять в управляющей структуре. Следует заметить, что. это можно рассматривать не как отличие, а как еще один вид управляю¬ щей структуры. Программа, описывающая знания эксперта и записанная на языке эксперта, получает исходные данные от пользователя и ему же выдает результаты. Внешнее представление данных. Язык пользователя. По за¬ просам ЭС пользователь должен задать основную цель решения и задавать значения интересующих экспертную систему атри¬ бутов. Весь процесс решения поставленной пользователем за¬ дачи проходит автоматически. Однако у пользователя могут возникнуть вопросы и сомнения в правильности решения задачи системой. Если у пользователя не будет доверия к системе, то он не будет ею пользоваться. Таким образом, ЭС должна содер¬ жать блок пояснений, который должен обеспечить ответы на вопросы пользователя типа ПОЧЕМУ и КАК, т. е. ПОЧЕМУ ЭС задает тот или иной вопрос, КАК система пришла к тому или иному выводу (факту). Так как пользователь должен отвечать на вопросы ЭС и в свою очередь сам должен иметь возможность задавать вопросы системе, то в ЭС должны быть предусмотрены средства для общения пользователя с ЭС, например, интерфейс пользователя* состоящий из языка пользователя и интерпретатора с этого языка. Интерфейс должен быть максимально дружественен поль¬ зователю, т. е. по возможности исправлять ошибки пользова¬ теля и выдавать подсказки. Интерфейс пользователя должен обеспечить возможность установки режима взаимодействия пользователя и системы, т. е. указания того, кто является ве¬ дущим, а кто ведомым. Предположим, что при вводе символа ф пользователь отвечает на вопрос системы, а при вводе сим¬ вола ? пользователь берет управление на себя и может зада¬ вать вопросы системе в любом порядке. Формально предложения языка пользователя можно запи¬ сать в виде Ф <ответ> —предложение типа ответ ? почему — предложение типа вопрос ? как <атрибут>—предложение типа вопрос. Примеры использования этого формализма приведены в табл. 1.1. На основании всего вышеизложенного можно построить структурную схему инструментальной экспертной системы, ко¬ торую мы будем реализовывать (рис. 1.4). Блок поиска реше¬ 22
ний назван блоком логического вывода, поскольку если реше¬ ние осуществляется представлением в пространстве состояний, то оно сводится к поиску. Если же используются предикаты (п. 1.3), то решение получается в результате логического вы¬ вода. Следует заметить, что с точки зрения эксперта или про¬ граммиста поиск решения в одной и той же ЭС может казаться организованным по-разному. Эксперт работает только с внеш¬ ние. 1.4. Структурная схема инструментальной экспертной системы: — управление; — информация ним представлением знаний, а оно может быть похоже на пред¬ ставление с помощью логики. Эксперт в этом случае может говорить о логическом выводе решения. Внутри же системы ре¬ шение может быть реализовано с помощью поиска в простран¬ стве состояний, но с внутренним представлением работает только программист. Наличие в составе базы данных стека целей и стека фактов подчеркивает использование в системе двунаправленного по¬ иска. Как видно из вышеизложенного, каждый работающий с ЭС (программист, эксперт, пользователь) выполняет свои функ¬ ции. 23
ПОЛЬЗОВАТЕЛЬ I Эксперт-машина Структура данных (атрибуты и их значения) Действия (вопросы, ответы) Программа (на языке пользователя) Управляющая структура (последовательное вы¬ полнение команд) 1 Транслятор с языка пользователя Предмет-машина ii " 1—гг г.--...~и Инструментальная экспертная система (транслятор с языка эксперта) Действия (правила вывода) Управляющая структура (двунаправленный вывод с поиском в глубину с возвратом) База данных (цели, факты) Программа (база знаний) Паскаль-машина Структура данных (логические) Действия (операторы, процедуры) Программа (иа Паскале) Управляющая структура (последовательное выпол¬ нение операторов) I Транслятор с Паскаля I Аппаратная (реальная) вычислительная машина Структура данных (физические) Действия (команды) Программа (в кодах) Управляющая структура (последовательное выпол¬ нение команд) Рис. 1.5. Уровни иерархии виртуальных машин
Программист, реализуя инструментальную ЭС с помощью какого-либо языка программирования, например Паскаля, фак¬ тически работает с Паскаль-машиной. Эксперт предметной об¬ ласти с помощью языка эксперта работает с некой виртуальной (кажущейся) машиной предметной области (предмет-маши¬ ной), базирующейся на инструментальной ЭС, в частности, на языке абстрактного эксперта. Реальный эксперт формирует знания из конкретной предметной области на своем языке и наполняет ими предмет-машину, т. е. настраивает ее на кон¬ кретную предметную область. Таким образом, предмет-машину можно рассматривать как двухуровневую машину. Пользова¬ тель с помощью языка пользователя работает фактически с но¬ вой машиной (эксперт-машиной или ЭС), базирующейся на предмет-машине. Таким образом, в результате создания экспертных систем уровень виртуальных машин приблизился к уровню пользова¬ телей, специализирующихся в различных предметных областях. Поясним, что под виртуальной машиной обычно понимается программно-моделируемая машина, частично состоящая из ап¬ паратуры, а частично — из программного обеспечения [17, 21]. На рис. 1.5 приведены уровни иерархии машин, поясняющие ход наших рассуждений. Каждая из машин позволяет работать с определенными структурами данных, использовать свойствен¬ ные ей действия и обладает характерной для нее управляющей структурой. 1.2. ЯЗЫК ЭКСПЕРТА Как отмечалось в п. 1.1, знания эксперта могут быть описаны с помощью трех типов предложений языка внешнего представ¬ ления знаний (или языка эксперта): правила, подсказки и переводы. Для реализации инструментальной ЭС, позволяющей менять наполнение знаний, необходимо построить транслятор с языка эксперта. Такая разработка сама по себе служит примером си¬ стематического структурированного подхода при написании программ нетривиальной сложности и размера. Знание этого предмета облегчает программисту разработку собственных си¬ стем, предназначенных для конкретных целей и областей при¬ менения, а не программисту (эксперту, пользователю) позволит более четко формулировать требования к соответствующим языкам. Структура транслятора отражает структуру языка: слож¬ ность или простота языка решающим образом влияет на слож¬ ность транслятора. Подробнее с теорией построения трансля¬ торов можно ознакомиться, например, в работе [24]. Мы начнем с описания строения языка, а затем сосредоточим внимание на простых структурах, для которых можно построить 25
простые модульные трансляторы. Такие простые языковые кон¬ струкции оказываются достаточными для удовлетворения прак¬ тически всех потребностей, возникающих при использовании языков программирования. В основе каждого языка лежит словарь. Его элементы обычно называют словами, но в теории формальных языков их назы¬ вают символами. Языки характеризуются тем, что некоторые последовательности слов считаются правильными предложе¬ ниями языка, а некоторые — неправильными, или не принадле¬ жащими данному языку. Является ли некоторая последователь¬ ность слов правильным предложением обычно определяется грамматикой, синтаксисом языка. Синтаксис определяется как множество правил или формул, которые задают множество- (формально правильных) предложений. Формализм, или нотация, используемая при написании пра¬ вил, называется бэкус-науровой формой (БНФ). В этом форма¬ лизме используются терминальные символы, т. е. символы, вхо¬ дящие в предложения описываемого языка, и нетерминальные символы, используемые для удобства задания формализма. Кроме того, используются метасимволы :: = и |. Символ :: = можно рассматривать как сочетание «это есть», а символ | —как «или». Нетерминальные символы заключаются в скобки <>. Таким образом, формально язык L задается четверкой (Г, N, Р, S), где Т — словарь терминальных символов; N — множе¬ ство нетерминальных символов; Р — множество порождающих правил; S — начальный символ (SeiV). Зададим в нотации Бэкуса — Наура язык эксперта: <предложение> :: = <правило> | <подсказка> | Спере- вод> <правило> :: = <номер> ЕСЛИ <условие> ТО <вывод> | <номер> ТО <вывод> <номер> =<цифра> | <цифра> <номер> <цифра> :: = 0|1|2|3|4|5|6|7|8|9 <условие> :: = <выражение> | <выражение> и Сусло- вие> <выражение> :: = <атрибут> —<значение> <конец строки> <вывод> :: = <выражение> <атрибут> :: =<лексема> <значение> :: = <лексема> <подсказка> :: = ПОДСКАЗКА <атрибут> Сконец стро- ки> <текст> Сконец строки> <перевод> :: = ПЕРЕВОД <атрибут> Сконец строки> Стекст> Сконец строки>. Под лексемой здесь понимается любая цепочка символов, между пробелами, а под текстом — любая цепочка символов, 26
поскольку реализуется язык абстрактного эксперта. Под кон¬ цом.строки понимается символ «возврат каретки» на терми¬ налах. Первую строку нашего описания можно читать следующим образом: предложение—это или правило или подсказка или перевод. В свою очередь правило языка эксперта определяется следующей строкой и должно состоять из номера, символа ЕСЛИ, из условия, символа ТО и вывода. Вторая часть этой строки говорит о том, что часть ЕСЛИ правила может отсутст¬ вовать, что может использоваться экспертом для задания неко¬ торых фактов. Скобки < > указывают на то, что номер, усло¬ вие и вывод будут пояснены с помощью других правил БНФ. Из определения условия видно, что оно может состоять из одного выражения или нескольких выражений, соединенных терми¬ нальным символом И. В качестве довольно полезного упражнения, которое нам пригодится в дальнейшем, читателю предлагается описать язык абстрактного эксперта с помощью языка конкретного эксперта (эксперта-лингвиста). Для реализации синтаксического анализа полезно представ¬ лять заданный синтаксис в виде так называемого синтаксиче¬ ского графа (или синтаксических диаграмм). Такой граф отра¬ жает управление ходом работы при грамматическом анализе предложения. Для нисходящего грамматического разбора характерно, что цель анализа известна с самого начала. Эта цель—распознать предложение, т. е. последовательность символов, которая может порождаться из начального символа. Применение порождаю¬ щего правила, т. е. замена одного символа последовательностью символов, соответствует расщеплению одной цели на некоторое число подцелей, которые должны следовать в определенном по¬ рядке. При построении программы грамматического разбора можно воспользоваться этим очевидным соответствием между нетерминальными символами и целями: для каждого нетерми¬ нального символа строится своя процедура грамматического раз¬ бора. Цель каждой такой процедуры — распознавание части предложения, которая может порождаться из соответствую¬ щего нетерминального символа. Этот метод синтаксического анализа называется методом рекурсивного спуска. Каждый не¬ терминальный символ отображается в подграф. Рассмотрим использование правил продукции в ЭС и в транс¬ ляторах. В инструментальной ЭС управляющие структуры неза¬ висимы от предметной области, что позволяет использовать ЭС для различных предметных областей. Ни одно правило не за¬ пускает непосредственно другое правило, все срабатывания пра¬ вил происходят только на основе содержимого базы данных. Такие управляющие структуры позволяют четко отделить при¬ 27
кладные знания (т. е. факты, зафиксированные в базе данных, отношения и правила) от собственно управляющих действий. При реализации транслятора набор правил может быть приме¬ нен только при определенном сочетании условий или в опреде¬ ленном контексте. В связи с этим удобно и целесообразно груп¬ пировать наборы правил с учетом контекста и разрешать сра¬ батывать правилу только при установлении соответствующего контекста. Например, если при работе нашего транслятора было установлено, что предложение начинается со слова «подсказка», то нет никакого смысла в использовании правил, относящихся к предложению типа «правило». При реализации транслятора правила находятся в фиксиро¬ ванных и известных отношениях. При таком условии их удобна объединять в сеть правил. Целесообразно рассматривать син¬ таксические диаграммы в качестве одного из видов сетей пра¬ вил. Использование сетей правил в ЭС повышает скорость их работы, но привязывает экспертную систему к конкретной предметной области и затрудняет организацию объясне¬ ний. Надо заметить, что если некая ЭС с конкретным наполне¬ нием знаниями очень часто используется, то необходимо прове¬ сти так называемую компиляцию знаний, т. е., иначе говоря, по¬ строить сеть правил для конкретной предметной области. В гл. 5- в качестве примеров будут даны основные моменты реализации: языка эксперта предметной области с помощью правил продук¬ ций, составленных экспертом-лингвистом. Как отмечалось в п. 1.1, различают два основных типа стра¬ тегии управления: безвозвратный и пробный. Так, реализация транслятора является примером безвозвратного режима управ¬ ления. В инструментальной ЭС используется пробный режим управления. После небольшого отступления продолжим разработку транс¬ лятора с языка абстрактного эксперта. Перечислим правила перехода от нотации Бэкуса—Наура к синтаксическим графам (диаграммам) [2]. Правила построения графа А1. Каждый нетерминальный символ А с соответствующим множеством порождающих правил А :: = Р\\Р2\.. .\Pn отобра¬ жается в синтаксический граф А, структура которого определя¬ ется правой частью порождающего правила в соответствии с А2—А6. А2. Каждое появление терминального символа х в Pi соот¬ ветствует оператору распознавания1 этого символа во входном предложении. На графе это изображается ребром, помеченным символом’х, заключенном в кружок (или овал): 28
©- АЗ. Каждому появлению нетерминального символа В в Pi соответствует обращение к процедуре распознавания В. На графе это изображается ребром, помеченным символом В, за¬ ключенным в квадрат (или прямоугольник): В А4. Порождающее правило, имеющее вид А :: = Pi \ Р2 \... | Рп> отображается в граф где Pi получено применением правила А2—А6. А5. Строка Р, имеющая вид P=ai02.. .ап, отображается: в граф «.2 и>1 ап ' где ai получено применением правил А2—Аб. А6. Строка Р, имеющая вид Р={а}, отображается в граф где а получено применением правил А2—А6 (Скобки {} означают, что заключенный в них символ может повториться несколько раз или не встретиться ни разу.) На рис. 1.6 приведены синтаксические диаграммы языка абстрактного эксперта, полученные с использованием правил А1—А6, а в прил. 1 приведены синтаксические диаграммы языка Паскаль. 29-
Программу, которая распознает какой-либо язык, легко по¬ строить на основе его детерминированного синтаксического графа. Этот граф фактически представляет собой блок-схему программы. При преобразовании графа в программу рекомен¬ дуется строго следовать правилам преобразования, подобным А1—А6, с помощью которых мы получили из БНФ графическое Предложение Пробило Подсказка Перебод Пробило Номер Если) Условие Подсказка -(^Подсказка^— Атрибут Пере б од—Qf]epeg0fl ^— Атрибут 1 Номер с -^Цисррс/У- Условие Вывод Выражение Выражение Атрибут —^—Значение Атрибут Значение Лексема Программа Предложение 7^ \ J Рис. 1.6. Синтаксические диаграммы языка эксперта представление синтаксиса. Они применяются в определенном контексте, предполагающем наличие основной программы, со¬ держащей процедуры, которые соответствуют различным под¬ целям, а также процедуру перехода к очередному символу. Эти правила приводятся для языка Паскаль, как языка публика¬ ций, но они могут быть легко трансформированы для других языков использующих рекурсию. Читателю, в качестве упраж¬ нения, рекомендуется записать эти правила для ЛИСПа и Пролога. 30
Для простоты будем считать, что предложение, которое нужно анализировать, представлено файлом INPUT и что тер¬ минальные символы — это отдельные значения типа CHAR. Пусть символьная переменная СН типа CHAR всегда содержит очередной читаемый символ. Тогда переход к следующему сим¬ волу выражается оператором READ(CH). Основная программа будет состоять из оператора чтения первого символа, за которым следует оператор активации ос¬ новной цели грамматического разбора. Отдельные процедуры* соответствующие целям грамматического разбора или графам* получаются по следующим правилам. Пусть оператор, получен¬ ный с помощью преобразования графа S, обозначается через; T(S). Правила преобразования графа в программу В1. Свести систему графов к как можно меньшему числу от¬ дельных графов с помощью соответствующих подстановок. В2. Преобразовать каждый граф в описание процедуры в со¬ ответствии с приведенными ниже правилами ВЗ—В7. ВЗ. Последовательность элементов. переводится в составной оператор BEGIN T(S1); T(S2);...;T(SN) END B4. Выбор элементов переводится в выбирающий или условный оператор CASE СН OF L1:T(S1); ' IF СН IN LI THEN T(S1) ELSE L2:T(S2); IF CH IN L2 THEN T(S2) ELSE i LNjT(SN) IF CH IN LN THEN T(SN) ELSE end error ) 31
где LI означает множество начальных символов конструкции SI (LI = FIRST (SI)). Множество FIRST (S) есть множество всех терминальных символов, которые могут встречаться в начале предложений, полученных из S. Если LI состоит из одного сим¬ вола А, то, разумеется, вместо СН INLI нужно писать СН = 'А'. В5. Цикл вида переводится в оператор WHILE СН IN L DO T(S) где T(S) есть отображение S в соответствии с правилами ВЗ— В7, a L есть множество L=FIRST(S). В6. Элемент графа, обозначающий другой граф А, переводится в оператор обращения к процедуре А. В7. Элемент графа, обозначающий терминальный символ переводится в оператор IF СН-'Х' THEN READ(CH) ELSE ERROR где ERROR — процедура, к которой обращаются при появлении неправильной конструкции. Таким образом, мы провели в общих чертах разработку языка абстрактного эксперта и наметили пути его реализации. Для внутреннего представления знаний конкретного эксперта ■будем использовать структуры данных, что означает трансля¬ цию программы на языке конкретного эксперта в структуры данных. Благодаря этому можно создать универсальную си¬ стему, которая позволит любую программу, записанную на языке конкретного эксперта (удовлетворяющую требованиям языка абстрактного эксперта), преобразовать (с помощью транслятора с языка абстрактного эксперта) в структуру дан¬ ных с конкретным наполнением. Универсальная (т. е. не завися¬ щая от конкретного наполнения базы знаний) программа логи- 32
ческого вывода, используя структуры данных, хранящие знания конкретного эксперта, осуществляет логический вывод решения задачи с учетом ответов пользователя. Таким образом, синтаксические диаграммы (графы) языка абстрактного эксперта будут преобразовываться в программу, а синтаксические диаграммы языка конкретного эксперта — в структуры данных. При смене предметной области меняется только наполнение этих структур данных, программа же логиче¬ ского вывода, их использующая, остается прежней. Имея пред¬ ставление знаний с помощью структур данных, мы легко смо¬ жем организовать их печать при реализации объяснений. Программная реализация графа является более эффектив¬ ной, но менее универсальной, чем реализация графа с помощью структур данных. При реализации языка конкретного эксперта будем исполь¬ зовать так называемый таблично-управляемый транслятор [2,24], причем для представления таблицы, как будет показано ниже, будем использовать списки. Блок логического вывода ЭС явля¬ ется развитием программы грамматического разбора, входящей в состав таблично-управляемых трансляторов. 1.3. БЛОК ЛОГИЧЕСКОГО ВЫВОДА Рассмотренные в п. 1.1 методы поиска применяются при пред¬ ставлении задач в пространстве состояний. Другим методом представления, получившим в последнее время широкое распро¬ странение, является представление с помощью исчисления пре¬ дикатов [12,13,19], которое позволяет формализовать предложе¬ ния естественного для предметной области языка. Этот метод после небольшой подготовки может быть освоен и неспециали¬ стами в вычислительной технике. Исчисление предикатов представляет собой развитие исчис¬ ления высказываний и включает его полностью как составную часть. Предикатом или логической функцией называется функ¬ ция от любого числа аргументов, принимающая значения: истина или ложь. Аргументы принимают значения из произвольного конечного или бесконечного множества М, называемого пред¬ метной областью. Напомним, что в исчислении высказываний все переменные принимают только логические значения. Предикат F (X) задает определенное свойство элементам множества М и интерпретируется как обозначение высказыва¬ ния «X обладает свойством F», причем F (X) принимает зна¬ чение «ИСТИНА», если это высказывание истинно, и значение «ЛОЖЬ», если оно ложно. Предикат F(Xi, ..., Хп) задает отно¬ шение между элементами Х\...Хп и интерпретируется как обо¬ значение высказывания «Xi...Xn находятся между собой в от¬ ношении F». 3 В. Э. Балтрашевич 33
В качестве примера рассмотрим следующие высказывания на естественном языке: «стебель является атрибутом» и «цвет стебля — зеленый». Эти высказывания можно формализовать, с помощью предикатов следующим образом: АТРИБУТ (СТЕБЕЛЬ); ЦВЕТ (СТЕБЕЛЬ, ЗЕЛЕНЫЙ). Подобные структуры служат для формирования основных предложений исчисления предикатов. В исчислении предикатов именам отношений соответствует термин «предикаты», а объек¬ там— «аргументы». Порядок аргументов (СТЕБЕЛЬ и ЗЕЛЕ¬ НЫЙ в предикате ЦВЕТ) должен всегда задаваться в соответ¬ ствии с интерпретацией предиката, принятой в рамках опреде¬ ленной предметной области. Это значит, что программист дол¬ жен принять решение о фиксированном, приемлемом для интер¬ претации порядке и соблюдать его с начала до конца. Отдельные высказывания (называемые элементарными), со¬ стоящие из предиката и связанных с ним аргументов, могут объединяться в сложные высказывания с помощью логических операций: И (Д), ИЛИ (V)»HE (~) и импликации (->). Особо важное значение имеет импликация, поскольку именно эта связка применяется для формирования правил и читается ЕСЛИ... ТО. Приведем несколько примеров применения этих операций при образовании сложных высказываний. Высказывание «если стебель растения является зеленым,, то тип растения является травянистым» можно формализовать следующим образом: СТЕБЕЛЬ (ЗЕЛЕНЫЙ)->ТИП (ТРАВЯНИСТЫЙ) или ЯВЛЯЕТСЯ (СТЕБЕЛЬ, ЗЕЛЕНЫЙ)^ЯВЛЯЕТСЯ (ТИП, ТРАВЯНИСТЫЙ). Высказывание «если стебель растения — древесный и поло¬ жение стебля — стелющееся, то растение относится к типу лианы» можно формализовать следующим образом: СТЕБЕЛЬ (ДРЕВЕСНЫЙ) Д ПОЛОЖЕНИЕ (СТЕЛЮЩЕ- ЕСЯ)->ТИП (ЛИАНЫ). В высказываниях в качестве аргументов могут быть исполь¬ зованы и переменные. Например, одна из интерпретаций выра¬ жения «ЯВЛЯЕТСЯ (X, ЗЕЛЕНЫЙ)» может быть такой: «име¬ ется некоторый объект X, который является зеленым». Заметим, что переменным можно задавать и какие-то осмысленные имена, но для того, чтобы их не перепутать с константами, эти имена должны начинаться с какого-нибудь специального символа, на¬ пример, ^: ЯВЛЯЕТСЯ (* ОБЪЕКТ, ЗЕЛЕНЫЙ). Переменные могут использоваться в качестве любых аргу¬ ментов. Так, выражение «ЯВЛЯЕТСЯ (СТЕБЕЛЬ, КАЧЕ¬ СТВО)» можно интерпретировать так: «СТЕБЕЛЬ ОБЛАДАЕТ КАКИМ-ТО КАЧЕСТВОМ». 34
Для того чтобы в исчислении предикатов можно было мани¬ пулировать переменными, потребовалось ввести дополнитель¬ ную структуру — «квантор». Различают «квантор общности», обозначаемый символом Y, и «квантор существования», кото¬ рому соответствует символ Я. С помощью кванторов высказы¬ вания типа «для любого X истинно F(X)» и «существует такое X, для которого истинно F(X)» записываются в виде YXF(X) и ЯXF(X) соответственно. Выражение VXF(X) обозначает выска¬ зывание истинное, когда F(X) истинно при всех ХеМ, и — лож¬ ное в противном случае. Выражение ЯXF (X) обозначает выска¬ зывание истинное, когда существует элемент ХеМ, для кото¬ рого F (X) истинно, и — ложное в противном случае. Кванторы V и Я являются двойственными: VXF(X)=EXf(X); ЯXF(X)=YXF(X). Считается, что в выражениях VXF(X, У), ЯХЕ(Х, У) кван¬ торы V и Я относятся к переменной X, или что переменная X связана с соответствующим квантором. Переменную, связанную с каким-либо квантором, называют связанной, а переменную, не связанную ни с каким квантором — несвязанной, или сво¬ бодной. Пользуясь кванторами, можно представить предложение «Все предложения языка эксперта имеют тип» следующим об¬ разом: УХ (ПРЕДЛОЖЕНИЕ (Х)-^ТИП(Х)). Предложение «Некоторые предложения языка эксперта яв¬ ляются подсказками» может быть представлено так: ЯХ (ПРЕДЛОЖЕНИЕ (Х)-^ПОДСКАЗКА (X)). Кванторы общности и кванторы существования могут пере¬ мещаться в пределах одного и того же выражения. В этом слу¬ чае порядок, в соответствии с которым вводятся квантифицируе¬ мые перменные, может влиять на смысл утверждения. Напри¬ мер, выражение УХЯУ (АТРИБУТ (Х)-^СВОИСТВО (X, У)), может быть интерпретировано так: «У каждого атрибута есть некоторое свойство». Заметим, что в процессе реализации экс¬ пертной системы мы с каждым атрибутом будем связывать ряд свойств: значение, перевод, подсказку их* д. Если же изменить порядок следования кванторов, например, ЯУУХ (АТРИБУТ (Х)-^СВОИСТВО (X, У)), то изменится и утверждение: «Есть такое свойство, которым об¬ ладает каждый атрибут». Отметим, что для нашей ЭС этим свойством является «значение». Предложение «Правило предметной области считается истин¬ ным, если значения всех атрибутов из части ЕСЛИ правила совпадают со значениями соответствующих атрибутов из стека фактов» может быть представлено так: 3* 35
У*АТРИБУТЯ*ЗНАЧЕНИЕ (ПРАВИЛО — ЕСЛИ АТРИБУТ, ^ЗНАЧЕНИЕ) ДСТЕК — ФАКТОВ (* АТРИ- БУТ, ^ЗНАЧЕНИЕ) -^ПРАВИЛО — ИСТИННО). Используя данный механизм представления, можно недву¬ смысленно выразить в стандартном виде многие сложные пред¬ ложения, свойственные разговорному языку. Средства исчисле¬ ния предикатов позволяют, не изменяя смысла, преобразовать их в форму, удобную для обработки с помощью ЭВМ. Такое преоб¬ разование становится возможным благодаря тому, что одни ло¬ гические операции могут быть выражены через другие, напри¬ мер, А\/В = А/\В\ А/\В = А\/В; А-+В = А\/В. Последнее преобразование имеет большое значение при: автоматизации операций исчисления предикатов. При конструировании сложных высказываний из элементар¬ ных, выполняемые кванторами и логическими операциями функции подчиняются четко определенным правилам, которые называются правилами построения. Благодаря им при видоиз¬ менении структуры набора высказываний сохраняется смысл последних. Образованные по этим правилам сложные высказы¬ вания называются правильно построенными формулами (ППФ). Более исчерпывающую информацию об исчислениях высказы¬ ваний и предикатов и их применимости в различных областях можно получить ознакомившись с работами [12, 13, 14]. При обработке знаний посредством исчисления предикатов- исключительно важное значение приобретает возможность логи¬ чески выводить новые факты и правила из некоторого заданного набора. Метод решения задач, использующий аппарат логики предикатов, основан на представлении задачи в виде теоремы: формула F логически следует из множества формул Ф0(Фо=^)- Доказательство этой теоремы можно осуществить двумя спосо¬ бами. Способ 1. Необходимо показать, что каждая интерпрета¬ ция, удовлетворяющая Ф0, удовлетворяет и F. Логика имеет дело главным образом с выявлением обоснованности утвержде¬ ний, т. е. с методами, позволяющими доказать, можно ли дан¬ ное заключение обоснованно вывести исходя из известных фак¬ тов. Более того, логика непосредственно связана с программиро¬ ванием, поскольку любая программа, по существу, представляет собой набор квазилогических утверждений, которые определен¬ ным образом обрабатываются для получения некоторого за¬ ключения. В рамках логики для выражения «утверждение истинно» существует точное, конкретное значение: утверждение считается истинным, если (и толко если) относящиеся к нему 36
предположения все истинны, при этом заключения самого утвер¬ ждения также истинны. Для принятия решения о приемлемости какого-либо конкрет¬ ного утверждения необходимо произвести проверку. В рамках логики такой метод сводится к сравнению интересующего нас текста с абстрактными моделями утверждения в поисках подхо¬ дящего. Заметим, что отсутствие формализма такого поиска за¬ трудняет его автоматизацию. Модели утверждения трактуются как «формы» и собираются из абстрагированных последователь¬ ностей фактов и правил, обоснованность которых доказана ра¬ нее. Обратимся к примеру. Предположим, что дано правило (по¬ добные правила называются правилами предметной области). ЕСЛИ стебель — зеленый ТО тип —травянистые. Допустим такой факт: стебель — зеленый, тогда естественно заключение «тип — травянистые». Более формально выразим это, применив логическую модель: если А то Ву А следовательно В или еще короче А-^Ву ЛЬ-В, где А и В означают соответственно два предложения: «стебель — зеленый» и «тип — травянистые». Обнаружив совпадение, можно утверждать, что суждение имеет некоторую приемлемую логическую структуру и заключе¬ ние «тип — травянистые» справедливо. Заметим, что предложе¬ ния, заменившие приведенные в форме буквы, называют содер¬ жанием, или интерпретацией утверждения. Приведенная в примерах простая форма утверждения счита¬ ется в логике одной из основных, и ей дано специальное назва¬ ние на латинском языке — modus potiens. Она тесным образом связана с конкретным подходом, использующим продукционные системы для обработки знаний, и применяется при реализации прямых методов поиска (см. п. 1.1). Взаимосвязь заключается в следующем. Правило ЕСЛИ А ТО В соответствует одному из правил продукции; единичное высказывание А соответствует не¬ которому факту, зафиксированному в базе данных системы, ко¬ торая при обнаружении совпадения для части правила ЕСЛИ фиксирует утверждение В в качестве нового факта. Более того, полный цикл вычислений, производимых с помощью простой продукционой системы, соответствует многократному примене¬ нию утверждения modus ponens; порожденное утверждение в свою очередь как факт фиксируется в базе данных. Следова¬ тельно, подобная логика обладает способностью как порождать,, так и оценивать утверждение. Способность логики к порождению (или «логическому вы¬ воду») новой информации на основании старой представляет определенный интерес в аспекте программирования как сред¬ 37
ства для управляемого порождения логического вывода. Сила логики заключается в возможности вывода новых сведений с по¬ мощью правил вывода на основании правил и фактов предмет¬ ной области. Кроме формы modus ponens имеется еще целый ряд форм, получивших название «правила вывода». Правила вывода — это утверждения самого общего характера о взаимосвязях ме¬ жду допущениями и заключениями, которые с позиций исчисле¬ ния предикатов всегда справедливы. В результате применения таких правил к ППФ из любой предметной области можно вы¬ вести иные правильно построенные формулы. Правила вывода отличаются от правил предметной области, так как истинность последних ограничивается конкретной предметной областью. Правила вывода можно представить себе как часть обобщенной структуры, в пределах которой манипулируют правилами пред¬ метной области. В исчислении предикатов существует много различных пра¬ вил вывода, которые можно применять либо для установления истинности утверждения в целом, либо для порождения заклю¬ чения. К тому же правила вывода можно использовать как от¬ дельно, так и в сочетании с другими правилами. Некоторые из них имеют следующий вид: 1) modus ponendo ponens: А-^В, А\— В; 2) modus tollendo tollens А->-В, В |— А; 3) двойное отрицание: Af— (А); 4) введение конъюнкции: А, В |— (А&В); 5) reductio ad absurdum: А-*-В, А—?-В |— А; 6) специализации: VXW(X),А|—W(A). Последнее правило фактически отражает интуитивное пред¬ ставление о том, что если некоторому классу объектов присуще какое-либо свойство, то любой объект этого класса будет обла¬ дать тем же свойством. Одно из очень важных свойств исчисления предикатов за¬ ключается в том, что существует множество путей утверждения одного и того же положения. В работе [28] приводятся примеры доказательства одного и того же утверждения путем использова¬ ния различных правил вывода и в различной последовательно¬ сти. Возникает вопрос: как автоматизировать этот процесс вы¬ вода? Человек, рассуждая логически, в состоянии решить, какое из правил следует применить в частном высказывании при про¬ ведении логического доказательства, т. е. он «чувствует», когда какое правило лучше применить. ЭВМ этим свойством не обла¬ дает. Один из «бездумных» подходов к решению этой проблемы сводится к перебору правил вывода в надежде на случайное по¬ рождение какого-либо «доказательства». Однако такой подход 38
очень сложно применить на практике, поскольку, во-первых, во многих случаях возникает ситуация, когда необходим ввод до¬ полнительных предположений для того, чтобы применяемое пра¬ вило можно было использовать на последующих этапах. В ре¬ зультате от ЭВМ требуется прогнозирование ее будущих дейст¬ вий. Во-вторых, при бездумном применении некоторых совер¬ шенно безупречных правил вывода может возникнуть «комбина¬ торный взрыв». Например, многократное применение правила «введение конъюнкции» к трем высказываниям А, В и С может породить неопределенное количество сложных высказываний, включая такие (не представляющие интереса), как А&В&В&В&В&С. При автоматизации вывода доказательств методами исчисле¬ ния предикатов требуется определить ряд процедур для выбора правил, позволяющих предотвратить комбинаторный взрыв. В последне время как в логике, так и в области искусственного интеллекта была проделана большая работа, направленная на поиск соответствующих эффективных процедур. При этом наме¬ тилось два подхода. При первом подходе к решению задачи управления, нашед¬ шем широкое распространение в приложениях концепции искус¬ ственного интеллекта, отбрасывался принцип универсальности и производился поиск методов обработки данных, эффективных для решения конкретных задач в пределах определенной пред¬ метной области. Источником высокой эффективности этих ме¬ тодов служат введенные в систему обширные знания в конкрет¬ ной предметной области и следование наблюдаемому факту, за¬ ключающемуся в том, что человек, выступающий в роли эксперта,, очень редко пользуется процедурами общего характера, дости¬ гая успеха за счет хорошего знания содержания задачи. В це¬ лях упрощения процесса програмирования для таких «основан¬ ных на знаниях» систем были разработаны соответствующие формализмы (семантические сети, фреймы). Многие подобные приемы были разработаны с использованием средств языка об¬ работки списков — ЛИСП. Второй подход, развиваемый в рамках традиционой логики, был направлен на сохранение универсальности, свойственной исчислению предикатов, путем выявления процедур вывода до¬ казательств, универсальных по своему характеру и в то же время позволяющих обойти проблему выбора правил и комби¬ наторного взрыва. Этот подход в основном представляет инте¬ рес для самой логики, в частности, при разработке методов авто¬ матизации вывода доказательств, названного доказательством теорем. До последнего времени многие из разработанных мето¬ дов подобного типа были слишком малоэффективны для приме¬ нения на практике. Но сравнительно недавно был разработан язык программирования Пролог, представляющий собой комби¬ 39
нацию одного из методов доказательства теорем — метода резо¬ люции— и исключительно эффективной стратегии управления. Теперь мы располагаем версией автоматизированного исчисле¬ ния предикатов, которой в виде универсального языка програм¬ мирования можно пользоваться для составления программ обра¬ ботки знаний. Способ 2. Задача формулируется в виде теоремы: формула F логически следует из множества формул Ф0 (Фо =>F). Доказа¬ тельство этой теоремы состоит в том, чтобы показать, что объе¬ динение Ф1 = Ф0иF невыполнимо. Метод резолюции позволяет справиться с такими пробле¬ мами, как выбор правил вывода и порождение не относящихся к делу высказываний, путем сведения процедуры доказатель¬ ства к применению единственного правила — modus tollens. При доказательстве теоремы все ППФ в Ф1 представляются в виде предложений или в так называемой клаузальной форме. Любая представленная в клаузальной форме фраза состоит из серии высказываний ^или их^отрицаний), соединенных связкой ИЛИ, например, АуВуСуД. Последовательность тождественных преобразований, кото¬ рые необходимо выполнить в процессе преобразования формулы исчисления предикатов в предложения, разбирается в работе [13] и состоит из следующих этапов: 1) исключение знаков импликации (А-*В=Ау В); 2) уменьшение области действия знака отрицания (А/\В=== = A\/Bf ..., VXF(X) = RXF(X)...); 3) стандартизация переменных; 4) исключение кванторов существования; 5) исключение кванторов общности. В основе метода резолюции лежит операция исключения вы¬ сказываний из различных предложений, если эти высказывания в одних предложениях отрицаются, а в других — нет. Сначала зафиксируем в клаузальной форме известные нам факты: 1) ВуА; 2) СУ В; 3) С. Предложения 1ч-3 образуют множество Ф0. Допустим, что мы хотим доказать А (F=A). Чтобы это сде¬ лать, дополним заданный набор отрицанием А (так как Ф1 = =Фо1Ю; 1) ВУА\ 2) СУ В; 3) С; 4) А. Исключим теперь вновь введенное предложение и его отри¬ цание в другом предложении. Этот процесс называется резолю¬ цией. Например, мы можем исключить А в четвертом предложе¬ нии и Л в первом, оставив в них без изменения совокупность остальных высказываний (такую совокупность называют ре- 40
зольвентой). В нашем случае это В. В результате остаются пред¬ ложения __ 1) В\ 2) С\/В\ 3) С. Очевидно, что мы фактически воспользовались правилом вы¬ вода modus tollens. После этого продолжим процесс, исключив, например, В в первом предложении и соответственно В — во втором. В ре¬ зультате остаются 2) СиЗ) С7 Наконец, исключив последние два предложения, получим пустое предложение, или нулевую резольвенту. Порождение ну¬ левой резольвенты указывает на то, что заданный набор (Ф1) предложений противоречив и, _ _ следовательно, можно заклю- ^BVA чить, что утверждение А спра¬ ведливо. Этот подход является общепринятым в математике. Его называют доказательством от противного или reductio ad absurdum. Рассмотренная процедура резолюции может быть пред¬ ставлена графически с по¬ мощью так называемого де¬ рева резолюции (рис. 1.7). Теперь, в той же последовательности рассмотрим конкрет¬ ный пример использования переменной в качестве аргумента функции F. Как мы уже знаем из п. 1.1., предложение типа «подсказка» и предложение типа «правило» относятся к языку одного типа, кроме того, известно, что предложение типа «правило» отно¬ сится к языку эксперта. Требуется ответить на вопрос: к ка¬ кому языку относится предложение типа «подсказка»? Представим задачу как задачу доказательства теоремы. Для этого введем предикат СООТВ (соответствие) со следующей структурой: СООТВ (>)<тип — предложения, >)<тип — языка). Условие задачи (констатирующую часть) можно записать в виде множества формул: Ф0={УХ[СООТВ (ПРАВИЛО, Х)-^СООТВ (ПОДСКАЗКА, X)]t СООТВ (ПРАВИЛО, ЭКСПЕРТА)}, а формула F примет вид ЭХ СООТВ (ПОДСКАЗКА, X). В множестве Ф0 первая формула отражает тот факт, что ка¬ кому бы языку не соответствовало предложение типа «правило», этому же языку соответствует предложение типа «подсказка», CVB Рис. 1.7. Дерево резолюции: В, С — резольвента; ( ) —нулевая ре¬ зольвента 41
вторая формула — что предложение типа «правило» соответ¬ ствует языку эксперта. Исходная задача сводится к доказатель¬ ству теоремы: Ф0=^ЯА СООТВ (ПОДСКАЗКА, А). Определив значение X, при котором теорема верна, получим ответ на вопрос. Для доказательства, что формула F следует из множества Ф0, следует к множеству Ф0 добавить формулу F и все члены расши¬ ренного множества Ф1 = Фои^ преобразовать в форму предложе¬ ний. Затем с помощью метода резолюции показывают, что мно¬ жество Ф1 невыполнимо. Так как ЗА СООТВ (ПОДСКАЗКА, X) = VX СООТВ (ПОД¬ СКАЗКА, А)=СООТВ (ПОДСКАЗКА, X), то расширенное множество после преобразования его формул в предложения имеет вид Ф1 = {СООТВ (ПРАВИЛО, J0VCOOTB (ПОДСКАЗКА, X), СООТВ (ПРАВИЛО, ЭКСПЕРТА),СООТВ (ПОДСКАЗКА,*)}. СООТВ(ПРАВИЛО, х) VСООТВ(ЛОДСКЛЗКА.х) С00ТВ(П0ДСКАЗКА,х) С00ТВ(ПРАВИЛО,х) СООТВ(ПРАВИЛО, ЭКСПЕРТА) ( ) при совмещении х и ЭКСПЕРТА Рис. 1.8. Дерево резолюции Дерево резолюции приведено на рис. 1.8. Нулевая резольвента получается при условии совмещения переменной X и ЭКСПЕРТА. Таким образом, теорема доказана. К сожалению, в методе резолюции не указывается, какие предложения следует выбирать для резолюции. В приведенных примерах, по существу, в этом не было необходимости, по¬ скольку предложений было очень мало. Однако даже при уме¬ ренном их количестве мы сталкиваемся с проблемой комбина¬ торного взрыва второго уровня. Достаточно эффективный спо¬ соб выбора предложений был введен разработчиками языка Пролог. Кратко рассмотрим переход от клаузальной формы к нота¬ ции Пролога [28]. Напомним, что логическое выражение в клаузальной форме состоит из высказываний (или их отрицаний), соединенных связ¬ ками ИЛИ. Любой набор высказываний, соединенных связками ИЛИ, может быть перестроен без изменения их значения. Сна¬ 42
чала отделим отрицаемые высказывания от неотрицаемых, пе¬ реносных соответственно налево и направо. Выражение А\/В\/С\/Д\/Ё~ в этом случае^приобретает следующий вид: (вудуЩу(Аус). Набор высказываний, связанных с помощью ИЛИ, может быть заменен эквивалентным ему набором высказываний, со¬ единенных связкой И (по правилам де Моргана), например, (ВУДЧЩ=(В/\Д/\Е). В результате исходному предложению эквивалентно следую¬ щее предложение: (ВКДШ\/(А\/С). Полученное выражение после преобразования в импликаци¬ онную форму с учетом соотношения А\/В = А-+В примет вид ВЛДЛЕ-*А\/С. Другими словами, набор условий, соединенных связкой Иу имплицирует набор заключений, соединенных связкой ИЛИ. Те¬ перь мы подошли вплотную к тому, чтобы сформировать пред¬ ложение, характерное для языка Пролог. Введем дальнейшее ограничение: каждое предложение мо¬ жет содержать только одно заключение. При таком условии при¬ веденное выше предложение следует представить как БАДАЕВА- ВАДАЕ-^с. В принятой для Пролога нотации эти выражения будут иметь вид +А-В-Д-Е#; + С-Я-Д-£#. Факт представляется как безусловное выражение +£ф. Запрос (то, что мы хотим подтвердить) отрицается в соот¬ ветствии с методом резолюции и представляется в виде — Лф. Однако в Прологе существует проблема выбора двух пред¬ ложений, сопоставляемых при выводе очередной резольвенты. Для ее решения требуется иметь некоторую форму управляющей структуры. Свойственный Прологу процесс управления лучше всего можно пояснить, воспользовавшись концепцией поиска в пространстве состояний (см. п. 1.1), применяемой при описа¬ нии экспертных систем. Высказывания в наборе взаимосвязан¬ ных предложений на языке Пролог могут быть представлены в виде иерархически организованного пространства состояний (как некоторое дерево типа И/ИЛИ). Покажем это на примере дерева состояний (рис. 1.9). Крона дерева сформирована на ос¬ новании взаимосвязанных правил, где фактам соответствуют терминальные вершины. Напомним, что в Прологе условия пра¬ 43
вил—это ветви со связками И. Там, где к одному и тому же за¬ ключению приводят различные условия, эти условия имеют связку ИЛИ, и такие ветви изображаются без перемычки между ними. Дерево типа И/ИЛИ можно рассматривать двояко; и как де¬ кларативное выражение, что обычно свойственно логическим выражениям, и как процедурное выражение, что характерно для программирования. Например, следуя логике, можно утвер¬ ждать: для того, чтобы высказывание А было истинным, оба вы¬ сказывания В и С должны быть истинны, а для того, чтобы В было истинным, должно быть истинным одно из высказыва¬ ний— либо Ду либо Е. С позиции процедурного представления + Л -В -СП +AU + я -еп +лт -4-С —К -МП Рис. 1.9. Дерево И/ИЛИ для Пролог-программы правила языка Пролог можно интерпретировать как декомпози¬ цию доказательства заданного высказывания. Доказательство А распадается на два доказательства (В и С), а доказательство В распадается или на доказательство Д, или на доказательство Е. Задав представление набора предложений Пролога в виде дерева типа И/ИЛИ, можно применять различные стратегии для его прохождения при поиске решения. Это эквивалентно выработке стратегии решения относительно того, какие из пред¬ ложений следует выбрать для резолюции при доказательстве теорем методом резолюции. В Прологе принята стратегия по¬ иска «сначала вглубь», начиная слева. Предположим, что в со¬ ответствии с приведенным примером мы хотим доказать выска¬ зывание А. Выразим это как отрицание —Лф и добавим обыч¬ ным способом это выражение к заданному набору предложений. В соответствии с терминологией Пролога высказывания запроса называют целью. Заданная цель —А после этого сопоставляется с первым предложением, имеющем А в качестве заключения (т. е. со знаком +). В рассматриваемом случае есть только одно такое высказывание: +Л—В—Сф. В Прологе берется пер¬ вое условное допущение (Б) и делается попытка доказать его истинность. Поскольку оно является условием (со знаком —), его можно представить через отрицание, рассматривать в каче¬ стве новой цели или подцели и снова сопоставить с первым встретившимся предложением, содержащим В в качестве за¬ 44
ключения (со знаком +). Такое высказывание — заключение в Прологе известно как головное высказывание предложения. Этот процесс продолжают до тех пор, пока не будет выбрана подцель—Д, с которой сопоставляется факт +Д. В результате доказывается истинность высказывания Д. Как только высказы¬ вание В будет удовлетворено через Д, программа на языке Про¬ лог приступит к обработке высказывания С, которое удовлетво¬ ряется через К, а затем через М. Таким образом, исходный за¬ прос— А подтверждается путем обхода последовательности уз¬ лов дерева Л, £, Д, С, К, М. Необходимо отметить, что если под¬ тверждение В или С невозможно в силу отсутствия в программе обоих высказываний Д и Е и любого из вы¬ сказываний К или Му то запрос — А пости¬ гнет неудача (в отношении его подтвержде¬ ния). Следует рассмотреть еще одну особен¬ ность исполнения программы на языке Про¬ лог. Когда для приведенного выше при¬ мера производился подбор цели — £, был сделан выбор головного высказывания первого встретившегося предложения с В в качестве заключения (со знаком 4-). После удовлетворения В (посредством удовлетворения Д) была продолжена по¬ пытка подбора пары для новой подцели — С. Однако при этом возникает вопрос: что произошло бы, если бы два предложе¬ ния, содержащие + £, были расположены в обратном порядке (или, что аналогично, отсутствовал факт +Д, а присутствовал факт4-£), т. е. 4-В—£ф шло первым? В такой ситуации при¬ меняется стратегия с возвратом (рис. 1.10). Предположим, что тот же самый запрос —А снова адресо¬ ван системе. Цели —А в этом случае соответствует головное вы¬ сказывание +Л, в результате будет порождена подцель — В. Этому будет соответствовать головное высказывание 4-В, по¬ рождающее подцель —£, которая не будет удовлетворена из-за отсутствия факта +£. Получив отрицательный результат, си¬ стема производит возврат к удовлетворенному сопоставлению и осуществляет поиск альтернативы, который завершится выбо¬ ром второго предложения с В и его головного высказывания 4-В—Д^=. Затем доказательство может протекать по прежнему. Таким образом, для автоматизации исчисления предикатов выбираем обратный вывод с поиском в глубину с возвратом. Для этого по заданной пользователем цели, в соответствии с прави¬ лом modus tollens, осуществляется поиск правила, в части ТО которого имеется этот атрибут. После этого производится оценка части ЕСЛИ правила слева направо. В соответствии с обратным выводом первый же атрибут в части ЕСЛИ должен безусловно 45 И/ИЛИ для иллю¬ страции возвратов
объявляться новой целью, но его значение уже может быть определено на предыдущих этапах работы системы при обра¬ ботке других правил, а так как значения некоторых атрибутов задаются пользователем, то объявление такого атрибута целью приведет к повторному запросу пользователя, что крайне неже¬ лательно. Чтобы не повторять запросы к пользователю, ответы пользователя (см. п. 1.1) запоминаются в стеке фактов, поэтому оценка части ЕСЛИ правила будет проводиться с помощью пря¬ мого вывода в соответствии с правилами вывода modus ponens и «введение конъюнкции». Если при оценке части ЕСЛИ встре¬ тится атрибут, отсутствующий в стеке фактов, то он (как и тре¬ бует обратный вывод) объявляется очередной целью, т. е. пря¬ мой вывод позволяет вначале проверить наличие атрибута в стеке фактов и только при его отсутствии в стеке фактов объ¬ являть его новой целью вывода. Правило предметной области считается истинным, если все атрибуты, входящие в часть ЕСЛИ правила, имеются в стеке фактов и их значения в правиле и в стеке фактов совпадают. Если же имеется атрибут, входящий в часть ЕСЛИ правила и в стек фактов, но значения атрибута в правиле и в стеке фактов различны, то правило считается ложным. Возникает вопрос, как оценивать правило в случае, когда атрибут, входящий в часть ЕСЛИ правила, отсутствует в стеке фактов. В этом случае существует два варианта: 1) значение правила считается неопределенным, а указан¬ ный атрибут объявляется целью вывода; 2) оценка значения правила откладывается, указанный атрибут объявляется целью и после получения его значения продолжается оценка значения правила (см. п. 5.2). Для реализации обратного вывода необходимо реализовать правило modus tollens, а для реализации прямого вывода — пра¬ вила modus ponens и «введение конъюнкции». Таким образом, реализуемый нами алгоритм поиска реше¬ ния (имитация логического вывода с помощью поиска в про¬ странстве состояний) в основном сводится к следующему. В про¬ цессе диалога системе задается основная цель (атрибут) вы¬ вода, фактически соответствующая отрицанию цели. Для каж¬ дой текущей цели (в соответствии с правилом вывода modus tollens) система пытается найти правило, в части ТО которого атрибут совпадает с целью. Если правило не найдено, то про¬ водится обращение к подсказками осуществляется запрос поль¬ зователя, ответ которого фиксируется в базе данных (стеке фактов). Если правило найдено, то проводится оценка его зна¬ чения. Если значение правила ЛОЖЬ, то оно запрещается для дальнейшего использования. Если значение правила ИСТИНА, то (в соответствии с правилом вывода modus ponens) значение ат¬ рибута из части ТО фиксируется в базе данных. Если же зна¬ 46
чение правила НЕОПРЕДЕЛЕНО, то атрибут из части ЕСЛИ правила, который отсутствует в базе данных, объ¬ является целью, т. е. помещается в вершину стека целей. Про¬ цесс продолжается до тех пор, пока основная цель не получит значение либо система не сможет найти ни правила, ни под¬ сказки и соответственно решения. Признаком успешного окон- Таблица 1. Шаг Анализи¬ руемое правило Значение правила Ответ и а подсказку Стек целей Стек фактов Номер от¬ брошенного правила Атрибут Номер правила Атрибут- Значение Номер правила 1 Язык 0 2 10 Неопре¬ Предложе¬ 10 дел ен о ние 3 1 То же Число 1 4 Нет Да Предложе¬ 10 Число—Да 0 ние 5 1 » Слово 1 6 Нет Если Предложе¬ 10 Слово—Если 0 ние 7 1 Ложь 1 8 2 Неопре¬ След- 2 дел ен о слово 9 Нет И Предложе¬ 10 След-слово— 0 ние И 10 2 Ложь 2 11 3 Неопре¬ То 3 де лен о 12 Нет Да Предложе¬ 10 То—Да 0 ние 13 3 Истина Язык 0 Предложе¬ 3 ние—Правило 14 10 » Язык—Экс¬ 10 перта чания работы является пустой стек целей, соответствующий ну¬ левой резольвенте и (на основании правила вывода reductio ad absurdum) подтверждающий достижение цели вывода. Таким образом, нами выбрана организация логического вы¬ вода, которую мы будем реализовывать. Чтобы ее закрепить, рассмотрим процесс вывода для программы-интерпретации пред¬ ложений, заданной на языке эксперта и представленной в п. 1.1. Пусть пользователь имеет предложение 3 (см. табл. 1.1) и он хочет определить тип языка, к которому относится это предло¬ жение. В табл. 1.4 приведен ход процесса вывода решения для данной задачи. 47
1.4. БЛОК ПОЯСНЕНИЙ И ЯЗЫК ПОЛЬЗОВАТЕЛЯ Как уже отмечалось, одним из основных свойств ЭС, которое многие считают главным, является способность системы по тре¬ бованию пользователя объяснять ход своих рассуждений понят¬ ным для пользователя образом. Обеспечивается это в результате программирования, основанного на формальных правилах, и ре¬ ализуется блоком пояснений. Перед ответом на запрос системы о значении какого-либо атрибута пользователь может задать системе два типа вопро¬ сов: ПОЧЕМУ и КАК. Ответы на вопросы ПОЧЕМУ поясняют, почему система за¬ дает определенный вопрос, т. е. приводится распечатка правила, вызвавшего этот вопрос. Последовательно задавая вопросы ПОЧЕМУ, пользователь может проследить весь ход рассужде¬ ния системы. С помощью вопросов КАК пользователь может узнать у си¬ стемы как было или как будет определено значение интересую¬ щего пользователя атрибута. Система (в зависимости от атри¬ бута) либо распечатывает правило, с помощью которого было или будет определено значение атрибута, либо выдает информа¬ цию о том, что значение данного атрибута определялось либо будет определяться с помощью пользователя. Поскольку работа ЭС — это фактически поиск на графе, для объяснения этого процесса необходимо обеспечить возможность возвращения по пройденному пути и пробного продвижения вперед. Организация объяснений процесса поиска решения зависит от организаций самого этого процесса. Как указывалось выше, поиск решения может осуществляться с помощью логического вывода или с помощью имитации логического вывода посредст¬ вом поиска в пространстве состояний. При поиске в пространстве состояний все состояния до¬ ступны для использования. Продвижение по графу поиска опре¬ деляется целевыми состояниями, которые хранятся в стеке це¬ лей. Задавая вопрос ПОЧЕМУ, пользователь может узнать, почему систему интересует значение запрашиваемого атрибута. Из рассмотрения блока логического вывода следует, что этот атрибут является текущей целью и находится на вершине стека целей. Объяснение сводится к тому, что распечатывается пра¬ вило, поместившее этот атрибут в стек целей. Из этого следует, что для организации ответов на вопрос ПОЧЕМУ в стек целей должен помещаться не только целевой атрибут, но и номер пра¬ вила, объявившего его текущей целью. Очевидно, что, задавая вопросы ПОЧЕМУ и продвигаясь по стеку целей, пользователь может проследить всю цепочку рассуждений системы. Когда 48
в результате вопросов ПОЧЕМУ система добирается до конца стека, то обычно в ЭС печатается сообщение типа «Вы этого* хотели сами». Естественно, что при распечатке правило должно выводиться в наиболее полном виде, поэтому при печати атрибуты заменя¬ ются своими переводами. Возможны различные варианты пе¬ чати правил. Например, можно просто распечатать правило, а можно разбить правило. При этом отдельно печатают часть правила, которая содержит атрибуты, имеющиеся в стеке фак¬ тов, с подзаголовком типа «Мы уже знаем...», и часть правила, которая содержит атрибуты, не имеющиеся в стеке фактов, с подзаголовком типа «Если мы узнаем, что...». Задавая вопрос КАК и указывая атрибут, пользователь узнает о действиях системы по определению значения этого атрибута. Если атрибут имеется в стеке фактов, то необходимо опреде¬ лить, как он туда попал: в результате срабатывания какого-то правила или в результате ответа пользователя. Эту задачу можно решить, если в стек фактов кроме названия атрибута и его значения поместить номер правила, определившего значение этого атрибута. Ответу же пользователя также нужно присвоить номер отсутствующего правила, например, ноль. Таким образом, если в стеке фактов атрибуту будет соответствовать номер ноль, то должно быть выдано сообщение типа «Значение атрибута было задано пользователем», в противном случае должно быть распечатано правило, определившее значение атрибута, с пред¬ варительным сообщением о том, что значение атрибута было определено с помощью правила. Если атрибута, входящего в вопрос КАК, в стеке фактов нет, то его ищут среди заключений всех разрешенных к использова¬ нию правил и в случае успеха выдают сообщение о том, что значение данного атрибута возможно будет определено с по¬ мощью правила с распечаткой самого правила. Слово «воз¬ можно» означает, что может быть несколько правил, определяю¬ щих значение данного атрибута, и какое из них будет использо¬ вано заранее сказать нельзя; система распечатывает первое из них. Если же правило найдено не будет, то должно быть выдано сообщение типа «Значение атрибута может быть определено только с помощью информации, вводимой пользователем». В случае, когда поиск решения производится с помощью языка логического вывода, реализованного, например, с помощью языка Пролог, поиск на графе скрыт в управляющей структуре логического вывода языка Пролог, и стек целей становится недоступным для разработчика ЭС. Необходимость организации ответов на вопросы ПОЧЕМУ заставляет организовать «след» вывода, т. е. список номеров использованных правил (см. п. 4.3). Что же касается реализации ответов на вопросы КАК, то она 49 4 В. Э. Балтрашевич
фактически не отличается от ее организации при поиске в про¬ странстве состояний, так как Пролог базируется только на об¬ ратном выводе, и чтобы реализовать и прямой вывод нам потре¬ буется реализовать аналог стека фактов. Диалог пользователя с системой идет на языке пользователя, описание которого с помощью синтаксических диаграмм приве- Предложение —ffl о д сказкаопрос режимаЗначение Объяснения HDH Объяснения v—{'Почему^ (иочему^-^ —^Сообщение об ошибке^-— Запрос Вопроса^ (^НепГу~ Рис. 1.11. Синтаксические диаграммы языка пользователя дено на рис. 1.11. Так как язык пользователя является диало¬ говым языком, то для отражения действий системы в синтакси¬ ческие диаграммы введены еще два типа блоков; параллело- грам—для печати сообщений системы, шестиугольник — для указания действий (процедур) системы. Трансляция с языка пользователя осуществляется интерпре¬ татором, и в этом случае возможны повторные запросы пользо¬ вателя при его неправильных действиях. В начале диалога ЭС печатает текст подсказки для интересующего ее атрибута и ждет от пользователя ответа на поставленный вопрос. Однако пользователь сам может задать интересующие его вопросы ПО¬ ЧЕМУ и КАК. Как видно из описания языка (см. рис. 1.11), признаком режима ответа является ввод пользователем знака #, а признаком режима объяснений — ввод знака?. Если поль¬ зователь введет любой другой символ (например, V), то он по¬ лучит сообщение о вводе неверного символа и повторный запрос указания режима. В режиме объяснения пользователь может чередовать в лю¬ бом порядке вопросы ПОЧЕМУ и КАК. 50
В режиме ответа система ждет от пользователя значения атрибута с учетом синтаксиса языка пользователя. Из приведен¬ ных синтаксических диаграмм видно, что система забирает лю¬ бой ответ пользователя без проверки его допустимости. Как следует из описания разработанного алгоритма логического вы¬ вода, при неправильном ответе пользователя ЭС не сможет до¬ стичь цели. В принципе можно доработать язык пользователя так, чтобы система сравнивала ответ пользователя с множест¬ вом возможных значений атрибута, который запрашивается, и в случае ошибки повторяла запрос. Однако такой вариант про¬ верки слишком громоздок. Существует более рациональный спо¬ соб: компилятор с языка эксперта, просматривая правила ЕСЛИ... ТО, выявляет атрибуты и строит списки их возмож¬ ных значений, которые могут быть распечатаны вместе с соот¬ ветствующей подсказкой. Как уже отмечалось (см. п. 1.2) в языке кроме правил грам¬ матики существует и множество терминальных и нетерминаль¬ ных символов (слов). В некоторых языках необходимо описание символов до их использования (например, в Паскале), в других языках (ЛИСПе, Прологе) такого описания не требуется. В языке эксперта также можно предварительно создать словарь атрибутов и их значений, либо этот словарь можно создать авто¬ матически при анализе предложений языка эксперта. Пример реализации с предварительным созданием словаря атрибутов и их значений приведен в работе [20]. Рассмотрим конкретный пример возможной работы пользо¬ вателя с ЭС. Пример. Пусть в предмет-машину (см. рис. 1.5) загружен текст про¬ граммы интерпретации предложений (см. п. 1.1). Необходимо определить тип языка, к которому относится предложение № 3 (см. табл. 1.1). Система выдает вопрос ПРЕДЛОЖЕНИЕ НАЧИНАЕТСЯ С ЧИСЛА (ДА/НЕТ)? Как мы уже отмечали, пользователь может либо отвечать, либо спраши¬ вать. Предположим, что у пользователя вопросов нет и он отвечает # ДА Система выдает вопрос С КАКОГО СЛОВА НАЧИНАЕТСЯ ПРЕДЛОЖЕНИЕ? Предположим, что здесь у пользователя возникли вопросы. Его интере¬ сует, почему система задает этот вопрос и поэтому пользователь задает вопрос РПОЧЕМУ, на который система отвечает распечаткой правила 1, определяющего значе¬ ние атрибута ПРЕДЛОЖЕНИЕ. На вопрос о том, как система определяет значение атрибута ЧИСЛО: КАК ЧИСЛО пользователь получает ответ ЗНАЧЕНИЕ АТРИБУТА БЫЛО ЗАДАНО ПОЛЬЗОВАТЕЛЕМ. ^На вопрос КАК СЛОВО дается ответ 4* 51
ЗНАЧЕНИЕ АТРИБУТА МОЖЕТ БЫТЬ ЗАДАНО ПОЛЬЗОВАТЕЛЕМ. Если пользователя интересует, почему системе нужно знать значение атрибута ПРЕДЛОЖЕНИЕ, он должен задать вопрос ПОЧЕМУ, на который система ответит распечаткой правила 10, определяющего зна¬ чение атрибута ЯЗЫК. На вопрос пользователя КАК ПРЕДЛОЖЕНИЕ 'система ответит, что значение атрибута ПРЕДЛОЖЕНИЕ она найдет (мо¬ жет быть), используя правило 1, и даст его распечатку. Если пользователя интересует, почему системе нужно знать значение атрибута ЯЗЫК, он должен задать вопрос ПОЧЕМУ, «а который система ответит ВЫ ЭТОГО ХОТЕЛИ САМИ. Предположим, что больше у пользователя вопросов нет и он сообщает об этом системе НЕТ. Система повторяет свой вопрос, так как за время диалога пользователь вполне мог его забыть С КАКОГО СЛОВА НАЧИНАЕТСЯ ПРЕДЛОЖЕНИЕ? На что пользователь отвечает # ЕСЛИ. Как видно из табл. 1.4, система при этом ответе пользователя запрещает для дальнейшего использования правило 1, переходит к правилу 2 и работа продолжается. Отметим, что подчеркнутые фразы в процессе приведенного диалога со¬ ставляют программу на языке пользователя. 1.5. ОПИСАНИЕ ФУНКЦИОНИРОВАНИЯ ЭКСПЕРТНОЙ СИСТЕМЫ В предыдущих параграфах фактически был разработан оче¬ редной уровень виртуальной (кажущейся) машины (см. рис. 1.5), более доступный эксперту и пользователю, чем универсальные виртуальные машины, такие как Паскаль-, ЛИСП- и Пролог- машины. Эксперт с помощью языка эксперта может описывать свои знания на языке, близком к естественному языку его пред¬ метной области, используя для обозначения атрибутов и их зна¬ чений привычную для него терминологию. С помощью разрабо¬ танной машины можно решать задачи класса интерпретации и диагностики, т. е. граф поиска решения которых может быть представлен в виде дерева. Атрибуты могут принимать значения из небольшого дискретного множества значений. Данные и пра¬ вила должны быть точными в том смысле, что система не предо¬ ставляет возможности работы с факторами уверенности. Пример реализации ЭС, использующей факторы уверенности, приве¬ ден в работе [20]. В качестве управляющей структуры разрабо¬ танной машины используется двунаправленный вывод с поис¬ ком в глубину с возвратом. Для реализации управляющей структуры рассмотрены варианты поиска в пространстве состоя¬ ний и варианты логического вывода на основе доказательства 52
теорем с помощью метода резолюции (обратный вывод) и с по¬ мощью использования других правил вывода (прямой вывод). Управляющая структура разработанной машины не зависит от предметной области. В п. 1.1 приведено описание задачи (программы) интерпре¬ тации различных предложений языков эксперта и пользователя. Возможно, этот пример и последующий анализ реализации ком¬ пилятора с языка эксперта позволит читателю лучше понять разницу между представлением знаний и управляющими струк¬ турами инструментальных экспертных систем и трансляторов, т. е. разницу между двумя наиболее плодотворно развивающи¬ мися направлениями искусственного интеллекта. Для того чтобы продемонстрировать возможность работы системы со знаниями из различных предметных областей, рас¬ смотрим задачу интерпретации (классификации) растений с по¬ мощью знаний эксперта-ботаника [18], описание которой приве¬ дено на стр. 54. Как уже отмечалось, в целях компактного представления программы на одной строке представлено несколько строк языка эксперта. Символ <ВК> обозначает нажатие клавиши «Возврат каретки». Если читатель не является специалистом в области ботаники, он все равно сможет работать с этой системой и несколько рас¬ ширит свой кругозор. Как видно из правил, приведенных в про¬ грамме, база знаний не является полной, так как не приведены правила для определения семейства растения при условии, что оно относится к классу покрытосемянных. Кроме того, с по¬ мощью приведенных правил можно определить класс и семейство растения лишь при условии, что оно относится к типу деревьев. Это нужно учитывать при работе с системой. Следует отметить, что полная база знаний содержит гораздо больше правил и позволяет проводить идентификацию видов хвойных расте¬ ний [18]. В табл. 1.5 приведен пример работы системы, когда целью является определение семейства растения (цель СЕМЕЙСТВО) и ответ пользователя о растении, относящемся к семейству кипарисовых. Читателю предлагается проанализировать работу системы при цели СЕМЕЙСТВО в предположении, что перед ним растение семейства «болотный кипарис», а также при цели ТИП, для которой есть правила на случай любого (в рамках подсказки) ответа пользователя. В работе [22] приведена аналогичная база знаний для задачи интерпретации из области зоологии, которая также может быть реализована с помощью нашей экспертной системы. Читателю предлагается выбрать похожую задачу из своей прёдметной области и записать ее на языке эксперта, а затем опробовать ее на действующей системе. 53
1 ЕСЛИ КЛАСС-ГОЛОСЕМЯННЫЕ И Ф0РМА_ЛИСТА-ЧЕШУЕ0БРАЗНАЯ ТО СЕМЕЙСТВО - КИПАРИСОВЫЕ 2 ЕСЛИ КЛАСС-ГОЛОСЕМЯННЫЕ И ФОРМА_ЛИСТА-ИГЛОПОДОБНАЯ И КОНФИГУРАЦИЯ - ХАОТИЧЕСКАЯ ТО СЕМЕЙСТВО - СОСНОВЫЕ 3 ЕСЛИ КЛАСС-ГОЛОСЕМЯННЫЕ И ФОРМА_ЛИСТА-ИГЛОПОДОБНАЯ И КОНФИГУРАЦИЯ-ДВА_РОВНЫХ_РЯДА И СЕРЕБРИСТАЯ_ПОЛОСА-ДА ТО СЕМЕЙСТВО - СОСНОВЫЕ 4 ЕСЛИ КЛАСС-ГОЛОСЕМЯННЫЕ И ФОРМА_ЛИСТА-ИГЛОПОДОБНАЯ И КОНФИГУРАЦИЯ - ДВА_РОВНЫХ_РЯДА И СЕРЕБРИСТАЯ_ПОЛОСА - НЕТ ТО СЕМЕЙСТВО - БОЛОТНЫЙ_КИПАРИС 5 ЕСЛИ ТИП - ДЕРЕВЬЯ И ШИРОКАЯ_И_ПЛОСКАЯ - ДА ТО КЛАСС - ПОКРЫТОСЕМЯННЫЕ 6 ЕСЛИ ТИП - ДЕРЕВЬЯ И ШИРОКАЯ_И_ПЛОСКАЯ - НЕТ ТО КЛАСС - ГОЛОСЕМЯННЫЕ 7 ЕСЛИ СТЕБЕЛЬ - ЗЕЛЕНЫЙ ТО ТИП - ТРАВЯНИСТЫЕ 8 ЕСЛИ СТЕБЕЛЬ - ДРЕВЕСНЫЙ И ПОЛОЖЕНИЕ - СТЕЛЮЩЕЕСЯ ТО ТИП - ЛИАНЫ 9 ЕСЛИ СТЕБЕЛЬ - ДРЕВЕСНЫЙ И ПОЛОЖЕНИЕ - ПРЯМОСТОЯЩЕЕ И ОДИН_ОСНОВНОЙ_СТВОЛ - ДА ТО ТИП - ДЕРЕВЬЯ 10 ЕСЛИ СТЕБЕЛЬ - ДРЕВЕСНЫЙ И ПОЛОЖЕНИЕ - ПРЯМОСТОЯЩЕЕ И ОДИН_ОСНОВНОЙ_СТВОЛ - НЕТ ТО ТИП - КУСТАРНИКОВЫЕ ПОДСКАЗКА СТЕБЕЛЬ КАКОЙ СТЕБЕЛЬ У РАСТЕНИЯ - ДРЕВЕСНЫЙ ИЛИ ЗЕЛЕНЫЙ? ПОДСКАЗКА ПОЛОЖЕНИЕ КАКОЕ ПОЛОЖЕНИЕ СТЕБЛЯ - ПРЯМОСТОЯЩЕЕ ИЛИ СТЕЛЮЩЕЕСЯ? ПОДСКАЗКА ОДИН_ОСНОВНОЙ_СТВОЛ ИМЕЕТ ЛИ РАСТЕНИЕ ОДИН ОСНОВНОЙ СТВОЛ (ДА ИЛИ НЕТ)? ПОДСКАЗКА ШИРОКАЯ_И_ПЛОСКАЯ ИМЕЮТ ЛИ ЛИСТЬЯ ШИРОКУЮ И ПЛОСКУЮ ФОРМУ (ДА ИЛИ НЕТ)? ПОДСКАЗКА ФОРМА_ЛИСТА КАКАЯ ФОРМА ЛИСТА - ИГЛОПОДОБНАЯ ИЛИ ЧЕШУЕОБРАЗНАЯ? ПОДСКАЗКА КОНФИГУРАЦИЯ КАКОЕ РАСПОЛОЖЕНИЕ ИГЛ-ХАОТИЧЕСКАЯ ИЛИ ДВА_РОВНЫХ_РЯДА? ПОДСКАЗКА СЕРЕБРИСТАЯ_ПОЛОСА ИМЕЕТСЯ ЛИ СЕРЕБРИСТАЯ ПОЛОСА СНИЗУ ИГЛЫ (ДА ИЛИ НЕТ)? ПЕРЕВОД СТЕБЕЛЬ <ВК> СТЕБЕЛЬ РАСТЕНИЯ ПЕРЕВОД ПОЛОЖЕНИЕ <ВК> ПОЛОЖЕНИЕ СТЕБЛЯ ПЕРЕВОД ОДИН_ОСНОВНОЙ_СТВОЛ РАСТЕНИЕ (НЕ)ИМЕЕТ ОДИН ОСНОВНОЙ СТВОЛ ПЕРЕВОД ТИП <ВК> ТИП РАСТЕНИЯ ПЕРЕВОД СЕМЕЙСТВО <ВК> СЕМЕЙСТВО РАСТЕНИЯ ПЕРЕВОД ШИРОКАЯ_И_ПЛОСКАЯ ФОРМА ЛИСТЬЕВ - (НЕ)ШИРОКАЯ И (НЕ)ПЛОСКАЯ ПЕРЕВОД КЛАСС <ВК> КЛАСС ДЕРЕВА ПЕРЕВОД ФОРМА_ЛИСТА <ВК> ФОРМА ЛИСТА ПЕРЕВОД КОНФИГУРАЦИЯ КОНФИГУРАЦИЯ РАСПОЛОЖЕНИЯ ИГЛ ВДОЛЬ ВЕТВИ ПЕРЕВОД СЕРЕБРИСТАЯ_ПОЛОСА СНИЗУ ИГЛЫ ИМЕЕТСЯ (ОТСУТСТВУЕТ) СЕРЕБРИСТАЯ ПОЛОСА 54
Из приведенных примеров становится ясно, что реализуемая инструментальная ЭС является только инструментом, облегчаю¬ щим специалистам в конкретных предметных областях процесс решения стоящих перед ними задач. Действительным же богат¬ ством являются знания экспертов по решению задач, записан¬ ные на языке эксперта, обеспечивающим накопление и обра¬ ботку этих знаний с помощью машины. Интересно проследить сходство применения экспертных си¬ стем в программировании и микропроцессоров в аппаратуре. Когда стало очевидным преимущество использования при разра- Таблица 1.5 Стек целей Стек фактов о 5 о <и X Я >> я X н а 1 <и ь х а н о о к я 2 о ч ® О к * 5 а> х 03 >» \о *5 ЕС >g «и ftS 5 и g S а 5 о «я сг а я а <и * Ш St X ft ч* в 5 я S V ft я | 5 s а в О о я а * >»ft < Р.С х а со с jr о О с н < ® ft К с н * <со 3 о. £ с Хюё 1 Семейство 0 2 1 Не опре- Класс 1 делено 3 5 То же Тнп 5 4 7 » Стебель 7 5 Нет Древес¬ Тип 5 Стебель—Дре¬ 0 ный весный 6 7 Ложь 7 8 Не опре¬ Положение 8 7 делено 8 Нет Прямо¬ Тип 5 Положение— 0 стоящее Прямостоящее 9 8 Ложь 8 10 9 Не опре¬ Один_ ос¬ 9 делено новной- ствол 11 Нет Да Тнп 5 Один—ОСНОВ¬ НОЙ-ствол—Да 0 12 9 Истина Класс 1 тип— 9 деревья 13 5 Не опре¬ Широкая- 5 делено и_плоская 14 Нет Нет Класс 1 Широкая-и— плоская—Нет 0 15 5 Ложь 5 16 6 Истина Семейство 0 Класс — Голо¬ семянные 6 17 1 Не опре¬ Форма¬ 1 делено листа 18 Нет Чешуе¬ Семейство 0 Форма—ли¬ 0 образная ста—Чешуе¬ образная 19 1 Истина Семейство— 1 Кипарисовые 55
ботке различной аппаратуры больших интегральных схем (БИС), каждый разработчик хотел иметь индивидуальную БИС, предназначенную для решения конкретной задачи, что было не¬ возможно по вполне понятной причине. Выход из создавшегося положения заключался в разработке универсальных БИС, допу¬ скающих настройку на решение любой конкретной задачи. Про¬ граммируемые БИС, получившие название микропроцессоров, представляют низший уровень в иерархии виртуальных машин (см. рис. 1.5), т. е. уровень реальной, или аппаратной, машины. С помощью микропроцессоров пользователи создают необходи¬ мые им виртуальные машины, заменяющие индивидуальные БИС. Хотя известно, что чем ближе виртуальная машина к ре¬ альной, тем она эффективнее, снижение уровня виртуальных машин, изготовленных разработчиками аппаратуры на основе микропроцессоров, практически невозможно, поскольку приво¬ дит к необходимости создания индивидуальных БИС. Аналогичная ситуация характерна и для экспертных систем. Специалисту в какой-либо предметной области для решения вполне определенной задачи необходима индивидуальная про¬ грамма, которой у него нет. Тогда ученые пошли по пути раз¬ работки инструментальных экспертных систем, допускающих настройку на решение конкретной задачи с помощью програм¬ мирования на языке эксперта. Следует отметить, что компиля¬ ция знаний, о которой говорилось выше, позволяет снизить уровень виртуальной машины, тем самым повысив ее эффек¬ тивность. Класс решаемых экспертом задач можно представить в виде графа. Язык эксперта позволяет эксперту описывать граф по кускам. Построение подграфов, необходимых для решения кон¬ кретной задачи, осуществляется экспертной системой автома¬ тически. ЭС как бы позволяет перейти от графов к систем^ про¬ дукций и решать (описывать) задачи в этой системе. Когда пра¬ вильность задания знаний эксперта проверена с помощью работы с ЭС и есть необходимость частого использования полу¬ ченной системы, то можно провести компиляцию знаний, т. е. получить эффективную реализацию полного графа класса ре¬ шаемых задач. Тем самым как бы происходит возврат от си¬ стемы продукций к графу, но на более высоком качественном уровне, т. е. на уровне машинной реализации графа.
2. РЕАЛИЗАЦИЯ ЭКСПЕРТНОЙ СИСТЕМЫ НА ЯЗЫКЕ ПАСКАЛЬ 2.1. КРАТКОЕ ОПИСАНИЕ ЯЗЫКА ПАСКАЛЬ Алгоритмический язык Паскаль был разработан Н. Виртом в 1971 г. [2, 3, 4]. Этот язык относится к процедурным языкам, отличающимся тем, что пользователь должен описать КАК ма¬ шина должна решать его задачу. Благодаря своим структурам (типам) данных и операторам, описывающим все виды вычисли¬ тельных процессов — линейный (составной оператор), ветвя¬ щийся (операторы IF и CASE) и циклический (операторы FOR, WHILE и REPEAT), Паскаль фактически стал языком публи¬ каций. В основе управляющей структуры Паскаля лежит последова¬ тельный запуск операторов. Кроме стандартных типов данных и стандартных действий Паскаль предоставляет пользователю возможность задавать свои типы данных и свои действия, т. е. процедуры и функции, которые допускают рекурсию. Словарь языка Паскаль состоит из основных символов, под¬ разделяемых на буквы, цифры и специальные символы: < буква >:: =|A|B|C|DIE|F|G|H|I|J|K|L|M|N|0|P|Q| R | S | Т | U | V | W | X | Y | Z <цифра > : : = 0|1|2|3|4|5|6|7|8|9 < специальный символ > :: = + | — | i> = id) mmm|: = н’I;I• гI (CASE | CONST | DIV | DO | DOWN TO |FUNCTION | GOTO | IF | IN | LABEL | MOD | NIL | NOT | OF | OR j | PACKED | PROCEDURE || PROGRAM | RECORD | REPEAT | SET| I THEN I TO I TYPE I UNTIL I VAR I WHILE I WITH. * |/| = I <| > I ОI <= I AND | ARRAY | BEGIN | I ELSE I END I FILE I FOR I Комментарии заключаются в скобки {} или (^с ^с). Структуру программы можно более точно определить с по¬ мощью синтаксических диаграмм, в которых прямоугольники содержат ссылки на другие синтаксические диаграммы. Кружок или овал содержат элемент, который должен встречаться в тек¬ сте непосредственно. В прил. 1 приводятся синтаксические диа¬ граммы, дающие полное описание языка. Так, структура про¬ граммы (рис. П.1.16, П.1.17) состоит из шести разделов, каждый из которых, кроме последнего, может быть пустым. Разделы должны обязательно следовать в таком порядке: раздел меток, раздел констант, раздел типов, раздел переменных, раздел про¬ цедур и функций, раздел операторов. 57
Определение констант вводит имя как синоним некоторой константы. Структура раздела CONST приведена на рис. П.1.16, синтаксис констант приведен на рис. П.1.5. Значения констант известны до выполнения программы и не могут меняться в теле программы. Использование имен констант делает программу более «чи¬ таемой» и способствует улучшению ее документируемое™. Кроме того, это позволяет программисту сгруппировать в начале про¬ граммы величины, характерные для данного примера: здесь они более заметны и их легче изменить (тем самым улучшается пере¬ носимость программ и их модульность). Определение типа данных задает множество значений, кото¬ рые может принимать переменная такого типа, а также опера¬ ции, которые могут с ней выполняться, и связывает сэтим типом некоторое имя. Структура раздела TYPE приведена на рис. П.1.16, синтаксис типов приведен на рис. П.1.12, П.1.13. Данные — есть общее понятие для всего того, с чем оперирует вычислительная машина. В аппаратуре все данные представля¬ ются как последовательности двоичных цифр (разрядов), та¬ кими же мыслятся данные и при программировании на уровне машинных команд. Языки высокого уровня позволяют абстраги¬ роваться от деталей представления данных главным образом за счет введения концепции типа данных. Любой тип данных определяет множество значений, прини¬ маемых переменной. Каждая встречающаяся в программе пере¬ менная должна быть сопоставлена с одним и только одним ти¬ пом. Хотя в Паскале типы данных очень разнообразны, тем не менее каждый из них строится в конце концов из простых типов. Простые типы данных Простые типы данных либо определяются программистом (в этом случае говорят об описанном скалярном типе), либо относятся к одному из четырех стандартных скалярных типов: целому, вещественному, булевскому или символьному. Скалярный тип определяет упорядоченное множество значе¬ ний, перечисляя имена, обозначающие эти значения. Его синтак¬ сис приведен во второй строке на рис. П.1.12. Скалярный тип имеет следующие свойства: его значения не могут делиться, образуя значения других типов; его значения отличны друг от друга и от значений любого другого типа; его значения упорядочены. Имена значений, перечисленные в описании скалярного типа, являются константами этого типа. Над переменными скалярного типа может быть произведена операция отношения ( = , <, >, < = , > = , <>, IN); упорядо¬ ченность значений определяется порядком перечисления кон¬ 58
стант. Порядковый номер первой из перечисленных констант — ноль. - Ко всем скалярным типам (за исключением вещественного) применимы следующие функции: SUCC — следующее (при перечислении) значение; PRED — предшествующее (при перечислении) значение. Введение скалярных типов расширяет возможность языка Паскаль в двух направлениях. 1. С определением подходящих типов появляется возмож¬ ность яснее и точнее ставить задачу, что в свою очередь облег¬ чает составление и чтение программы. 2. Определение таких типов дает возможность передавать компилятору больше информации о программе, вследствие чего компилятор осуществляет тщательные проверки синтаксических ошибок и формирует наиболее эффективную рабочую про¬ грамму. Булевский тип (BOOLEAN). Булевский тип предопределен следующим образом: TYPE BOOLEAN= (FALSE, TRUE), где TRUE и FALSE — имена. Существуют следующие логические операции, дающие бу¬ левское значение при применении их к булевским операндам: AND — логическое И; OR — логическое ИЛИ; NOT — логическое НЕ. Булевское значение дает и любая из операций отношения. Так как FALSE<TRUE, то любую из 16 булевских операций можно определить с помощью указанных логических операций и отношений. Например, если Р и Q — булевские переменные, то можно представить импликацию, как P< = Q, а исключающее ИЛИ, как P<>Q. Целый тип (INTEGER). Значения целого типа образуют под¬ множество целых чисел, зависящее от реализации. Для обозна¬ чения значений употребляются целые числа. Существует стандартное имя MAXINT, представляющее за¬ висящую от реализации константу. Если А и В — целые выра¬ жения, то правильное выполнение операции АЩЕ гарантиру¬ ется при выполнении условий ABS (АЩВ) ^MAXINT; ABS (A)<MAXINT ABS(B)^ ^MAXINT. При применении к целым операндам следующие операции дают целые значения: —умножение; DIV— деление и «отсечение», т. е. значение не округляется; MOD —AMOD В = А— ((ADIV В) >fcВ); Н сложение; вычитание. 59
Вещественный тип (REAL). Значения вещественного типа образуют зависящее от реализации конечное подмножество ве¬ щественных чисел. Сами значения обозначаются вещественными числами. Так как представление вещественных чисел приближенно, то и арифметические действия над ними выполняются прибли¬ женно. При условии, что хотя бы один из операндов вещественного типа (другой может быть и целым), следующие операции дают вещественный результат: — умножение; / — деление (целыми могут быть и оба операнда, но резуль¬ тат всегда вещественный); Н сложение; вычитание. Следует отметить, что хотя вещественный тип и относится к скалярным, тем не менее это верно не в любых контекстах. В частности, к вещественным аргументам нельзя применять функции PRED и SUCC. Нельзя использовать значения вещест¬ венного типа при индексации массивов, для управления в цикле с параметром и при определении базового типа множества. Символьный тип (CHAR). Значения символьного типа соот¬ ветствуют множеству символов, которыми оперирует конкретная машина. Для обозначения используются сами символы, заклю¬ ченные в кавычки. Является ли конкретная литера элементом этого множества, а также ее порядковый номер (если он существует) —зависит от реализации. Вне зависимости от реализации для символьного типа спра¬ ведливы следующие допущения. 1. Десятичные цифры упорядочены и непрерывны (не содер¬ жат пропусков), т. е. SUCC(‘0’) = 1, SUCC(Т) =2 и т. д. 2. Буквы упорядочены, т. е. ‘А^'В'^С’С.. но не обязательно непрерывны. 3. Множество символов включает символ пробела. Ограниченные типы. Тип можно определить, накладывая ограничения на уже определенный некоторый скалярный тип, который называют базовым скалярным типом. Ограничение определяется заданием диапазона: минимального и максималь¬ ного значений констант. Ограничение вещественного типа не до¬ пускается. Синтаксис ограниченного типа приведен в последней строке на рис. П.1.12. Семантически любой ограниченный тип можно подставлять в любых определениях вместо базового скалярного типа. Более того, именно базовый скалярный тип определяет допустимость всех операций над значениями ограниченного типа. Попытка присвоить переменной ограниченного типа., значение, не входящее 60
в необходимый диапазон, приведет к возникновению ошибки при счете. Важным аспектом программирования является проверки диапазонов. Введение ограничений перекладывает тяжесть этой проверки с программиста на компилятор. Составные типы данных Составные типы характеризуются структурой соответствую¬ щих объектов и типов (типами) компонент. Кроме того, опреде¬ ление составного типа может содержать указание на предпочти¬ тельное представление данных. Если оно содержит префикс PACKED, то это указывает компилятору, что необходимо эконо¬ мить память даже за счет эффективности обращения к данным и увеличения объема программы, порожденного дополнитель¬ ными командами доступа к компонентам данных. Регулярные типы. Регулярные типы характеризуют объекты (называемые массивами), содержащие фиксированное число* компонент одного типа, который называется типом компонент,, или базовым типом. Элементы массивов обозначаются с по¬ мощью индексов. Значения индексов относятся к типу, называе¬ мому типом индексов. Описание регулярного типа задает как: тип компонент, так и тип индексов. (Синтаксис описания приве¬ ден в третьей строке сверху на рис. П1.13). Если заданы N ти¬ пов индексов, то массив называют N-мерным, а компоненты обозначают с помощью N индексов. Комбинированные типы. Комбинированный тип характери¬ зует объекты (называемые записями), состоящие из фиксиро¬ ванного числа компонент, возможно, разных типов. Для каждой компоненты записи, называемой полем, в определении комбини¬ рованного типа задается его тип и имя. Областью действия этих имен полей является само определение комбинированного типа,, но они воспринимаются и внутри обозначения поля, относяще¬ гося к некоторой комбинированной переменной (записи) этого типа. Комбинированный тип может задавать несколько вариантов структуры. В этом случае можно выделить некоторое поле как: дискриминант (поле-признак). Его значение указывает, к ка¬ кому из вариантов относится в данный момент тип записи. Ва¬ рианты структуры идентифицируются метками вариантов, ко¬ торые представляют собой константы типа дискриминанта. Син¬ таксис описания приведен в нижней строке на рис. П.1.13 и на рис. П.1.14. Множественные типы. Множественный тип определяет мно¬ жество значений, которые представляют собой множество всех подмножеств базового типа, включая и пустое множество. Базо¬ вым типом может быть скалярный (кроме вещественного) или 61
ограниченный тип. Синтаксис описания приведен в предпослед¬ ней строке на рис. П.1.13. При реализации Паскаля размеры множеств могут быть ограничены, причем диапазон может ока¬ заться весьма небольшим. Множества строятся из своих элементов с помощью конст¬ руктора множества посредством перечисления через запятую элементов множества, т. е. выражений базового типа, которые заключаются в квадратные скобки [и]. Соответственно [] обозна¬ чает пустое множество. Синтаксис приведен в последней строке рис. П.1.7. Конструкция [M..N] обозначает множество всех элементов I базового типа, для которых выполняется условие Если M>N, то [M..N] обозначает пустое множество. Ко всем объектам, имеющим структуру множества, приме¬ нимы операции: Н объединение, ^ — пересечение, вычитание множеств (например, А—В обозначает мно¬ жество всех элементов А, не являющихся элементами В). К операндам-множествам применимы и операции отношения: = < > —проверка на равенство, неравенство; <=>= —проверка на включение; IN — проверка на принадлежность множеству. Второй операнд — множественного типа, первый—соответ¬ ствующего базового типа. Результат проверки — TRUE, если первый является элементом второго, иначе — FALSE. Действия с множествами не требуют слишком много вре¬ мени, и их можно использовать для исключения более сложных проверок. Например, вместо проверки IF(CH='A') OR (СН='.В') OR (СН='С') OR (CH='Zr) THEN S можно написать IF CH IN ['A' •.'C','Z'] THEN S Файловые типы. Определение файлового типа характеризует структуру, представляющую собой последовательность компо¬ нент одного типа. Сама последовательность устанавливает есте¬ ственный порядок компонент, и в любой момент доступна только одна компонента. Другие компоненты становятся доступными по мере продвижения по файлу. Число компонент, называемое длиной файла, в определении файлового типа не фиксируется. Эта особенность явно отличает понятие файла от понятия мас¬ 62
сива. Если файл не имеет компонент, то его называют пустым. Синтаксис описания приведен в третьей строке снизу на рис. П.1.13. Описание каждой переменной — файла F — автоматически вводит некоторую буферную переменную, обозначаемую Ff; она относится к типу компонент. Эту переменную можно рассматри¬ вать как некоторое окно, через которое можно либо посмотреть на существущие компоненты, либо добавить (записать) новые компоненты. Окно автоматически передвигается при некоторых из операций над файлами. Файлы с компонентами символьного типа — текстовые файлы — несколько особый случай, поскольку диапазон значе¬ ний компоненты считается расширенным за счет введения спе¬ циального маркера конца строки. Тип TEXT является стандарт¬ ным типом, предопределенным таким образом: TYPE TEXT = FILE OF CHAR. Ссылочные типы. Статической переменной (статически раз¬ мещенной) называется описанная где-либо в программе пере¬ менная; она обозначается с помощью соответствующего имени. Статической ее называют потому, что она существует, т. е. под нее выделена память на протяжении выполнения блока, в кото¬ ром она локализована. С другой стороны, переменную можно* создать и динамически (без какой-либо связи со статической структурой программы). Это делается с помощью стандартной процедуры NEW. Такие переменные называются динамическими. Динамическая переменная не указывается явно в описаниях переменных, и ее нельзя обозначить с помощью имени. Вместо этого при порождении динамической переменной создается ссы¬ лочное значение, представляющее не что иное, как адрес места в памяти, где находится вновь созданная переменная. Следова¬ тельно, ссылочный тип Р представляет собой неограниченное множество значений, ссылающихся на элементы заданного типа Т. Для ссылок не существует никаких операций, кроме сравне¬ ния на равенство. Синтаксис определения ссылочного типа при¬ веден во второй строке сверху на рис. П. 1.13. Ссылочное значение NIL принадлежит любому из ссылочных типов; оно вообще не указывает ни на какой элемент. Если Р — ссылочная переменная, связанная с типом Т с по¬ мощью описания VAR Р : fT, то Р —ссылка на переменную типа Т, Pf— обозначение самой этой переменной. Для того чтобы создать, сформировать такую переменную, используется стан¬ дартная процедура NEW. При обращении к NEW(P) формиру¬ ется переменная типа Т, и адрес ее присваивается Р. Ссылки являются простым механизмом, позволяющим стро¬ ить данные со сложной и меняющейся структурой. Если тип Т
характеризует запись со структурой, включающей одно или несколько полей типа |Т, то можно построить структуру, эквива¬ лентную произвольному конечному графу. В этом случае объекты типа Т представляют вершины, а ссылки — ребра. Описание и обозначение переменных Описание переменных состоит из списка имен, обозначающих новые переменные, за которым следует тип. Синтаксис приве¬ ден в четвертой строке сверху на рис. П.1.6. Описание переменной файла F с компонентами типа Т, кроме того, неявно описывает так называемую буферную переменную того же типа Т. Эта переменная обозначается через Ff и исполь¬ зуется либо для добавления компонент в файл при его формиро¬ вании, либо для доступа в файл при его чтении. Обозначение переменной относится или полностью ко всей переменной, или к компоненте переменной, или к переменной, на которую указывает ссылка. Синтаксис обозначений перемен¬ ных приведен на рис. П.1.16. Полная переменная обозначается с помощью своего имени. Компонента переменной обозначается с помощью переменной, за которой идет селектор, задающий саму компоненту. Вид селектора зависит от структуры переменной. Компонента Af-мерного массива обозначается с помощью пе¬ ременной, за которой следуют N индексных выражений. Типы индексных выражений должны соответствовать типам индексов, указанных в определении регулярного типа. Компоненты переменной-записи обозначаются с помощью са¬ мой переменной, за которой через точку следует имя компоненты поля. Если Р — переменная-ссылка, связанная с типом Т, то обо¬ значение Р относится именно к этой переменной, к ее ссылоч¬ ному значению, а обозначение Р| относится к переменной типа Т, на которую указывает эта ссылка. Выражения Выражения представляют собой конструкции, задающие пра¬ вила получения значений переменных и образования путем при¬ менения операций новых значений. Выражения состоят из опе¬ рандов, т. е. переменных и констант, операций и функций. Правила построения выражений устанавливают приоритет¬ ность операций, разбивая их на четыре класса. Операция NOT обладает наивысшим приоритетом, затем идут так называемые мультипликативные операции, следом — аддитивные и, наконец, •с наименьшим приоритетом — операции отношения. Последова¬ тельность операций одного приоритета выполняется слева на- 64
право. Правила приоритета зафиксированы в синтаксисе, приве¬ денном на рис. П.1.1—П.1.10. Использование обозначения функции задает активацию этой функции. Оно состоит из имени, обозначающего функцию, и списка фактических параметров. Параметры—это переменные, выражения, процедуры или функции; они подставляются вместо соответствующих формальных параметров. Стандартные функции. Стандартные функции предполага¬ ются предопределенными для каждой реализации языка Пас¬ каль. При реализации могут быть добавлены и дополнительные предопределенные функции. Ниже приводится список стандарт¬ ных функций и пояснения. Арифметические функции ABS(X) —вычисляет абсолютное значение X. Тип X должен быть REAL или INTEGER, тип результата — тот же. SQR(X)—вычисляет X2. Тип X должен быть REAL или INTEGER, тип результата — тот же. SIN(X) ) COS(X) ЕХР(Х) I тип X — REAL или INTEGER, тип результата — LN(X) REAL. SQRT(X) ARCTAN(X) j Предикаты ODD(X)—тип X должен быть INTEGER, результата — BOOLEAN. Если X — нечетное, то результат — TRUE и наобо¬ рот. EOF(F)—этот предикат указывает, находится ли файл F в «конечном» состоянии. EOLN(F) —указывает на конец строки в текстовом файле F. Функции преобразования TRUNC(X) —вещественное значение X «усекается» до его целой части. ROUND(X) —вещественный аргумент X округляется до бли¬ жайшего целого. ORD(X) — аргумент X должен быть скалярного (включая BOOLEAN и CHAR) типа, результат (целого типа) —порядко¬ вый номер значения X во множестве, определяемом типом аргу¬ мента X. CHR(X) —X должен быть типа INTEGER, а результат (типа CHAR) —символ, порядковый номер которого есть зна¬ чение X, если такой символ существует. 5 В. Э. Балтрашевич 65
Другие стандартные функции SUCC(X) —X — любого скалярного или ограниченного типа, а результат — значение, следующее за X (если оно существует). PRED(X) —X — любого скалярного или ограниченного типа, а результат — значение, предшествующее X (если оно суще* ствует). Операторы Основное в программе для вычислительной машины — вы* полняемые ею действия. Описывают эти действия операторы. Операторы можно помечать (метками) и ссылаться на них в операторах перехода (рис. П. 1.15). Операторы бывают простые и сложные. Простые операторы. Операторы, не содержащие в качестве составных частей другие операторы, называются простыми. Оператор присваивания предназначен для замены текущего значения переменной новым выражением. Синтаксис приведен в верхней строке на рис. П.1.15. Допустимо присваивание переменных любого типа, за исклю¬ чением файлов. Переменная (или функция) и выражение дол¬ жны быть идентичного типа, однако допускаются следующие исключения: переменная — вещественного типа, а выражение — целого или ограниченного целого типа; выражение — ограниченного типа по отношению к типу пе¬ ременной и наоборот. Оператор процедуры предназначен для выполнения про¬ цедуры, задаваемой ее именем. Такой оператор может содер¬ жать список фактических параметров, которыми заменяют соответствующие формальные параметры, определяемые в опи¬ сании процедуры. Соответствие устанавливается на основе ме¬ стоположения параметров в списках фактических и формальных параметров. Параметры бывают четырех видов: параметры-зна¬ чения, параметры-переменные, параметры-процедуры (фактиче¬ ский параметр — имя процедуры) и параметры-функции (фак¬ тический параметр —имя функции). В случае параметра-значения фактический параметр должен быть выражением (в простейшем виде — переменной). Соответ¬ ствующий формальный параметр представляет собой локаль¬ ную переменную вызываемой процедуры; этой переменной вука- честве начального присваивается текущее значение упомянутого выражения. В случае параметра-переменной фактический пара¬ метр должен быть переменной, а соответствующий формаль¬ ный— представляет эту фактическую переменную во все время выполнения процедуры. Если переменная является компонентой массива, то ее индекс вычисляется при обращении к процедуре. 66
Когда параметр представляет собой результат процедуры, он должен обязательно быть параметром-переменной. Предполагается, что стандартные процедуры как бы пред¬ описаны в любой из реализаций языка Паскаль. При реализа¬ ции можно добавлять и другие предописанные процедуры. По¬ скольку они, как и любые стандартные величины, считаются описанными в области действия, окружающей всю программу, то не возникает никаких неприятностей при переопределении этих же имен внутри программы. Ниже перечисляются с пояс¬ нениями стандартные процедуры языка. Процедуры работы с файлами PUT(F)—значение буферной переменной Ff добавляется к файлу F. Эффект определен, если только до выполнения пре¬ дикат EOF(F) имел значение TRUE. После выполнения EOF(F) остается TRUE, а значение Ff становится неопределенным. GET(F)—смещает положение файла к очередной компо¬ ненте и присваивает значение этой компоненты буферной пере¬ менной Ff. Если такой компоненты нет, то EOF(F) становится TRUE, а значение Ff неопределенно. Эффект определен, только если до выполнения EOF(F) = FALSE. RESET(F) —восстанавливает файл в начальное положение и присваивает буферной переменной Ff значение первого эле¬ мента F. Предикат EOF(F) становится FALSE, если F не пуст; иначе Ff неопределенно, a EOF(F) остается TRUE. REWRITE(F)—текущее значение файла уничтожается и можно формировать файл. Предикат EOF(F) становится рав¬ ным TRUE. Процедуры динамического размещения NEW(P)—размещает новую переменную V и присваивает ссылочной переменной Р ссылку на V. DISPOSE(Р) указывает, что память, занимаемая перемен¬ ной Pf, больше не нужна. Оператор перехода предназначен для указания того, что дальнейшая работа программы должна продолжаться с другого места, а именно с места, где находится соответствующая метка. Синтаксис оператора приведен в предпоследней строке на рис. П.1.15. С использованием меток связаны два ограничения: область действия метки — это процедура, внутри которой она определяется, поэтому переход внутрь процедуры невозможен; каждая метка должна быть задана в описании меток в заго¬ ловке той процедуры, где этой меткой маркируется некоторый оператор. Сложные операторы и вычислительные процессы. Сложные (структурированные) операторы представляют собой конструк¬ 5* 67
ции, включающие другие операторы; они выполняются либо последовательно (составной оператор), либо в зависимости от некоторых условий (выбирающие операторы), либо повторя¬ ются несколько раз (операторы цикла). Сложные операторы описывают вычислительные процессы. Вычислительный процесс называется линейным, если состав¬ ляющие его действия выполняются в порядке записи (последо¬ вательно). Линейный вычислительный процесс имеет один вход и один выход. Описывается линейный вычислительный процесс составным оператором, который указывает, что входящие в него операторы должны выполняться в том порядке, в каком они на¬ писаны. Служебные слова BEGIN и END выступают в качестве операторных скобок. Синтаксис оператора приведен в третьей строке сверху на рис. П.1.15. Обратите внимание, что «тело» любой программы есть один составной оператор. Точка с запятой в Паскале используется как разделитель между операторами, а не заканчивает оператор, т. е. не входит в оператор. Ветвящийся вычислительный процесс — это процесс, в кото¬ ром в зависимости от значения исходных данных или промежу¬ точных результатов реализуется одно из возможных и заранее известных направлений. Он имеет один вход и один выход и описывается условным оператором или оператором варианта. Синтаксис условного оператора приведен в четвертой строке сверху рис. П.1.15. Выражение между словами IF и THEN дол¬ жно относиться к булевскому типу. Условный оператор указывает, что оператор, стоящий за сло¬ вом THEN, нужно выполнять только в том случае, если условие (булевское выражение) имеет значение TRUE. Если значение FALSE, то либо не выполняется никакой оператор, либо выпол¬ няется оператор, следующий за словом ELSE. Синтаксис оператора варианта приведен в пятой строке сверху на рис. П.1.15. Оператор состоит из выражения (селек¬ тора) и списка операторов, каждый из которых помечен кон¬ стантой того же типа, что и селектор. Селектор должен быть скалярного, но не вещественного типа. Оператор варианта вы¬ бирает для исполнения оператор, метка которого равна теку¬ щему значению селектора. Если такая метка в списке не встре¬ чается, то действие оператора неопределенно. По окончании вы¬ полнения выбранного оператора управление передается в конец оператора варианта. Вычислительный процесс, в котором некоторая группа опера¬ торов повторяется многократно, называется циклическим вычис¬ лительным процессом. Существуют два вида циклических вычислительных процес¬ сов: с неизвестным числом повторений; с известным числом по¬ вторений. 68
У всех циклических вычислительных процессов один вход и один выход. Циклические вычислительные процессы описываются опера¬ торами цикла с пред-, постусловием или оператором цикла с па¬ раметром. Синтаксис оператора цикла с предусловием приведен в ше¬ стой строке сверху на рис. П.1.15. Управляющее повторени¬ ями выражение должно быть булевого типа. Оператор повто¬ ряется до тех пор, пока выражение не примет значение FALSE. Если оно имело такое значение уже в начале, то оператор во¬ обще не выполняется. Оператор должен изменять значения вы¬ ражения. Синтаксис оператора цикла с постусловием приведен в пятой строке снизу на рис. П.1.15. Управляющее повторениями выра¬ жение должно быть булевого типа. Последовательность опе¬ раторов между словами REPEAT и UNTIL повторяется (выпол¬ няется) несколько раз (по крайней мере один) до тех пор, пока выражение не примет значение TRUE. Слова REPEAT и UNTIL играют роль операторных скобок. Синтаксис оператора цикла с параметром приведен в четвер¬ той строке снизу на рис. П.1.15. Цикл с параметром задает по¬ рядок изменения переменной, называемой параметром цикла и управляющей повторениями некоторого оператора. Параметр цикла, начальное и конечное значения должны быть одного и того же скалярного типа (кроме вещественного) и не должны изменяться внутри цикла с параметром. Начальное и конечное значения вычисляются лишь единожды. Если при спецификации ТО (DOWNTO) начальное значение больше (меньше) конеч¬ ного значения, то цикл не выполняется. При нормальном выходе из цикла с параметром значение параметра остается неопреде¬ ленным. Оператор цикла с параметром вида FOR V: =Е1 ТО Е2 DO S эквивалентен следующей последовательности операторов IF Е1<Е2 THEN BEGIN V: =Е1; S; V: =SUCC(V); S; ...; V: =Е2; S END. Синтаксис оператора присоединения приведен в третьей строке снизу рис. П.1.15. Внутри оператора, входящего в состав оператора присоединения, компоненты (поля) переменных-запи¬ сей, определенных в заголовке оператора, можно обозначать, просто с помощью имен полей без предшествующего указания всей переменной записи. Фактически заголовок оператора от¬ крывает область действия, содержащую имена полей указанных переменных-записей, поэтому такие имена можно употреблять как имена переменных.
Действия, определяемые программистом Если программист не удовлетворен примитивными опера¬ циями, встроенными в язык (которым он пользуется), то он мо¬ жет расширить язык путем включения новых операций своей собственной конструкции. Средством для конструирования но¬ вых операций являются процедуры и функции. По мере прогресса в программировании программы стали создаваться методом последовательных уточнений. На каждом этапе программист разбивает задачу на некоторое число подза¬ дач, определяя тем самым некоторое количество отдельных про¬ грамм. Концепция процедур и функций позволяет выделить под¬ задачу как явную подпрограмму. Описание процедуры. Описание процедуры служит для выде¬ ления некоторой части программы и связывает с этой частью имя так, что ее можно активировать с помощью оператора про¬ цедуры. Синтаксис описания процедуры приведен в третьей и четвертой строках снизу на рис. П1.16 и на рис. П1.11. Параметры бывают параметрами-значениями, параметрами- переменными, параметрами-процедурами и параметрами-функ¬ циями. Процедуры и функции, выступающие в качестве пара¬ метров в других процедурах и функциях, должны иметь лишь п ар ам етр ы-зн ачения. Все имена, вводимые в разделах параметров, констант, ти¬ пов, переменных, процедур и функций, являются локальными по отношению к описанию процедуры, которое называется об¬ ластью действия этих имен. Вне этой области действия они не¬ известны. Что касается локальных переменных, то в начале раз¬ дела операторов их значения неопределенны. Раздел операторов задает алгоритмические действия, кото¬ рые нужно выполнять при активации процедуры с помощью оператора процедуры. Использование имени процедуры в операторе процедуры внутри ее описания предполагает рекурсивное выполнение про¬ цедуры. Описание функций. Описание функции предназначено для выделения части программы, вычисляющей некоторое ска¬ лярное значение или ссылку. Функция активируется при вы¬ зове ее, когда обозначение функции входит в какое-либо вы¬ ражение. Синтаксис описания функции приведен во второй и в четвер¬ той строках снизу на рис. П.1.16 и на рис. П.1.11. В заголовке функции определяются ее имя, формальные па¬ раметры и ее тип. Тип функции должен относиться к скалярному, ограничен¬ ному или ссылочному. Внутри описания функции должно быть по крайней мере одно присваивание значения имени функции. 70
Это присваивание определяет результат функции. Появление имени функции в обозначении функции внутри ее описания предполагает рекурсивное выполнение этой функции. Ввод и вывод В основу организации ввода — вывода положены текстовые файлы. Такие файлы передаются как параметры программе на Паскале, и в окружении этой программы они представляют не¬ которые вводные или выводные устройства вроде терминалов, устройств для чтения перфокарт или печатающих устройств. Для облегчения работы с текстовыми файлами кроме процедур GET и PUT вводятся дополнительные четыре стандартные про¬ цедуры: READ, WRITE, READLN и WRITELN. Синтаксис списков параметров этих процедур не стандартен, например, кроме всего прочего, здесь допускается переменное число параметров. Далее параметры должны быть не только символьного типа, но других типов. В этом случае при передаче данных происходит неявное их преобразование. Если первый па¬ раметр— файл, то чтение или запись связаны именно с этим файлом. Если это не так, то автоматически подразумевается, что чтение или запись относятся соответственно к стандартным файлам INPUT или OUTPUT. Эти файлы предописаны так VAR INPUT, OUTPUT : TEXT. Процедура READ. Для процедуры READ справедливы сле¬ дующие правила (F обозначает текстовый файл; VI,..., VN — переменные символьного, целого или ограниченного целого и ве¬ щественного типа). 1. READ (VI, ..., VN) эквивалентно READ(INPUT, VI, ... ..., VN). 2. READ (F, VI, ..., VN) эквивалентно READ (F, VI); ...; READ (F, VN). 3. Если V — переменная типа CHAR, READ (F, V) эквива¬ лентно V: = Ff; GET(F). 4. Если V —переменная целого (ограниченного целого) или вещественного типа, то предполагается, что READ(F, V) приво¬ дит к чтению из F последовательности символов, которые в со¬ ответствии с синтаксисом языка Паскаль образуют число, и присваиванию этого числа V. Предшествующие числу пробелы и маркеры строк пропускаются. Процедуру READ можно использовать для чтения информа¬ ции и из файлов, отличных от текстовых (зависит от реализа¬ ции). В этом случае READ(F, X) эквивалентно X: = Ff; GET(F). Процедура READLN. Процедура READLN используется для чтения и последующего пропуска информации до начала сле¬ дующей строки. 1. READLN (F) эквивалентно 71
WHILE NOT(EOLN(F)) DO GET(F); GET (F). 2. READLN(F, VI, ..VN) эквивалентно READ(F, VI,, VN); READLN(F). 3. READLN (VI, ..., VN) эквивалентно READLN (INPUT, VI,..VN). Процедура WRITE. Для процедуры WRITE справедливы сле¬ дующие правила (F обозначает текстовый файл; Р1,...., PN — так называемые параметры записи; Е — некоторое выражение; М и N — выражения целого типа). 1. WRITE (Р1, ..PN) эквивалентно WRITE (OUTPUT, PI,..., PN). 2. WRITE (F, PI, ..., PN) эквивалентно WRITE (F, PI); ...; WRITE (F,PN). 3. Параметры записи P могут быть E : M E :M: N E, где E представляет собой значение, которое нужно записать в файл F, а М и N — параметры размера поля. Если значение Е, представляющее собой число, символ, булевое значение или строку, требует для своего представления менее М символов, то добавляется такое число пробелов, чтобы можно было записать М символов. Если М опущено, то подра¬ зумевается некоторое зависящее от реализации значение. Пара¬ метр размера N употребляется только при Е вещественного типа для обозначения числа цифр после точки. 4. Если Е — массив (упакованный) символов, то в файл F записывается строка Е и перед ней ставится (в соответствии с М) несколько пробелов. Процедура WRITELN. Для процедуры справедливы следую¬ щие правила. 1. WRITELN (Р1, ..., PN) эквивалентно WRITELN (OUTPUT, PI, ...,PN). 2. WRITELN (F, PI,..., PN) эквивалентно WRITE (F, PI, ...,PN); WRITELN (F). 3. WRITELN(F) добавляет в файл F маркер строки. 2.2. ВЫБОР СТРУКТУР ДАННЫХ В начале реализации инструментальной экспертной системы необходимо выбрать структуры данных для внутреннего пред¬ ставления базы знаний, т. е. правил, подсказок и переводов, а также — для внутреннего представления базы данных, т. е. для стека целей и стека фактов. Рассмотрим требования к выбору структур данных для пред¬ ставления правил ЕСЛИ... ТО. Как уже отмечалось, в процессе логического вывода осущест¬ вляется поиск правила по атрибуту в части ТО правила, поэтому представляется целесообразным при представлении правил в па¬ 72
мяти отделить часть ЕСЛИ от части ТО. С другой стороны, часть ЕСЛИ может содержать переменное число элементов, со¬ стоящих из атрибута и его значения, вследствие этого удобно часть ЕСЛИ и часть ТО правил представлять в виде списков. В состав структуры элементов списка должны входить поля, со¬ ответствующие названию атрибута, его значению и номеру пра¬ вила, который, как указывалось выше, будет использован при организации объяснений. Для работы с этим списком необходимо реализовать следую¬ щие действия: добавление элементов в конец списка, при этом список будет рассматриваться как очередь; поиск в списке эле- Рис. 2.1. Структура данных для представления правил мента, содержащего требуемый атрибут; печать этого списка* необходимую для отладки программ и проверки правильности создания списка. В процессе объяснений работы экспертной системы требу¬ ется печать правила по его номеру. В целях упрощения поиска правила по его номеру для представления множества правил используется двумерный массив указателей на части ЕСЛИ и ТО соответственно. Это несколько ограничивает возможности системы, так как в Паскале массивы должны иметь фиксирован¬ ные размеры. Однако, во-первых, путем перетрансляции си¬ стемы с новой константой, определяющей длину массива, мо¬ жно расширить возможности системы, во-вторых, в качестве уп¬ ражнения можно представить множество правил в виде списка или файла. Таким образом, в рассматриваемой реализации правила ЕСЛИ. . . ТО будут представлены с помощью структур данных, приведенных на рис. 2.1. Для представления названия атрибута и его значения введем тип СЛОВО = PACKED ARRAY [1 ...ДЛИНА СЛОВА]ОЕ CHAR; где ДЛИНА_СЛОВА—константа, равная в рассматриваемой реализации 30. 73
Массив берется упакованным (PACKED), так как во всех реализациях Паскаля переменные такого типа должны просто распечатываться оператором печати. Проведем выбор структур данных для подсказок и перево¬ дов. Так как подсказки и переводы связаны с атрибутами, а чи¬ сло атрибутов заранее неизвестно, кроме того, для некоторых атрибутов подсказки или переводы могут отсутствовать, то це¬ лесообразно их заключить в список (список атрибутов). Эле¬ менты этого списка кроме поля связи списка и поля названия атрибута будут содержать указатели на соответствующие под¬ сказки и переводы. Поскольку тексты подсказок и переводов Рис. 2.2. Структура данных для представления списка атрибутов могут быть громоздкими, их удобно организовать как список строк, каждая из которых содержит не более 80 символов (ши¬ рина экрана дисплея) (рис. 2.2). Для работы с этим списком надо реализовать следующие действия: добавление элементов в начало списка, при этом спи¬ сок будет рассматриваться как стек; поиск в списке элемента, содержащего требуемый атрибут; печать списка. Что касается разработки структур данные для базы данных, то она фактически уже была проведена при рассмотрении орга¬ низации логического вывода и блока пояснений. База данных, как отмечалось, состоит из стека целей и стека фактов. Элемент стека фактов должен содержать название и значе¬ ние атрибута, а также номер правила, поместившего этот атри¬ бут в стек фактов для организации ответов на вопрос КАК. На¬ помним, что нулевой номер правила соответствует ответу поль¬ зователя. Элемент стека целей должен содержать название атрибута для организации логического вывода и номер правила, объявив¬ шего этот атрибут целью, для организации ответов на вопрос ПОЧЕМУ. Как показали проведенные исследования, для ана¬ лиза различных вариантов организации логического вывода в состав элементов стека целей целесообразно ввести поле зна¬ 74
чения атрибута. Кроме того, введение этого поля делает одно¬ типными структуры элементов в стеке целей, стеке фактов и в списке правил. Для работы со стеком необходимы следующие действия: до¬ бавление элемента в начало списка; удаление элемента из на¬ чала списка; печать элементов списка. Кроме того, стек фактов может выступать в роли простого списка, для которого нужно реализовать поиск элемента, содержащего заданный атрибут. В итоге были выбраны следующие типы данных: CONST ДЛИНА_СЛОВА = 30; ДЛИНА_СТРОКИ - 80; КОЛИ4ЕСТВО_ПРАВИЛ = 50; TYPE СЛОВО = PACKED ARRAY [ 1. . ДЛИНА_СЛОВА] OF CHAR; СТРОКА = PACKED ARRAY [1..ДЛИНА_СТРОКИ] OF CHAR; С4ЕТ4ИК = 0..КОЛИ4ЕСТВО_ПРАВИЛ; СПИСОК_СТРОК - ^ЗЛЕМЕНТ^СТРОК; ЗЛЕМЕНТ_СТРОК = RECORD ИНФОРМАЦИЯ: СТРОКА; СЛЕД_СТРОКА: СПИСОК_СТРОК; END; СПИСКИ = ~ЭЛЕМЕНТ; ЭЛЕМЕНТ = RECORD СВЯЗЬ: СПИСКИ; АТРИБУТ: СЛОВО; CASE ВИД: BOOLEAN OF TRUE: (ЗНА4ЕНИЕ: СЛОВО; НОМЕР_ПРАВИЛА: С4ЕТ4ИК); FALSE: (ПОДСКАЗКА, ПЕРЕВОД: СПИСОК_СТРОК); END; ТАБЛИЦА_ПРАВИЛ = ARRAY [С4ЕТ4ИК, 1..2] OF СПИСКИ; Уместен вопрос: на каком языке (русском или английском) писать идентификаторы? Так как книга рассчитана на широкий круг читателей и на машинах семейства СМ ЭВМ и ЕС ЭВМ имеются трансляторы с Паскаля, допускающие использование русских букв (кроме букв ч, ш, щ, э, ю), было решено использо¬ вать идентификаторы на русском языке. Для определения типов СЛОВО и СТРОКА используется ре¬ гулярный тип с элементами символьного типа. Для типа СЧЕТ¬ ЧИК используется ограниченный тип. Для определения типов СПИСОК СТРОК и СПИСКИ используется ссылочный тип. Тип ЭЛЕМЕНТ-СТРОК задается с помощью комбинированного типа, причем поле ИНФОРМАЦИЯ служит для записи строк подсказок или переводов. Поле СЛЕД-СТРОКА служит для связи элементов строк в список. Тип ЭЛЕМЕНТ определяется с помощью комбинированного типа с вариантами. Поле СВЯЗЬ служит для связи элементов в список. В поле АТРИБУТ записывается название атрибута. 75
Если ВИД имеет значение TRUE, то такой вариант элемента используется для представления правил и стеков целей и фак¬ тов. В поле ЗНАЧЕНИЕ записывается и хранится значение атрибута, а в поле НОМЕР- ПРАВИЛА хранится номер пра¬ вила, к которому относится атрибут. Если ВИД имеет значе¬ ние FALSE, то этот вариант элемента используется для органи¬ зации списка атрибутов. Поле ПОДСКАЗКА указывает на под¬ сказку, если она имеется, аналогично поле ПЕРЕВОД указы¬ вает на перевод. Тип ТАБЛИЦА-ПРАВИЛ образован с помощью регулярного типа, элементами которого являются элементы ссылочного типа. После выбора типа данных приведем реализацию действий, необходимых для работы с ними. Процедура ВВОД_СТРОКИ предназначена для ввода строки любой длины (в пределах допустимой) из текстового файла INP: PROCEDURE ВВОД_СТРОКИ(УАИ INP: TEXT? VAR А: СТРОКА)? VAR J: 0..ДЛИНА_СТРОКИ? BEGIN FOR J := 1 ТО ДЛИНА_СТРОКИ DO A[J] := ' '? J := 0? REPEAT J := J + 1? READ(INP, A[J])? UNTIL EOLN(INP) OR (J = ДЛИНА_СТРОКИ)? END (*ВВОД_СТРОКИ*)? Рекурсивная процедура ПОИСК обеспечивает поиск в списке элемента, содержащего заданный атрибут, и выдает в качестве результата указатель на этот элемент: PROCEDURE ПОИСК(VAR УКАЗАТЕЛЬ: СПИСКИ? СПИСОК: СПИСКИ? АТРИБУТ: СЛОВО)? {*ПОИСК УКАЗАТЕЛЯ НА ЭЛЕМЕНТ СПИСКА, СОДЕРЖАЩЕГО АТРИБУТ*) BEGIN IF СПИСОК = NIL THEN УКАЗАТЕЛЬ := NIL ELSE IF АТРИБУТ = СПИСОК~.АТРИБУТ THEN УКАЗАТЕЛЬ := СПИСОК ELSE ПОИСК(УКАЗАТЕЛЬ, СПИСОК*4.СВЯЗЬ, АТРИБУТ)? END (*ПОИСК*)? Следует подчеркнуть, что при обработке списков предпочте¬ ние отдается рекурсивным процедурам, так как их структура наиболее соответствует обрабатываемой структуре данных. Ре¬ курсивное определение списка выглядит так: список может быть либо пустым, либо состоять из узла, содержащего ссылку на список. Структура рекурсивной процедуры, обрабатывающей список, будет соответствовать определению списка в том смысле, 76
что она должна содержать условный оператор, одна ветвь кото¬ рого выполняет действия, соответствующие обработке пустого списка, в то время как другая обрабатывает информацию, со¬ держащуюся в одиночном узле, а для обработки оставшейся ча¬ сти списка процедура рекурсивно обращается к самой себе. Процедура ЗАПИСЬ_В_СТЕК служит для записи элементов списка, содержащего атрибут, его значение и номер правила, к которому относится атрибут, либо в стек целей, либо в стек фактов: PROCEDURE 3АПИСЬ_В__СТЕК(VAR СПИСОК: СПИСКИ; АТРИБУТ; ЗНА4ЕНИЕ: СЛОВО; НОМЕР: С4ЕТ4ИК); VAR Р: СПИСКИ; BEGIN NEW(P); Р".ВИД := TRUE; Р".АТРИБУТ := АТРИБУТ; Р" .ЗНА4ЕНИЕ := ЗНА4ЕНИЕ; Р" .НОМЕР_ПРАВИЛА := НОМЕР; Р".СВЯЗЬ := СПИСОК; СПИСОК := Р; END (*ЗАПИСЬ_В_СТЕК*); Процедура ВЫТАЛКИВАНИЕ-ИЗ-СТЕКА имеет вид PROCEDURE ВЫТАЛКИВАНИЕ_ИЗ_СТЕКА(VAR СПИСОК: СПИСКИ); BEGIN IF СПИСОК <> NIL THEN СПИСОК := СПИСОК".СВЯЗЬ ELSE BEGIN WRITELN('ЧТЕНИЕ ИЗ ПУСТОГО СТЕКА'); GOTO 1; END; END (*ВЫТАЛ КИВАНИЕ__ИЗ_СТЕ КА*); Рекурсивная процедура ДОБАВЛЕНИЕ производит добавле¬ ние в конец списка части правила (или ЕСЛИ, или ТО) эле¬ мента, содержащего атрибут, его значение и номер правила: PROCEDURE ДОБАВЛЕНИЕ(VAR СПИСОК: СПИСКИ; АТРИБУТ, ЗНА4ЕНИЕ: СЛОВО; НОМЕР: С4ЕТ4ИК); (*ДОБАВЛЕНИЕ В КОНЕЦ СПИСКА ПРАВИЛ*) BEGIN IF СПИСОК = NIL THEN BEGIN NEW(СПИСОК); СПИСОК".ВИД := TRUE; СПИСОК".АТРИБУТ := АТРИБУТ; СПИСОК".ЗНА4ЕНИЕ := ЗНА4ЕНИЕ; СПИСОК".НОМЕР_ПРАВИЛА := НОМЕР; СПИСОК".СВЯЗЬ := NIL; END ELSE ДОБАВЛЕНИЕ(СПИСОК".СВЯЗЬ, АТРИБУТ, ЗНА4ЕНИЕ, НОМЕР); END (*ДОБАВЛЕНИЕ*); 77
Процедура ЗАПИСЬ-АТРИБУТА производит добавление в начало списка атрибутов элемента, содержащего заданный атрибут: PROCEDURE ЗАПИСЬ_АТРИБУТА(VAR СПИСОК: СПИСКИ; АТРИБУТ: СЛОВО); (*ЗАПИСЬ В НАЧАЛО СПИСКА АТРИБУТОВ*) VAR Р: СПИСКИ; BEGIN NEW(Р); Р".ВИД := FALSE; Р".АТРИБУТ := АТРИБУТ; Р".ПОДСКАЗКА := NIL; Р".ПЕРЕВОД ;= NIL; Р".СВЯЗЬ := СПИСОК; СПИСОК := Р; END (*ЗАПИСЬ АТРИБУТА* ); Печать списка в текстовый файл OUT производится рекур¬ сивной процедурой ПЕЧАТЬ-СПИСКА: PROCEDURE ПЕ4АТЬ_СПИСКА(VAR OUT: TEXT; СПИСОК: СПИСКИ); BEGIN IF СПИСОК <> NIL THEN BEGIN WITH СПИСОК" DO CASE ВИД OF TRUE: WRITELN(OUT, АТРИБУТ, ЗНА4ЕНИЕ, ' (', HOMEР_ПРАВИЛА: 3, ')'); FALSE: BEGIN WRITELN(OUT, 'АТРИБУТ ', АТРИБУТ); WRITELN(OUT, 'ПЕРЕВОД: '); IF ПЕРЕВОД <> NIL THEN WRITELN(OUT, ПЕРЕВОД" .ИНФОРМАЦИЯ); WRITELN(OUT, 'ПОДСКАЗКА: '); IF ПОДСКАЗКА <> NIL THEN WRITELN(OUT, ПОДСКАЗКА".ИНФОРМАЦИЯ); END; END; ПЕ4АТЬ_СПИСКА(OUT, СПИСОК".СВЯЗЬ); END; END (*ПЕ4АТЬ_СПИСКА*); Следует отметить, что возможность использования в Паскале типов данных, определяемых программистом, и соответствующих им процедур обработки, также определяемых программистом, позволяет на уровне основной программы не заботиться о дета¬ лях представления структур данных и решать задачу на нужном уровне абстракции. 78
2.3. РЕАЛИЗАЦИЯ ЯЗЫКА ЭКСПЕРТА В п.1.2 были приведены синтаксические диаграммы языка абстрактного эксперта и правила перехода от диаграмм к про¬ граммам. Рассмотрим ограничения, накладываемые в реализации на Паскале. Поскольку для организации слов и строк, соответствующих лексеме и тексту на диаграммах (см. рис. 1.6), используются массивы фиксированной длины, то число символов в слове и в строке должно быть не больше 30 и 80 соответственно. С другой строны, в Паскале очень удобно обрабатывать оди¬ ночные символы, поэтому было решено несколько изменить синтаксис языка эксперта, чтобы не загромождать тексты про¬ цедур. Так, вместо ЕСЛИ используется символ вместо символа И — символ &, вместо ТО — символ:. Признаком начала подсказок является символ #, а призна¬ ком начала перевода — символ %. Перед дальнейшим чтением читателю рекомендуется нарисо¬ вать откорректированные синтаксические диаграммы языка эксперта. Будем считать, что исходные данные для компилятора, т. е. внешнее представление знаний (программа на языке конкрет¬ ного эксперта), содержатся в текстовом файле INP. В резуль¬ тате работы компилятора должны быть получены МАССИВ- ПРАВИЛ, содержащий указатели на части ЕСЛИ и ТО соот¬ ветствующих правил, и СПИСОК-АТРИБУТОВ, содержащий атрибуты и соответствующие им подсказки и переводы. Иными словами, на вход компилятора подается программа на языке конкретного эксперта, а на выходе компилятора получают внут¬ реннее представление программы. Для ввода лексем предназначена процедура ВВОД-СЛОВА, которая вводит слово А любой длины из текстового файла INP, при этом первые пробелы пропускаются. Выражение INPf = ’—’ означает «заглядывание» (без ввода) на один символ вперед и проверку, не является ли этот символ тире: PROCEDURE ВВОД__СЛОВА(VAR INP: TEXT; VAR А: СЛОВО)? VAR J: 0..ДЛИНА_СЛОВА; BEGIN FOR J := 1 ТО ДЛИНА_СЛОВА DO A[J] := ' WHILE INP~ = 9 9 DO GET(INP); J := 0; REPEAT J := J + 1; READ(INP, A[J])? UNTIL EOLN(INP) OR (J = ДЛИНА СЛОВА) OR (INP~ END (*ВВОД_СЛОВА*); 79
Процедура ВВОД-СЛОВА используется также при реали¬ зации логического вывода для ввода ответа пользователя. Если в предложениях входного языка содержится синтакси¬ ческая ошибка, то процедура СБОЙ выводит ожидаемый сим¬ вол и ошибочный символ, а также прерывает работу системы, выходя на конец программы: ч • PROCEDURE СБОЙ(С1, С2: CHAR); BEGIN WRITE('ОШИБКА: ВМЕСТО СИМВОЛА С1: 2); WRITELN(' ‘ ВВЕДЕН СИМВОЛ ', С2); GOTO 1; END (*СБОИ*); Для того чтобы не загромождать тексты процедур, в данной реализации компилятора мы не будем выявлять все синтаксиче¬ ские ошибки в тексте программы на языке эксперта. В тексте же компилятора, приведенном в программе из прил. 2, реали¬ зуем выявление большинства возможных ошибок в исходной для компилятора программе. Напомним, что при реализации синтаксических диаграмм по методу рекурсивного спуска нужно вместо прямоугольников син¬ таксических диаграмм подставлять соответствующие процедуры (см. п. 1.2). Рассмотрим процедуру ПОДСКАЗКА и соответствующую ей синтаксическую диаграмму. PROCEDURE ПОДСКАЗКА; VAR СИМВОЛ: CHAR; АТРИБУТ: СЛОВО; УКАЗАТЕЛЬ: СПИСКИ; Р: СПИСОК_СТРОК; BEGIN READ(INP, СИМВОЛ); ВВОД_СЛОВА(INP, АТРИБУТ); READLN(INP); NEW (Р); ВВОД_СТРОКИ(INP, Р~.ИНФОРМАЦИЯ); READLN(INP); ПОИСК(УКАЗАТЕЛЬ, СПИСОК_АТРИБУТОВ, АТРИБУТ); IF УКАЗАТЕЛЬ = NIL THEN BEGIN ЗАПИСЬ_АТРИБУТА(СПИСОК_АТРИБУТОВ, АТРИБУТ); УКАЗАТЕЛЬ := СПИСОК_АТРИБУТОВ; END; УКАЗАТЕЛЬ~.ПОДСКАЗКА := Р; END (*ПОДСКАЗКА*); Процедура ПОДСКАЗКА должна в исходном файле выявить символ начала подсказки (#), ввести атрибут и со следующей строки исходного файла ввести значение подсказки. Как уже указывалось, ввод атрибута осуществляется процедурой ВВОД- СЛОВА, а ввод текста подсказки — процедурой ВВОД-СТРО¬ КИ (см. п. 2.2). Эти действия связаны с синтаксисом подсказки, семантика же ее сводится к добавлению введенной подсказки 80
к соответствующему атрибуту в СПИСКЕ-АТРИБУТОВ. Если: же этот атрибут еще отсутствует в списке, то процедура ПОД¬ СКАЗКА проводит добавление атрибута в список, а затем под¬ соединяет к нему введенную подсказку. Как видно из приведен¬ ной реализации, текст подсказки может занимать только одну строку. Аналогично организована процедура ПЕРЕВОД, которая вы¬ являет в исходном файле символ начала перевода (%), вводит атрибут и со следующей строки вводит текст перевода, который подсоединяется к соответствующему атрибуту СПИСКА-АТРИ- БУТОВ. Отличие от процедуры ПОДСКАЗКА состоит в замене последней строки на строку УКАЗАТЕЛЬ!. ПЕРЕВОД: = Р. Перейдем к процедуре ПРАВИЛО, реализующей соответ¬ ствующую синтаксическую диаграмму. В качестве внутренних процедур она использует процедуры ВВОД-ЦЕЛОГО, ВЫРА¬ ЖЕНИЕ и УСЛОВИЕ. Процедура ВВОД ЦЕЛОГО предназначена для ввода но¬ мера правила и осуществляет посимвольный ввод цифр номера и компоновку из них числа, являющегося значением номера: PROCEDURE ВВОД_ЦЕЛОГО(VAR INPrTEXT; VAR НОМЕР:С4ЕТ4ИК); VAR I, J: С4ЕТ4ИК; BEGIN I := 0? READ(INP, СИМВОЛ); WHILE СИМВОЛ IN [ ' 0 ' . . ' 9 ' ] DO BEGIN J := ОRD(СИМВОЛ) - ORD('O'); I := 10 * I + J; READ(INP, СИМВОЛ); END; НОМЕР := I; END (*ВВОД_ЦЕЛОГО*); Процедура ВЫРАЖЕНИЕ реализует соответствующую син¬ таксическую диаграмму PROCEDURE ВЫРАЖЕНИЕ(VAR АТРИБУТ, ЗНА4ЕНИЕ: СЛОВО); VAR СИМВОЛ: CHAR; BEGIN ВВОД_СЛОВА(INP, АТРИБУТ); READ(INP, СИМВОЛ); IF СИМВОЛ <> THEN СБОЙ,''-', СИМВОЛ); ВВОД__СЛОВА( INP, ЗНА4ЕНИЕ) ; END (* ВЫРАЖЕНИЕ *); * Процедура УСЛОВИЕ также реализует соответствующую синтаксическую диаграмму. Ее семантика заключается в добав- 6 В. Э. Балтрашевич 81
лении введенных выражений в конец списка части ЕСЛИ пра¬ вила с соответствующим номером: PROCEDURE УСЛОВИЕ; VAR АТРИБУТ, ЗНА4ЕНИЕ: СЛОВО; BEGIN REPEAT ВЫРАЖЕНИЕ(АТРИБУТ, ЗНА4ЕНИЕ); READLN(INP); ДОБАВЛЕНИЕ(МАССИВ_ПРАВИЛ[НОМЕР, 1J, АТРИБУТ, ЗНА4ЕНИЕ, НОМЕ Р); READ(INP, СИМВОЛ); UNTIL СИМВОЛ <> END (‘УСЛОВИЕ*); Теперь можно полностью описать процедуру ПРАВИЛО: PROCEDURE ПРАВИЛО; VAR СИМВОЛ:CHAR; НОМЕР: С4ЕТ4ИК; АТРИБУТ, ЗНА4ЕНИЕ: СЛОВО; PROCEDURE ВВОД_ЦЕЛОГО(VAR INP: TEXT; VAR НОМЕР: С4ЕТ4ИК); (‘ОПИСАНИЕ СМ. П.2.3*) PROCEDURE ВЫРАЖЕНИЕ(VAR АТРИБУТ, ЗНА4ЕНИЕ: СЛОВО); (‘ОПИСАНИЕ СМ. П.2.3*) PROCEDURE ДОБАВЛЕНИЕ(VAR СПИСОк: СПИСКИ; АТРИБУТ, ЗНА4ЕНИЕ: СЛОВО; НОМЕР: С4ЕТ4ИК); (‘ОПИСАНИЕ СМ. П.2.2*) PROCEDURE УСЛОВИЕ;(‘ОПИСАНИЕ СМ. П.2.3*) BEGIN (‘ПРАВИЛО*) ВВОД_ЦЕЛОГО(INP, НОМЕР); IF СИМВОЛ = '*' THEN УСЛОВИЕ; IF СИМВОЛ <> THEN СБОЙ(':', СИМВОЛ); ВЫРАЖЕНИЕ(АТРИБУТ, ЗНА4 ЕНИЕ); ДОБАВЛЕНИЕ(МАССИВ_ПРАВИЛ[НОМЕР, 2], АТРИБУТ, ЗНА4ЕНИЕ, НОМЕР); READLN(INP); END (‘ПРАВИЛО*); Вместо слов (>[с описание см. п. .. .>[с) нужно подставить со¬ ответствующее описание процедуры или слово EXTERNAL, если в используемой версии транслятора с Паскаля возможна раз¬ дельная компиляция и соответствующие процедуры входят во внешнюю библиотеку процедур. Процедура ПРАВИЛО закан¬ чивает формирование внутреннего представления правила фор¬ мированием части ТО правила с помощью процедуры ДОБАВ¬ ЛЕНИЕ (п. 2.2). Процедура, реализующая синтаксическую диаграмму для процедуры ПРЕДЛОЖЕНИЕ, принимает вид 82
PROCEDURE ПРЕДЛОЖЕНИЕ(VAR INPs TEXT; VAR МАССИВ_ПРАВИЛ: ТАБЛИЦА_ПРАВИЛ; VAR СПИСОК_АТРИБУТОВ: СПИСКИ); VAR СИМВОЛ: CHAR; PROCEDURE ВВОД__СТРОКИ(VAR INP: TEXT; VAR А: СТРОКА); (*ОПИСАНИЕ CM. П.2.2*) PROCEDURE ПОИСК(VAR УКАЗАТЕЛЬ: СПИСКИ;СПИСОК: СПИСКИ; АТРИБУТ: СЛОВО); (*ОПИСАНИЕ СМ. П.2.2*) PROCEDURE ЗАПИСЬ_АТРИБУТА(VAR СПИСОК: СПИСКИ; АТРИБУТ: СЛОВО); (*ОПИСАНИЕ СМ. П.2.2*) PROCEDURE ВВОД_СЛОВА(VAR INP: TEXT; VAR А: СЛОВО); (‘ОПИСАНИЕ СМ. П.2.3*) PROCEDURE СБОЙ(Cl, С2: CHAR);(‘ОПИСАНИЕ СМ. П.2.3*) PROCEDURE ПОДСКАЗКА; (‘ОПИСАНИЕ СМ. П.2.3*) PROCEDURE ПЕРЕВОД; (‘ОПИСАНИЕ СМ. П.2.3*) PROCEDURE ПРАВИЛО; (‘ОПИСАНИЕ СМ. П.2.3*) BEGIN (‘ПРЕДЛОЖЕНИЕ*) СИМВОЛ := 1ЫРЛ; IF СИМВОЛ IN ['0'..'9'] THEN ПРАВИЛО ELSE IF СИМВОЛ = '#' THEN ПОДСКАЗКА ELSE IF СИМВОЛ = '%' THEN ПЕРЕВОД ELSE СБОЙ(' 1 ', СИМВОЛ); END (‘ПРЕДЛОЖЕНИЕ*); Если первый символ предложения во входном файле явля¬ ется неправильным, то процедура ПРЕДЛОЖЕНИЕ с помощью процедуры СБОЙ выдает сообщение о том, что вместо символа! (так обозначается этот тип ошибок) введен символ, значение которого будет напечатано. Процедура КОМПИЛЯЦИЯ реализует синтаксическую ди¬ аграмму для программы на языке эксперта: PROCEDURE КОМПИЛЯЦИЯ(VAR INP: TEXT; VAR МАССИВ_ПРАВИЛ: ТАБЛИЦА_ПРАВИЛ; VAR СПИСОКАТРИБУТОВ: СПИСКИ); VAR I: С4ЕТ4ИК; PROCEDURE ПРЕДЛОЖЕНИЕ(VAR INP: TEXT; VAR МАССИВ_ПРАВИЛ: ТАБЛИЦА_ПРАВИЛ VAR СПИСОК_АТРИБУТОВ: СПИСКИ); (♦ОПИСАНИЕ СМ. П.2.3*) BEGIN (‘КОМПИЛЯЦИЯ*) FOR I := 1 ТО КОЛИ4ЕСТВО_ПРАВИЛ DO BEGIN МАССИВ_ПРАВИЛ[I, 1] := NIL; МАССИВПРАВИЛ[I, 2] := NIL; END; СПИСОК_АТРИБУТОВ := NIL; WHILE NOT EOF(INP) DO ПРЕДЛОЖЕНИЕ(INP, МАССИВ_ПРАВИЛ, СПИСОК_АТРИБУТОВ); CLOSE (I'TP) ; END (‘КОМПИЛЯЦИЯ*); 6* 83
Реализация компилятора завершена. Чтобы быть уверенным в его работоспособности, необходимо провести испытания. Так как в результате работы процедуры КОМПИЛЯЦИЯ, обраба¬ тывающей программу на языке эксперта из входного файла INP, должны быть построены СПИСОК-АТРИБУТОВ и МАС¬ СИВ-ПРАВИЛ с указателями на списки, соответствующие ча¬ стям ЕСЛИ и ТО правил, то результатом испытания компиля¬ тора можно считать печать содержимого этих списков и сравне¬ ние его с содержимым файла INP. Для проведения испытаний потребуется вспомогательная процедура ПЕЧАТЬ-СПИСКА (см. п. 2.2). Программа проведения испытаний имеет вид PROGRAM ИСПЫТАНИЕ1(INPUT,OUTPUT); (*ИСПЫТАНИЕ КОМПИЛЯТОРА*) LABEL 1; CONST (*СМ. П.2.2*) TYPE (*СМ. П.2.2*) VAR МАССИВ_ПРАВИЛ:ТАБЛИЦА_ПРАВИЛ; СПИСОК_АТРИБУТОВ:СПИСКИ; INP,OUT:TEXT? I :С4ЕТ4ИК; PROCEDURE КОМПИЛЯЦИЯ(VAR INP:TEXT; VAR МАССИВ_ПРАВИЛ:ТАБЛИЦА_ПРАВИЛ; VAR СПИСОК_АТРИБУТОВ:СПИСКИ); (‘ОПИСАНИЕ СМ. П.2.3*) PROCEDURE ПЕ4АТЬ_СПИСКА(VAR OUT:TEXT; СПИСОК:СПИСКИ); (‘ОПИСАНИЕ СМ. П.2.2*) BEGIN (‘ИСПЫТАНИЕ1*) RESET(INP, 'INP'); КОМПИЛЯЦИЯ(INP, MACСИВ_ПРАВИЛ, СПИСОК_АТРИБУТОВ); REWRITE(OUT, 'OUT'); WRITELN(OUT, 'СПИСОК_АТРИБУТОВ:'); ПЕ4АТЬ_СПИСКА(OUT, СПИСОК_АТРИБУТОВ); WRITELN(OUT); WRITELN(OUT, 'СПИСОК_ПРАВИЛ:'); FOR I := 1 TO КОЛИ4 ЕСТВО_ПРАВИЛ DO BEGIN WRITE(OUT, 'ЕСЛИ '); ПЕ4АТЬ_СПИСКА(OUT, МАССИВ_ПРАВИЛ[I, 1]); WRITE(OUT, 'TO '); ПЕ4АТЬ_СПИСКА(OUT, МАССИВ_ПРАВИЛ[I, 2]); END; CLOSE(OUT); 1: WRITELN('КОНЕЦ ИСПЫТАНИЙ КОМПИЛЯТОРА'); END (* ИСПЫТАНИЕ1*). При этом предполагается, что внешнее описание знаний под¬ готовлено во внешнем глобальном файле INP. Во внешнем файле OUT распечатываются все списки. Этот файл можно рас¬ 84
печатать с помощью сервисных программ операционной системы. В этой и дальнейших реализациях будем предполагать, что файл INPUT соответствует клавиатуре дисплея, а файл OUTPUT соответствует экрану дисплея. Ниже приведена программа интерпретации предложений типа правило (т. е. часть программы из п. 1.1) на языке эксперта с учетом ограничений приведенной реализации. Текст этой про¬ граммы можно использовать в качестве исходных данных при проверке компилятора: 1*ЧИСЛО-ДА <ВК>&СЛОВО-ТО <ВК>:ПРЕДЛОЖЕНИЕ-ПРАВИЛО 2*ЧИСЛО-ДА <ВК>&СЛОВО-ЕСЛИ <ВК>&СЛЕД_СЛОВО-ТО 8ПРЕДЛОЖЕНИЕ-ПРАВИЛО 3*ЧИСЛО-ДА <ВК>&СЛОВО-ЕСЛИ <ВК>&СЛЕД_СЛОВО-И &ТО-ДА <ВК>:ПРЕДЛОЖЕНИЕ-ПРАВИЛО 4*ЧИСЛО-ДА <ВК>&СЛОВО-ЕСЛИ <ВК>&СЛЕД_СЛОВО-И &ТО-НЕТ <ВК>:ПРЕДЛОЖЕНИЕ-ОШИБОЧНОЕ_ПРАВИЛО #ЧИСЛО <ВК> ПРЕДЛОЖЕНИЕ НАЧИНАЕТСЯ С ЧИСЛА?(ДА/НЕТ) 4СЛ0В0 <ВК> С КАКОГО СЛОВА НАЧИНАЕТСЯ ПРЕДЛОЖЕНИЕ? #СЛЕД_СЛОВО С КАКОГО СЛОВА НАЧИНАЕТСЯ СЛЕДУЮЩАЯ СТРОКА? #ТО <ВК> ИМЕЕТСЯ СТРОКА НАЧИНАЮЩАЯСЯ С ТО?(ДА/НЕТ) %ЧИСЛО <ВК> ИМЕЕТСЯ ЧИСЛО %СЛЕД_СЛОВО <ВК> СЛЕДУЮЩАЯ СТРОКА НАЧИНАЕТСЯ СО СЛОВА %СЛОВО <ВК> СЛОВО ИМЕЕТ ЗНАЧЕНИЕ %ТО <ВК> ИМЕЕТСЯ СТРОКА НАЧИНАЮЩАЯСЯ С ТО %ПРЕДЛОЖЕНИЕ <ВК> ТИП ПРЕДЛОЖЕНИЯ Таким образом, мы программно реализовали язык абстракт¬ ного эксперта, являющийся метаязыком, описывающим язык конкретного эксперта. Предложения языка конкретного экс¬ перта преобразуются разработанным компилятором языка абст¬ рактного эксперта в структуры данных. Как уже отмечалось, в качестве второй универсальной части получаемого таблично¬ управляемого транслятора можно рассматривать блок логиче¬ ского вывода. Предложениями для языка конкретного эксперта будут являться ответы пользователя на вопросы системы. 2.4. РЕАЛИЗАЦИЯ ЛОГИЧЕСКОГО ВЫВОДА Реализация экспертной системы на Паскале соответствует представлению задач в пространстве состояний, поэтому блок логического вывода экспертной системы фактически реализует поиск решения в пространстве состояний. Состояния задаются стеком фактов, стеком целей и списком разрешенных правил. Процедура ВЫВОД использует МАССИВ-ПРАВИЛ и СПИСОК-АТРИБУТОВ, сформированные с помощью компиля¬ тора (см. п. 2.3). Кроме того, при реализации логического вы¬ вода нужны дополнительные типы данных. 85
Тип АКТИВНЫЕ нужен для фиксации разрешенных, т. е. активных (TRUE) и запрещенных для использования правил '(FALSE). Тип ЗНАЧЕНИЕ используется для оценки значения правила Т — истина, F — ложь, U — не опредлено): PROCEDURE ВЫВОД(VAR МАССИВ_ПРАВИЛ: ТАБЛИЦАПРАВИЛ; VAR СПИСОК_АТРИБУТОВ: СПИСКИ)? ТУРЕ АКТИВНЫЕ = ARRAY [1..КОЛИ4ЕСТВО_ПРАВИЛ] OF BOOLEAN; ЗНА4ЕНИЕ = (Т, F, U); VAR ОСНОВНАЯ_ЦЕЛЬ: СЛОВО; АКТИВНЫЕ_ПРАВИЛА: АКТИВНЫЕ? СТЕК_Ф АКТОВ, СТЕК_ЦЕЛЕЙ, КОПИЯ_СТЕКА_ЦЕЛЕЙг СПИСКИ; УКАЗАТЕЛЬ, УКАЗАТЕЛЫ: СПИСКИ; ГОТОВНОСТЬ: BOOLEAN; I: С4ЕТ4ИК; (* ОПИСАНИЕ ПРОЦЕДУР И ФУНКЦИЙ: ПОИСК, ЗАПИСЬ_В_СТЕК, ВЫТАЛКИВАНИЕ_ИЗ_СТЕКА, ВВОД_СЛОВА, ПОЛУ4ИТЬ_ОСНОВНАЯ_ЦЕЛЬ, ПОИСК_ПРАВИЛА, ЗНА4ЕНИЕ_ПРАВИЛА ПРАВИЛО_ИСТИННО, ЗАП0МНИТЬ_ЦЕЛЬ, П0ИСК_П0ДСКАЗКИ, ПОЛУ4ИТЬ_ОТВЕТ, ПРОВЕРКА, ПЕ4АТЬ_ЗНА4ЕНИЯ_ЦЕЛИ *) BEGIN (*ВЫВОД*) FOR I := 1 ТО КОЛИ4 ЕСТВО_ПРАВИЛ DO АКТИВНЫЕ_ПРАВИЛА[I] := TRUE; СТЕК_ЦЕЛЕЙ := NIL; СТЕК_ФАКТОВ := NIL; ПОЛУ4 ИТЬ_ОСНОВНАЯ_ЦЕЛЬ(ОСНОВНАЯ_ЦЕЛЬ, СТЕК_ЦЕЛЕЙ)? ГОТОВНОСТЬ := FALSE; WHILE NOT ГОТОВНОСТЬ DO IF ПОИСК_ПРАВИЛА(МАССИВ_ПРАВИЛ, СТЕК_ЦЕЛЕЙЛ.АТРИБУТ, АКТИВНЫЕ_ПРАВИЛА, УКАЗАТЕЛЬ) THEN CASE ЗНА4 ЕНИЕ ПРАВИЛА(УКАЗАТЕЛЬ -.НОМЕР_ПРАВИЛА, л МАССИВ_ПРАВИЛ,СТЕК_ФАКТОВ, УКАЗАТЕЛЫ) OF Т:ПРАВИЛО_ИСТИННО(УКАЗАТЕЛЬ-.НОМЕР_ПРАВИЛА, СТЕК_ФАКТОВ, СТЕК_ЦЕЛЕЙ, ГОТОВНОСТЬ); F: АКТИВНЫЕ_ПРАВИЛА[УКАЗАТЕЛЬ-.НОМЕР_ПРАВИЛА] :“FALSE; U:ЗАП0МНИТЬ_ЦЕЛЬ(УКАЗАТЕЛЬ1, СТЕК_ЦЕЛЕЙ); END ELSE IF П0ИСК_П0ДСКАЗКИ(СПИС0К_АТРИБУТ0В, СТЕК_ЦЕЛЕЙ-.АТРИБУТ, УКАЗАТЕЛЬ) THEN BEGIN КОПИЯ_СТЕКА_ЦЕЛЕЙ := СТЕК_ЦЕЛЕЙ; (♦НУЖНА ДЛЯ БЛОКА ОБЬЯСНЕНИЙ*) ПОЛУ4ИТЬ_ОТВЕТ(УКАЗАТЕЛЬ-.ПОДСКАЗКА-.ИНФОРМАЦИЯ, СТЕК_ФАКТОВ, СТЕК_ЦЕЛЕЙ) END ELSE(*НЕТ НИ ПРАВИЛ НИ ПОДСКАЗКИ*) ГОТОВНОСТЬ := TRUE; IF NOT ПРОВЕРКА(ОСНОВНАЯ_ЦЕЛЬ, СТЕК_ФАКТОВ, УКАЗАТЕЛЬ) THEN WRITELN('НЕТ ЗНАЧЕНИЯ ВЕЛИЧИНЫ ', ОСНОВНАЯ_ЦЕЛЬ) ELSE ПЕ4АТЬ_ЗНА4ЕНИЯ_ЦЕЛИ(СТЕК_ФАКТОВ, УКАЗАТЕЛЬ); END (*ВЫВОД*); 86
Рассмотрим структуру и функционирование процедуры ВЫ¬ ВОД, а затем обсудим особенности используемых ею процедур. После начальной очистки стеков целей и фактов и объявле¬ ния активными всех правил процедура ВЫВОД обеспечивает запрос у пользователя основной цели вывода и заносит получен¬ ную цель в стек целей. Далее процесс вывода входит в цикл до появления признака готовности, который устанавливается в двух случаях. Во-первых, при пустом стеке целей, что свиде¬ тельствует о достижении цели вывода, во-вторых, при отсут¬ ствии правил и подсказок, позволяющих определить значение какого-либо атрибута, что свидетельствует о невозможности до¬ стижения цели вывода. В зависимости от причин, вызвавших установку признака готовности, процедура ВЫВОД в конце своей работы выдает соответствующие сообщения. Значение текущей цели вывода может быть определено с по¬ мощью какого-либо правила предметной области либо с по¬ мощью запроса у пользователя. Для определения конкретного варианта используется поиск правила и поиск подсказки. В случае успешного завершения поиска подсказки по целе¬ вому атрибуту в списке атрибутов осуществляется запрос значе¬ ния целевого атрибута у пользователя. Текущая цель считается достигнутой и происходит ее выталкивание из стека целей. Атри¬ бут, его значение и ноль в качестве номера правила записыва¬ ются в стек фактов. Если успешно завершается поиск активного правила с целевым атрибутом в части ТО, то дальнейший ход процесса вывода зависит от значения найденного правила. Ко¬ гда правило истинно, то значение целевого атрибута определя¬ ется значением этого атрибута в части ТО правила. Текущая цель считается достигнутой и происходит ее выталкивание из стека целей. Атрибут, его значение и номер правила записыва¬ ются в стек фактов. Если правило ложно, то оно запрещается для дальнейшего использования и процесс поиска продолжа¬ ется. Если же значение правила не определено, то первый атри¬ бут из части ЕСЛИ этого правила, который отсутствует в стеке фактов, объявляется текущей целью вывода. Процедура ПОЛУЧИТЬ_ОСНОВНАЯ-ЦЕЛЬ запрашивает у пользователя цель (атрибут) вывода и заносит ее в стек целей: PROCEDURE ПОЛУ4ИТЬ_ОСНОВНАЯ_ЦЕЛЬ (VAR ОСНОВНАЯ__ЦЕЛЬ: СЛОВО; VAR СТЕК ЦЕЛЕЙ: СПИСКИ 1 ; BEGIN ~ ; WRITE('ЗАДАЙТЕ ОСНОВНУЮ ЦЕЛЬ '); ВВОД_СЛОВА(INPUT, ОСНОВНАЯ_ЦЕЛЬ); ЗАПИСЬ_В_СТЕК(СТЕК_ЦЕЛЕЙ, ОСНОВНАЯ__ЦЕЛЬ, ОСНОВНАЯ__ЦЕЛЬ, 0); END ( * ПОЛУЧИТЬ__ОСНОВНАЯ__ЦЕ ЛЬ *) ; 87
Как уже отмечалось, для организации вывода в стеке целей используется только поле АТРИБУТ (поле НОМЕР ПРАВИЛА нужно для организации объяснений), а поле ЗНАЧЕНИЕ — не используется. Иначе говоря, в рассматриваемой реализации целью является атрибут, а его значение выводится в процессе работы процедуры ВЫВОД. Если бы мы использовали и поле ЗНАЧЕНИЕ, то целью объявлялись бы атрибут и его значение и осуществлялся бы не поиск, а проверка значения. Проведение подобных экспериментов не входит в нашу за¬ дачу, однако поле ЗНАЧЕНИЕ резервируется для целей экспе¬ риментирования. В данной реализации в поле ЗНАЧЕНИЕ стека целей можно писать любую синтаксически верную информацию. Функция ПОИСК-ПРАВИЛА осуществляет поиск среди активных правил правила, в части ТО которого имеется требуе¬ мый атрибут. Напомним, что на часть ТО правил указывают элементы второго столбца МАССИВ-ПРАВИЛ. В случае успеха функ¬ ция принимает значение TRUE, УКАЗАТЕЛЬ указывает на часть ТО найденного правила: FUNCTION ПОИСК_ПРАВИЛА(МАССИВ_ПРАВИЛ: ТАБЛИЦАПРАВИЛ; АТРИБУТ: СЛОВО; АКТИВНЫЕ_ПРАВИЛА: АКТИВНЫЕ; VAR УКАЗАТЕЛЬ: СПИСКИ): BOOLEAN; VAR I: С4ЕТ4ИК; ФЛАГ: BOOLEAN; BEGIN I := 0; ФЛАГ := FALSE; REPEAT I := I + 1; IF АКТИВНЫЕ_ПРАВИЛА[I] AND (МАССИВ ПРАВШЦ1, 2] <> NIL) THEN ФЛАГ := МАССИВ_ПРАВИЛ[I, 2]~.АТРИБУТ = АТРИБУТ; UNTIL ФЛАГ OR (I = КОЛИ4ЕСТВО_ПРАВИЛ); ПОИСК_ПРАВИЛА := ФЛАГ; IF ФЛАГ THEN УКАЗАТЕЛЬ := МАССИВ_ПРАВИЛ[I, 2] ELSE УКАЗАТЕЛЬ := NIL; END (*ПОИСК_ПРАВИЛА*); Если вспомнить метод резолюции (см. п. 1.3) и считать, что в стеке целей находится отрицание целевого атрибута, то фак¬ тически функция ПОИСК ПРАВИЛА ищет второе предложение для резолюции, т. е. подготавливает условия для срабатывания правила вывода modus tollens. Функция ЗНАЧЕНИЕ-ПРАВИЛА проводит оценку значения части ЕСЛИ правила с заданным номером и выдает одно из трех значений: Т (истина), F (ложь) или U (значение не определено). 88
В последнем случае формируется указатель на элемент правила, который не содержится в стеке фактов. Напомним, что правило имеет значение ИСТИНА, если зна¬ чения всех атрибутов в части ЕСЛИ совпадают со значениями этих атрибутов в стеке фактов. Если значение хотя бы одного атрибута из части ЕСЛИ правила не совпадает со значением атрибута в стеке фактов, то правило имеет значение ЛОЖЬ. Если часть ЕСЛИ правила пуста, то значение правила — ИСТИНА. Функция ЗНАЧЕНИЕ ПРАВИЛА использует процедуру ПОИСК (см. п. 2.2). Можно считать, что функция ЗНАЧЕНИЕ- ПРАВИЛА реализует правило вывода «введение конъюнкции (см. п. 1.3): FUNCTION ЗНА4ЕНИЕ_ПРАВИЛА(НОМЕР: С4ЕТ4ИК; МАССИВ_ПРАВИЛ: ТАБЛИЦА_ПРАВИЛ; СТЕК_ФАКТОВ: СПИСКИ; VAR УКАЗАТЕЛЬ: СПИСКИ): ЗНА4ЕНИЕ; VAR УКАЗАТЕЛЬ!., Р: СПИСКИ; Q: ЗНА4ЕНИЕ; BEGIN Р := МАССИВ_ПРАВИЛ[НОМЕР, 1]; УКАЗАТЕЛЬ := NIL; IF Р <> NIL THEN BEGIN Q := Т; REPEAT ПОИСК(УКАЗАТЕЛЫ, СТЕК_ФАКТОВ, Р~ .АТРИБУТ) ; IF УКАЗАТЕЛЫ = NIL THEN BEGIN Q := U; УКАЗАТЕЛЬ := P; END ELSE IF Рл.ЗНА4ЕНИЕ О УКАЗАТЕЛЫл.ЗНА4ЕНИЕ THEN Q := F; p •= рл.СВЯЗЬ* UNTIL (P = NIL)9 OR (Q = U) OR (Q = F); ЗНА4ЕНИЕ_ПРАВИЛА := Q; END ELSE 3HA4ЕНИЕ_^ПРАВИЛА := T; END ( *ЗНАЧЕНИЕ_ПРАВИЛА* ) ; Процедура ПРАВИЛО-ИСТИННО выполняется, когда зна¬ чение части ЕСЛИ правила имеет значение ИСТИНА, и осуще¬ ствляет следующие действия: записывает в стек фактов атрибут и его значение из части ТО правила, на которую указывает элемент второго столбца МАССИВА-ПРАВИЛ, т. е. тем самым фактически реализуется правило вывода modus ponens; выталкивает текущую цель из стека целей, так как она уже достигнута; в случае, если стек целей после этого оказывается пустым, устанавливает признак ГОТОВНОСТЬ в состояние TRUE 89
PROCEDURE ПРАВИЛО_ИСТИННО(НОМЕР: С4ЕТ4ИК; VAR СТЕК_ФАКТОВ, СТЕК_ЦЕЛЕЙ: СПИСКИ; VAR ГОТОВНОСТЬs BOOLEAN); BEGIN ЗАПИСЬ_В_СТЕК(СТЕК_ФАКТОВ, МАССИВ_ПРАВИЛ[НОМЕР, 2 ] - .АТРИБУТ, МАССИВ_ПРАВИЛ[НОМЕР, 2 ] -.ЗНА4 ЕНИЕ, НОМЕР); ВЫТАЛКИВАНИЕ ИЗ_СТЕКА(СТЕК_ЦЕЛЕЙ); IF СТЕК_ЦЕЛЕЙ = NIL THEN ГОТОВНОСТЬ := TRUE; END (*ПРАВИЛ0_ИСТИННО*); Процедура ПРАВИЛО-ИСТИННО использует процедуры ЗАПИСЬ_В_СТЕК и ВЫТАЛКИВАНИЕ-ИЗ-СТЕКА (см. п. 2.2). Процедура ЗАПОМНИТЬ_ЦЕЛЬ объявляет текущей целью,, т. е. записывает в стек целей, атрибут, из-за которого оценивае¬ мое правило получило значение НЕ ОПРЕДЕЛЕНО. Процедура ЗАПОМНИТЬ-ЦЕЛЬ использует процедуру ЗАПИСЬ_В_СТЕК: PROCEDURE ЗАП0МНИТЬ_ЦЕЛЬ(УКАЗАТЕЛЬ: СПИСКИ; VAR СТЕКЦЕЛЕЙ: СПИСКИ); BEGIN IF УКАЗАТЕЛЬ <> NIL THEN ЗАПИСЬ_В_СТЕК(СТЕК_ЦЕЛЕЙ, УКАЗАТЕЛЬ -.АТРИБУТ, УКАЗАТЕЛЬл.ЗНА4ЕНИЕ, УКАЗАТЕЛЬ-.НОМЕР_ПРАВИЛА) ELSE BEGIN WRITELN('УКАЗАТЕЛЬ ПУСТ'); GOTO 1; END; END (*ЗАПОМНИТЬ_ЦЕЛЬ*); Функция ПОИСК-ПОДСКАЗКИ осуществляет поиск под¬ сказки в списке атрибутов по заданному атрибуту и в случае успеха принимает значение TRUE, а УКАЗАТЕЛЬ указывает на найденную подсказку. Функция ПОИСК ПОДСКАЗКИ исполь¬ зует процедуру ПОИСК (см. п. 2.2): FUNCTION П0ИСК_П0ДСКАЗКИ(СПИС0К_АТРИБУТ0В: СПИСКИ; АТРИБУТ: СЛОВО; VAR УКАЗАТЕЛЬ: СПИСКИ): BOOLEAN; BEGIN ПОИСК(УКАЗАТЕЛЬ, СПИСОК_АТРИБУТОВ, АТРИБУТ); IF УКАЗАТЕЛЬ = NIL THEN П0ИСК_П0ДСКАЗКИ := FALSE ELSE IF УКАЗАТЕЛЬ-.ПОДСКАЗКА = NIL THEN П0ИСК_П0ДСКАЗКИ := FALSE ELSE П0ИСК_П0ДСКАЗКИ := TRUE; END (*П0ИСК_П0ДСКАЗКИ*);
При нисходящей разработке программ часто возникает си¬ туация, когда нужный модуль не готов к моменту завершения испытаний какого-либо другого модуля. В этом случае требу¬ ется имитировать работу первого модуля. Это может быть осуществлено двумя способами: посредством фиктивного модуля и посредством замещающего модуля. Фиктивный модуль состоит только из одной точки входа и одной точки возврата, замещающий модуль выполняет ряд вы¬ числений, но в очень упрощенной форме. Он применяется в тех случаях, когда использование фиктивного модуля не может дать желаемого эффекта. Процедура ПОЛУЧИТЬ-ОТВЕТ осуществляет диалог поль¬ зователя с экспертной системой. В общем случае эта процедура должна устанавливать два режима диалога: режим объяснений и режим ответа. Описание режима объяснений будет приведено в следующем параграфе. Здесь же мы рассмотрим упрощенный вариант (замещаю¬ щий модуль) процедуры ПОЛУЧИТЬ_ОТВЕТ, которая осущест¬ вляет только ввод ответа пользователя на подсказку о значе¬ нии интересующего экспертную систему атрибута. Полученное значение атрибута и сам атрибут должны быть записаны в стек фактов. В поле НОМЕР-ПРАВИЛА записывают ноль, как признак того, что значение атрибута было получено от пользователя для использования при реализации объяснений. Текущая цель, связанная с получением значения атрибута, находящегося на вершине стека целей, достигается после по¬ лучения ответа, поэтому необходимо провести ее выталкивание из стека целей. Процедура ПОЛУЧИТЬ_ОТВЕТ использует процедуры ВВОД-СЛОВА, ЗАПИСЬ-В-СТЕК и ВЫТАЛКИВАНИЕ_ИЗ_ СТЕКА: PROCEDURE ПОЛУ4 ИТЬ_ОТВЕТ(ПОДСКАЗКА: СТРОКА; VAR СТЕК_ФАКТОВ, СТЕК_ЦЕЛЕЙ: СПИСКИ); VAR ОТВЕТ: СЛОВО; BEGIN WRITELN ( ' ' : 5, ' ПОДСКАЗКА ' ) ; WRITELN (ПОДСКАЗКА) ; ВВОД_СЛОВА(INPUT,ОТВЕТ); ЗАПИСЬ_В_СТЕК (СТЕК_ФАКТОВ, СТЕК_ЦЕЛЕЙЛ . АТРИБУТ, ОТВЕТ,0); ВЫТАЛКИВАНИЕ ИЗ_СТЕКА(СТЕК_ЦЕЛЕЙ) ; IF СТЕК_ЦЕЛЕЙ=Ы1Ь THEN ГОТОВНОСТЬ:=TRUE; END(*ПОЛУЧИТЬ JDTBET*); 91
Рекурсивная функция ПРОВЕРКА проверяет наличие основ* ной цели в стеке фактов, и в случае успеха УКАЗАТЕЛЬ ука¬ зывает на этот элемент: FUNCTION ПРОВЕРКА(ОСНОВНАЯ_ЦЕЛЬ: СЛОВО; СТЕК_ФАКТОВ: СПИСКИ; VAR УКАЗАТЕЛЬ: СПИСКИ): BOOLEAN; 4 BEGIN IF СТЕК_ФАКТОВ = NIL THEN BEGIN УКАЗАТЕЛЬ := NIL; ПРОВЕРКА := FALSE; END ELSE IF ОСНОВНАЯ_ЦЕЛЬ = СТЕК_ФАКТОВл.АТРИБУТ THEN BEGIN УКАЗАТЕЛЬ := СТЕК_ФАКТОВ; ПРОВЕРКА := TRUEг END ELSE ПРОВЕРКА := ПРОВЕРКА(ОСНОВНАЯ_ЦЕЛЬ, С ТЕ К__ФАКТОВ л . СВЯЗЬ, УКАЗАТЕЛЬ) ; END (*ПРОВЕРКА*); Процедура ПЕЧАТЬ-ЗНАЧЕНИЯ-ЦЕЛИ активируется при наличии основной цели в стеке фактов. В общем случае УКАЗА¬ ТЕЛЬ показывает на нее, но при анализе алгоритма работы реа¬ лизованной экспертной системы становится очевидным, что ос¬ новная цель в нашем случае может находиться только на вер* шине стека фактов: PROCEDURE ПЕ 4АТЬ_ЗНА4 ЕНИЯ_ЦЕЛИ (СТЕК_ФАКТОВ, УКАЗАТЕЛЬ: СПИСКИ) BEGIN IF СТЕК_ФАКТОВ <> NIL THEN WITH СТЕК_ФАКТОВл DO WRITELN('ОТВЕТ? АТРИБУТ, ' - ЗНА4ЕНИЕ); END (*ПЕЧАТЬ_ЗНАЧЕНИЯ_ЦЕЛИ*); Перед тем как завершить описание вывода решения кратко обсудим проблему «сборки мусора». При работе со ссылочным типом данных мы фактически имеем дело с динамическими переменными, которые, как из¬ вестно (см. п. 2.1), порождаются процедурой NEW по мере на¬ добности. Так, при включении нового элемента в стек целей мы сначала «порождаем» этот элемент с помощью процедуры NEW, потом заполняем все его информационные поля и включаем в список, т. е. в стек целей. После каждой процедуры ВЫТАЛ- КИВАНИЕ_ИЗ_СТЕКА освобождается один элемент списка, все указатели на него теряются. Этот элемент становится так называемым «мусором», так как он «засоряет» память машины. При частых записях в стек и выталкиваниях из него вся па¬ мять забивается мусором, и система становится неработоспособ¬ ной. Во избежание этого в тексте процедуры ВЫТАЛКИВА- НИЕ_ИЗ_СТЕКА нужно использовать процедуру DISPOSE, 92
обратную процедуре NEW, отдающую ненужный элемент списка обратно в управляемую память. В некоторых реализациях Паскаля процедура DISPOSE от¬ сутствует, и чтобы решить проблему мусора в этом случае про¬ граммист должен сам организовать список свободных элемен¬ тов. Как только потребуется новая запись, ее можно будет взять нз этого списка. Процедурой NEW записи будут порождаться только в том случае, если список свободной памяти окажется пустым. Когда программа заканчивает пользование какой-либа записью, она возвращается в список свободных записей. Для реализации сборки мусора необходимо, во-первых,, в разделе VAR основной программы описать переменную СПИ- СОК-СВОБОДНОЙ-ПАМЯТИ: СПИСКИ, во-вторых, среди процедур основной программы описать процедуры СОЗДАНИЕ и УДАЛЕНИЕ: PROCEDURE СОЗДАНИЕ(VAR Р, СПИСОК_СВОБОДНОЙ_ПАМЯТИ:СПИСКИ); (♦РАСШИРЕНИЕ NEW*) BEGIN IP СПИСОК_СВОБОДНОЙ_ПАМЯТИ=Н1Ь THEN NEW(P) ELSE BEGIN P:=СПИСОК_СВОБОДНОЙ_ПАМЯТИ; СПИСОК СВОБОДНОЙ_ПАМЯТИ:= СПИСОК_СВОБОДНОЙ_ПАМЯТИл.СВЯЗЬ; END; END(*С03ДАНИЕ*); PROCEDURE УДАЛЕНИЕ(РгСПИСКИ; VAR СПИСОК_СВОБОДНОЙ_ПАМЯТИ:СПИСКИ); (♦АНАЛОГ DISPOSE*) BEGIN Рл.СВЯЗЬ s =СПИСОК_СВОБОДНОЙ_ПАМЯТИ; С1ШСОК_СВОБОДНОЙ_ПАМЯТИ:=Р; END(*УДАЛЕНИЕ*); в-третьих, в теле основной программы записать оператор СПИ- СОК-СВОБОДНОЙ ПАМЯТИ: = NIL; в-четвертых, во всех про¬ цедурах и функциях, использующих стек целей, заменить NEW(P) на СОЗДАНИЕ (Р, СПИСОК-СВОБОДНОЙ-ПА- •МЯТИ), а при удалении элемента стека воспользоваться проце¬ дурой УДАЛЕНИЕ. 1 В заключение опишем программу проведения испытаний блока логического вывода. Для ее работы требуется работаю¬ щая процедура КОМПИЛЯЦИЯ и файл внешнего представле¬ ния знаний, оформленный по аналогии с программой интерпре¬ тации предложений (см. п. 2.3). Для проведения испытаний по¬ требуется вспомогательная процедура ПЕЧАТЬ-СПИСКА (см. I®. 2.2) для печати содержимого стека фактов и стека целей:
PROGRAM ИСПЫТАНИЕ2(INPUT,OUTPUT); LABEL 1; CONST (*CM. П.2.2*) TYPE (*CM. П.2.2*) VAR МАСС ИВ_ПРАВИЛ:ТАБЛИЦА_ПРАВИЛ; СПИСОК_АТРИБУТОВ: СПИСКИ; INP,OUT:TEXT; I:С4ЕТ4ИК; PROCEDURE ПЕ4АТЬ_СПИСКА(VAR OUT:TEXT; СПИСОК:СПИСКИ); (*ОПИСАНИЕ CM. П.2.2*) PROCEDURE КОМПИЛЯЦИЯ(VAR INP:TEXT; VAR МАССИВ_ПРАВИЛ:ТАБЛИЦА_ПРАВИЛ; VAR СПИСОК_АТРИБУТОВ:СПИСКИ); (*ОПИСАНИЕ СМ. П.2.3*) PROCEDURE ВЫВОД(VAR МАССИВ_ПРАВИЛ: ТАБЛИЦАПРАВИЛ; VAR СПИСОК_АТРИБУТОВ: СПИСКИ); (*ОПИСАНИЕ СМ. П.2.4*) BEGIN (*ИСПЫТАТЕЛЬНАЯ2 *) RESET(INP,'INP'); КОМПИЛЯЦИЯ(INP,МАССИВ_ПРАВИЛ,СПИСОК_АТРИБУТОВ); CLOSE(INP); REWRITE(OUT,'OUT'); ВЫВОД(МАССИВ_ПРАВИЛ,СПИСОК_АТРИБУТОВ); 1:WRITELN('КОНЕЦ ИСПЫТАНИЙ БЛОКА ЛОГИЧЕСКОГО ВЫВОДА') END(*ИСПЫТАТЕЛЬНАЯ2*). Для проведения испытаний в тело процедуры ВЫВОД надо вставить операторы промежуточной печати значений правил, со¬ держимого стека целей и стека фактов. В файле OUT будет храниться протокол работы с эксперт¬ ной системой, правильность которого можно проверить, напри¬ мер, по тестовому примеру, приведенному в табл. 1.4. 2.5. РЕАЛИЗАЦИЯ БЛОКА ОБЪЯСНЕНИИ И ЯЗЫКА ПОЛЬЗОВАТЕЛЯ Синтаксические диаграммы реализуемого языка пользова¬ теля приведены на рис. 2.3. По сравнению с синтаксическими диаграммами, приведенными на рис. 1.11, здесь введены сле¬ дующие ограничения. Поскольку на Паскале удобно работать с символьным ти¬ пом, то из слов ПОЧЕМУ, КАК и НЕТ будут использованы только первые буквы, хотя пользователь может набирать эти слова полностью. При задании вопроса КАК пользователь вместо ввода ат¬ рибута должен задать номер I атрибута в части ЕСЛИ пра¬ вила. 94
Предложение Ооьяснения ^Почемуу- -/Запрос Вопроса/ -^ПочемуУ— —©н 4—-/Сообщение о5 ошибке/-^ ^—-/Сообщение од ошибке }- ^ Рис. 2.3. Синтаксические диаграммы языка пользователя <*>■ Управление диалогом между пользователем и экспертной системой осуществляется процедурой ПОЛУЧИТЬ — ОТВЕТ, полное описание которой с учетом рис. 2.3 имеет вид PROCEDURE ПОЛУ4 ИТЬ_ОТВЕТ(ПОДСКАЗКА:СТРОКА; VAR СТЕК_ФАКТОВ, СТЕК_ЦЕЛЕЙ:СПИСКИ); VAR ОТВЕТ:СЛОВО; CHsCHAR; PROCEDURE ОБЪЯСНЕНИЯ(КОПИЯ_СТЕКА_ЦЕЛЕЙ:СПИСКИ); (*ОПИСАНИЕ СМ. П.2.5*) BEGIN (*ПОЛУЧИТЬ_ОТВЕТ*) WRITELN('ПОДСКАЗКА:'); WRITELN(ПОДСКАЗКА); REPEAT WRITELN('ЕСЛИ БУДЕТЕ ОТВЕЧАТЬ,ТО ВВЕДИТЕ # '); WRITE('ЕСЛИ БУДЕТЕ СПРАШИВАТЬ,ТО ВВЕДИТЕ ? '); WHILE INPUTл = ' ' DO GET(INPUT); READLN(CH); IF CH = '#' THEN BEGIN WRITE('ОТВЕЧАЙТЕ '); ВВОД_СЛОВА(INPUT,ОТВЕТ); END ELSE IF CH = '?' THEN BEGIN ОБЪЯСНЕНИЯ(КОПИЯ_СТЕКА_ЦЕЛЕЙ); WRITELN(ПОДСКАЗКА); ВВОД_СЛОВА(INPUT, ОТВЕТ); ENb ELSE WRITELN('ВМЕСТО ?/# ВВЕДЕН СИМВОЛ ', CH); UNTIL CH IN ['#', '?']; ЗАПИСЬ_В_СТЕК(СТЕК_ФАКТ0В, СТЕК_ЦЕЛЕЙЛ.АТРИБУТ, ОТВЕТ, 0); ВЫТАЛКИВАНИЕ ИЗ_СТЕКА(СТЕК_ЦЕЛЕЙ); IF СТЕК_ЦЕЛЕЙ = NIL THEN ГОТОВНОСТЬ := TRUE; END (*ПОЛУЧИТЬ_ОТВЕТ*) ; 95
Процедура ПОЛУЧИТЬ—ОТВЕТ фактически реализует ре¬ жим интерпретации предложений языка пользователя, связан¬ ных с установкой режима диалога. Эти предложения можно рассматривать как правила продукций со структурой ЕСЛИ <условие> ТО <действие>, например: ЕСЛИ введен символ # ТО осуществи ввод ответа. ЕСЛИ введен символ ? ТО проведи объяснения. Эти правила продукций независимы, а именно одно не вы¬ зывает другое, и запуск их осуществляется под управлением данных, которые формулирует пользователь. Очевидно, что число интерпретируемых команд (правил продукций) легко может быть увеличено. При этом, правда, рекомендуется заменить использование вложенных операторов IF оператором CASE. Однако столь же очевидно, что любое увеличение числа интерпретируемых команд, как и смена их наполнения, приводит к необходимости перетрансляции проце¬ дуры ПОЛУЧИТЬ-ОТВЕТ, так как соответствие между вве¬ денным символом и обслуживающим его действием жестко определено в теле процедуры. Кроме того, это частично объяс¬ няется особенностями языка Паскаль, в котором нельзя осу¬ ществить запуск какой-либо процедуры по ее имени. Нельзя ввести какой-то символ А и сразу запустить процедуру А. Для этого нужно использовать оператор CASE, устанавливающий PROCEDURE ПЕ4АТЬ__ПРАВИЛА(VAR OU: TEXT; I: РАЗМЕР; J: С4ЕТ4ИК); VAR Р, Р1: СПИСКИ; BEGIN Р МАССИВ_ПРАВИЛ[J, 1]; WRITELN(OU, 'ЕСЛИ'); WHILE Р <> NIL DO BEGIN ПОИСК(Р1, СПИСОК_АТРИБУТОВ, Р *.АТРИБУТ); IF (PI = NIL) OR (Р1*.ПЕРЕВОД = NIL) THEN WRITELN(OU, I: 2, ' ', P*.АТРИБУТ, ' ', Р*•ЗНА4ЕНИЕ,'(', Р*.НОМЕР_ПРАВИЛА: 3, ')') ELSE WRITELN(OU, I: 2, ' ', Р1*.ПЕРЕВОД*.ИНФОРМАЦИЯ, ' ', Р* .ЗНА4ЕНИЕ, '(', Р*.НОМЕР_ПРАВИЛА: 3, ')'); I := I + 1; Р := Р*.СВЯЗЬ; END; Р :* МАССИВ__ПРАВИЛ[J, 2]; WRITELN(OU, 'ТО'); ПОИСК(Р1, СПИСОК_АТРИБУТОВ, Р *.АТРИБУТ); IF (PI » NIL) OR (Р1*.ПЕРЕВОД = NIL) THEN WRITELN(OU, P*.АТРИБУТ, ' ', Р*.ЗНА4ЕНИЕ, ' (', P*.HOMEPJTPАВИЛА: 3, ')') ELSE WRITELN(OU, PI*.ПЕРЕВОД*.ИНФОРМАЦИЯ, ' ', P*•ЗНА4ЕНИЕ, ' ( ', Р*.НОМЕР_ПРАВИЛА: 3, ')'); END (*ПЕЧАТЬ_ПРАВИЛА*);
соответствие между командой и процедурой ее реализующей. Как увидим в дальнейшем, этого недостатка лишены языки ЛИСП и Пролог. Из синтаксических диаграмм (см. рис. 2.3) видно, что в рас¬ сматриваемой реализации команды ПОЧЕМУ и КАК не явля¬ ются независимыми вследствие наличия параметра I. Поскольку в качестве транслятора с языка пользователя применяется интерпретатор, можно организовать наиболее дру¬ жественный диалог с исправлением ошибок пользователя и с организацией повторных запросов. Процедура ПОЛУЧИТЬ-ОТВЕТ использует процедуры ЗАПИСЬ-В-СТЕК, ВЫТАЛКИВАНИЕ-ИЗ-СТЕКА и ОБЪЯС¬ НЕНИЯ. Перед тем как описать процедуру ОБЪЯСНЕНИЯ, рассмотрим вспомогательные процедуры и типы данных. Для ответов на вопросы КАК правило будет распечаты¬ ваться процедурой ПЕЧАТЬ-ПРАВИЛА (см. стр. 96). Каждая составляющая части ЕСЛИ правила распечатыва¬ ется на отдельной строке экрана дисплея; и при этом строки PROCEDURE КАК( VAR МАССИВ: СОСТАВНЫЕ; I: РАЗМЕР); VAR УКАЗАТЕЛЬ: СПИСКИ; BEGIN »ПОИСК(УКАЗАТЕЛЬ, СТЕК_ФАКТОВ, МАССИВ[I].АТРИБУТ); IP УКАЗАТЕЛЬ <> NIL THEN BEGIN IF УКАЗАТЕЛЬ* • ЗНА4ЕНИЕ = МАССИВ[ I ] .чЗНА4ЕНИЕ THEN BEGIN IF УКАЗАТЕЛЬ*.НОМЕР_ПРАВИЛА <> О THEN BEGIN WRITELN('БЫЛО ИСПОЛЬЗОВАНО ПРАВИЛО УКАЗАТЕЛЬ* . НОМЕР_ПРАВИЛА); ПЕ 4АТЬ_ПРАВИЛА(OUTPUT, 1, УКАЗАТЕЛЬ*.НОМЕР_ПРАВИЛА); END ELSE WRITELN('ЗНАЧЕНИЕ АТРИБУТА ЗАДАНО ПОЛЬЗОВАТЕЛЕМ1) END END ELSE IF ПОИСК_ПРАВИЛА(МАССИВ_ПРАВИЛ, МАССИВ[ I ] . АТРИБУТ, АКТИВНЫЕ_ПРАВИЛА, УКАЗАТЕЛЬ) THEN BEGIN WRITELN('МОЖЕТ БУДЕТ ИСПОЛЬЗОВАНО ПРАВИЛО', УКАЗАТЕЛЬ* .НОМЕР—ПРАВИЛА:. 2); ПЕ4АТЬ__ПРАВИЛА(OUTPUT, 1, УКАЗАТЕЛЬ* . НОМЕР_ПРАВИЛА) END ELSE BEGIN WRITE('ЗНАЧЕНИЕ АТРИБУТА МОЖЕТ БЫТЬ ОПРЕДЕЛЕНО '); WRITELN('ТОЛЬКО ПОЛЬЗОВАТЕЛЕМ'); END; END (*КАК*); 7 В. Э. Балтрашевич 97
части ЕСЛИ перенумеровываются, начиная с 1. При распет чатке правила в режиме объяснений атрибуты заменяют соот¬ ветствующими переводами. При вводе вопроса КАК пользова¬ тель только указывает номер строки правила для задания ат¬ рибута, значение которого интересует пользователя. Для реа¬ лизации этих действий был организован массив составляющих части ЕСЛИ правила с помощью типа СОСТАВНЫЕ, который определяется следующим образом: CONST N=10; (* максимальное число составляющих части ЕСЛИ*) TYPE РАЗМЕР=0..N; СОСТАВНЫЕ=ARRAY [РАЗМЕР] OF ЭЛЕМЕНТ. Как уже отмечалось, при ответе на вопрос ПОЧЕМУ дол¬ жно быть распечатано правило, поместившее атрибут в стек целей. Это реализует процедура ПОЧЕМУ, которая, кроме того, определяет число составляющих в части ЕСЛИ распеча¬ тываемого правила и формирует массив составляющих части ЕСЛИ. При пустом стеке целей или нулевом номере правила в стеке целей печатается сообщение «Вы этого хотели сами»: PROCEDURE ПО4ЕМУ(VAR МАССИВ: СОСТАВНЫЕ; VAR I: РАЗМЕР); VAR Р: СПИСКИ; BEGIN IP (КОПИЯ_СТЕКА_ЦЕЛЕЙ = NIL) OR (КОПИЯ_СТЕКА_ЦЕЛЕЙ л.НОМЕР_ПРАВИЛА = 0) THEN WRITELN('ВЫ ЭТОГО ХОТЕЛИ САМИ') ELSE BEGIN WRITELN('ЦЕЛЬ ', КОПИЯ_СТЕКА_ЦЕЛЕЙл.АТРИБУТ); WRITELN('ПРАВИЛО ', КОПИЯ_СТЕКА_ЦЕЛЕЙл.НОМЕР_ПРАВИЛА: 2,' ГЛАСИТ:'); ПЕ4АТЬ_ПРАВИЛА(OUTPUT, 1, КОПИЯ_СТЕКА_ЦЕЛЕЙл.НОМЕР_ПРАВИЛА); Р МАССИВ_ПРАВИЛ [КОПИЯ_СТЕКА_ЦЕЛЕЙл.НОМЕР_ПРАВИЛА, 1]; I := 0; WHILE Р <> NIL DO BEGIN I I + 1; МАССИВ[1] := Рл; P := PA.СВЯЗЬ; END; КОПИЯ_СТЕКА_ЦЕЛЕЙ I» КОПИЯ_СТЕКА_ЦЕЛЕЙл.СВЯЗЬ; END; END (*ПОЧЕМУ*); Процедура КАК поясняет как было или как будет опреде¬ лено значение интересующего пользователя атрибута. Она ис¬ пользует процедуру ПОИСК, ПОИСК-ПРАВИЛА и ПЕЧАТЬ- ПРАВИЛА ((см. стр. 97). 98
Теперь запишем процедуру ОБЪЯСНЕНИЯ с учетом син¬ таксических диаграмм (см. рис. 2.3) и введенных процедур ПОЧЕМУ и КАК: PROCEDURE ОБЪЯСНЕНИЯ(КОПИЯ_СТЕКА_ЦЕЛЕЙ: СПИСКИ); CONST N = 10; TYPE РАЗМЕР = 0..N; СОСТАВНЫЕ = ARRAY [РАЗМЕР] OF ЭЛЕМЕНТ; VAR I, Л РАЗМЕР; CH: CHAR; МАССИВ: СОСТАВНЫЕ; PROCEDURE ПЕ4АТЬ_ПРАВИЛА(VAR OU: TEXT; I: РАЗМЕР; J:.C4ET4HK); (♦ОПИСАНИЕ СМ. П.2.5*) PROCEDURE П04ЕМУ(VAR МАССИВ: СОСТАВНЫЕ; VAR I: РАЗМЕР); (♦ОПИСАНИЕ СМ. П.2.5*) PROCEDURE КАК(VAR МАССИВ: СОСТАВНЫЕ; I: РАЗМЕР); (♦ОПИСАНИЕ СМ. П.2.5*) BEGIN (*ОБ'ЯСНЕНИЯ*) П04ЕМУ(МАССИВ, J); REPEAT WRITE('ЖДУ ВОПРОСОВ[ПОЧЕМУ,КАК,НЕТ] '); WtfILE INPUT* = ' ' DO GET(INPUT); READLN(CH); IF CH IN ['П', 'К', 'H'] THEN CASE CH OF 'П': П04ЕМУ(МАССИВ, J); 'К': BEGIN WRITE('1“'); READLN(I); IF I IN [1..JJ THEN КАК(МАССИВ, I) ELSE WRITELN('НЕВЕРНОЕ ЗНАЧЕНИЕ I'); END; r 'H': (*HET ВОПРОСОВ*) END ELSE WRITELN('НЕВЕРНОЕ ЗНАЧЕНИЕ ВОПРОСА'); UNTIL CH = 'H'; END (*ОБ'ЯСНЕНИЯ*); Как видно из текста процедуры ОБЪЯСНЕНИЯ, она реа¬ лизует интерпретатор вопросительных предложений языка пользователя с помощью оператора CASE, т. е. язык пользова¬ теля, как и язык абстрактного эксперта, реализуется с по¬ мощью преобразования синтаксических диаграмм в программу. Итак, на этом фактически заканчивается разработка и реа¬ лизация инструментальной экспертной системы на языке Па¬ скаль. Испытание блока пояснений сводится к испытанию всей системы. В качестве начального примера можно взять про¬ грамму интерпретации предложений из п. 1.1, при этом только надо учитывать, что файл исходных данных должен быть пред¬ ставлен с учетом ограничений реализованной системы, по ана¬ логии с программой интерпретации предложений из п. 2.3. За¬ тем можно проверить работу системы на основе примера из области ботаники с помощью программы интерпретации расте¬ ний из п. 1.5 и табл. 1.5. 7* 99
2.0. ОСНОВНАЯ ПРОГРАММА ИНСТРУМЕНТАЛЬНОЙ ЭКСПЕРТНОЙ СИСТЕМЫ Окончательный текст программы, реализующей инструмен¬ тальную экспертную систему, предназначенную для решения задач интерпретации, имеет вид: PROGRAM ИЗС(INPUT,OUTPUT); (♦ИНСТРУМЕНТАЛЬНАЯ ЭКСПЕРТНАЯ СИСТЕМА*) LABEL 1; CONST (*СМ. П.2.2*) TYPE (*СМ. П.2.2*) VAR МАССИВ_ПРАВИЛIТАБЛИЦА_ПРАВИЛ; СПИСОК_АТРИБУТОВ:СПИСКИ; INP:TEXT; PROCEDURE КОМПИЛЯЦИЯ(VAR INP:TEXT; VAR МАССИВ_ПРАВИЛ:ТАБЛИЦА_ПРАВИЛ; VAR СПИСОК_АТРИВУТОВ:СПИСКИ)? (♦ОПИСАНИЕ СМ. П.2.3*) PROCEDURE ВЫВОД(VAR МАССИВ_ПР АВИЛ:ТАБЛИЦА_ПРАВИЛ; VAR СПИСОК_АТРИБУТОВ:СПИСКИ); (♦ОПИСАНИЕ СМ. П.2.4*) BEGIN (*ИЭС*) RESET(INP, 'INP')? КОМПИЛЯЦИЯ(INP, МАССИВ_ПРАВИЛ, СПИСОК_АТРИБУТОВ); CLOSE(INP); REWRITE(OUT, 'OUT'); ВЫВОД(МАССИВ_ПРАВИЛ, СПИСОК_АТРИБУТОВ); 1:WRITELN('КОНЕЦ РАБОТЫ С СИСТЕМОЙ'); END (*ИЭС*). Теперь мы можем подвести некоторые итоги реализации ин¬ струментальной экспертной системы на Паскале и наметить некоторые перспективы развития реализации, которая проводи¬ лась на основе рекомендаций модульного и структурного про¬ граммирования [1]. Разработанная программа достаточно сложна, чтобы быть написанной как единое целое. Кроме того, как известно, про¬ граммы разбиваются на модули, для того чтобы упростить раз¬ работку и реализацию, облегчить чтение программ, упростить их настройку и модификацию, облегчить работу с данными, имеющими сложную структуру, избежать чрезмерной детали¬ зации алгоритмов, обеспечить более выгодное размещение про¬ грамм в памяти ЭВМ. Задача разбивалась на ряд основных подзадач, заключающихся в реализации языка эксперта, логи¬ ческого вывода, объяснений и языка пользователя. 100
В начале реализации была проведена разработка структур данных на основе необходимых действий. Все из указанных подзадач далее разбивались на более мелкие подзадачи, каж¬ дая из которых выполняла одну функцию и могла быть реали¬ зована с помощью простой процедуры или функции. Заметим, что некоторые подзадачи намеренно упрощались в целях получения программы меньшего объема, более обозри¬ мой, дающей ясное понятие о ее функциях и возможных пу¬ тях реализации, но обязательно работающей. Уже ни у кого не вызывает сомнение тот факт, что реально работающая, пусть и не очень сложная система, гораздо полезнее сложней¬ шей системы, «работающей на бумаге», т. е. так называемого «бумажного тигра». Программа реализована как самодокументированная, т. е. не требующая дополнительной документации. При обозначе¬ нии типов, переменных, процедур и функций использовались содержательные обозначения, облегчающие чтение и понима¬ ние текста программы. Объяснения, приведенные в тексте па¬ раграфов, предназначены для указания особенностей реали¬ зации. Работа над реализацией экспертной системы подтверждает тот факт [13], что не нужно спешить с разработкой сложней¬ шей версии программы. Намного удобнее построить ее упро¬ щенный вариант, оценив возможности системы, уяснив цели разработки, переходить к более сложной версии, т. е. предпоч¬ тительнее путь от простого к сложному. В последнее время Паскаль, получив широкое распростра¬ нение среди программистов, стал фактически языком публи¬ каций. Однако следует отметить, что для непрограммиста он до¬ вольно сложен, так как требует знания достаточно сложных структур данных с различной организацией, их описания и ис¬ пользования, умения организовать различные вычислительные процессы с помощью большого разнообразия операторов Па¬ скаля, умения использовать широкие возможности по органи¬ зации процедур и функций. Язык эксперта гораздо быстрее осваивается непрограмми¬ стом, чем Паскаль. Рассмотрим возможные пути улучшения реализации экс¬ пертной системы и возможные пути экспериментирования с ней. 1. Язык эксперта: заменить односимвольные обозначения терминальных сим¬ волов (ЕСЛИ, ТО и т. д.) полными; реализовать возможность записи предложений в одну строку, реализовать словарь возможных значений атрибутов и организовать проверку ответа пользователя; 101
снабдить компилятор более подробной диагностикой воз¬ можных ошибок в программе на языке эксперта; устранить использование массива для представления пра¬ вил, заменив его либо списком, либо файлом. 2. Логический вывод: реализовать использование значения атрибута в стеке це¬ лей, что позволит лучше понять процесс совмещения перемен¬ ных и констант, характерный для Пролога, а также процесс логического вывода, используемый в Прологе; реализовать «чистый» обратный вывод, т. е. без помощи прямого вывода, используя только стек целей с обязательным присутствием откорректированного блока объяснений; устранить побочный эффект, которым обладают функции ПОИСК-ПРАВИЛА и ПОИСК-ПОДСКАЗКИ, выдавая указа¬ тель на найденный элемент, сделав эти функции ссылочного типа, и изменить текст процедуры ВЫВОД; провести рекурсивную реализацию процедуры ВЫВОД, об¬ ратив особое внимание на то, что стек целей будет реализовы¬ ваться автоматически механизмом рекурсии языка Паскаль. Для организации объяснений потребуется ввести программный эквивалент стека целей, т. е. след вывода. Кроме того, каждое правило сможет иметь только два значения — истина или ложь. 3. Реализация объяснений: изменить организацию задания атрибута в вопросе КАК; выполнить более содержательную распечатку правил. 4. Язык пользователя: ввести дружественную проверку на допустимость значений атрибутов; расширить возможности языка за счет дополнительных ко¬ манд пользователя: печать правил (всех или выборочно); пе¬ чать списка атрибутов, удаление правила, ввод правила с тер¬ минала, печать стека фактов или стека целей и др. 3. РЕАЛИЗАЦИЯ ЭКСПЕРТНОЙ СИСТЕМЫ НА ЯЗЫКЕ ЛИСП 3.1. КРАТКАЯ ХАРАКТЕРИСТИКА ЯЗЫКА ЛИСП Язык программирования ЛИСП создан под руководством Джона Маккарти в 1960 г. и получил широкое распростране¬ ние в области искусственного интеллекта [6, 11, 22]. ЛИСП во ,102
многом отличается от большинства других языков, таких как Фортран, Алгол, Бэйсик, Паскаль. Наиболее удивительная черта — это эквивалентность представления программ и дан¬ ных в языке, что позволяет выполнять структуры данных как программы и модифицировать программы как данные. Другой особенностью является применение в качестве основной управ¬ ляющей структуры не итерации (цикла), как в большинстве языков программирования (например, Паскале), а рекурсии. Третья особенность состоит в широком использовании струк¬ туры данных связанных списков и наличии общих операций для их модификации. Обработка списков лежит в основе боль¬ шинства алгоритмов ЛИСПа, хотя в языке имеются также ог¬ раниченные возможности для работы с числами и литерами. Главная программа на ЛИСПе имеет простую структуру: последовательность определений подпрограмм — функций, за которой следует последовательность вызовов этих функций с конкретными аргументами. Каждая подпрограмма-функция определяется отдельно. Никаких сложных синтаксических кон¬ струкций типа блочных структур нет. Взаимодействие между разными функциями возможно только через вызовы во время выполнения. Функции ЛИСПа определяются как выражения. Каждый оператор является функцией, возвращающей некоторое значе¬ ние, и подпрограмма записывается как одно (часто довольно сложное) выражение. Остальные средства ЛИСПа, такие как определение функций, условные и безусловные передачи управ¬ ления в программе и др., определяются путем создания специ¬ альных функций, которые выполняют эти действия. Использование функциональных символов для именования результатов вычислений является основой функционального программирования [25]. Функциональное программирование — это способ составления программ, в которых единственным дей¬ ствием является вызов функции, единственным способом рас¬ членения программы на части является введение имени для функции и задание для этого имени выражения, вычисляющего значение функции, а единственным правилом композиции — оператор суперпозиции функции. Никаких ячеек памяти, опе¬ раторов присваивания, циклов, передач управления. С исполь¬ зованием идей функционального программирования ниже бу¬ дет проведена реализация экспертной системы, а пока про¬ должим знакомство с возможностями языка ЛИСП, которые будут нами использованы. Набор типов данных в ЛИСПе довольно ограничен. Атомы (символы) и числа являются основными простыми типами. Связанные списки и списки свойств образуют основные струк¬ туры данных. Вся обработка списков осуществляется во время выполнения, никаких описаний не требуется.
ЛИСП содержит широкий набор примитивов для создания, уничтожения и модификации списков (включая списки свойств). Имеются и основные арифметические примитивы. Во время выполнения программы с помощью специальных примитивов могут осуществляться трансляция и выполнение других про¬ грамм, т. е. программы могут создаваться и выполняться дина¬ мически. Базовыми единицами информации в ЛИСПе являются атомы и списки. Атом — это любая последовательность буквенно-цифровых символов и специальных знаков, заключенных между ограни¬ чителями «пробел» или «круглые скобки». Каждый атом мо¬ жет иметь значение. Т и NIL являются особыми атомами, по¬ скольку их значения заранее положены равными Т и NIL, т. е. значение атома Т всегда есть Т, значение атома NIL всегда есть NIL. Все числа также обладают этим свойством, т. е. зна¬ чение числа всегда равно этому числу. Список — это упорядоченная совокупность элементов, в ка¬ честве которых могут выступать либо атомы, либо другие списки. Списки строятся в виде сбалансированных по скобкам структур, допускающих произвольную вложенность. Под выражением в ЛИСПе понимается либо атом, либо список. Наибольшее распространение получили S-выражения, рекурсивное определение которых выглядит следующим обра¬ зом [11]: S-выражение — это либо атом, либо левая круглая скобка, за которой следует последовательность S-выражений, отделенных друг от друга пробелами, и правая круглая скобка. Свойство включать списки внутрь списков с использованием скобок позволяет строить древовидные структуры данных и осуществлять их преобразования. В ЛИСПе есть аппарат интерпретации выражений, называ¬ емый вычислением (оцениванием). Первый элемент списка ин¬ терпретируется как имя функции, остальная часть списка рас¬ сматривается как множество аргументов функции. Работа ЛИСП-системы полностью отличается от работы Паскаль-си¬ стемы. При использовании Паскаля мы обычно говорим о ком¬ пиляторе с Паскаля, на вход которого подают исходную про¬ грамму, а на выходе получают объектную программу, кото¬ рая затем и выполняется. В ЛИСПе нормальная работа осу¬ ществляется под управлением интерпретатора. Функция вво¬ дится в систему, ее значение вычисляется и печатается, затем вводится другая функция и т. д. Переменная в ЛИСПе может иметь значение. Один из спо¬ собов приписывания значения переменной — использование функции SETQ, первым аргументом которой является перемен¬ ная, значение которой определяется значением второго аргу¬ мента. Второй аргумент может быть сколь угодно сложным. 104
В результате вычисления функция SETQ принимает значение, определяемое вторым аргументом и, очевидно, совпадающее со значением первого аргумента. Выражение (SETQ Х5) и переменная X в результате вы¬ числения принимают значение, совпадающее со значением атома 5, которое равно 5. Выражение (SETQ A (SETQ В NIL)) и переменные А и В в результате вычисления принимают значения NIL. Заметим, что в конце S-выражения вместо всех закрываю¬ щихся круглых скобок можно использовать одну ]. Для отмены режима вычисления S-выражений используется функция QUOTE, значением которой является аргумент функ¬ ции, именно в том виде, в каком он записан, т. е. без вычис¬ ления его значения. Например, выражение (SETQ A (QUOTE (SETQ В NIL))) и переменная А примут значение (SETQ В NIL). Функция QUOTE, в связи с частым ее использованием, может кратко обозначаться апострофом (кавычкой). Например, выше описанное выражение можно записать в виде (SETQ А 4 (SETQ В NIL]. Важно знать, что область действия механизма кавычки в точности распространяется на идущее за ней S-выражение. Кавычка, стоящая перед списком, предотвращает всякую по¬ пытку расценивать список как некую операцию. Не сущест¬ вует никакого механизма снятия кавычки. Это значит, что нет способа включения процесса оценивания где-нибудь внутри списка, отмеченного кавычкой. Функции для обработки списков. Для обработки списков используется ряд системных функций, таких как CAR, CDR, CONS и др., поскольку ЛИСП — главным образом язык спи¬ сков, a CAR, CDR и CONS являются тремя примитивными функциями, из которых получают все другие функции обра¬ ботки списков. Функция CAR в качестве аргумента получает список. Ее значением является первый элемент этого списка. Так, выра¬ жение (CAR ’(СТЕБЕЛЬ ЗЕЛЕНЫЙ)) принимает значение СТЕБЕЛЬ. Функция CDR в качестве аргумента также получает список. Ее значением является остаток списка после удаления первого элемента. Так, выражение (CDR ’ (СТЕБЕЛЬ ЗЕЛЕНЫЙ)) принимает значение (ЗЕЛЕНЫЙ). Если X является атомом, то выражение (CAR X) не имеет смысла и будет причиной ошибки. Если X — список, содержа¬ щий в точности один элемент, то (CDR X) не имеет смысла по данному выше определению, но принято соглашение, по кото¬ рому значение этого выражения будет принимать значение NIL. Операции CAR и CDR можно комбинировать друг с другом как обыкновенные математические функции. Чтобы выделить 105
второй элемент списка, следует сначала воспользоваться CDR, а затем CAR. Так, выражение (CAR (CDR ’ (СТЕБЕЛЬ ЗЕ¬ ЛЕНЫЙ))) принимает значение ЗЕЛЕНЫЙ. Когда для вы¬ бора какого-то элемента внутри S-выражения требуется не¬ сколько функций CAR и CDR, обычно удобно пользоваться со¬ ставной функцией С R. Так, вышеприведенное выражение полностью эквивалентно (CADR ‘ (СТЕБЕЛЬ ЗЕЛЕНЫЙ]. Функция CONS собирает вновь то, что CAR и CDR разбили на части. Вторым аргументом должен быть список, к началу которого подсоединяется первый аргумент, который может быть чем угодно, включая атом. Выражение (CONS ‘ СТЕ¬ БЕЛЬ 4 (ЗЕЛЕНЫЙ)) принимает значение (СТЕБЕЛЬ ЗЕЛЕ¬ НЫЙ). Рассмотрим еще некоторые системные функции, обеспечи¬ вающие обработку списков. Функция APPEND выстраивает в одну цепочку элементы всех списков, поставляемых в качестве аргументов. Выражение (APPEND ‘(А В) 4 (С Д)) принимает значение (А В С Д) в отличие от выражения (CONS 4 (А В) 4 (С Д)), которое при¬ нимает значение ((А В) С Д). Функция LIST представляет собой функцию, аргументы ко¬ торой заключаются в круглые скобки, при этом создается но¬ вый список, вложенный на один уровень круглых скобок глубже любого ее аргумента. Так выражение (LIST 4 (А В) 4 (С Д)) принимает значение ((А В) (С Д)). Предикаты. Предикат представляет собой функцию, значе¬ ние которой ограничено двумя специальными атомами; Т и NIL. Эти значения Т и NIL соответствуют разговорному пред¬ ставлению понятий истина и ложь. Функция АТОМ в качестве аргумента имеет атом или спи¬ сок. Если значением аргумента служит атом, то ее значение Т, в противном случае — NIL. Функция NULL проверяет, не является ли значением ее ар¬ гумента NIL. Если так, то значением NULL будет Т, в против¬ ном случае — NIL. Функция EQ проверяет, равны ли значения двух ее аргу¬ ментов. Если да, то ее значение Т, в противном случае—NIL. Предикат MEMBER возвращает Т только в том случае, если его первый аргумент является элементом последующего списка. В большинстве вычислительных машин нельзя определить что записано в слове памяти: целое число, число с плавающей точкой или строка символов. Это свойство машин характерно и для Паскаля, в котором невозможно обратиться к функции, которая определила бы, какого рода данные занесены под име¬ нем некоторой переменной. Однако в ЛИСПе мы имеем дело с атомами, являющимися не просто одиночными словами па¬ 106
мяти. Атом содержит разнообразную информацию, тип кото¬ рой, в частности, может быть числовым или символьном. Так, для каждой переменной в ЛИСПе можно определить, присво¬ ено ли ей значение в виде числа или нет. Это делаете# преди¬ катом NUMBERP, который принимает значение Т, если в ка¬ честве значения его аргумента используется число. Логические функции. Функции AND и OR имеют неопреде¬ ленное число аргументов. NIL берется в качестве FALSE, а все остальное обозначает TRUE, насколько это касается логики. Так, значением AND всегда будет NIL, если хотя бы один ар¬ гумент равен NIL, иначе значением AND будет Т. Аналогично значением OR будет NIL, если значения всех ее аргументов есть NIL, иначе значением OR будет Т. Аргументы в AND вычисляются слева направо. ЕслН встре¬ чается NIL, то NIL сразу же возвращается этой функцией, а остальные аргументы оставляются без внимания. В против¬ ном случае AND возвращает значение своего последнего' аргу¬ мента. Аргументы в OR вычисляются слева направо. Если рстреча- ется что-либо отличное от NIL, то эта величина немедленно возвращается функцией, а остальные аргументы игнорируются. В противном случае OR возвращает NIL. Такая организация вычислений функций AND и OR не только сокращает время, но и предотвращает возникновение ошибок, встречающихся во многих важных ситуациях. Функция ветвления. Предикаты наиболее часто использу¬ ются для определения, по какому из возможных путей должна развиваться программа. В действительности путь, или ветвь, часто определяется предикатом вместе с функцией ветвления COND, поэтому COND является наиболее употребительной функцией. У нее несколько специфический синтаксис по срав¬ нению с остальными функциями. За именем функции COND идет некоторое число списков, каждый из которых содержит проверку и нечто, чье значение следует выдать, если условие в проверке оказывается выполненным. Таким образом, в об¬ щем случае указанный синтаксис выражается так: (COND <1-й список) <2-й список) ...). Каждый список называется предложением. При более под¬ робном описании предложений мы получаем (COND «тест)... <результат>) (<тест>... (результат)) ((тест)... (результат))). Значение какого-то одного из результирующих элементов и будет значением всей функции COND. Идея состоит в том, 107
чтобы проходить по спискам, обращая внимание только на их первые элементы, до тех пор, пока не найдется элемент, зна¬ чение которого не равно NIL. Тогда все остальное в этом ото¬ бранном списке подвергается оцениванию, и значение послед¬ ней из оцениваемых величин выдается в качестве значения функции COND. Ясно, что любые выражения, стоящие между первым и последним элементами в списке функции COND, должны использоваться только из-за побочных эффектов, по¬ скольку никоим образом они не могут повлиять на значение COND. Если ни один подходящий список не найден, COND возвращает NIL. Если выбранный список содержит ровно один элемент, то возвращается значение этого элемента. Иными словами, <тест> и <результат> могут совпадать. Этот частный слу¬ чай использования функции COND будет часто нами приме¬ няться при реализации экспертной системы. Отметим, что для выбора между предложениями не требу¬ ется строгого Т, а годится все, что отлично от NIL. Такое свой¬ ство желательно потому, что оно позволяет в качестве тесто¬ вых функций использовать не только те функции, значения ко¬ торых, как в случае предикатов, ограничены двумя величи¬ нами— Т и NIL. PRO G-выражения. Для того чтобы писать программу в виде последовательности операторов (по аналогии с Паскалем), в ЛИСПе имеется PROG-выражение, которое представляет со¬ бой функцию с неопределенным числом аргументов, позволяю¬ щую создавать новые переменные. Аргументами для функции PROG преимущественно служат S-выражения, которые оцениваются одно за другим. Если уп¬ равление выходит за рамки функции PROG, то (как и в слу¬ чае функции COND) возвращается NIL. Первую позицию в функции PROG всегда занимает список переменных, которые все связываются при входе в PROG, а при выходе их величины восстанавливаются в прежних зна¬ чениях. Каждой из них автоматически присваивается началь¬ ное значение NIL. Когда в ходе вычисления функции PROG встречается функ¬ ция RETURN, PROG немедленно завершается. Значением та¬ кой завершенной функции PROG является значение аргумента для функции RETURN, которая остановила работу PROG. Всякий атом, появляющийся в качестве аргумента функции PROG, рассматривается в качестве метки в программе. Эти атомы указывают на те места, куда управление передается функциями GO. Функция (GO <метка>) передает управление в то место программы, которое помечено атомом с именем <метка>. Вычисляющая функция. Если имеется переменная, значе- 108
йием которой является список с таким S-выражением, что его можно понимать как обращение к функции, т. е. первым эле¬ ментом является имя функции, а другими элементами—ее ар¬ гументы, и нам надо найти значение этой функции, применен¬ ной к данным аргументам, то используется функция EVAL, в качестве аргумента которой применяется эта переменная. Функция EVAL всегда выдает значение своего аргумента. Для функции EVAL нет аналогий в Паскале. Это одно из наиболее важных понятий ЛИСПа, которое делает его бо¬ лее мощным, чем Паскаль. Используя EVAL, мы можем вы¬ полнить «оператор», который в действительности создан нашей ЛИСП-программой и который может меняться в процессе вы¬ полнения программы. В большинстве языков все операторы должны быть написаны до начала работы, и форма этих опе¬ раторов не может меняться в процессе ее работы. Ввод-вывод. В ЛИСПе операторы, которые читают и запи¬ сывают (вводят и выводят) данные подобно всем остальным операторам ЛИСПа, являются функциями. Мы опишем самый простой набор функций ввода-вывода, названных READ, PRINT и TERPR, которые используются во многих ЛИСП-си- стемах. Функция READ в качестве аргумента использует имя файла, в котором находится информация. Если аргумент от¬ сутствует, то чтение происходит с клавиатуры терминала. При каждом обращении к READ ЛИСП-система читает одно S-вы¬ ражение. Значением READ служит полученное S-выражение. Функция PRINT имеет один аргумент и печатает S-выра¬ жение, равное значению этого аргумента. ЛИСП-системы, ис¬ пользующие построчную печать, требуют для печати всю строку. В этих системах, если мы хотим использовать PRINT несколько раз внутри одной строки, PRINT по существу не мо¬ жет выполнить такую печать. В этом случае символы заносятся в специальную символьную строку памяти, которая печатается при использовании функции TERPR. Создание новых функций. Пользуясь системными функци¬ ями, программист может создавать свои функции с помощью функции DEF, которая имеет следующий синтаксис: (DEF <имя функции> (LAMBDA (<список формальных параметров>) (<тело>))). (Тело представляет собой произ¬ вольное выражение.) В качестве фактических параметров функциям могут пере¬ даваться произвольные структуры данных, и любая функция может вернуть в качестве своего значения любую структуру данных. Таким образом, функции ЛИСПа по существу не ог¬ раничены в возможности создавать, уничтожать или модифи¬ цировать структуры данных. Поскольку эти структуры данных могут быть определениями подпрограмм, можно писать про¬ 109
граммы, которые создают или модифицируют другие про¬ граммы на ЛИСПе. При определении новых функций, в которых описывается периодически повторяющийся процесс решения одной и той же задачи заново с более простыми аргументами, в ЛИСПе очень широко используется рекурсия. 3.2. ВЫБОР СТРУКТУР ДАННЫХ Для реализации инструментальной экспертной системы нам необходимо выбрать структуры данных для внутреннего пред¬ ставления знаний (базы знаний) и базы данных. Напомним, что к знаниям в нашем случае относятся правила, подсказки и переводы, а база данных состоит из стека целей и стека фактов. Кроме того, в процессе логического вывода все пра¬ вила разделяются на активные, которые можно использовать в процессе вывода, и пассивные, которые использовать запре¬ щено. Нам необходимо выбрать структуру и для этою разделе¬ ния правил. При выборе структур данных необходимо учиты¬ вать те действия, которые будут проводиться с этими структу¬ рами. Так, при работе с правилами, как это следует из описа¬ ния процесса логического вывода (п. 1.3), отдельно обрабаты¬ вают части ЕСЛИ и ТО, при оценке значения правила часть ЕСЛИ анализируется поэлементно, причем каждый элемент состоит из атрибута и значения, поэтому должен быть доступ к каждому атрибуту и значению. Кроме того, для печати пра¬ вила в процессе работы блока пояснений, осуществляется по¬ иск правила по его номеру, следовательно, структура правила должна обеспечивать простой доступ к номеру. На основании вышеизложенного было решено использовать для представле¬ ния правил следующую структуру данных: ПРАВИЛА: (ПРАВИЛО 1 ПРАВИЛО2 ... ПРАВИЛО L) ПРАВИЛО I: ’(НОМЕР-ПРАВИЛА (ЧАСТЬ_ЕСЛИ) (ЧАСТЬ_ТО)) (ЧАСТЬ_ЕСЛИ): ((АТРИБУТ ЗНАЧЕНИЕ) (АТРИБУТ ЗНАЧЕНИЕ)... (АТРИБУТ ЗНАЧЕНИЕ)) (ЧАСТЬ_ТО): ((АТРИБУТ-ЗНАЧЕНИЕ)). Таким образом, список всех правил представляется в виде одного S-выражения. При выборе структуры данных для подсказок необходимо учитывать, что в процессе работы экспертной системы осуще¬ ствляется поиск подсказки по атрибуту, к которому она отно¬ сится, и в случае успеха выдается текст соответствующей под¬ сказки, т. е. должен быть обеспечен легкий доступ к атрибуту и соответствующей ему подсказке. Поэтому для представления ПО
Подсказок было решено использовать следующие структуры Данных: ПОДСКАЗКИ: (ПОДСКАЗКА 1 ПОДСКАЗКА2 ... ПОД¬ СКАЗКА К) ПОДСКАЗКА 1: (АТРИБУТ(ТЕКСТ-ПОДСКАЗКИ)), т. е. список всех подсказок представляется в виде одного S-выра¬ жения. По аналогичным причинам для представления переводов ■было решено использовать одно S-выражение со следующей структурой: ПЕРЕВОДЫ: (ПЕРЕВОД 1 ПЕРЕВОД 2 ... ПЕРЕВОД N) ПЕРЕВОД I: (АТРИБУТ (ТЕКСТ-ПЕРЕВОДА)). Внутреннее представление знаний (внутреннее представле¬ ние программы эксперта) для программы интерпретации пред¬ ложений из п. 1.1 имеет вид А V. У ((1((ЧИСЛО ДА){СЛОВО ТО))((ПРЕДЛОЖЕНИЕ ПРАВИЛО))) (2{(ЧИСЛО ДА)(СЛОВО ЕСЛИ)(СЛЕД_СЛОВО ТО)) ((ПРЕДЛОЖЕНИЕ ПРАВИЛО))) (3((ЧИСЛО ДА)(СЛОВО ЕСЛИ)(СЛЕД_СЛОВО И)(ТО ДА)) ((ПРЕДЛОЖЕНИЕ ПРАВИЛО))) (4{(ЧИСЛО ДА)(СЛОВО ЕСЛИ)(СЛЕД_СЛОВО И)(ТО НЕТ)) ({ПРЕДЛОЖЕНИЕ ОШИБОЧНОЕ_ПРАВИЛО))) (5((ЧИСЛО НЕТ)(# ДА))((ПРЕДЛОЖЕНИЕ ОТВЕТ))) .(6 ((ЧИСЛО НЕТ) ( # НЕТ) ( ? ДА) (СЛОВО ПОЧЕМУ)) ((ПРЕДЛОЖЕНИЕ ВОПРОС))) (7((ЧИСЛО НЕТ)(# НЕТ)(? ДА)(СЛОВО КАК)) ({ПРЕДЛОЖЕНИЕ ВОПРОС))) (8{(ЧИСЛО НЕТ){# НЕТ)(? НЕТ)(СЛОВО ПЕРЕВОД)) ({ПРЕДЛОЖЕНИЕ ПЕРЕВОД))) (9((ЧИСЛО НЕТ)(# НЕТ)(? НЕТ)(СЛОВО ПОДСКАЗКА)) ((ПРЕДЛОЖЕНИЕ ПОДСКАЗКА))) (10((ПРЕДЛОЖЕНИЕ ПРАВИЛО))((ЯЗЫК ЭКСПЕРТА))) (11((ПРЕДЛОЖЕНИЕ ПЕРЕВОД))((ЯЗЫК ЭКСПЕРТА))) (12((ПРЕДЛОЖЕНИЕ ПОДСКАЗКА))({ЯЗЫК ЭКСПЕРТА))) (13{(ПРЕДЛОЖЕНИЕ ОТВЕТ)){(ЯЗЫК ПОЛЬЗОВАТЕЛЯ))) (14 ((ПРЕДЛОЖЕНИЕ ВОПРОС)) ((ЯЗЫК ПОЛЬЗОВАТЕЛЯJ ((ЧИСЛО(ПРЕДЛОЖЕНИЕ НАЧИНАЕТСЯ С ЧИСЛА?(ДА/НЕТ))) (СЛОВО(С КАКОГО СЛОВА НАЧИНАЕТСЯ ПРЕДЛОЖЕНИЕ?)) (СЛЕД_СЛОВО (С КАКОГО СЛОВА НАЧИНАЕТСЯ СЛЕДУЮЩАЯ СТРОКА?)) (ТО(ИМЕЕТСЯ СТРОКА НАЧИНАЮЩАЯСЯ С ТО?(ДА/НЕТ))) (#(ПРЕДЛОЖЕНИЕ НАЧИНАЕТСЯ С #?(ДА/НЕТ))) (?(ПРЕДЛОЖЕНИЕ НАЧИНАЕТСЯ С ? ?(ДА/НЕТ] {(ЧИСЛО(ИМЕЕТСЯ ЧИСЛО)){#(ПРЕДЛОЖЕНИЕ НАЧИНАЕТСЯ С #)) (СЛЕД_СЛОВО(СЛЕДУЮЩАЯ СТРОКА НАЧИНАЕТСЯ СО СЛОВА)) (СЛОВО(СЛОВО ИМЕЕТ ЗНАЧЕНИЕ))(ЯЗЫК(ТИП ЯЗЫКА)) (?(ПРЕДЛОЖЕНИЕ НАЧИНАЕТСЯ С ?)) (ТО(ИМЕЕТСЯ СТРОКА НАЧИНАЮЩАЯСЯ С ТО)) < ПРЕДЛОЖЕНИЕ(ТИП ПРЕДЛОЖЕНИЯ))) 111
Каждое S-выражение заканчивается закрывающейся квад¬ ратной скобкой. В начале приведено S-выражение, представля¬ ющее правила, затем подсказки и переводы. ЛИСП предназначен для работы со списками, поэтому нет никаких проблем при вводе списков, представляющих внешнее описание знаний. Таким образом приведенное представление можно рассматривать и как внешнее представление знаний, т. е. внутреннее и внешнее представления знаний могут совпа¬ дать. Предположим, что в файл INP.LSP записаны правила, под¬ сказки и переводы в указанном, порядке и с учетом выше при¬ веденного синтаксиса. Тогда после входа в ЛИСП можно вве¬ сти эти знания в оперативную память следующим образом: “^-(INFILE ‘ INP) подготавливаем файл INP для чтения -MSETQ ПРАВИЛА (READ INP)) -*(SETQ ПОДСКАЗКИ (READ INP)) -*(SETQ ПЕРЕВОДЫ (READ INP)) (CLOSE INP) закрытие файла INP. Транслятор с ЛИСПа является интерпретатором, стрелочка в начале строки признак того, что интерпретатор ждет указа¬ ний и после ввода очередное S-выражение сразу обрабатыва¬ ется. После проведения указанных действий правила, подсказки и переводы находятся в оперативной памяти, и к ним можно применять функции ЛИСПа, например, копирование на экран дисплея -^(COPY ПРАВИЛА) и функции, реализующие экс¬ пертную систему, описание которых будет приведено ниже. Таким образом, можно считать, что выбрав указанные структуры данных для правил, подсказок и переводов, мы тем самым определили упрощенный язык внешнего представления знаний (язык эксперта). Приведенную последовательность функций SETQ можно рассматривать как компилятор с этого языка, которого нам пока вполне достаточно для испытания разрабатываемой экспертной системы. Ограничением этого языка по сравнению с языком эксперта, разработанным в п. 1.2, является жесткий порядок ввода правил, подсказок и переводов. Рассмотрев внешнее и внутреннее представление знаний, пе¬ рейдем к рассмотрению базы данных. Как было показано прн описании логического вывода (п. 1.3) и блока пояснений (п. 1.4), в стеке фактов в качестве элемента должны храниться атрибут, его значение и номер правила, поместившего атрибут в стек фактов. Таким образом, для организации стека фактов, хранящего выводимые факты, выбираем следующую структуру данных: 112
ЭЛЕ- СТЕК-ФАКТОВ: (ЭЛЕМЕНТ 1 ЭЛЕМЕНТ 2 МЕНТ N) ЭЛЕМЕНТ I: (НОМЕР-ПРАВИЛА АТРИБУТ ЗНАЧЕНИЕ). Напомним, что в стеке фактов номер правила нужен для организации работы блока пояснений. Для организации стека целей предпочтение отдается списку со следующей структурой данных: СТЕК-ЦЕЛЕЙ: (ЭЛЕМЕНТ 1 ЭЛЕМЕНТ 2... ЭЛЕМЕНТ L) ЭЛЕМЕНТ I: (НОМЕР-ПРАВИЛА АТРИБУТ). Номер правила в стеке целей нужен для обеспечения отве¬ тов на вопрос ПОЧЕМУ. Теперь рассмотрим представление активных и пассивных правил. Будем предполагать, что активных правил всегда больше, чем пассивных, поэтому выберем структуру для пред¬ ставления пассивных правил, а все правила, не входящие в пассивные, будем считать активными. Это сократит и требу¬ емую память, и время определения типа правила. Таким обра¬ зом, для запрещенных правил будем использовать список ПАС¬ СИВНЫЕ ПРАВИЛА из номеров правил: ПАССИВНЫЕ-ПРАВ ИЛА (НОМЕР-ПРАВИЛА 1 НОМЕР-ПРАВИЛА2 ... НОМЕР- ПРАВИЛА N). Теперь рассмотрим действия, которые должны быть свя¬ заны с выбранными структурами данных. Так как все выбран¬ ные структуры являются списками, то должны быть действия по обработке списков, такие как печать списка, разделение и слияние списков, выделение элемента списка и т. п. Но язык ЛИСП предназначен для обработки списков, и все эти дей¬ ствия являются его стандартными действиями. Наша же за¬ дача скомпоновать эти элементарные действия (функции) с учетом конкретной структуры списка в некие более сложные функции. Так, часто в процессе вывода решения требуется вы¬ делять текущую цель (или подцель) из стека целей. Для этого с учетом структуры стека целей необходимо из верхнего эле¬ мента стека выделить атрибут. Функция ПОДЦЕЛЬ реализует указанные действия: (DEF ПОДЦЕЛЬ(LAMBDA(СТЕК_ЦЕЛЕЙ) (CAR(CDAR СТЕК_ЦЕЛЕЙ] Очевидно, что для испытания этой функции предварительно необходимо сформировать СТЕК-ЦЕЛЕЙ, например: -^(SETQ СТЕК-ЦЕЛЕЙ ‘ ((2 СЛОВО) (1 ПРЕДЛОЖЕ¬ НИЕ]. 8 В. Э. Валтрашевич 113
Вызов функции ПОДЦЕЛЬ осуществляется следующим об¬ разом: -►(ПОДЦЕЛЬ СТЕК-ЦЕЛЕЙ), что в нашем конкретном случае приведет к выделению подцели СЛОВО. Следует подчеркнуть, что проверка разработанных функций или их частей имеет большое значение на первых этапах ра¬ боты с ЛИСПом, поскольку большое число скобок как в опи¬ сании функций, так и в данных может привести к ошибкам. Интересно, что синтаксис вызова функции ПОДЦЕЛЬ бли¬ зок к синтаксису естественного языка. Наличие аргумента у функции ПОДЦЕЛЬ позволяет ее ис- лользовать и в случае выработки текущего значения стека це¬ лей с помощью какой-либо функции. Если же обращение к функции всегда имеет вид приведенного выше, т. е. с исполь¬ зованием глобальной структуры данных, то в этом случае с точки зрения экономии памяти аргумент лучше не использо¬ вать. Это нарушение требования функционального программи¬ рования о неиспользовании побочных эффектов обусловлено малым объемом оперативной памяти современных машин. Таким образом, описание функции будет иметь вид (DEF ПОДЦЕЛЬ (LAMBDA ( ) (CAR (CDAR СТЕК-ЦЕ¬ ЛЕЙ], а обращение >-(ПОДЦЕЛЬ). Рекурсивная функция ПОДСКАЗКА осуществляет поиск подсказки среди всех подсказок по заданному атрибуту. В слу¬ чае неудачи поиска функция выдает значение NIL, в случае успеха — текст подсказки. Входными аргументами функции яв¬ ляются атрибут и подсказки: (DEF ПОДСКАЗКА(LAMBDA(АТРИБУТ ПОДСКАЗКИ) (COND ((NULL ПОДСКАЗКИ)NIL) {(EQ(CAAR ПОДСКАЗКИ) АТРИБУТ) (CAR{CDAR ПОДСКАЗКИ))) (Т(ПОДСКАЗКА АТРИБУТ(CDR ПОДСКАЗКИ] Работа функции ПОДСКАЗКА под управлением функции COND осуществляется следующим образом: если список ПОДСКАЗКИ пуст, то выдается NIL; стан¬ дартная функция NULL в этом случае выполняет роль отрица¬ ния; иначе проверяется совпадение требуемого атрибута и теку¬ щего (первого) атрибута в списке ПОДСКАЗКИ, в случае ус¬ пеха выдается текст подсказки, относящийся к этому атрибуту; иначе, так как на месте условия стоит атом Т, происходит рекурсивное обращение к функции ПОДСКАЗКА с тем же ат- 114
рибутом, но список ПОДСКАЗКИ уже берется на одну под¬ сказку короче. Очевидно, что для испытания этой функции предварительно должны быть введены ПОДСКАЗКИ, например, с помощью квазикомпилятора. Вызов этой функции осуществляется следу¬ ющим образом: -►(ПОДСКАЗКА ‘СЛОВО ПОДСКАЗКИ) или -►(SETQ АТРИБУТ ‘ СЛОВО) -►(ПОДСКАЗКА АТРИБУТ ПОДСКАЗКИ). В результате получим текст подсказки, соответствующей атрибуту СЛОВО: (С КАКОГО СЛОВА НАЧИНАЕТСЯ ПРЕДЛОЖЕНИЕ?). При разработке функции ПОДСКАЗКА правильность ком¬ позиции функции CAR и CDR можно проверить специально в режиме интерпретации: -►(CAR (CDAR ПОДСКАЗКИ)) При этом получают текст подсказки, находящейся в начале списка подсказок. Аналогично функции ПОДСКАЗКА определяется функция ПЕРЕВОД: (DEF ПЕРЕВОД(LAMBDA(АТРИБУТ ПЕРЕВОДЫ) (COND ((NULL ПЕРЕВОДЫ)NIL) ((EQ(CAAR ПЕРЕВОДЫ)АТРИБУТ)(CAR(CDAR ПЕРЕВОДЫ))) (Т(ПЕРЕВОД АТРИБУТ(CDR ПЕРЕВОДЫ] Рекурсивная функция НАЙТИ осуществляет поиск элемента стека фактов, содержащего заданный атрибут: (DEF НАЙТИ(LAMBDA(АТРИБУТ СТЕК_ФАКТОВ) (COND ((NULL СТЕК_ФАКТОВ)NIL) ((EQ(CAR(CDAR СТЕК_ФАКТОВ))АТРИБУТ) (CAR СТЕК_ФАКТОВ)) (Т(НАЙТИ АТРИБУТ(CDR СТЕК_ФАКТОВ] В случае неудачи поиска функция выдает значение NIL, в случае успеха — значение элемента в виде (НОМЕР-ПРАВИЛА АТРИБУТ ЗНАЧЕНИЕ). Работа функции НАЙТИ под управлением функции COND происходит аналогично работе функции ПОДСКАЗКА. 8* 115
Пусть СТЕК-ФАКТОВ сформирован следующим образом: -►(SETQ СТЕК-ФАКТОВ ‘ ((ОСЛОВО ЕСЛИ) (ОЧИСЛО ДА]. Тогда в результате вызова функции НАЙТИ -►(НАЙТИ ‘ ЧИСЛО СТЕК-ФАКТОВ) получим (О ЧИСЛО ДА). Рекурсивная функция ПРАВИЛО осуществляет поиск ак¬ тивного правила, в части ТО которого имеется заданный атри¬ бут. В случае неудачи функция выдает значение NIL, а в слу¬ чае успеха — правило: (DEF ПРАВИЛО(LAMBDA(АТРИБУТ ПРАВИЛА) (COND ((NULL ПРАВИЛА)NIL) ((AND(NULL(MEMBER(CAAR ПРАВИЛА) ПАССИВНЫЕ_ПРАВИЛА)) (EQ АТРИБУТ (CAAR(CADR(CDAR ПРАВИЛА))))) (CAR ПРАВИЛА)) (Т(ПРАВИЛО АТРИБУТ (CDR ПРАВИЛА] Стандартная функция MEMBER проверяет наличие номера правила среди пассивных правил. Стандартная функция NULL в этом случае выполняет роль отрицания. При разработке этой функции самым сложным было до¬ стать атрибут из части ТО первого правила списка правил. Как уже отмечалось, правильность композиции функций CAR и CDR можно проверить специально в режиме интерпретации ->-(CAAR(CADR(CDAR ПРАВИЛА] при условии, что предварительно ПРАВИЛА были заданы. Если предположить, что все правила активны и было вы¬ полнено выражение -►(SETQ АТРИБУТ ‘ЯЗЫК), то при вызове функции ПРАВИЛО -►(ПРАВИЛО АТРИБУТ ПРАВИЛА] получим значение соответствующего правила. (10 ((ПРЕДЛОЖЕНИЕ ПРАВИЛО)) ((ЯЗЫК ЭКС¬ ПЕРТА))). Функции ПОДСКАЗКА, ПЕРЕВОД, ПРАВИЛО являются примером реализации процедурного (точнее функционального) задания данных. 116
В процессе логического вывода нам часто потребуются ча¬ сти правил, а именно ПРАВИЛО-ЕСЛИ и ПРАВИЛО_ТО с со¬ ответствующими структурами (НОМЕР_ПРАВИЛА (ЧАСТЬ_ЕСЛИ)) (НОМЕР-ПРАВИЛА (ЧАСТЬ_ТО)). Функция ПРАВИЛО-ЕСЛИ по входному аргументу ПРА¬ ВИЛО формирует список из номера правила и части ЕСЛИ. Аналогично функция ПРАВИЛО-ТО формирует список из но¬ мера правила и части ТО: (DEF ПРАВИЛО_ЕСЛИ(LAMBDA(ПРАВИЛО) (LIST (CAR ПРАВИЛО)(CADR ПРАВИЛО] (DEF ПРАВИЛ0_Т0(LAMBDA {ПРАВИЛО) (LIST (CAR ПРАВИЛО)(CAR(CDDR ПРАВИЛО] Рассмотрим разные варианты вызова функции ПРАВИЛО- ЕСЛИ. Вариант 1. Пусть -►(SETQ RULE ‘ (10 ((ПРЕДЛОЖЕНИЕ ПРАВИЛО)) ((ЯЗЫК ЭКСПЕРТА] -►(ПРАВИЛО-ЕСЛИ RULE), получим (10 ((ПРЕДЛОЖЕНИЕ ПРАВИЛО))) При этом варианте обращения мы использовали вспомога¬ тельную переменную RULE, которой с помощью «оператора присваивания» SETQ присвоили значение в виде константы. Вариант 2. Пусть -►(SETQ RULE (ПРАВИЛО ‘ЯЗЫК ПРАВИЛА)) -►(ПРАВИЛО-ЕСЛИ RULE) В этом варианте для задания значения переменной RULE мы использовали функцию ПРАВИЛО. Вариант 3. Пусть -►(ПРАВИЛО-ЕСЛИ (ПРАВИЛО ‘ ЯЗЫК ПРАВИЛА]. В этом варианте значение правила создается в результате работы функции ПРАВИЛО и воспринимается в качестве вход¬ ного аргумента функцией ПРАВИЛО-ЕСЛИ, т. е. аргументу как бы присваивается значение правила. Этот простейший пример полностью демонстрирует ненуж¬ ность использования оператора присваивания, о чем говори¬ лось в п. 3.1 при изложении основ функционального програм¬ мирования. Таким образом, в данном параграфе мы задали часть струк¬ тур данных декларативно, а для других структур данных под¬ готовили порождающие функции. 117
3.3. РЕАЛИЗАЦИЯ ЛОГИЧЕСКОГО ВЫВОДА Алгоритм логического вывода, т. е. фактически поиска ре¬ шения в пространстве состояний, был описан в п. 1.3 и п. 2.4. Поэтому будем считать, что действия, необходимые для его реализации, в основном поняты и перейдем к их реализации с учетом особенностей языка ЛИСП. Функция ЭС является основной функцией, вызывая которую мы активируем работу экспертной системы. Так как процесс работы функции состоит из последовательного выполнения ряда действий, то для ее описания используется PROG-выра- жение. Как известно, все локальные переменные при входе в PROG-выражение принимают значения NIL, что освобождает нас от необходимости проведения начальной установки: (DEF ЭС (LAMBDA( ) (PROG(ГОТОВНОСТЬ ПАССИВНЫЕ_ПРАВИЛА СТЕК_ЦЕЛЕЙ СТЕК_ФАКТОВ ОСНОВНАЯ_ЦЕЛЬ ПРАВИЛА ПОДСКАЗКИ ПЕРЕВОДЫ) (INFILE 'INP1) (SETQ ОСНОВНАЯ_ЦЕЛЬ(ПОЛУЧИ'ГЬ_ОСНОВНУЮ_ЦЕЛЬ)) (SETQ ПРАВИЛА (READ INP1)) (SETQ ПОДСКАЗКИ (READ INP1)) (SETQ ПЕРЕВОДЫ (READ INP1)) (CLOSE INP1) (ВЫВОД ГОТОВНОСТЬ ОСНОВНАЯ_ЦЕЛЬ) (RETURN T] Будем предполагать, что файл INP1.LSP содержит про¬ грамму интерпретации предложений из п. 3.2, так что к мо¬ менту вызова функции ВЫВОД значения правил, подсказок и переводов определены. Основная цель вывода задается функ¬ цией ПОЛУЧИТЬ_ОСНОВНУЮ_ЦЕЛЬ. Переменная ГОТОВ¬ НОСТЬ, первоначально имеющая значение NIL, а затем зна¬ чение Т, символизирует об окончании процесса вывода. Следует отметить, что с учетом требований функциональ¬ ного программирования правила, подсказки и переводы надо было бы использовать в качестве аргументов функции ВЫ¬ ВОД, тогда не было бы необходимости явно описывать соот¬ ветствующие переменные в функции ЭС и использовать опера¬ торы присваивания, а достаточно в качестве фактических значений аргументов функции ВЫВОД передать значения функ¬ ции (READ INP1). Однако это приводит к большой загрузке памяти при рекурсивном вызове функции ВЫВОД, и поэтому этот вариант здесь не используется. 118
Вызов функции ЭС, т. е. запуск всей системы имеет вид -*(ЭС). Функция RETURN выдает в качестве значения функции Т, несмотря на смысловое содержание процесса вывода решения, который, как видно, является побочным эффектом работы функции ЭС. Функция ПОЛУЧИТЬ_ОСНОВНУЮ_ЦЕЛЬ запрашивает ос¬ новную цель вывода у пользователя и записывает ее в СТЕК- ЦЕЛЕЙ. Так как алгоритм работы этой функции сводится к последовательному выполнению действий, то для ее описа¬ ния используем PROG-выражение и локальную переменную ОСНОВНАЯ-ЦЕЛЬ. Напомним, что ноль в стеке целей явля¬ ется признаком информации, вводимой пользователем. В каче¬ стве своего значения функция выдает значение основной цели: (DEF ПОЛУЧИТЬ_ОСНОВНУЮ_ЦЕЛЬ(LAMBDA( ) (PROG(ОСНОВНАЯ ЦЕЛЬ) (PRINT'(ЗАДАЙТЕ ОСНОВНУЮ ЦЕЛЬ))(TERPR) (SETQ ОСНОВНАЯ_ЦЕЛЬ(CAR(READ))) (SETQ СТЕК_ЦЕЛЕЙ NIL) (SETQ СТЕК_ЦЕЛЕЙ (CONS(LIST О ОСНОВНАЯ_ЦЕЛЬ) СТЕК_ЦЕЛЕЙ)) (Return основная_цель] Вызов этой функции осуществляется следующим образом: -*(ПОЛУЧИТЬ_ОСНОВНУЮ_ЦЕЛЬ). После введения основной цели можно просмотреть содержи¬ мое стека целей ->-(COPY СТЕК-ЦЕЛЕЙ). Рекурсивная функция ВЫВОД определяет все этапы про¬ цесса поиска решения. Аргументами функции являются при¬ знак готовности и текущая цель вывода. Процесс работы функции организован с помощью двух функций COND, рекур¬ сивного вызова самой себя при новом значении цели и исполь¬ зования ряда вспомогательных функций: (DEF ВЫВОД(LAMBDA(ГОТОВНОСТЬ ЦЕЛЬ ) (COND (ГОТОВНОСТЬ(ВЫДАЧА_РЕЗУЛЬТАТА ОСНОВНАЯ ЦЕЛЬ)) (T(COND ((ПОИСК_И_ОБРАБОТКА_ПРАВИЛА(ПРАВИЛО ЦЕЛЬ ПРАВИЛА))) ((0ТВЕТ_НА_П0ДСКАЗКУ ЦЕЛЬ (ПОДСКАЗКА ЦЕЛЬ ПОДСКАЗКИ))) (T(SETQ ГОТОВНОСТЬ Т))) (ВЫВОД ГОТОВНОСТЬ(ПОДЦЕЛЬ СТЕК ЦЕЛЕЙ) ] 119
Если ГОТОВНОСТЬ имеет значение отличное от NIL, то это значит, что процесс вывода закончен и функция ВЫДАЧА- РЕЗУЛЬТАТА выполнит действия, определяемые ее названием. В противном случае по условию Т начинает работать вторая функция COND, после которой осуществляется рекурсивный вызов функции ВЫВОД с новой целью, определяемой функцией ПОДЦЕЛЬ. Первые две строки второй функции COND состоят только из условий. Это означает следующий порядок выполнения со¬ держащихся в них функций. Функция ПОИСК-И_ОБРАБОТКА_ ПРАВИЛА осуществляет указанные в ее названии действия, причем если правило не найдено, то функция выдает значение NIL. Далее функция COND передает управление следующей строке, т. е. функции ОТВЕТ_НА_ПОДСКАЗКУ, которая пред¬ варительно ищет подсказку и в случае неудачи выдает значе¬ ние NIL, по которому функция COND передает управление третьей строке, в которой присваивается значение Т признаку ГОТОВНОСТЬ, так как этот случай соответствует отсутствию и правил, и подсказок для определения цели и цель не может быть достигнута. Таким образом, при используемом приеме программирова¬ ния функции ПОИСК-И-ОБРАБОТКА-ПРАВИЛА и ОТВЕТ- НА-ПОДСКАЗКУ проверяют возможность своего запуска и только в случае успеха выполняются. Функция ВЫВОД очень компактно и наглядно описывает весь алгоритм (систему управления) вывода, все подробности (стратегия управления) которого поясняются используемыми функцией ВЫВОД вспомогательными функциями, к рассмот¬ рению которых мы и переходим. Функция ВЫДАЧА_РЕЗУЛЬТАТА завершает работу экс¬ пертной системы и выдает результат вывода. Вначале с по¬ мощью функции ПОИСК-ЦЕЛИ проверяется наличие основной цели в стеке фактов и в случае неудачи выдается на печать сообщение «нет значения цели». Если цель в стеке фактов есть, то очевидно, что она находится в первом элементе стека* и этот верхний элемент стека и распечатывается в качестве ре¬ зультата вывода: (DEF ВЫДАЧА_РЕЗУЛЬТАТА (LAMBDA (ОСНОВНАЯ ЦЕЛЬ) (COND ( (НиЪЬ(ПОИСК__ЦЕЛИ ОСНОВНАЯ__ЦЕЛЬ СТЕК ФАКТОВ)) (PRINT'(НЕТ ЗНАЧЕНИЯ ЦЕЛИ))(TERPR)) (Т(PRINT'(ОТВЕТ))(TERPR) (PRINT (CAR СТЕК__ФАКТОВ) ) (TERPR] Рекурсивная функция ПОИСК-ЦЕЛИ проверяет наличие основной цели в стеке фактов. Работа функции определяется 120
функцией COND. Если стек фактов пуст, то выдается значение NIL, что является классическим условием остановки рекурсив¬ ных функций. Во второй строке функции COND проводится проверка на эквивалентность основной цели и атрибута из верхнего элемента стека фактов, и в случае успеха функция ПОИСК-ЦЕЛИ вы¬ дает значение Т, в противном случае производится рекурсивный вызов функции ПОИСК-ЦЕЛИ, но со стеком фактов уже без первого элемента: (DEF ПОИСК_ЦЕЛИ(БАМВОА(ОСНОВНАЯ ЦЕЛЬ СТЕК ФАКТОВ) (COND ((NULL СТЕК_ФАКТОВ)NIL) ((EQ ОСНОВНАЯ_ЦЕЛЬ (CAR(CDAR СТЕК_ФАКТОВ)))T) (Т(ПОИСК_ЦЕЛИ ОСНОВНАЯ_ЦЕЛЬ (CDR СТЕК_ФАКТОВ] Реализованный вариант алгоритма выдачи результата до¬ статочно общий (так же этот алгоритм реализован на Па¬ скале) . Но в качестве упражнения интересно рассмотреть другой вариант алгоритма выдачи результатов. В основе этого алгоритма лежит идея, что судить об успехе вывода можно не только по наличию основной цели в стеке фактов (т. е. по наличию переменной ОСНОВНАЯ-ЦЕЛЬ), но и по пустому стеку целей. Если признак ГОТОВНОСТЬ не NIL и стек целей пуст, то ответ находится в вершине стека фактов. При использовании этого алгоритма в функции ЭС надо убрать переменную ОСНОВНАЯ-ЦЕЛЬ с соответствующим оператором присваивания (SETQ), и в вызове функции ВЫ¬ ВОД вместо аргумента ОСНОВНАЯ-ЦЕЛЬ подставить вызов функции ПОЛУЧИТЬ_ОСНОВНУЮ-ЦЕЛЬ. Функция ПОИСК- ЦЕЛИ становится не нужной, а функция ВЫДАЧА-РЕЗУЛЬ¬ ТАТА принимает тривиальный вид. Функция ПОИСК-И_ОБРАБОТКА_ПРАВИЛА использует в качестве аргумента правило, которое принимает свое значе¬ ние при вызове этой функции из функции ВЫВОД, где в ка¬ честве фактического значения аргумента рассматриваемой функции использовалась функция ПРАВИЛО: (DEF ПОИСК_И_ОБРАБОТКА_ПРАВИЛА (LAMBDA(ПРАВИЛО) (COND ((NULL ПРАВИЛО)NIL) (Т(ОБРАБОТКА_ПРАВИЛА(ЗНАЧЕНИЕ_ПРАВИЛА (ПРАВИЛО_ЕСЛИ ПРАВИЛО)СТЕК_ФАКТОВ) (ПРАВИЛО ТО ПРАВИЛО] 121
Если правило не найдено и обрабатывать нечего, то функ¬ ция ПОИСК-И-ОБРАБОТКА-ПРАВИЛА принимает значение NIL, что используется в функции ВЫВОД. Если же правило найдено, то вызывается функция ОБРА¬ БОТКА-ПРАВИЛА с аргументами ЗНАЧЕНИЕ-ПРАВИЛА и ПРАВИЛО-ТО, которые формируются с помощью композиции функций ПРАВИЛО-ЕСЛИ, ЗНАЧЕНИЕ-ПРАВИЛА и функ¬ ции ПРАВИЛО-ТО. Рассмотрим несколько подробнее организацию вызова функции ПОИСК-И-ОБРАБОТКА_ПРАВИЛА из функции ВЫ¬ ВОД, который организован, как уже отмечалось, с помощью функции COND следующим образом: (COND ((ПОИСК-И_ОБРАБОТКА_ПРАВИЛА (ПРАВИЛО ЦЕЛЬ ПРАВИЛА)))... Возможен другой вариант вызова: (COND ((ПРАВИЛО ЦЕЛЬ ПРАВИЛА) (ОБРАБОТКА- ПРАВИЛА ПРАВИЛО ЦЕЛЬ ПРАВИЛА)))..., но в этом случае происходят два вызова функции ПРА¬ ВИЛО, что снижает быстродействие работы системы. Если же запомнить значение правила во вспомога¬ тельной переменной (COND ((SETQ RULE (ПРАВИЛО ЦЕЛЬ ПРАВИЛА)) (ОБРАБОТКА-ПРАВИЛА RULE))..., то нарушится четкость функционального программирования. Теперь рассмотрим реализацию функции ЗНАЧЕНИЕ-ПРА¬ ВИЛА, которая с помощью функции ОЦЕНКА-ПРАВИЛА оце¬ нивает значение части ЕСЛИ правила по следующему алго¬ ритму. Если значения всех атрибутов в части ЕСЛИ правила совпадают со значениями этих атрибутов в стеке фактов, то функция выдает значение ДА, если значение одного атрибута в части ЕСЛИ правила не совпадает со значением этого атри¬ бута в стеке фактов, то функция выдает значение НЕТ. Если же при анализе части ЕСЛИ встречается атрибут, ко¬ торый отсутствует в стеке фактов, то в качестве неопределен¬ ного значения функция выдает оставшуюся часть части ЕСЛИ правила: 122
(DEF ЗНАЧЕНИЕ_ПРАВИЛА(LAMBDA(ПРАВИЛО_ЕСЛИ СТЕК- ФАКТОВ) (COND ((NULL (CADR ПРАВИЛО_ЕСЛИ))'ДА) (Т(ОЦЕНКА_ПРАВИЛА (НАЙТИ(CAAR (СADR ПРАВИЛО_ЕСЛИ)) СТЕК_ФАКТОВ) ПРАВИЛО_ЕСЛИ] (DEF ОЦЕНКА_ПРАВИЛА (LAMBDA(ЭЛЕМЕНТ_КОНТЕКСТА ПРАВИЛО_ЕСЛИ) (COND ((NULL ЭЛЕМЕНТКОНТЕКСТА) ПРАВИЛО_ЕСЛИ) (Т(COND ((EQ(CAR(CDAR(CADR ПРАВИЛО_ЕСЛИ))) (CAR(CDDR ЭЛЕМЕНТ_КОНТЕКСТА))) (ЗНАЧЕНИЕ_ПРАВИЛА(LIST(CAR ПРАВИЛО_ЕСЛИ) (CDR(CADR ПРАВИЛО_ЕСЛИ))) СТЕК_ФАКТОВ)) (Т 'НЕТ] Эта функция наиболее сложная из всех рассмотренных функций, поэтому целесообразно на ее примере рассмотреть дополнительные возможности по испытанию функций. Преды¬ дущие примеры испытаний функций позволяли только конста¬ тировать работает функция или нет. Не было возможности анализа самого процесса работы функции. Перед анализом функций ЗНАЧЕНИЕ-ПРАВИЛА и ОЦЕНКА-ПРАВИЛА введем вспомогательную функцию RE¬ PORT, описанную в работе [22]: (DEF REPORT(LAMBDA(REP) (PROG(INPUT) (PRINT REP)(TERPR) LOOP(SETQ INPUT(READ)) (COND((AND(NULL(ATOM INPUT)) (EQ(CAR INPUT)'REPORT)) (RETURN(EVAL(CADR INPUT)))) (T(PRINT(EVAL INPUT))(TERPR))) (GO LOOP)))) Когда встречается функция REPORT, она печатает свой ар¬ гумент и входит в цикл. На каждом витке этого цикла пользо¬ ватель набирает на терминале выражение, и происходит рас¬ печатка его значения. С помощью вводимых выражений можно уточнить все интересующие пользователя значения переменных и функций к моменту включения функции REPORT. Можно изменить значения переменных, если это потребуется для от¬ ладки. Чтобы выйти из цикла, пользователю достаточно напе¬ чатать лишь (REPORT <любое S — выражение>), тогда функция RE¬ PORT возвратит значение этого выражения, и далее все пой¬ дет как обычно. 123
Отладочные функции обычно системно зависимы и намного сложнее простой функции REPORT, которая позволяет обнару¬ живать ошибки, встречающиеся при оценивании разрабатывае¬ мых функций, прежде чем они приведут к разрушению кон¬ текста, который эта функция позволяет проанализировать. Следует подчеркнуть, что без использования отладочных функций, подобных REPORT, отладка сложных программ очень затруднительна. Теперь приведем текст взаимно-рекурсивных функций ЗНА¬ ЧЕНИЕ-ПРАВИЛА и ОЦЕНКА-ПРАВИЛА с включенными от¬ ладочными функциями: (DEF ЗНАЧЕНИЕ_ПРАВИЛА(LAMBDA(ПРАВИЛО_ЕСЛИ СТЕК_ФАКТОВ) (COND ((REPORT '(НАЧАЛО ФУНКЦИИ ЗНАЧЕНИЕ_ПРАВИЛА))) ((NULL (CADR ПРАВИЛО_ЕСЛИ))'ДА) ((REPORT '(ПРАВИЛО_ЕСЛИ НЕ ПУСТО))) (Т(ОЦЕНКА_ПРАВИЛА (НАЙТИ(CAAR(CADR ПРАВИЛО_ЕСЛИ)) СТЕК_ФАКТОВ) ПРАВИЛО_ЕСЛИ] (DEF ОЦЕНКА_ПРАВИЛА(LAMBDA(ЭЛЕМЕНТ_КОНТЕКСТА ПРАВИЛО_ЕСЛИ) (COND ((REPORT '(НАЧАЛО ФУНКЦИИ ОЦЕНКА_ПРАВИЛА))) ((NULL ЭЛЕМЕНТ_КОНТЕКСТА) ПРАВИЛО_ЕСЛИ) (Т(COND ((REPORT '(АТРИБУТ НАЙДЕН В СТЕКЕ ФАКТОВ))) ((EQ(CAR(CDAR(CADR ПРАВИЛО_ЕСЛИ))) (CAR(CDDR ЭЛЕМЕНТ_КОНТЕКСТА))) (ЗНАЧЕНИЕ_ПРАВИЛА(LIST(CAR ПРАВИЛО_ЕСЛИ) (CDR(CADR ПРАВИЛО_ЕСЛИ))) СТЕК_ФАКТОВ)) ((REPORT '(ЗНАЧЕНИЯ АТРИБУТОВ НЕ СОВПАЛИ))) (Т 'НЕТ] С помощью функций REPORT можно полностью проанали¬ зировать процесс работы этих функций. Во всех случаях при¬ менения функций REPORT в этом примере выход из них дол¬ жен осуществляться с помощью пустых выражений (REPORT ‘ ( ) ), имеющих значение NIL. Функция ОБРАБОТКА-ПРАВИЛА вызывается функцией ПОИСК-И_ОБРАБОТКА_ПРАВИЛА и организована на основе гетерархического принципа управления, при котором вспомо¬ гательные функции (ПРАВИЛО-ИСТИНА, ПРАВИЛО-ЛОЖЬ, ПРАВИЛО-НЕОПРЕДЕЛЕНО) включаются только при появ¬ лении необходимых условий. Если условия запуска очередной функции не выполняются, то функция выдает значение NIL, благодаря чему функция COND передает управление своей следующей строке. Аргументами функции являются ЗНАЧЕ- 124
i НИЕ-ПРАВИЛА и ПРАВИЛО-ТО, значения которых опреде¬ ляются при вызове функции ОБРАБОТКА-ПРАВИЛА функци¬ ями с соответствующими названиями: (OEF ОБРАБОТКА_ПРАВИЛА (LAMBDA (ЗНАЧЕНИЕ_ПРАВИЛА ПРАВИЛО ТО), i (COND ((NULL ЗНАЧЕНИЕ_ПРАВИЛА) NIL) ((ПРАВИЛО_ИСТИНА ЗНАЧЕНИЕ_ПРАВИЛА ПРАВИЛО_ТО)) ((ПРАВИЛО_ЛОЖЬ ЗНАЧЕНИЕ_ПРАВИЛА ПРАВИЛО_ТО)) (. (ПРАВИЛО_НЕОПРЕДЕЛЕНО ЗНАЧЕНИЕ_ПРАВИЛА] 1 Таким образом, функция ОБРАБОТКА-ПРАВИЛА в зави- | симости от значения правила проводит соответствующие дей- ствия. Функция ПРАВИЛО-ИСТИНА включается при значении оцениваемого правила ДА и записывает в стек фактов атри¬ бут и его значение из части ТО правила и номер правила (т. е. , реализует правило modus ponens), выталкивает из стека це¬ лей достигнутую цель и, если стек целей становится пустым, то устанавливает признак ГОТОВНОСТЬ: I DEF ПРАВИЛО_ИСТИНА (LAMBDA (ЗНАЧЕНИЕ_ПРАВИЛА ПРАВИЛО_ТО) (COND ((AND (АТОМ ЗНАЧЕНИЕ_ПРАВИЛА) (EQ ЗНАЧЕНИЕ_ПРАВИЛА 'ДА)) (SETQ СТЕК_4> АКТОВ (CONS(CONS(CAR ПРАВИЛО_ТО) (CAR(СADR ПРАВЙЛО_ТО))) СТЕК_ФАХТОВ)) (SETQ СТЕК_ЦЕЛЕЙ(CDR СТЕК_ЦЕЛЕЙ)) (COND ((NULL СТЕК_ЦЕЛЕЙ)(SETQ ГОТОВНОСТЬ Т)) (ТТ))) (Т NIL] Если значение правила не равно ДА, то функция ПРА¬ ВИЛО-ИСТИНА описанные действия не производит, а выдает значение NIL. Проверка равенства значения правила значению ДА осуще¬ ствляется функцией AND, при этом вначале проверяется явля¬ ется ли ЗНАЧЕНИЕ-ПРАВИЛА атомом и в случае успеха проводится сравнение со значением ДА. Функция ПРАВИЛО-ЛОЖЬ включается при значении пра¬ вила НЕТ и добавляет номер правила в список ПАССИВНЫЕ- ПРАВИЛА. Если же значение правила не равно НЕТ, то функция < описанное действие не производит, а выдает значение NIL: 125
(DEF ПРАВИЛО_ЛОЖЬ (LAMBDA (ЗНАЧЕНИЕ_ПРАВИЛА ПРАВИЛО_ТО) (COND ((AND(АТОМ ЗНАЧЕНИЕ_ПРАВИЛА) (EQ ЗНАЧЕНИЕ_ПРАВИЛА 'НЕТ)) (SETQ ПАССИВНЫЕ_ПРАВИЛА (CONS(CAR ПРАВИЛО_ТО)ПАССИВНЫЕ ПРАВИЛА))) (Т NIL] Функция ПРАВИЛО-НЕОПРЕДЕЛЕНО включается при не¬ определенном значении правила, в качестве которого, как было указано выше, функция ЗНАЧЕНИЕ-ПРАВИЛА выдает неоцененную часть части ЕСЛИ правила. В результате сраба¬ тывания функции ПРАВИЛО-НЕОПРЕДЕЛЕНО в стек целей записывается первый атрибут и номер правила из ПРАВИЛА- ЕСЛИ, т. е. устанавливается текущая цель вывода: (DEF ПРАВИЛО_НЕОПРЕДЕЛЕНО(LAMBDA(ЗНАЧЕНИЕ ПРАВИЛА) (SETQ СТЕК_ЦЕЛЕЙ(CONS(LIST(CAR ЗНАЧЕНИЕ_ПРАВИЛА) (CAAR(CADR ЗНАЧЕНИЕ_ПРАВИЛА)))СТЕК_ЦЕЛЕЙ] Функция ОТВЕТ-НА-ПОДСКАЗКУ запускается функцией ВЫВОД, и при этом с помощью функции ПОДСКАЗКА опре¬ деляется значение аргумента ПОДСКАЗКА для текущей цели вывода: (DEF 0ТВЕТ_НА_П0ДСКАЗКУ(LAMBDA(АТРИБУТ ПОДСКАЗКА) (COND (ПОДСКАЗКА(ПОЛУЧИТЬ_ОТВЕТ АТРИБУТ ПОДСКАЗКА)) (Т NIL] В процессе работы функции ОТВЕТ_НА_ПОДСКАЗКУ про¬ водится проверка с помощью функции COND значения аргу¬ мента ПОДСКАЗКА и если оно NIL, то никаких действий не выполняется и выдается значение NIL, в остальных случаях осуществляется запуск функции ПОЛУЧИТЬ_ОТВЕТ: (DEF ПОЛУЧИТЬ_ОТВЕТ (LAMBDA(АТРИБУТ ПОДСКАЗКА) (PROG(ОТВЕТ ) (PRINT ПОДСКАЗКА)(TERPR) (SETQ ОТВЕТ(CAR(READ))) (SETQ СТЕК_*АКТОВ(CONS(CONS 0(LIST АТРИБУТ ОТВЕТ)) СТЕК_ФАКТОВ)) (SETQ СТЕК_ЦЕЛБЙ(CDR. СТЕК ЦЕЛЕЙ)) (COND ((NULL СТЕК_ЦЕЛЕЙ)(SETQ ГОТОВНОСТЬ Т)) (Т Т)) (RETURN ОТВЕТ] 126
Функция ПОЛУЧИТЬ-ОТВЕТ обеспечивает диалог пользо¬ вателя с экспертной системой и кроме ввода значения ответа Пользователя она должна обеспечить возможность объяснений. Реализация блока пояснений будет рассмотрена в п. 3.4, по¬ этому здесь приводится упрощенный вариант (замещающий Модуль) функции. Входными аргументами являются атрибут и соответствующая ему подсказка. Так как в процессе работы функции надо выполнить ряд последовательных действий, В частности печатей, то для организации функции используется PROG-выражение и вводится локальная переменная ОТВЕТ. Вводимый ответ пользователя обрабатывается функцией CAR, поскольку, как уже указывалось, оператор ввода воспри¬ нимает только S-выражения, т. е. ответ вводится в круглых скобках, которые с помощью функции CAR удаляются. Атрибут, его значение, заданное пользователем, и номер О,, означающий, что значение атрибута задано пользователем, вво¬ дится в стек фактов. Так как очередная цель достигнута, то она удаляется из стека целей и проводится проверка, не явля¬ ется ли эта цель последней с соответствующей установкой признака готовности. На этом заканчивается описание всех функций, необходимых для реализации логического вывода. Следует отметить, что в процессе разработки и реализации каждой функции должен быть предусмотрен этап ее испытаний на тестовых примерах по аналогии с примерами, приведен¬ ными в п. 3.2 и п. 3.3. Если функция не удовлетворяет тесто¬ вым примерам, а эти примеры верны, то, введя в текст функ¬ ции отладочную функцию REPORT, необходимо провести от¬ ладку функции. Для проведения испытаний блока логического вывода надо подготовить файл (INP1. LSP) исходных данных по аналогии с программой интерпретации предложений из п. 3.2. Все выше приведенные функции должны быть записаны в некий файл и введены в ЛИСП-систему. Запуск блока логического вывода осуществляется следующим образом: ->-(ЭС). Все ответы на запросы системы должны даваться в круг¬ лых скобках. Правильность работы системы можно проверить по тесто¬ вым примерам, приведенным в табл. 1.4, 1.5. В «традиционных» программах, о которых шла речь в п. 1.1* обычно используется иерархическая структура. При управле¬ нии процессом решения от данных, например, при реализации логического вывода, такая централизованная организация ста¬ новится неприемлемой. В этом случае используют гетерархи¬ ческую структуру, при которой программа выглядит как демократическое сообщество сотрудничающих между собой под¬ программ. При гетерархическом программировании руковод¬ ствуются следующими принципами [22]: 12 Т
функции управления должны быть распределены; процедуры строятся вокруг целей; в процедурах должно быть как можно меньше предположе¬ ний относительно ситуации в системе на момент, когда они вызываются; между процедурами должны свободно циркулировать со¬ веты, предположения и жалобы; система должна иметь возможность для построения вре¬ менных заключений; система должна содержать достаточно сведений о самой себе, чтобы устранять некоторые из своих ошибок. В общем, гетерархия приводит к более гибким программам, тогда как иерархия обеспечивает эффективность программ в ситуациях, когда гибкость не требуется. Описанная система логического вывода не является гете¬ рархической в чистом виде, так как в ней в явной форме нет представления о самой себе и отсутствуют характерные потоки советов, предположений, жалоб, замечаний и критики. Тем не менее некоторые элементы гетерархического программирования в ней имеются. Так, функции управления распределены по си¬ стеме. Модули взаимодействуют, как совокупность равноправ¬ ных подпрограмм. Графически система скорее напоминает сеть процедур, чем структуру с главной программой и подпрограм¬ мами, вызываемыми в строго определенном и неизменном по¬ рядке. Процедуры связаны с другими процедурами посредст¬ вом звеньев потенциальной передачи управления, используемых в соответствии с контекстом, который определяется совместно системой и той задачей, которая решается. Кроме того, си¬ стема является целенаправленной. Процедуры на всех уровнях весьма короткие и связаны с достижением определенных це¬ лей. Цели достигаются либо путем формулирования неболь¬ шого числа подцелей для других процедур, либо путем пря¬ мого обращения к нескольким элементарным единицам. Сами процедуры содержат в себе необходимую информа¬ цию для формулирования условий, при которых они способны выполнить свою работу. Это делается посредством специфика¬ ций, расположенных в начале процедуры. Обычно достаточно простого обращения к базе данных, чтобы убедиться, что си¬ стема находится в состоянии, обеспечивающем нормальную работу процедуры, а если нет, то вызываются соответствующие предваряющие процедуры. Таким образом, видно, что имеется много общих черт в ор¬ ганизации работы самой экспертной системы, трансляторов с языков эксперта и пользователя, а также блока логического вывода,-являющегося фактически интерпретатором правил про¬ дукций. Коротко это объясняется тем, что во всех этих случаях управление идет от данных. 128
3.4. РЕАЛИЗАЦИЯ БЛОКА ОБЪЯСНЕНИИ И ЯЗЫКА ПОЛЬЗОВАТЕЛЯ Синтаксические диаграммы языка пользователя приведены на рис. 1.11. Отличие реализуемого на ЛИСПе языка пользова¬ теля будет состоить в том, что все задаваемые пользователем символы и слова должны быть заключены в круглые скобки. Управление диалогом между пользователем и экспертной си¬ стемой осуществляется функцией ПОЛУЧИТЬ-ОТВЕТ, полный текст описания которой с учетом рис. 1.11 приведен ниже. Она фактически реализует режим интерпретации предложений языка пользователя, связанных с установкой режима диалога. Режим интерпретации (в отличие от режима компиляции) позволяет организовать дружественный диалог с исправлением ошибок пользователя и с организацией повторных запросов: (DEF ПОЛУЧИТЬ_ОТВЕТ (LAMBDA(АТРИБУТ ПОДСКАЗКА) ' (PROG(ОТВЕТ СН) ЦИКЛ(PRINT ПОДСКАЗКА)(TERPR) (PRINT '(ЕСЛИ БУДЕТЕ ОТВЕЧАТЬ,ТО ВВЕДИТЕ #)) (TERPR) (PRINT '(ЕСЛИ БУДЕТЕ СПРАШИВАТЬ,ТО ВВЕДИТЕ ?)) (TERPR) (SETQ СН(CAR(READ))) (COND ((MEMBER СН '(# ?)) (COND ((EQ CH '?)(ОБЪЯСНЕНИЕ СТЕК_ЦЕЛЕЙ) (GO ЦИКЛ)) ((EQ CH '#)(PRINT ПОДСКАЗКА)(TERPR) (PRINT '(ОТВЕЧАЙТЕ))(TERPR) (SETQ ОТВЕТ(CAR(READ))) (SETQ CTEK_*AKTOB(CONS(CONS 0 (LIST АТРИБУТ ОТВЕТ)) СТЕК_ФАКТОВ)) (SETQ СТЕК_ЦЕЛЕЙ(CDR СТЕК_ЦЕЛЕЙ)) (COND ((NULL СТЕК_ЦЕЛЕЙ)(SETQ ГОТОВНОСТЬ T)) (T Т) ) (RETURN ОТВЕТ)))) (Т(PRINT '(ВВЕДЕН НЕВЕРНЫЙ СИМВОЛ))(TERPR))) (GO ЦИКЛ] В этой функции организован не рекурсивный цикл, а цикл с использованием функции GO, передающей управление функ¬ ции, помеченной атомом ЦИКЛ. Это сделано для того, чтобы неверные ответы пользователя в рекурсивном цикле не зани¬ мали зря память. Читателю же в качестве упражнения рекомен¬ дуется попробовать избавиться от функции GO. 9 В. Э. Балтрашевич 129
Функция ОБЪЯСНЕНИЕ реализует интерпретатор вопроси- тельных предложений языка пользователя в соответствии с син¬ таксическими диаграммами, приведенными на рис. 1.11. Следует подчеркнуть, что введение в качестве аргумента функции СТЕКА-ЦЕЛЕЙ позволяет фактически при объяснениях рабо¬ тать с копией основного стека целей без его изменения. После каждого вопроса ПОЧЕМУ из копии стека целей удаляется один элемент, и пользователь может проследить всю историю вы¬ вода. (DEF ОБЪЯСНЕНИЕ(LAMBDA(СТЕК_ЦЕЛЕЙ)(PROG(ОТВЕТ) ЦИКЛ(PRINT'(ЖДУ ВОПРОСОВ(ПОЧЕМУ,КАК,НЕТ)))(TERPR) (SETQ ОТВЕТ(CAR(READ))) (COND ((MEMBER ОТВЕТ '(ПОЧЕМУ КАК НЕТ)) (COND ((EQ ОТВЕТ 'ПОЧЕМУ)(ПОЧЕМУ СТЕК_ЦЕЛЕЙ) (SETQ СТЕК_ЦЕЛЕЙ(CDR СТЕК_ЦЕЛЕЙ))) ((EQ ОТВЕТ 'КАК) (PRINT '(ЗАДАЙТЕ НАЗВАНИЕ АТРИБУТА)) (TERPR) (КАК (CAR(READ))СТЕК_ФАКТОВ)) ((EQ ОТВЕТ 'НЕТ)(RETURN)))) (Т(PRINT '(НЕВЕРНЫЙ СИМВОЛ))(TERPR))) (GO ЦИКЛ] Цикл в функции ОБЪЯСНЕНИЕ организован аналогично циклу функции ПОЛУЧИТЬ-ОТВЕТ по аналогичным причинам. Функция ОБЪЯСНЕНИЕ использует две функции COND. С по¬ мощью первой определяется, входит ли вопрос пользователя в множество возможных вопросов (ПОЧЕМУ, КАК, НЕТ) и если не входит, то выдается сообщение о неверном символе и пользователю предоставляется возможность задать вопрос пра¬ вильно. Если вопрос задан правильно, то с помощью второй функции COND определяется, какой конкретно вопрос задан и производится запуск соответствующей функции ПОЧЕМУ или КАК. Функция ПОЧЕМУ обслуживает вопросы пользователя с аналогичным названием и обеспечивает прослеживание исто¬ рии вывода, (см. п. 1.4). Если стек целей пуст или номер пра¬ вила в верхнем элементе стека целей равен нулю, т. е. цель за¬ давалась пользователем, то выдается сообщение «Вы этого хо¬ тели сами». Если стек не пуст, то распечатывается цель, т. е. атрибут, находящийся в вершине стека, и номер правила, по¬ местившего его туда. Затем выдается текст этого правила с по¬ мощью функции ПЕЧАТЬ-ПРАВИЛА, которой в качестве аргу¬ ментов передаются НОМЕР-ПРАВИЛА и ПРАВИЛА: 130
(DEF ПОЧЕМУ(LAMBDA(СТЕК_ЦЕЛЕЙ) (COND ((OR(NULL СТЕК_ЦЕЛЕЙ) (EQ(CAAR СТЕК_ЦЕЛЕЙ)'0)) (PRINT'(ВЫ ЭТОГО ХОТЕЛИ САйИ))(TERPR)) (Т(PRINT'(ЦЕЛЬ))(PRINT(CDAR СТЕК_ЦЕЛЕЙ))(TERPR) (PRINT'(ПРАВИЛО))(PRINT(CAAR СТЕК_ЦЕЛЕЙ)) (PRINT'(ГЛАСИТ))(TERPR) (ПЕЧАТЬ_ПРАВИЛА (CAAR СТЕК_ЦЕЛЕЙ) ПРАВИЛА] Рекурсивная функция ПЕЧАТЬ-ПРАВИЛА осуществляет поиск среди имеющихся правил правила с заданным номером: (DEF ПЕЧАТЬ_ПРАВИЛА(LAMBDA(НОМЕР_ПРАВИЛА ПРАВИЛА) (COND ((NULL ПРАВИЛА) (PRINT'(ПРАВИЛА С ТАКИМ НОМЕРОМ НЕТ))(TERPR)) ((EQ НОМЕР_ПРАВИЛА(CAAR ПРАВИЛА)) (PRINT'(ЕСЛИ)) (ПЕЧАТЬ_СПИСКА(CAR(CDAR ПРАВИЛА)))(TERPR) (PRINT'(ТО)) (ПЕЧАТЬ_СПИСКА(CADR(CDAR ПРАВИЛА)))(TERPR)) (Т(ПЕЧАТЬ_ПРАВИЛА НОМЕР_ПРАВИЛА(CDR ПРАВИЛА] Если такого правила не найдено, то выдается соответствую¬ щее сообщение, а в случае успеха производится печать сначала части ЕСЛИ правила, а затем части ТО с помощью функции ПЕЧАТЬ-СПИСКА: (DEF ПЕЧАТЬ_СПИСКА(LAMBDA(СПИСОК) (COND ((NULL СПИСОК)Т) (Т(ПЕЧАТЬ_АТРИБУТА(CAAR СПИСОК) (ПЕРЕВОД(CAAR СПИСОК) ПЕРЕВОДЫ)) (PRINT(CDAR СПИСОК))(TERPR) (ПЕЧАТЬ_СПИСКА(CDR СПИСОК] Рекурсивная функция ПЕЧАТЬ-СПИСКА осуществляет дей¬ ствия, определяемые ее названием, при этом под списком пони¬ мается либо часть ЕСЛИ, либо часть ТО правила. Особенно¬ стью печати является то, что вместо атрибута печатается его перевод, если он имеется. Поиск перевода осуществляется функ¬ цией ПЕРЕВОД. Функция ПЕЧАТЬ-АТРИБУТА получает в качестве аргумен¬ тов атрибут и соответствующий ему перевод. Если перевод от¬ сутствует (NIL), то просто печатается сам атрибут, в противном случае печатаются и атрибут и его перевод. Эта двойная печать объясняется тем, что перевод атрибута облегчает пользователю восприятие текста распечатываемого правила, но, как видно из 131 9»
синтаксических диаграмм, в текст вопроса КАК должен входить атрибут, а по переводу пользователь может не понять, как точно называется атрибут: (DEF ПЕЧАТЬ_АТРИБУТА(LAMBDA(АТРИБУТ ПЕРЕВОД) (COND ((NULL ПЕРЕВОД)(PRINT АТРИБУТ)) (Т(PRINT АТРИБУТ)(PRINT ПЕРЕВОД] ^ Функция КАК обеспечивает ответ на соответствующий воп¬ рос пользователя об атрибуте, являющимся параметром этой функции. Она оформлена в виде PROG-выражения для того, чтобы ввести две вспомогательные переменные: ЭЛЕМЕНТ и ПРАВИЛОК Структура действий, выполняемых в результате работы функции КАК, определяется функцией COND. Вначале с помощью функции НАЙТИ осуществляется поиск атрибута в стеке фактов; в случае успеха переменной ЭЛЕМЕНТ присваи¬ вается значение соответствующего элемента стека фактов. Если атрибут в стеке фактов отсутствует, то с помощью функции ПРАВИЛО осуществляется поиск правила, в части ТО которого имеется необходимый атрибут. В случае успеха поиска в пере¬ менную ПРАВИЛ01 записывается значение соответствующего правила. Если атрибута нет в стеке фактов (значением перемен¬ ной ЭЛЕМЕНТ является NIL) и нет соответствующего правила (значением переменной ПРАВИЛСЯ является NIL), то по всегда истинному условию Т осуществляется печать сообщения о том, что значение атрибута может задать только пользователь: (DEF КАК(LAMBDA(АТРИБУТ СТЕК_ФАКТОВ) (PROG(ЭЛЕМЕНТ ПРАВИЛО1) (COND ((SETQ ЭЛЕМЕНТ(НАЙТИ АТРИБУТ СТЕК_ФАКТОВ)) (COND ((EQ(CAR ЭЛЕМЕНТ)'0) (PRINT '(ФРАЗА ОБОСНОВАНА ИНФОРМАЦИЕЙ ВВОДИМОЙ ПОЛЬЗОВАТЕЛЕМу (TERPR)) (Т(PRINT'{БЫЛО ИСПОЛЬЗОВАНО ПРАВИЛО)) (PRINT(CAR ЭЛЕМЕНТ))(TERPR) (ПЕЧАТЬ_ПРАВИЛА(CAR ЭЛЕМЕНТ)ПРАВИЛА)))) ((SETQ ПРАВИЛ01(ПРАВИЛО АТРИБУТ ПРАВИЛА)) (PRINT'(МОЖЕТ БУДЕТ ИСПОЛЬЗОВАНО ПРАВИЛО)) (PRINT(CAR ПРАВИЛ01))(TERPR) (ПЕЧАТЬ_ПРАВИЛА(CAR ПРАВИЛО1)ПРАВИЛА)) (Т(PRINT '(ДАННАЯ ФРАЗА МОЖЕТ БЫТЬ ОПРЕДЕЛЕНА ТОЛЬКО)) (TERPR) (PRINT '(С ПОМОЩЬЮ ИНФОРМАЦИИ ВВОДИМОЙ ПОЛЬЗОВАТЕЛЕМ)) (TERPR] 132
При реализации функции КАК в качестве условий функции COND использовалась функция SETQ, значение которой совпа¬ дает со значением ее аргументов. Если переменная ЭЛЕМЕНТ имеет значение, отличное от NIL, т. е. атрибут находится в стеке фактов, то срабатывает вто¬ рая функция COND, которая определяет, задавалась ли инфор¬ мация пользователем или нет, в зависимости от значения номера правила. На этом мы закончили разработку и реализацию инструмен¬ тальной экспертной системы (с упрощенным языком эксперта). Испытание блока пояснений фактически сводится к испытанию ((1((КЛАСС ГОЛОСЕМЯННЫЕ)(ФОРМА_ЛИСТА ЧЕШУЕОБРАЗНАЯ)) ((СЕМЕЙСТВО КИПАРИСОВЫЕ))) (2((КЛАСС ГОЛОСЕМЯННЫЕ)(ФОРМА_ЛИСТА ИГЛОПОДОБНАЯ) (КОНФИГУРАЦИЯ ХАОТИЧЕСКАЯ)) ((СЕМЕЙСТВО СОСНОВЫЕ))) (3((КЛАСС ГОЛОСЕМЯННЫЕ)(ФОРМА_ЛИСТА ИГЛОПОДОБНАЯ) (КОНФИГУРАЦИЯ ДВА_РОВНЫХ_РЯДА)(СЕРЕБРИСТАЯ_ПОЛОСА ДА)) ((СЕМЕЙСТВО СОСНОВЫЕ))) (4((КЛАСС ГОЛОСЕМЯННЫЕ)(ФОРМА_ЛИСТА ИГЛОПОДОБНАЯ) (КОНФИГУРАЦИЯ ДВА_РОВНЫХ_РЯДА)(СЕРЕБРИСТАЯ_ПОЛОСА НЕТ)) ((СЕМЕЙСТВО БОЛОТНЫЙ_КИПАРИС))) (5((ТИП ДЕРЕВЬЯ)(ШИРОКАЯ_И_ПЛОСКАЯ ДА)) ((КЛАСС ПОКРЫТОСЕМЯННЫЕ))) (б((ТИП ДЕРЕВЬЯ)(ШИРОКАЯ_И_ГШОСКАЯ НЕТ)) ((КЛАСС ГОЛОСЕМЯННЫЕ))) ( 7 ((СТЕБЕЛЬ ЗЕЛЕНЫЙ).) ( (ТИП ТРАВЯНИСТЫЕ) ) ) (8((СТЕБЕЛЬ ДРЕВЕСНЫЙ)(ПОЛОЖЕНИЕ СТЕЛЮЩЕЕСЯ)) ((ТИП ЛИАНЫ))) (9((СТЕБЕЛЬ ДРЕВЕСНЫЙ)(ПОЛОЖЕНИЕ ПРЯМОСТОЯЩЕЕ) (ОДИН_ОСНОВНОЙ_СТВОЛ ДА))((ТИП ДЕРЕВЬЯ))) (10((СТЕБЕЛЬ ДРЕВЕСНЫЙ)(ПОЛОЖЕНИЕ ПРЯМОСТОЯЩЕЕ) (ОДИН_ОСНОВНОЙ_СТВОЛ НЕТ))((ТИП КУСТАРНИКОВЫЕ] ((СТЕБЕЛЬ (КАКОЙ СТЕБЕЛЬ У РАСТЕНИЯ ДРЕВЕСНЫЙ ИЛИ ЗЕЛЕНЫЙ?)) (ПОЛОЖЕНИЕ (КАКОЕ ПОЛОЖЕНИЕ СТЕБЛЯ ПРЯМОСТОЯЩЕЕ ИЛИ СТЕЛЮЩЕЕСЯ?)) (ОДИН_ОСНОВНОЙ_СТВОЛ (ИМЕЕТ ЛИ РАСТЕНИЕ ОДИН ОСНОВНОЙ СТВОЛ?(ДА/НЕТ))) (ШИРОКАЯ_И_ПЛОСКАЯ (ИМЕЮТ ЛИ ЛИСТЬЯ ШИРОКУЮ И ПЛОСКУЮ ФОРМУ?(ДА/НЕТ))) (ФОРМА_ЛИСТА (КАКАЯ ФОРМА ЛИСТА ЧЕШУЕОБРАЗНАЯ ИЛИ ИГЛОПОДОБНАЯ?)) (КОНФИГУРАЦИЯ (КАКАЯ КОНФИГУРАЦИЯ РАСПОЛОЖЕНИЯ ИГЛ ХАОТИЧЕСКАЯ ИЛИ ДВА_РОВНЫХ_РЯДА?)) (СЕРЕБРИСТАЯ_ПОЛОСА (ИМЕЕТСЯ ЛИ СЕРЕБРИСТАЯ ПОЛОСА СНИЗУ ИГЛЫ?(ДА/НЕТ)] '() 133
всей системы. В качестве начального примера можно взять при¬ мер из п. 1.4, но при этом надо учитывать, что файл исходных данных должен быть представлен с учетом ограничений реали¬ зованной системы. Затем можно проверить работу системы на основе примера из области ботаники (см. стр. 134). 3.5. РЕАЛИЗАЦИЯ ЯЗЫКА ЭКСПЕРТА В п. 3.2 был описан упрощенный компилятор с языка эксперта, использующий совпадение внутреннего и внешнего представлений знаний. Этот компилятор накладывал очень силь¬ ные ограничения на форму представления знаний, так как все правила, подсказки и переводы должны быть записаны в ука¬ занные группы и в указанном порядке. Рассмотрим возможность создания компилятора и языка внешнего представления зна¬ ний, которые позволят записывать правила, подсказки и пере¬ воды в произвольном порядке без обязательного объединения в группы. Внутреннее представление знаний остается преж¬ ним. На основании синтаксических диаграмм (см. рис. 1.6) и огра¬ ничений, накладываемых языком ЛИСП (точнее функцией READ, которая вводит только S-выражения) были разработаны синтаксические диаграммы языка эксперта, приведенные на рис. 3.1. Предложение Подекадна (()—(Поде — Атрибут —— Текст —(3^— ^3^ Перебод ^—(Перевод —(х)—{Атрибут |—[Текст |—(3)—(J)- ПраВило— \число Часть -Если | Часть - 7Ь~| Часть-Если / Часть-То, ^ 1 Значение —\Атри5ут\— ■о -(C)—— >4/77/7^5^/77 —[Значение—() ()- Атрибут . Текст гtt-z 1 ’Значение 1 Атом | 1о-Выражение]- Рис. 3.1. Синтаксические диаграммы языка эксперта 134
В новых диаграммах отсутствует признак конца строки, что позволяет записывать компоненты предложений языка в про¬ извольном порядке. Реализацию языка эксперта будем проводить по принципу сверху вниз. Начнем с функции ПРОВЕРКА, которая позволяет проверить работоспособность разработанного компилятора. Так как в процессе работы этой функции должен быть выполнен це¬ лый ряд последовательных действий, то она реализуется с по¬ мощью PROG-выражения. В процессе работы происходит открытие и закрытие файла INPA. LSP, в котором находятся знания, представленные на языке эксперта. Ввод знаний и компоновка их в соответствующие списки ПРАВИЛА, ПОДСКАЗКИ и ПЕРЕВОДЫ проводится в резуль¬ тате выполнения функции ВВОД-ЗНАНИИ. Затем осуществля¬ ется проверочная печать сформированных списков. Функция ПРОВЕРКА всегда принимает значение Т, а все указанные действия являются побочным эффектом ее выпол¬ нения: (DEF ПРОВЕРКА(LAMBDA()(PROG(ПРАВИЛА ПОДСКАЗКИ ПЕРЕВОДЫ ) (INFILE 'INPA) (ВВОД_ЗНАНИЙ (READ INPA)) (CLOSE INPA) (PRINT 'ПРАВИЛА)(PRINT ПРАВИЛА)(TERPR) (PRINT 'ПОДСКАЗКИ)(PRINT ПОДСКАЗКИ)(TERPR) (PRINT 'ПЕРЕВОДЫ)(PRINT ПЕРЕВОДЫ)(TERPR) (RETURN T] Рекурсивная функция ВВОД-ЗНАНИИ обеспечивает ввод предложений (S-выражений) из входного файла до появления признака конца файла EOF. Каждое введенное предложение пе¬ редается функции КОМПИЛЯЦИЯ для обработки: (DEF ВВ0Д_ЗНАНИЙ(LAMBDA(ПРЕДЛОЖЕНИЕ) (COND ((NULL ПРЕДЛОЖЕНИЕ)(PRINT '(ПУСТОЕ ПРЕДЛОЖЕНИЕ)) (TERPR)Т) ((АТОМ ПРЕДЛОЖЕНИЕ) (COND ((EQ ПРЕДЛОЖЕНИЕ 'EOF)(PRINT '(КОНЕЦ ФАЙЛА)) (TERPR)T) (Т(PRINT '(ОШИБОЧНОЕ ПРЕДЛОЖЕНИЕ)) (PRINT ПРЕДЛОЖЕНИЕ) (TERPR)T))) (Т(КОМПИЛЯЦИЯ ПРЕДЛОЖЕНИЕ)(ВВОД_ЗНАНИЙ(READ INPA] 135
Функция КОМПИЛЯЦИЯ предназначена для реализации синтаксических диаграмм (см. рис. 3.1) и с помощью функции COND проводит анализ первого элемента предложения и в зави¬ симости от его значения начинает обработку либо подсказки, либо перевода, либо правила, либо выдает сообщение об ошибке в первом слове текущего предложения с распечаткой ошибоч¬ ного предложения: (DEF КОМПИЛЯЦИЯ(LAMBDA(ПРЕДЛОЖЕНИЕ) (COND ( (EQ (CAR ПРЕДЛОЖЕНИЕ) 'ПОДСКАЗКА) (COND ( (ПРОВЕРКА__АТРИБУТА (CAR (С ADR ПРЕДЛОЖЕНИЕ) ) 'ПОДСКАЗКА)) ((ПРОВЕРКА_ТЕКСТА(CADR(CADR ПРЕДЛОЖЕНИЕ)) 'ПОДСКАЗКА)) ((ЗАПИСЬ_П0ДСКАЗКИ (CADR ПРЕДЛОЖЕНИЕ))))) ((EQ (CAR ПРЕДЛОЖЕНИЕ) 'ПЕРЕВОД) (COND ((ПРОВЕРКА_АТРИБУТА(CAR(CADR ПРЕДЛОЖЕНИЕ)) 'ПЕРЕВОД)) ((ПРОВЕРКА_ТЕКСТА(CADR(CADR ПРЕДЛОЖЕНИЕ)) 'ПЕРЕВОД)) ( (ЗАПИСЬ_ПЕ РЕ ВОДА (CADR ПРЕДЛОЖЕНИЕ) ) ) ) ) ( (NUMBERP (CAR ПРЕДЛОЖЕНИЕ)) (COND ((ПРОВЕРКА_ЧАСТИ_ЕСЛИ(CADR ПРЕДЛОЖЕНИЕ))) ((ПРОВЕРКА_ЧАСТИ_ТО(CAR(CDDR ПРЕДЛОЖЕНИЕ))) ( (ЗАПИСЬ_ПРАВИЛА ПРЕДЛОЖЕНИЕ )))) (Т(PRINT '(ОШИБКА В ПЕРВОМ СЛОВЕ ПРЕДЛОЖЕНИЯ)) (PRINT ПРЕДЛОЖЕНИЕ)(TERPR)T] При обработке предложений всех типов используется выше — описанный прием гетерархического управления. Обработка каждого предложения управляется функцией COND, каждая строка которой состоит из одного элемента. Все функции, обрабатывающие соответствующие части соответст¬ вующего предложения, в случае успешного завершения своей работы принимают значение NIL, благодаря чему функция COND передает управление следующей функции обработки. Обработка каждого предложения завершается соответствующей семантической функцией, которая при успешном завершении своей работы принимает значение, отличное от NIL, которое и является значением функции КОМПИЛЯЦИЯ. Функция ПРОВЕРКА-АТРИБУТА проверяет синтаксиче¬ скую правильность записи атрибута в предложении языка эксперта. С помощью функции COND вначале проверяется, имеет ли атрибут значение, отличное от NIL и, если атрибут от¬ Д36
сутствует, выдается соответствующее сообщение. При наличии атрибута проверяется, является ли он атомом; если является, то проверка считается успешной, и с учетом выше описанной орга¬ низации функции КОМПИЛЯЦИЯ функция ПРОВЕРКА-АТРИ¬ БУТА принимает значение NIL: (DEF ПРОВЕРКА_АТРИБУТА(LAMBDA(АТРИБУТ ТИП ПРЕДЛОЖЕНИЯ) (COND (АТРИБУТ (COND ((АТОМ АТРИБУТ) NIL ) (Т(PRINT '(АТРИБУТ НЕ СЛОВО В )) (PRINT ТИП_ПРЕДЛОЖЕНИЯ)(TERPR)))) (Т(PRINT '(ОТСУТСТВУЕТ АТРИБУТ В)) (PRINT ТИП_ПРЕДЛОЖЕНИЯ)(TERPR)Т] I Функция ПРОВЕРКА_ТЕКСТА проверяет синтаксическую правильность текста в предложении «подсказка» или в предло¬ жении «перевод». В случае наличия текста функция ПРО¬ ВЕРКА-ТЕКСТА принимает значение NIL, в противном случае выдается соответствующее сообщение об ошибке: (DEF ПРОВЕРКА_ТЕКСТА(LAMBDA(ТЕКСТ ТИП ПРЕДЛОЖЕНИЯ) (COND (ТЕКСТ NIL) (Т(PRINT ' (ОТСУТСТВУЕТ ТЕКСТ В )) (PRINT ТИП_ПРЕДЛОЖЕНИЯ)(TERPR)Т] Функции ЗАПИСЬ-ПОДСКАЗКИ и ЗАПИСЬ-ПЕРЕВОДА проводят семантические действия, связанные с добавлением введенного и проверенного предложения в начало соответствую¬ щего списка (либо списка подсказок либо списка переводов): (DEF ЗАПИСЬ_П0ДСКАЗКИ(ЬАМВ0А(ПОДСКАЗКА) (SETQ ПОДСКАЗКИ(CONS ПОДСКАЗКА ПОДСКАЗКИ] (DEF ЗАПИСЬ_ПЕРЕВОДА(LAMBDA(ПЕРЕВОД) (SETQ ПЕРЕВОДЫ(CONS ПЕРЕВОД ПЕРЕВОДЫ] Рекурсивная функция ПРОВЕРКА-ЧАСТИ-ЕСЛИ реали¬ зует соответствующую диаграмму (см. рис. 3.1). Если часть ЕСЛИ правила пуста, проверка успешна, и с учетом вышеопи¬ санной организации функции КОМПИЛЯЦИЯ функция ПРО¬ ВЕРКА-ЧАСТИ-ЕСЛИ выдает значение NIL. Если же часть ЕСЛИ правила не пуста, то проводится проверка атрибута и его значения с помощью соответствующих функций и рекурсивное 137
обращение к функции ПРОВЕРКА-ЧАСТИ-ЕСЛИ, но уже с остатком части ЕСЛИ без первого элемента: (DEF ПРОВЕРКА_ЧАСТИ_ЕСЛИ(LAMBDA(ЧАСТЬ_ЕСЛИ) (COND ((NULL ЧАСТЬ_ЕСЛИ)NIL) (Т(COND ((ПРОВЕРКА_АТРИБУТА(CAAR ЧАСТЬ_ЕСЛИ) 'ПРАВИЛО)) ((ПР0ВЕРКА_ЗНАЧЕНИЯ(CAR(CDAR ЧАСТЬ_ЕСЛИ)))) (Т(ПРОВЕРКА_ЧАСТИ_ЕСЛИ(CDR ЧАСТЬ_ЕСЛИ] Функция ПРОВЕРКА-ЗНАЧЕНИЯ проверяет синтаксиче¬ скую правильность значения атрибута аналогично проверке пра¬ вильности атрибута, осуществляемой функцией ПРОВЕРКА- АТРИБУТА: (DEF ПР0ВЕРКА_ЗНАЧЕНИЯ(LAMBDA(ЗНАЧЕНИЕ) (COND (ЗНАЧЕНИЕ (COND ((АТОМ ЗНАЧЕНИЕ) NIL ) (Т(PRINT '(ЗНАЧЕНИЕ АТРИБУТА В ПРАВИЛЕ - НЕ СЛОВО)) (TERPR)))) (Т(PRINT '(ОТСУТСВУЕТ ЗНАЧЕНИЕ АТРИБУТА В ПРАВИЛЕ)) (TERPR)T] Функция ПРОВЕРКА-ЧАСТИ-ТО реализует соответствую¬ щую диаграмму (см. рис. 3.1) ив случае успеха выдает значе¬ ние NIL: (DEF ПРОВЕ РКА_ЧАСТИ_ТО(LAMBDA(ЧАСТЬ_ТО) (COND ((ПРОВЕРКА АТРИБУТА(CAAR ЧАСТЬ_ТО) 'ПРАВИЛО)) ((ПР0ВЕРКА~ЗНАЧЕНИЯ(CAR(CDAR ЧАСТЬ ТО)))) (Т NIL] Функция ЗАПИСЬ-ПРАВИЛА осуществляет добавление проверенного правила в конец списка ПРАВИЛА: (DEF ЗАПИСЬ_ПРАВИЛА(LAMBDA(ПРАВИЛО) (SETQ ПРАВИЛА(APPEND ПРАВИЛА (LIST ПРАВИЛО] На этом разработка и реализация компилятора завершена. Для осуществления его испытаний надо подготовить файл ис¬ ходных данных INPA. LSP, аналогичный следующему: 138
(1((ЧИСЛО ДА)(СЛОВО ТО))((ПРЕДЛОЖЕНИЕ ПРАВИЛО))) (ПОДСКАЗКА (ЧИСЛО(ПРЕДЛОЖЕНИЕ НАЧИНАЕТСЯ С ЧИСЛА?(ДА/НЕТ)))) (10((ПРЕДЛОЖЕНИЕ ПРАВИЛО))((ЯЗЫК ЭКСПЕРТА))) (ПЕРЕВОД(ЧИСЛО(ПРЕДЛОЖЕНИЕ НАЧИНАЕТСЯ С ЧИСЛА))) Все приведенные функии должны быть введены в ЛИСП-си- стему, например, с помощью какого-либо файла. Запуск проверки компилятора осуществляется следующим образом: -►(ПРОВЕРКА). 3.6. ОСНОВНАЯ ПРОГРАММА ИНСТРУМЕНТАЛЬНОЙ ЭКСПЕРТНОЙ СИСТЕМЫ После реализации блоков компилятора, логического вывода и пояснений можно записать основную программу (функцию) инструментальной экспертной системы: (DEF ИЭС(LAMBDA( ) (PROG(ГОТОВНОСТЬ ПАССИВНЫЕ_ПРАВИЛА СТЕК_ЦЕЛЕЙ СТЕК_ФАКТОВ ОСНОВНАЯ_ЦЕЛЬ ПРАВИЛА ПОДСКАЗКИ ПЕРЕВОДЫ) (INFILE 'INP) (ВВОД_ЗНАНИЙ(READ INP)) (CLOSE INP) (ВЫВОД ГОТОВНОСТЬ ОСНОВНАЯ_ЦЕЛЬ) (RETURN Т] Для проведения ее испытаний надо сформировать файл INP. LSP, содержащий, например, знания, приведенные в п. 3.2, но оформленные с учетом требований полного языка эксперта, приведенных в п. 3.5. Часто ЛИСП-системы обладают возможностью протоколиро¬ вания, т. е. записи всей информации, представляемой на экране дисплея, в специальный файл с последующим просмотром или печатью. Возможность протоколирования довольно полезна при изучении и документировании процесса функционирования экс¬ пертной системы. Запуск режима протоколирования в той версии ЛИСП-си¬ стемы, которой обладал автор, осуществляется следующим об¬ разом: -►(PROTOCOL), а его отмена — -► (UNPROTOCOL 1). Теперь можно подвести некоторые итоги реализации инстру¬ ментальной экспертной Системы на ЛИСПе. Реализация прово¬ 139
дилась на основе требований функционального программирова¬ ния с максимально возможным использованием композиции функций и с минимально возможным использованием оператора присваивания. В начале реализации была проведена разработка структур данных с учетом необходимых действий по их обработке. Вся задача была разбита на ряд основных подзадач: реализацию логического вывода; реализацию объяснений и языка пользо¬ вателя; реализацию языка эксперта. Эти подзадачи в свою оче¬ редь разбивались на более мелкие подзадачи, каждая из кото¬ рых выполняла одну функцию и могла быть реализована с по¬ мощью простой функции, записанной на языке ЛИСП. Программа реализована как самодокументированная, т. е. не требующая дополнительной документации. При обозначении функций и их аргументов использовались содержательные мне¬ монические обозначения, облегчающие чтение и понимание функций. Объяснения, приведенные в тексте параграфов, пред¬ назначены для указания особенностей реализации. Приспособленность ЛИСПа для обработки списков значи¬ тельно облегчает их обработку. Для этого достаточно только сравнить действия по обработке списков, реализованные на ПАСКАЛе и ЛИСПе. Атомы в ЛИСПе имеют неограниченную переменную длину, что также значительно облегчает обработку слов по сравнению с выше используемой реализацией на Па¬ скале. Представляется, что читателю не программисту легче освоить программы на ЛИСПе, чем на Паскале, поскольку в ЛИСПе для обозначений данных и действий фактически ис¬ пользуются одинаковые структуры (S-выражения). Из тех же S-выражений формируются структуры данных любой сложности. Однако применение рекурсии накладывает главное ограничение на использование ЛИСПа. Поэтому при разработке функций не¬ обходимо проявлять большую аккуратность и идти на компро¬ миссы. В структурном программировании для лучшей наглядности и понимаемости программ рекомендуется все входные и выход¬ ные для какой-то процедуры и функции данные включать в чи¬ сло параметров этой процедуры или функций. Например, функ¬ ция КАК для ответа на вопрос КАК для конкретного атрибута должна использовать СТЕК-ФАКТОВ и ПРАВИЛА, т. е. списки довольно большого объема. В соответствии с рекомендациями структурного программирования эти два списка должны быть включены в параметры (аргументы) функции КАК. Если их включить в параметры, то при каждом вызове функции КАК будут создаваться копии этих списков, что приводит к излишней перегрузке памяти. Однако поскольку значения этих списков в процессе работы функции КАК не изменяются, нет рекурсив¬ ного обращения с остатком списков (так как функция не явля¬ 140
ется рекурсивной), а также не используется эквивалент при¬ сваивания, целесообразно эти два списка использовать в функ¬ ции КАК как глобальные, т. е. без использования их копий. По аналогичным причинам можно удалить аргумент СТЕК-ЦЕЛЕЙ из функций ПОЧЕМУ и ПОДЦЕЛЬ, аргумент СТЕК-ФАК¬ ТОВ из функций НАЙТИ и ЗНАЧЕНИЕ. ПРАВИЛА. Представляется, что используя ЛИСП, гораздо проще, чем на Паскале, строить системы для экспериментирования. Однако программируя на Паскале, можно полнее использовать возмож¬ ности современных машин с ограниченной памятью. В качестве рекомендаций по улучшению экспертной системы и экспериментирования с ней можно использовать имеющие смысл для ЛИСПа рекомендации из п. 2.6. Кроме того, полезно провести реализацию экспертной системы с использованием списка свойств (6, 11]. Так как с каждым атрибутом связана подсказка или перевод, то их можно (и нужно) рассматривать как свойства атрибута с определенными значениями. 4. РЕАЛИЗАЦИЯ ЭКСПЕРТНОЙ СИСТЕМЫ НА ЯЗЫКЕ ПРОЛОГ 4.1. КРАТКАЯ ХАРАКТЕРИСТИКА ЯЗЫКА ПРОЛОГ Рассмотрим краткое описание реализации языка Пролог для СМ ЭВМ [7, 8], которая будет использована для реализации ин¬ струментальной экспертной системы. Основным достоинством рассматриваемой реализации Пролога для нашего случая явля¬ ется возможность работы с русскими буквами. Синтаксис этой реализации совпадает с точностью до обозначений с другими реализациями. Если читатель разберется с приведенными при¬ мерами, то в качестве упражнения ему не составит труда напи¬ сать свою версию экспертной системы на имеющейся у него реа¬ лизации Пролога. Язык Пролог обеспечивает возможность написания легко модифицируемых, модульных программ в виде аксиом формаль¬ ной логики. В состав системы Пролог входит библиотека встро¬ енных функций, которые реализуют элементарные операции. Программа на Прологе состоит из совокупности аксиом и теоремы, которую надо вывести, исходя из этой аксиоматики. Аксиомы записываются в виде + А0(...)—А1 (...)—...—AN(.. .)#. По смыслу аксиома эквивалентна следующей формуле в ис¬ числении предикатов: VX1.. .VXI А0(.. .)^-А1 (...)& А2(. ..)&.. .AN(...), 141
где AM — предикаты; XI — переменные, входящие в аргументы предикатов. Можно провести аналогию между программами на Прологе и базами данных, так как аксиоматика представляет собой опи¬ сание некоторых объектов и отношений между ними, т. е. именно то, что обычно хранится в базе данных. Теорема Пролога дока¬ зывается от противного, а именно, предполагается, что не суще¬ ствует объектов, удовлетворяющих теореме. В результате ра¬ боты при удачном доказательстве находим объекты, определяе¬ мые аксиоматикой, удовлетворяющие теореме. Это типичный поиск в базе данных. Проведем аналогию между программами на Прологе и паке¬ том процедур. Пусть имеется некоторая процедура FACT (X, Y), которая вычисляет факториал Y: = X!. Можно ввести предикат FACT (#:Х, H<Y), который принимает значение TRUE, если ^:Х целое и >fcY=^cX!. Таким образом, любой процедуре можно по¬ ставить в соответствие некоторый предикат и, следовательно, любому пакету процедур можно поставить в соответствие неко¬ торую аксиоматику Пролога. Пример 1. (Иллюстрация к первой аналогии.) + СМЕРТЕН ( * X) — ЧЕЛОВЕК (* X)#. Это аксиома, которая заключает в себе утверждение: человек смертен: + ЧЕЛОВЕК (ТЬЮРИНГ)# +ЧЕЛОВЕК (СОКРАТ)# + ГРЕК (СОКРАТ)# Это факты: Тьюринг — человек, Сократ — человек, Сократ — грек. + ЗАПРОС — СМЕРТЕН ( * X) — ГРЕК ( *Х) — PRINT (*Х)#. Напечатать * X, который смертен н является греком. Пример 2. (Иллюстрация ко второй аналогии.) Вычисление факториала + FACT (0,1)# (1) +FACT ( * X, * Y) (2) —MINUS (*Х, 1, *Z). (3) Встроенная функция MINUS реализует операцию: * Z:= * X—1 — FACT ( *Z, * L). (4) Это рекурсивное обращение к определению факториала. — TIMES ( * L, * X, * Y)#. (5) Встроенная функция TIMES реализует операцию * Y: = ( * L) * ( * X). + ВЫЧИСЛИТЬ — FACT (6, * L) — PRINT ( * L)#. (6) Это теорема, которая состоит нз обращения к описанию факториала — FACT (6. * L) и печати результата — PRINT ( * L). Каждая аксиома имеет плюс-часть, состоящую нз плюс-литерала, и минус- часть, состоящую нз последовательности минус-литералов. Конец аксиомы обозначается #. Часть «—» может быть пустой. В примере 2 (1); (2) —(5), (6) — аксиомы. Аксиома (1) с пустой минус-частью. В аксиоме (2) — (5) : (2)—плюс-часть, (3) — (5) — минус-часть, (3), (4), (5) — минус-литералы. Аксиомы, не имеющие минус-части, определяют отношения между объектами. Так, -(-FACT (0,1)фозначает, что <С0 и 1 на¬ ходятся в отношении FACT^>. 142
Аксиомы с минус-частью сводят некоторое понятие к сово¬ купности других, более простых. Так, в примере понятие FACT сводится к понятиям MINUS, FACT и TIMES. Несколько аксиом могут описывать одно понятие (отношение, функцию). При работе интепретатор сам выбирает подходящую альтернативу. Часто встречающиеся функции описаны в библио¬ теке Пролога и могут использоваться в минус-частях аксиом, не требуя описания в базе данных пользователя. В примере MINUS, TIMES, PRINT — встроенные процедуры. Термы. Терм — это объединяющее название элементов и функций, к которым применима предикатная буква. Бывают простые термы и сложные. Простые термы подразделяются на числа и переменные. В тексте программы могут использоваться целые неотрицательные числа. Отрицательные числа могут по¬ являться только в результате вычислений. Переменные имеют следующую структуру: < иде нт иф ик атор >, где <идентификатор>—это последовательность букв и цифр, начинающаяся с буквы, или любая последовательность симво¬ лов в одинарных кавычках. Длина идентификатора не более 132 символов, буквы могут быть и русскими. Переменные, как и в ЛИСПе, явно не описываются. Пере¬ менной может быть присвоено любое значение. Область дейст¬ вия переменной—аксиома, в которой она встречается (анало¬ гично локальной переменной процедуры). При каждом обраще¬ нии к аксиоме заводятся новые экземпляры переменных. Значение переменной присваивается не более одного раза, т. е. если переменной присвоилось значение, то все вхождения пере¬ менной в аксиому заменяются на это значение; попытка после этого присвоить новое значение окончится неудачей. При выпол¬ нении возврата переменные, которым было присвоено значение, «очищаются» и им можно опять присваивать какие-то значения. Сложный (функциональный) терм имеет следующую струк¬ туру: <идентификатор> [(терм I, ..., терм1)], где терм 1,..., терм I — аргументы, любые термы. Это сложный тип, аналогичный записям Паскаля. Он позво¬ ляет описывать иерархические структуры. Аргументов может не быть. Операторы. В Прологе есть специальные средства, позволяю¬ щие записывать сложные термы в виде, отличном от префикс¬ ного. Например, можно указать, что если в тексте встречается строка вида 1Р<выражение 1 >THEN<выpaжeниe 2>ЕЬ5Е<выражение 3>FI, то ее надо рассматривать как терм 1Р(<выражение 1>, <выражение2>, <выражение3>). 143
Такие термы, для которых задана особая форма записи, на¬ зываются операторами. Оператор определяется специальной ди¬ рективой OPERATOR со следующим синтаксисом: OPERATOR (<имя оператора>, <определение> [, <при- оритет>]), где <имя оператора>—имя терма в префиксной записи (в примере IF); <определение>—формат представле¬ ния в тексте программы; в нем операнды заменяются символом ^S. Следует подчеркнуть, что ^S—не есть переменная; <при- оритет> — число от 0 до 9. Если транслятор встречает текст, который нельзя рассматри¬ вать как объект префиксного вида, число или переменную, то он ищет среди описаний операторов такое, из которого может быть получен такой же текст путем подходящей замены вхождений >|<S, а затем транслирует текст в объект префиксного вида. При этом имя объекта префиксного вида—имя оператора, число аргументов равно числу вхождений ^:S в <определение>, зна¬ чения аргументов равны тем значениям, на которые надо заме¬ нить вхождения S, чтобы получить текст, совпадающий с тем. который мы транслируем. Для вышеприведенного примера определение оператора дол¬ жно иметь вид OPERATOR (IF, IF*S THEN*S ELSE*S FI). Если имеется описание OPERATOR (‘+\ ^S + H<S), to 6 + 5 транслируется в + (6,5). Для инфиксных операторов (« + », «—», «:» и т. п.) можно указывать приоритет, который оказывает влияние на способ пе¬ ревода выражения в префиксный вид. Так, если имеются описания OPERATOR (*:’, S:S, 6) и OPERATOR (‘ + \ ^S + ^S, 5), то А:В + С транслируется в +(:(А, В), С). Списки. Списки в Прологе не являются отдельным типом данных. Они представляются с помощью оператора «.» следую¬ щим образом: Al. А2... AN.NIL, где А1, ..., AN — элементы списка; NIL — пустой список. Таким образом, А.В.С. NIL представляет собой обычный терм .(А,(В,.(С,NIL))), соответствующий дереву 144
Это представление списков стандартное в том смысле, что некоторые встроенные процедуры (например, COMP, ADDAX) именно такие списки используют в качестве своих аргументов. Пример. Введем предикат MEMBER ( * X, * LIST), определяющий, что * X является элементом списка * LIST»: +MEMBER ( * X, * X, * LIST)#, т. е. * X является элементом списка, если он его первый элемент, +MEMBER ( * X, * А. * LIST) — MEMBER ( * X, * LIST) #, т. е. * X яв¬ ляется элементом списка, если он является элементом «хвоста» списка, т. е. списка без первого элемента. Следует подчеркнуть, что оператор «•»—единственный уже описанный в Прологе оператор: OPERATOR (‘-\ ^S.^S, 3). Присваивание переменным значений и передача параметров (в традиционном смысле) осуществляется процедурой совмеще¬ ния. Совмещение заключается в том, что некоторым перемен¬ ным в каждом из двух совмещаемых выражений присваиваются такие значения, что выражения принимают одинаковый вид. При этом выбирается минимальный, по числу присваиваний, ва¬ риант. Примеры. А н * X — совместимы: * Х:=А, F(A) н F( * X) —совместимы: *Х: = А, G(A) н F(A) — не совместимы. Если отбросить механизм возвратов и наличие нескольких альтернатив, то механизм работы Пролога укладывается в тра¬ диционную схему, при которой плюс-часть рассматривается как заголовок процедуры, а минус-часть—как последовательность вызовов процедур. Таким образом, + А—В—С—Д#имеет аналогом PROC А: CALL В; CALL С; CALL D END А. Опишем механизм работы подробнее. 1. Обработка теоремы начинается с обработки ее первого ми¬ нус-литерала. 2. Обработка произвольного минус-литерала заключается в следующем: а) среди аксиом ищется первая, заголовок которой может быть совмещен с данным минус-литералом. Присваивание зна¬ чений переменным, ставшее необходимым при совмещении, вы¬ полняется в «—хвосте» (т. е. в последовательности минус-лите¬ ралов, которые еще предстоит обработать) и в теле выбранной аксиомы. Затем преобразованная минус-часть аксиомы ставится в минус-хвост вместо обрабатываемого минус-литерала. Таким образом, длина минус-хвоста уменьшается, если найденная 10 В. Э. Балтрашевич 145
аксиома не имеет минус-части или если вызвана встроенная функция; б) если «совместимая» аксиома не найдена, то считается, что обработка минус-литерала закончилась неудачей и управле¬ ние передается механизму возвратов. Работа механизма возвратов заключается в следующем. Если обработка какого-то минус-литерала закончилась неудачей, то осуществляется возврат к обработке минус-литерала, непосред¬ ственно предшествующего данному. При этом происходит очи* стка переменных, которым присваивались значения при совме¬ щении. Поиск подходящих аксиом продолжается, начиная с ак¬ сиомы, следующей за той, которая была использована. Таблица 4.1 Номер аксиомы Присваивается при совмещении «мннус-хвост» (5) (1) (2) ГРЕК (ТЬЮРИ рую альтернат! (3) (4) * X: = *У * У: =ТЬЮРИНГ [НГ) — закончился неу, щу ЧЕЛОВЕК » У : = СОКРАТ —СМЕРТЕН ( * X)—ГРЕК ( * X)— PR INT ( * X) —ЧЕЛОВЕК (* У) —ГРЕК ( * У) — PRINT (*У) —ГРЕК (ТЬЮРИНГ)—PRINT (ТЬЮ¬ РИНГ) дачей, возвращаемся и применяем вто- —ГРЕК (СОКРАТ) — PRINT (СО¬ КРАТ) —PRINT (СОКРАТ) Таким образом, механизм работы Пролог-интерпретатора представляет собой реализацию перебора со стратегией «поиск по образцу в глубину с возвратом». Очевидно, что работа Про¬ лог-программы существенно зависит от порядка аксиом и от по¬ рядка минус-литералов в аксиоме. Пример. COMMENT человек смертен# + СМЕРТЕН ( * Y) — ЧЕЛОВЕК ( * Y)# (1) COMMENT Тьюрннг — человек, Сократ — человек, Сократ —грек# +ЧЕЛОВЕК (ТЬЮРИНГ)# (2) -{-ЧЕЛОВЕК (СОКРАТ)# (3) + ГРЕК (СОКРАТ)# (4) -{-ЗАПРОС — СМЕРТЕН ( * X) — ГРЕК ( * X) — PRINT ( * X)#. (5) Заметим, что комментарии в ПРОЛОГЕ имеют синтаксис: COMMENT <текст комметария>#. Работа интерпретатора для этого примера показана в табл. 4.1. Встроенные процедуры. Рассмотрим несколько из большого числа встроенных процедур, которые будут использованы при реализации инструментальной экспертной системы. Встроенные процедуры представляют собой реализацию элементарных функ¬ 146
ций, на основе которых можно описывать более сложные функ¬ ции. Действие встроенных процедур следующее: 1) если не удается выполнение, то осуществляется воз¬ врат; 2) если выполнение удается, в этом случае осуществляется какое-либо из приведенных ниже действий. 1. Присваивание значений переменным. Эти процедуры мо¬ делируют факты, для описания которых требуется либо беско¬ нечное число аксиом, либо описание на «чистом» Прологе неэф¬ фективно (арифметические функции и т. п.). 2. Изменения в вводе-выводе. 3. Изменения в базе данных. 4. Изменения в режиме интерпретации. Описание встроенных функций дается в следующем виде: имя, вызов, действие [, пример]. EQ. Вызов: — EQ(A, В), где А, В — любые выражения. Дей¬ ствие: совмещает А с В, удачно, если совместились. NUM. Вызов: — NUM(A), где А—выражение. Действие: удачно, если А— число. СОМР. Вызов: — СОМР (А, В), где А — список, первый эле¬ мент которого идентификатор. Действие: В совмещается с тер¬ мом, имя которого равно первому элементу списка А, а аргу¬ менты совпадают с остальными элементами списка: — СОМР (ALFA.*X.3.NIL,*Y); *Y:=ALFA(*X, 3) ADDAX. Вызов: — ADDAX (А), где А — терм или список тер¬ мов. Действие: аксиома добавляется в базу данных, причем до¬ бавление производится в конец списка аксиом с таким же име¬ нем. Если список имел вид: (FI). (F2).. .(FN). NIL, то добавляемая аксиома имеет вид + F1 — F2—FN#. Например, — ADDAX (ТИП (*Х). СТЕБЕЛЬ (*Х). NIL). Добавится аксиома + ТИП(*Х) —СТЕБЕЛЬ (>|<Х)# — ADDAX (СТЕБЕЛЬ (ЗЕЛЕНЫЙ))#. Добавится аксиома -1-СТЕБЕЛЬ (ЗЕЛЕНЫЙ)#. DELAX. Вызов: — DELAX (N, А), где А — терм, N —число. Действие: удаляется аксиома с именем А и номером в списке аксиом с этим именем, равным N. SLASH. Вызов: —/ (или — SLASH) —SLASH (А), где А — идентификатор. Действие: 10* 147
1. SLASH — изменяет режим работы механизма возврата следующим образом. Пусть в аксиоме есть вызов SLASH. Если интерпретатор попадает на него при возврате, то вызов аксиомы заканчивается неудачно, т. е. попытка выбора новой альтернативы применяется к вызову, предшествующему вызову данной аксиомы. Например, + NOT (*Х)—*Х—/—FALSE# + NOT(*X)#. Вызов — NOT (>|<Х) удачен лишь тогда, когда выполнение вызова — ^X окончится неудачей. 2. SLASH (А)—действие аналогично SLASH с той разни¬ цей, что неудачно завершается вызов ближайшего предка с име¬ нем А. Удобна для выхода из глубоко вложенной аксиомы во внешнюю аксиому. REPEAT. Вызов: — REPEAT. Действие: используется для организации циклов. Работает так, как если бы была определена на Прологе: +REPEAT# + REPEAT—REPEAT#. Через нее никогда не пройдет возврат. Выйти из такого цикла можно только с помощью SLASH. Например, + ONE—REPEAT—TWO# +TWO—MAINPROC—SLASH—FALSE# + TWO—SLASH (ONE) —FALSE#. Функция MAINPROC будет повторяться до тех пор, пока ее неудача не заставит выполниться вторую альтернативу TWO. OUTPUT. Вызов: —OUTPUT (STR), где STR — любое выра¬ жение. Действие: выводит данное выражение на выводное уст¬ ройство. NEWLINE. Вызов: —NEWLINE. Действие: вызывает переход на новую строку при выводе. PRINT. Вызов: —PRINT (STR), где STR — любое выраже¬ ние. Действие: выводит выражение с новой строки. Может быть определена как + PRINT (*Х) — NEWLINE— OUTPUT (*Х)#. OUTTAB. Вызов: —OUTTAB — OUTTAB (N), где N —целое число от 1 до 18. Действие: выводит указанное число символов табуляции или один, если вызов без аргументов. INOPEN. Вызов: —INOPEN (FILE), где FILE — имя файла. Действие: открывает существующий файл с указанным име¬ нем, с расширением по умолчанию DAT. Аргумент, не являю¬ щийся идентификатором, должен быть заключен в кавычки. 148
INCLOSE. Вызов:—INCLOSE. Действие: закрывает откры¬ тый вводный файл. По умолчанию ввод производится с терминала, для его пере¬ ключения на другие устройства служат следующие процедуры. CSWITCH. Вызов:—CSWITCH. Действие: устанавливает ввод с терминала (TI:). BSWITCH. Вызов: —BSWITCH. Действие: устанавливает ввод из файла, открытого процедурой INOPEN, при этом не Проверяется, был ли файл на самом деле открыт. INWORD. Вызов: —INWORD (>|<Х). Действие: из входного потока вводится очередное слово [число, идентификатор, знак (не являющийся буквой или цифрой), строка в кавычках]. INSTRING. Вызов: —INSTRING (>|<Х). Действие: вводит всю физическую строку (от текущей позиции до конца), как если бы она была заключена в кавычки. NEWSTRING. Вызов: —NEWSTRING. Действие: переходит на новую строку при вводе. SAVE. Вызов: —SAVE (А), где А—имя. Действие: сохра¬ няет прологовские аксиомы с указанным именем. Обычно в результате неудачного завершения встроенных функций не только происходит возврат, но и выдается сообще¬ ние об ошибке с указанием имени функции, в которой произо¬ шла ошибка, а также имени вызвавшей ее аксиомы. Сообщения об ошибках всегда выдаются на терминал неза¬ висимо от текущего выводного устройства. Для управления выдачей ошибок используются следующие процедуры. ERNOT. Вызов: —ERNOT. Действие: отменяет выдачу сооб¬ щений об ошибках. ERYES. Вызов: —ERYES. Действие: возобновляет выдачу сообщений об ошибках после ERNOT. 4.2. РЕАЛИЗАЦИЯ ЛОГИЧЕСКОГО ВЫВОДА При реализации логического вывода на языках Паскаль и ЛИСП мы фактически осуществляли поиск по образцу в глу¬ бину с возвратом для нахождения значения целевого атрибута. Но поиск по образцу в глубину с возвратом является управляю¬ щей структурой, заложенной в основу Пролога. Поэтому для реализации вывода решения нам необходимо только записать правила предметной области на языке Пролог, а правила вы¬ вода используются Прологом автоматически. Как уже неоднократно отмечалось, при выводе решения реа¬ лизуемая экспертная система должна получать значения неко¬ торых атрибутов в результате ответов пользователя, но чтобы не усложнять первую версию программы зададим эти значения 149
в виде фактов. Тогда первую версию программы вывода реше¬ ния, т. е. представления знаний эксперта на языке Пролог, можно представить в следующем виде: +СЕМЕЙСТВО(КИПАРИСОВЫЕ)-КЛАСС(ГОЛОСЕМЯННЫЕ) -ФОРМА_ЛИСТА(ЧЕШУЕОБРАЗНАЯ)# +СЕМЕЙСТВО(СОСНОВЫЕ)-КЛАСС(ГОЛОСЕМЯННЫЕ) -ФОРМА_ЛИСТА(ИГЛОПОДОБНАЯ) -КОНФИГУРАЦИЯ(ХАОТИЧЕСКАЯ)# +СЕМЕЙСТВО(СОСНОВЫЕ)-КЛАСС(ГОЛОСЕМЯННЫЕ) -ФОРМА_ЛИСТА(ИГЛОПОДОБНАЯ) -КОНФИГУРАЦИЯ(ДВА_РОВНЫХ_РЯДА) -СЕРЕБРИСТАЯ_ПОЛОСА(ДА)# +СЕМЕЙСТВО(БОЛОТНЫЙ_КИПАРИС)-КЛАСС(ГОЛОСЕМЯННЫЕ) -ФОРМА_ЛИСТА(ИГЛОПОДОБНАЯ) -КОНФИГУРАЦИЯ(ДВА_РОВНЫХ_РЯДА) -СЕРЕБРИСТАЯ_ПОЛОСА(НЕТ)# +КЛАСС(ПОКРЫТОСЕМЯННЫЕ)-ТИП(ДЕРЕВЬЯ) -ШИРОКАЯ_И_ПЛОСКАЯ(ДА)# +КЛАСС(ГОЛОСЕМЯННЫЕ)-ТИП(ДЕРЕВЬЯ) -ШИРОКАЯ_И_ПЛОСКАЯ(НЕТ)* +ТИП(ТРАВЯНИСТЫЕ)-СТЕБЕЛЬ(ЗЕЛЕНЫЙ)# +ТИП(ЛИАНЫ)-СТЕБЕЛЬ(ДРЕВЕСНЫЙ)-ПОЛОЖЕНИЕ(СТЕЛЮЩЕЕСЯ)# +ТИП(ДЕРЕВЬЯ)-СТЕБЕЛЬ(ДРЕВЕСНЫЙ) -ПОЛОЖЕНИЕ(ПРЯМОСТОЯЩЕЕ) -ОДИН_ОСНОВНОЙ_СТВОЛ(ДА)# +ТИП(КУСТАРНИКОВЫЕ)-СТЕБЕЛЬ(ДРЕВЕСНЫЙ) -ПОЛОЖЕНИЕ(ПРЯМОСТОЯЩЕЕ) -ОДИН_ОСНОВНОЙ_СТВОЛ(НЕТ)# +СТЕБЕЛЬ(ДРЕВЕСНЫЙ)# +ПОЛОЖЕНИЕ(ПРЯМОСТОЯЩЕЕ)# +ОДИН_ОСНОВНОЙ_СТВОЛ(ДА)# +ШИРОКАЯ_И_ПЛОСКАЯ(НЕТ)# +ФОРМА_ЛИСТА(ЧЕШУЕОБРАЗНАЯ)# +ЗАПРОС-ТИП(*Х)-OUTPUT('ОТВЕТ ')-PRINT(*Х)# +ЗАПР0СА-СЕМЕЙСТВ0(*Х)-OUTPUT('ОТВЕТ ')-PRINT(*Х)# Запуск программы, т. е. запрос пользователя, задается в виде ЗАПРОС. Таким образом, с помощью данной версии пользова¬ тель может решать задачу по определению типа растения при наличии соответствующих фактов о растении. Заметим, что язык пользователя пока очень ограничен и позволяет использо¬ вать только одно слово ЗАПРОС. Как видно из порядка расположения правил, вначале пере¬ менная в целевом предикате ТИП примет значение (совме¬ стится) ТРАВЯНИСТЫЕ. Но для того, чтобы это предположе¬ ние было истинным надо, чтобы стебель был зеленым, но такого факта нет, поэтому происходит возврат. При реализации на Пас¬ кале и ЛИСПе это правило запрещалось для дальнейшего ис¬ 150
пользования. Пролог автоматически пытается применить сле¬ дующее правило для определения типа растения. Переменная ^:Х принимает значение ЛИАНЫ. Для того чтобы это предполо¬ жение было истинным, стебель должен быть древесным. Такой факт задан. Тогда проверяется, является ли положение стелю¬ щимся; это предположение в нашем случае не выполняется, так как отсутствует соответствующий факт, и происходит возврат. Пролог пытается применить (проверить применимость) следую¬ щее правило для определения типа. Переменная $:Х принимает значение ДЕРЕВЬЯ. Как видно из заданных фактов, это пред¬ положение истинно (подтверждается). После этого в соответ¬ ствии с аксиомой ЗАПРОС, происходит печать сообщения ОТ¬ ВЕТ и печать значения переменной >|<Х, т. е. ДЕРЕВЬЯ- Пролог использует обратный вывод, поэтому при попытке применить первое правило и совместив ^:Х с ТРАВЯНИСТЫЕ, он проверяет наличие факта СТЕБЕЛЬ ЗЕЛЕНЫЙ, т. е. целью объявляется атрибут и его значение. В реализациях логического вывода на Паскале и ЛИСПе целью объявлялся лишь атрибут, и поэтому в процессе работы не проверялось, а искалось его значение с использованием прямого вывода [т. е. не проверя¬ лось, что стебель зеленый, а просто искалось значение атрибута СТЕБЕЛЬ (в данном случае с помощью запроса у пользова¬ теля)]. Полученное значение запоминалось в стеке фактов, и в случае возврата и перехода к следующему правилу, в котором также используется стебель, запроса к пользователю уже не было, так как значение бралось из стека фактов. Как видно, для запоминания ответов пользователя при реализации на Прологе придется применять дополнительные меры. Таким образом, ос¬ новным отличием рассмотренных реализаций на Паскале и ЛИСПе от реализации на Прологе является использование в реализациях на Паскале и ЛИСПе в качестве цели атрибута и поиск значения этого атрибута, а в реализации на Прологе целью объявляется атрибут и его значение, и происходит про¬ верка этой цели. Поэтому при реализации на Паскале в стеке целей было зарезервировано место для значения атрибута, что позволяет при желании провести эксперименты по реализации на Паскале вывода еще более близкого к прологовскому. Пользователь может запустить систему на решение задачи определения семейства того же растения с помощью ЗАПРОСА. Таким образом, язык пользователя уже расширился до двух слов. Читателю предлагается с помощью табл. 1.5, приведенных аксиом и фактов, а также с учетом управляющей структуры Пролога убедиться, что ответ будет КИПАРИСОВЫЕ. Теперь, не изменяя правил предметной области и предпола¬ гая, что они сохранились в памяти ЭВМ, попробуем организо¬ вать запрос у пользователя недостающих фактов: 151
+W1-PRINT('КАКОЙ СТЕБЕЛЬ У РАСТЕНИЯ - ') -OUTPUT('ДРЕВЕСНЫЙ ИЛИ ЗЕЛЕНЫЙ? ') -INWORD(*Х)-ADDAX(СТЕБЕЛЬ(*Х))# +W2-PRINT('КАКОЕ ПОЛОЖЕНИЕ СТЕБЛЯ - ') -OUTPUT('ПРЯМОСТОЯЩЕЕ ИЛИ СТЕЛЮЩЕЕСЯ? ') -INWORD(*Х)-ADDAX(ПОЛОЖЕНИЕ(*Х))# +W3-PRINT('ИМЕЕТ ЛИ РАСТЕНИЕ ОДИН ОСНОВНОЙ СТВОЛ - ') -OUTPUT('ДА ИЛИ НЕТ? ') -INWORD(*Х)-ADDAX(ОДИН_ОСНОВНОЙ_СТВОЛ(*Х))# +W4-PRINT('ИМЕЮТ ЛИ ЛИСТЬЯ ШИРОКУЮ И ПЛОСКУЮ ФОРМУ - ') -OUTPUT('ДА ИЛИ НЕТ? ') -INWORD(*Х)-ADDAX(ШИРОКАЯ_И_ПЛОСКАЯ(*Х))# +W5-PRINT('КАКАЯ ФОРМА ЛИСТА - ') -OUTPUT('ИГЛОПОДОБНАЯ ИЛИ ЧЕШУЕОБРАЗНАЯ? ') - INWORD ( *Х) -ADDAX (ФОРМА_ЛИСТА( *Х) ) # +3AnPOCB-Wl-W2-W3-W4-W5 -СЕМЕЙСТВО(*Х)-PRINT('ОТВЕТ ')-OUTPUT(*Х)# ^ Например, аксиома W1 печатает подсказку, вводит значение атрибута, заданное пользователем, и записывает с помощью встроенной процедуры ADDAX в базу данных предикат СТЕ¬ БЕЛЬ с соответствующим значением переменной >^Х. Запуск системы на решение задачи по определению семей¬ ства растения, характеристики которого задаются пользовате¬ лем в процессе диалога, осуществляется с помощью ЗАПРОСЕ. Тем самым язык пользователя уже значительно расширен за счет возможных ответов пользователя на вопросы системы. В этой версии осуществляется сначала выяснение у пользо¬ вателя всех фактов, а потом производится вывод, т. е. это упро¬ щенный пример, внешне напоминающий прямой вывод. Недостатком этой версии является то, что всегда задается пять (максимальное число) вопросов, несмотря на значения от¬ ветов пользователя. Например, если на первый вопрос пользо¬ ватель дает ответ ЗЕЛЕНЫЙ, то из правил ясно, что тип расте¬ ния ТРАВЯНИСТЫЕ и больше вопросов задавать не надо, так как цель—СЕМЕЙСТВО,— из-за неполноты базы знаний до¬ стигнута быть не может. Теперь попробуем реализовать обратный вывод с заданием вопросов пользователю только при условии необходимости. Но во время вывода, как мы уже видели, могут быть возвраты и не хотелось бы, чтобы при возвратах пользователю повторялся за¬ прос, на который он уже отвечал. Для этого надо перед запро¬ сом пользователя попытаться поискать факт в базе данных и уж в случае неудачи, т. е. при отсутствии факта, спрашивать поль¬ зователя и запомнить его ответ. Тогда аксиомы для определения значения, например, стебля могут быть записаны в виде: 152
+СТ(*Х)-СТЕБЕЛЬ(*Y)-/-EQ(*Х,*Y)# +CT(PRINT ('КАКОЙ СТЕБЕЛЬ У РАСТЕНИЕ- ДРЕВЕСНЫЙ ИЛИ ЗЕЛЕНЫЙ?') . -INWORD(*Y)-ADDAX(СТЕБЕЛЬ(*Y))-/-EQ(*Х,*Y)# Обращение к этим аксиомам из правил предметной области производится с каким-то конкретным значением переменной ^сХ. Автоматически производится поиск предиката (факта) СТЕ¬ БЕЛЬ в базе данных. В случае успеха переменная прини¬ мает соответствующее значение, которое с помощью предиката EQ сравнивается со значением переменной ^:Х. Если они совпа¬ дают, то аксиома СТ принимает значение TRUE. Если значения переменных не совпадают, то предикат EQ выдает значение FALSE. Пролог пытается делать возврат, но предикат/отменяет возвраты, аксиома СТ получает значение FALSE. Если предикат СТЕБЕЛЬ в базе данных найти не удалось, то ПРОЛОГ пыта¬ ется применить вторую версию аксиомы СТ, в результате кото¬ рой производится запрос пользователя и запись его ответа в базу данных. Предикат EQ сравнивает проверяемое значение атрибута (т. е. значение переменной ^<Х) и заданное пользова¬ телем. Результат этого сравнения становится результатом аксиомы СТ. Текст соответствующей третьей версии программы вывода решения представлен на стр. 154. Запуск системы на решение задачи по определению семей¬ ства растения, нужные характеристики которого пользователь задает в процессе диалога, осуществляется с помощью ЗА- ПРОСВ. Второй вариант аксиомы ЗАПРОСВ срабатывает лишь тогда, когда цель не может быть достигнута. Это воз¬ можно в двух случаях. Либо не хватает правил, например, если цель вывода — СЕМЕЙСТВО, а при ответе на вопрос о стебле был дан ответ, что стебель зеленый. Для этого случая в базе знаний нет правил по определению семейства растений с зеле¬ ным стеблем. Второй случай возникает, если при наборе пра¬ вильного ответа пользователь допускает синтаксическую ошибку, так как поиск идет по образцу и, следовательно, обра¬ зец должен быть точным. Очевидным недостатком управления с помощью аксиомы ЗАПРОСВ является жесткое задание цели. То есть, если поль¬ зователя интересует ие семейство, а класс или тип растения, то при данной организации запроса его надо заново записывать, меняя слово семейство, например, на класс или тип с последую¬ щей заменой аксиомы в базе данных. Организуем запрос так, чтобы пользователь мог задать цель вывода в процессе диалога. При запросе ЗАПРОСГ система запрашивает цель вывода, предположим, что пользователь ответил СЕМЕЙСТВО, тогда : 153
+СЕМЕЙСТВО(КИПАРИСОВЫЕ)-КЛАСС(ГОЛОСЕМЯННЫЕ) -ФОР(ЧЕШУЕОБРАЗНАЯ)# +СЕМЕЙСТВО(СОСНОВЫЕ)-КЛАСС(ГОЛОСЕМЯННЫЕ) -ФОР(ИГЛОПОДОБНАЯ)-КОН(ХАОТИЧЕСКАЯ)# +СЕМЕЙСТВО(СОСНОВЫЕ)-КЛАСС(ГОЛОСЕМЯННЫЕ) -ФОР(ИГЛОПОДОБНАЯ)-КОН(ДВА_РОВНЫХ_РЯДА) -СЕР(ДА)# +КЛАСС(ПОКРЫТОСЕМЯННЫЕ)-ТИП(ДЕРЕВЬЯ)-ШИР(ДА)# +ТИП(КУСТАРНИКОВЫЕ)-СТ(ДРЕВЕСНЫЙ)-ПОЛ(ПРЯМОСТОЯЩЕЕ > -ОДИН(НЕТ)# +СТ(*Х)-СТЕБЕЛЬ(*У)-/-EQ(*Х,*У)# +СТ(*Х)-PRINT('КАКОЙ СТЕБЕЛЬ У РАСТЕНИЯ - ') -OUTPUT('ДРЕВЕСНЫЙ ИЛИ ЗЕЛЕНЫЙ? ') -INWORD(*У)-ADDAX(СТЕБЕЛЬ(*У))-EQ(*Х,*У)# +ПОЛ(*Х)-ПОЛОЖЕНИЕ(*У)-/-EQ(*Х,*У)# +ПОЛ(*Х)-PRINT('КАКОЕ ПОЛОЖЕНИЕ СТЕБЛЯ - ') -OUTPUT('ПРЯМОСТОЯЩЕЕ ИЛИ СТЕЛЮЩЕЕСЯ? ') -INWORD(*У)-ADDAX(ПОЛОЖЕНИЕ(*У))-EQ(*Х,*У)# +ОДИН(*Х)-ОДИНОСНОВНОЙСТВОЛ(*У)-/-EQ(*Х,*У)# +ОДИН(*Х) -PRINT('ИМЕЕТ РАСТЕНИЕ ОДИН ОСНОВНОЙ СТВОЛ - ') -OUTPUT('ДА ИЛИ НЕТ? ') -INWORD(*У) -ADDAX(ОДИНОСНОВНОЙСТВОЛ(*У))-EQ(*У,*Х)# +ШИР(*Х)-ШИРОКАЯИПЛОСКАЯ(*У)-/-EQ(*Х,*У)# +ШЙР(*Х)-PRINT('ИМЕЮТ ЛИСТЬЯ ШИРОКУЮ И ПЛОСКУЮ ФОРМУ ') -OUTPUT('- ДА ИЛИ НЕТ? ') -INWORD(*У) -ADDAX(ШИРОКАЯИПЛОСКАЯ(*У))-EQ(*У,*Х)# +ФОР(*Х)-ФОРМАЛИСТА(*У)-/-EQ(*Х, *У)# +ФОР(*Х)-PRINT('КАКАЯ ФОРМА ЛИСТА - ') -OUTPUT('ИГЛОПОДОБНАЯ ИЛИ ЧЕШУЕОБРАЗНАЯ? ') -INWORD(*У)-ADDAX(ФОРМАЛИСТА(*У))-EQ(*Х,*У)# +КОН(*Х)-КОНФИГУРАЦИЯ(*У)-/-EQ(*У,*Х)# +КОН(*Х)-PRINT('КАКАЯ КОНФИГУРАЦИЯ РАСПОЛОЖЕНИЯ ') -OUTPUT{'ИГЛ ВДОЛЬ ВЕТВИ ') -PRINT('ХАОТИЧЕСКАЯ ИЛИ ДВА_РОВНЫХ_РЯДА? ') -INWORD(*У) -ADDАХ(КОНФИГУРАЦИЯ(*У))-EQ(*Х,*У)# +СЕР(*Х)-СЕРЕБРИСТАЯПОЛОСА(*У)-/-EQ(*Х,*У)# +СЕР(*Х)-PRINT('ИМЕЕТСЯ ЛИ СЕРЕБРИСТАЯ ПОЛОСА ') -OUTPUT('СНИЗУ ИГЛЫ - ДА ИЛИ НЕТ? ') -INWORD(*У) -ADDAX(СЕРЕБРИСТАЯПОЛОСА(*У))-EQ(*У,*Х)# +ЗАПР0СВ-СЕМЕЙСТВ0(*Х)-PRINT('ОТВЕТ ')-OUTPUT(*Х)# +3AnP0CB-PRINT('ЦЕЛЬ НЕ МОЖЕТ БЫТЬ ДОСТИГНУТА')# +ЗАПР0СГ-РД1ЫТ('ЗАДАЙТЕ ЦЕЛЬ ')-INWORD(*У) -СОМР(*У.*X.NIL,*CALL)-*CALL -PRINT('ОТВЕТ ')-OUTPUT(*Х)# +3AnP0Cr-PRINT('ЦЕЛЬ НЕ МОЖЕТ ВЫТЬ ДОСТИГНУТА')# 154
£ результате работы предиката COMP переменная >fcCALL по¬ лучит значение СЕМЕЙСТВО (Н<Х), и потом этой переменной Передается управление, в результате чего определяется значе¬ ние заданной цели. ' Вторым очевидным недостатком разработанной версии явля¬ ется то, что для каждого запрашиваемого атрибута нужна своя дара аксиом (или аксиома с двумя версиями). Если эту аксиому рассматривать как процедуру определения значения, то хоте¬ лось бы иметь одну аксиому определения, параметром которой являлось бы не только значение атрибута, как в разработанной версии, но и сам атрибут. Процедура определения, которую назовем ДИАЛОГ, будет определять было ли уже определено значение атрибута. Если значение атрибута определено не было, то будет выдаваться подсказка и производиться получение ответа пользователя. То есть процедура ДИАЛОГ должна иметь возможность по атри¬ буту определять значение подсказки. Для этого введем новое отношение ПОДСКАЗКИ со следующей структурой: ПОДСКАЗКИ (^атрибут, >|<текст — подсказки), которое можно рассматривать как внутреннее представление для под¬ сказок. Полный текст описания подсказок имеет вид ♦ПОДСКАЗКИ (СТЕБЕЛЬ, 'КАКОЙ СТЕБЕЛЬ У РАСТЕНИЯ-ДРЕВЕСНЫЙ ИЛИ ЗЕЛЕНЫЙ? ' )# ♦ПОДСКАЗКИ(ПОЛОЖЕНИЕ, 'КАКОЕ ПОЛОЖЕНИЕ СТЕБЛЯ-ПРЯМОСТОЯЩЕЕ ИЛИ СТЕЛЮЩЕЕСЯ? ')# ♦ПОДСКАЗКИ(ОДИНОСНОВНОЙСТВОЛ, 'ИМЕЕТ ЛИ РАСТЕНИЕ ОДИН ОСНОВНОЙ СТВОЛ? ')# ♦•ПОДСКАЗКИ (ШИР ОКАЯИП ЛОСКАЯ, 'ИМЕЮТ ЛИ ЛИСТЬЯ ШИРОКУЮ И ПЛОСКУЮ ФОРМУ? ')# «♦■ПОДСКАЗКИ (ФОРМАЛИСТА, 'КАКАЯ ФОРМА ЛИСТА-ИГЛОПОДОБНАЯ ИЛИ ЧЕШУЕОБРАЗНАЯ? ')# •♦■ПОДСКАЗКИ (КОНФИГУРАЦИЯ, 'КАКОЕ РАСПОЛОЖЕНИЕ ИГЛ ВДОЛЬ ВЕТВИ -ХАОТИЧЕСКАЯ ИЛИ ДВАРОВНЫХРЯДА? ' ) # «♦■ПОДСКАЗКИ (СЕРЕБРИСТАЯПОЛОСА, 'ИМЕЕТСЯ ЛИ СЕРЕБРИСТАЯ ПОЛОСА СНИЗУ ИГЛЫ? ')# При предположении, что значения атрибутов, задаваемых пользователем, будут определяться аксиомой ДИАЛОГ, пра¬ вила можно представить в виде ♦СЕМЕЙСТВО(КИПАРИСОВЫЕ)-КЛАСС(ГОЛОСЕМЯННЫЕ) -ДИАЛОГ(ФОРМАЛИСТА f ЧЕШУЕ ОБРАЗНАЯ)# Текст четвертой версии программы вывода решения можно предстатвить в следующем виде: 155
+СЕМЕЙСТВО(КИПАРИСОВЫЕ)-КЛАСС(ГОЛОСЕМЯННЫЕ) -ДИАЛОГ(ФОРМАЛИСТА,ЧЕШУЕОБРАЗНАЯ)# +СЕМЕЙСТВО(СОСНОВЫЕ)-КЛАСС(ГОЛОСЕМЯННЫЕ) -ДИАЛОГ (ФОРМАЛИСТА, ИГЛОПОДОБНАЯ) -ДИАЛОГ (КОНФИГУРАЦИЯ, ХАОТИЧЕСКАЯ) # +КЛАСС (ГОЛОСЕМЯННЫЕ) -ТИП (ДЕРЕВЬЯ) -ДИАЛОГ (ШИРОКАЯИПЛОСКАЯ, НЕТ) # +ТИП(КУСТАРНИКОВЫЕ)-ДИАЛОГ(СТЕБЕЛЬ,ДРЕВЕСНЫЙ) -ДИАЛОГ(ПОЛОЖЕНИЕ,ПРЯМОСТОЯЩЕЕ) -ДИАЛОГ(ОДИНОСНОВНОЙСТВОЛ,НЕТ)# +ДИАЛОГ(*АТРИБУТ,*ЗНАЧЕНИЕ) -СОМР(*АТРИБУТ.*ОТВЕТ.NIL,*CALL) -*CALL-/-EQ(*ЗНАЧЕНИЕ,*ОТВЕТ)# ♦ДИАЛОГ(*АТРИБУТ,* ЗНАЧЕНИЕ) -ПОДСКАЗКИ ( * АТРИБУТ, *ТЕКСТ) -PRINT(*ТЕКСТ)-INWORD(*ОТВЕТ) -СОМР(*АТРИБУТ.*ОТВЕТ.NIL,*CALL) -ADDAX(*CALL)-/-EQ(*ЗНАЧЕНИЕ,*ОТВЕТ)# +3AnP0Cfl-PRINT('ЗАДАЙТЕ ЦЕЛЬ ')-INWORD(*ЦЕЛЬ) -СОМР(*ЦЕЛЬ. *Х.NIL,* CALL)-* CALL -PRINT('ОТВЕТ ')-OUTPUT(*X)# +3AnPOCfl-PRINT('ЦЕЛЬ HE МОЖЕТ БЫТЬ ДОСТИГНУТА')# Первая версия аксиомы ДИАЛОГ проверяет наличие атри¬ бута в базе данных. Если есть, то проверяет имеет ли он то же значение, что и в запрашивающем правиле. При наличии атри¬ бута в базе данных с помощью SLASH запрещается анализ вто¬ рой версии аксиомы ДИАЛОГ. Вторая версия аксиомы ДИАЛОГ обеспечивает поиск под¬ сказки, соответствующей заданному атрибуту, распечатывает эту подсказку, вводит ответ пользователя, с помощью систем¬ ного предиката СОМР формирует предикат ответа и записывает его в базу данных, после этого сравнивает значение атрибута, находящегося в правиле, и значение ответа пользователя. Ре¬ зультат сравнения выдается в качестве значения аксиомы ДИА¬ ЛОГ. Если результат сравнения FALSE, т. е. значение атрибута в правиле, и значение атрибута, заданное пользователем, не сов¬ падают, то для запрета дальнейшего поиска используется SLASH. Рассмотрим пример. Пусть логический вывод дошел до проверки правила 1-ДИАЛОГ (СТЕБЕЛЬ, ЗЕЛЕНЫЙ) -СОМР (СТЕБЕЛЬ, * ОТВЕТ .NIL, *CALL -*GALL-/-EQ(ЗЕЛЕНЫЙ,*ОТВЕТ)# С помощью предиката СОМР переменная >fcCALL примет значение СТЕБЕЛЬ ОТВЕТ),которому будет передано управление. 156
Если предикат СТЕБЕЛЬ имеется в базе данных, то пере¬ менная >|<ОТВЕТ получит какое-то значение, которое будет сравнено со значением ЗЕЛЕНЫЙ. Если результат сравнения TRUE, то на этом работа аксиомы ДИАЛОГ завершается. Если результат сравнения FALSE, то ПРОЛОГ попробует проверить другой вариант и начнет возврат, при этом пройдет через/,ко¬ торый отменит возврат, и работа аксиомы завершится. Если же предиката СТЕБЕЛЬ в базе данных нет, т. е. за¬ проса о значении стебля еще не было, то Пролог будет прове¬ рять вторую версию аксиомы ДИАЛОГ, которая в данном слу¬ чае принимает вид +ДИАЛОГ(СТЕБЕЛЬ,ЗЕЛЕНЫЙ)-ПОДСКАЗКИ(СТЕБЕЛЬ,*ТЕКСТ) -PRINT(*ТЕКСТ)-INWORD(*ОТВЕТ) -СОМР(СТЕБЕЛЬ.*ОТВЕТ.NIL,*CALL)-ADDAX(*CALL) -/-EQ(ЗЕЛЕНЫЙ,* ОТВЕТ)# Когда управление передается предикату ПОДСКАЗКА (СТЕБЕЛЬ, >|<ТЕКСТ), то Пролог автоматически осуществляет поиск текста подсказки, относящейся к атрибуту СТЕБЕЛЬ. Сравните с тем, сколько действий для нахождения подсказки нам приходилось сделать на ЛИСП$ и особенно на Паскале^. После нахождения подсказки ее текст совместится с переменной >|<ТЕКСТ и будет распечатан. В результате ответа пользователя переменная ^ОТВЕТ получит некоторое значение. С помощью предиката СОМР переменная ^<CALL получит значение СТЕ¬ БЕЛЬ (>|<ОТВЕТ), которое и будет записано в базу данных. Да¬ лее происходит сравнение значения ответа пользователя и зна¬ чения ЗЕЛЕНЫЙ. В результате работа аксиомы ДИАЛОГ за¬ вершается значением TRUE или FALSE, определяющим значе¬ ние вызвавшей ее аксиомы. Запуск четвертой версии системы на решение любой задачи по определению типа, класса или семейства растения, характе¬ ристики которого пользователь задает в процессе диалога, осу¬ ществляется с помощью атрибута ЗАПРОСД. Оценим недостатки версии с точки зрения нашей главной задачи, т. е. построения инструментальной экспертной системы. 1. В правилах структура записи атрибутов, определяемых с помощью правил (семейство, класс, тип), отличается от струк¬ туры записи атрибутов, определяемых с помощью пользователя (стебель, положение, ...). Это значительно может усложнить построение компилятора с языка внешнего представления зна¬ ний во внутреннее. 2. Атрибуты, значения которых определяются пользовате¬ лем, перед запросом пользователя проходят проверку на то, не было ли определено их значение. Атрибуты, определяемые с по¬ мощью правил, такой проверке перед запуском правила не под- I вергаются. 157
-+Т0(СЕМЕЙСТВО,КИПАРИСОВЫЕ,*СЛЕД) -ЕСЛИ(КЛАСС,ГОЛОСЕМЯННЫЕ,1.*СЛЕД) -ЕСЛИ(ФОРМАЛИСТА,ЧЕШУЕОБРАЗНАЯ,1.*СЛЕД) -ADDAX(КОНТЕКСТ(СЕМЕЙСТВО,КИПАРИСОВЫЕ,1))# -+ТО (СЕМЕЙСТВО, СОСНОВЫЕ , *СЛЕД) -ЕСЛИ(КЛАСС,ГОЛОСЕМЯННЫЕ,2.*СЛЕД) -ЕСЛИ(ФОРМАЛИСТА,ИГЛОПОДОБНАЯ,2.*СЛЕД) -ЕСЛИ(КОНФИГУРАЦИЯ,ХАОТИЧЕСКАЯ,2.*СЛЕД) -ADDAX(КОНТЕКСТ(СЕМЕЙСТВО,СОСНОВЫЕ,2))# -+ТО (СЕМЕЙСТВО, СОСНОВЫЕ , * СЛЕД) -ЕСЛИ(КЛАСС,ГОЛОСЕМЯННЫЕ,3.*СЛЕД) -ЕСЛИ(ФОРМАЛИСТА,ИГЛОПОДОБНАЯ,3.*СЛЕД) -ЕСЛИ(КОНФИГУРАЦИЯ,ДВАРОВНЫХРЯДА,3.*СЛЕД) -ЕСЛИ(СЕ РЕБРИСТАЯПОЛОСА,ДА,3.*СЛЕД) -ADDAX(КОНТЕКСТ(СЕМЕЙСТВО,ЕЛОВЫЕ,3))# +ТО(СЕМЕЙСТВО,БОЛОТНЫЙКИПАРИС,*СЛЕД) -ЕСЛИ(КЛАСС,ГОЛОСЕМЯННЫЕ,4.* СЛЕД) -ЕСЛИ(ФОРМАЛИСТА,ИГЛОПОДОБНАЯ,4.*СЛЕД) -ЕСЛИ(КОНФИГУРАЦИЯ,ДВАРОВНЫХРЯДА,4.*СЛЕД) -ЕСЛИ(СЕРЕБРИСТАЯПОЛОСА,НЕТ,4.*СЛЕД) -ADDAX(КОНТЕКСТ(СЕМЕЙСТВО,БОЛОТНЫЙКИПАРИС,4))# +ТО{КЛАСС,ПОКРЫТОСЕМЯННЫЕ,*СЛЕД) -ЕСЛИ(ТИП,ДЕРЕВЬЯ,5.*СЛЕД) -ЕСЛИ(ШИРОКАЯИПЛОСКАЯ,ДА,5.*СЛЕД) -ADDAX(КОНТЕКСТ(КЛАСС,ПОКРЫТОСЕМЯННЫЕ,5))# +ТО(КЛАСС,ГОЛОСЕМЯННЫЕ,*СЛЕД) -ЕСЛИ(ТИП,ДЕРЕВЬЯ,б.* СЛЕД) -ЕСЛИ(ШИРОКАЯИПЛОСКАЯ,НЕТ,б.*СЛЕД) -ADDAX(КОНТЕКСТ(КЛАСС,ГОЛОСЕМЯННЫЕ,б))# +ТО(ТИП,ТРАВЯНИСТЫЕ,*СЛЕД) -ЕСЛИ(СТЕБЕЛЬ,ЗЕЛЕНЫЙ,7.*СЛЕД) -ADDAX(КОНТЕКСТ(ТИП,ТРАВЯНИСТЫЕ,7))# +ТО(ТИП,ЛИАНЫ,*СЛЕД)-ЕСЛИ(СТЕБЕЛЬ,ДРЕВЕСНЫЙ,8.*СЛЕД) -ЕСЛИ(ПОЛОЖЕНИЕ,СТЕЛЮЩЕЕСЯ,8.*СЛЕД) -ADDAX(КОНТЕКСТ(ТИП,ЛИАНЫ,8))# +ТО(ТИП,ДЕРЕВЬЯ,*СЛЕД)-ЕСЛИ(СТЕБЕЛЬ,ДРЕВЕСНЫЙ,9.*СЛЕД) -ЕСЛИ(ПОЛОЖЕНИЕ,ПРЯМОСТОЯЩЕЕ,9.*СЛЕД) -ЕСЛИ(ОДИНОСНОВНОЙСТВОЛ,ДА,9.*СЛЕД) -ADDAX(КОНТЕКСТ(ТИП,ДЕРЕВЬЯ,9))# +ТО(ТИП,КУСТАРНИКОВЫЕ,*СЛЕД) -ЕСЛИ(СТЕБЕЛЬ,ДРЕВЕСНЫЙ,10.*СЛЕД) -ЕСЛИ(ПОЛОЖЕНИЕ,ПРЯМОСТОЯЩЕЕ,10.*СЛЕД) -ЕСЛИ(ОДИНОСНОВНОЙСТВОЛ,НЕТ,10.*СЛЕД) -ADDAX(КОНТЕКСТ(ТИП,КУСТАРНИКОВЫЕ,10))# 3. Факты, получаемые от пользователя, записываются в виде АТРИБУТ (ЗНАЧЕНИЕ). Но как показал проведенный анализ (см. п. 1.3), для организации пояснений факты желательно за¬ писывать в форме СТЕК-ФАКТОВ (^АТРИБУТ, *ЗНАЧЕ НИЕ, >fcHOMEP_ПРАВИЛА). Таким же образом должны быть записаны и факты, получаемые в результате работы правил. 158
Отметим, что для Пролога, в котором все тонкости реализации «спрятаны» от пользователя, наименование СТЕК-ФАКТОВ лучше заменить на КОНТЕКСТ, т. е. получаемые факты будут Храниться в отношении КОНТЕКСТ со следующей структурой: КОНТЕКСТ (^АТРИБУТ, ^ЗНАЧЕНИЕ, ^НОМЕР-ПРА¬ ВИЛА). 4. В версиях инструментальной экспертной системы на Пас¬ кале и ЛИСПЕ для организации работы блока пояснений мы использовали стек целей. При реализации на Прологе этот стек находится внутри управляющей структуры Пролога, и непосред¬ ственный доступ к нему невозможен. Поэтому нам надо как-то получить след работы системы при выводе. В результате ана¬ лиза был сделан вывод о целесообразности включения в пра¬ вила предметной области еще одного параметра, в котором бу¬ дет копиться след вывода в виде списка. На основании устранения всех указанных недостатков была выбрана структура внутреннего представления правил предмет¬ ной области для управления выводом (см. стр. 158). Ниже приведена программа логического вывода, осуществ¬ ляющая коррекцию логического вывода, заложенного в ПРО¬ ЛОГ, с учетом выше изложенных требований. Запуск программы логического вывода осуществляется с помощью ЗАПРОСА +ЕСЛИ(«АТРИБУТ,«ЗНАЧЕНИЕ,«СЛЕД) -ПРОВЕРКА(«АТРИБУТ,«ЗНАЧЕНИЕ) -/ # +ЕСЛИ(«АТРИБУТ,«ЗНАЧЕНИЕ,«СЛЕД) -ТО(«АТРИБУТ,«ЗНАЧЕНИЕ,«СЛЕД)-/# +ЕСЛИ(«АТРИБУТ,«ЗНАЧЕНИЕ,«СЛЕД) -/-ДИАЛОГ(«АТРИБУТ,«ЗНАЧЕНИЕ,«СЛЕД)-/# +ПРОВЕРКА(«АТРИБУТ,«ЗНАЧЕНИЕ) -КОНТЕКСТ(«АТРИБУТ,«ЗНАЧЕНИЕА,«НОМЕР) -SLASH(ЕСЛИ)-EQ(«ЗНАЧЕНИЕ,«ЗНАЧЕНИЕА)# +ДИАЛОГ(«АТРИБУТ,«ЗНАЧЕНИЕ,«СЛЕД) -ПОДСКАЗКИ(«АТРИБУТ,«ТЕКСТ)-PRINT(«ТЕКСТ) -INWORD(«ОТВЕТ) -ADDAX(КОНТЕКСТ(«АТРИБУТ,«ОТВЕТ,0)) —/—EQ(«ЗНАЧЕНИЕ,«ОТВЕТ)# +nE4ATb-PRINT('КОНТЕКСТ')-PRINT('АТРИБУТ')-OUTTAB -OUTPUT('ЗНАЧЕНИЕ') -OUTTAB-OUTPUT('НОМЕР ПРАВИЛА') -КОНТЕКСТ(«АТРИБУТ,«ЗНАЧЕНИЕ,«НОМЕР) -PRINT(«АТРИБУТ)-OUTTAB-OUTPUT(«ЗНАЧЕНИЕ) -OUTTAB-OUTPUT(«НОМЕР)-FALSE# +ПЕЧАТБ# +3AnPOCA-ERNOT-DELALL(КОНТЕКСТ) -ADDAX(КОНТЕКСТ(NIL,NIL,0))-FALSE# +ЗАПР0СА-ЕRYES^-PRINT('ЗАДАЙТЕ ЦЕЛЬ ')-INWORD(«ЦЕЛЬ) -ТО(«ЦЕЛЬ,«ЗНАЧЕНИЕ,«NIL) -PRINT('ОТВЕТ ')-OUTPUT!«ЗНАЧЕНИЕ)-ПЕЧАТЬ# •' +3AnP0CA-PRINT( 'ЦЕЛЬ НЕ МОЖЕТ БЫТЬ ДОСТИГНУТА')-ПЕЧАТЬ
Первая версия аксиомы ЗАПРОСА удаляет из базы данных старое отношение КОНТЕКСТ и организует новое, заканчива¬ ется версия аксиомы фактом FALSE, в результате чего ПРО¬ ЛОГ запускает вторую версию аксиомы. Вторая версия аксиомы ЗАПРОСА организует ввод цели вывода, запускает логический вывод, передавая управление пра¬ вилам предметной области, с конкретной целью. Третий пара¬ метр в вызове ТО (^цель, ^значение, NIL), предназначенный для накопления следа вывода, получает значение NIL, т. е. зна¬ чение пустого списка. Далее вторая версия аксиомы ЗАПРОСА обеспечивает печать полученного значения цели, затем получает управление аксиома ПЕЧАТЬ, которая используется при испы¬ тании блока логического вывода и осуществляет контрольную печать содержимого КОНТЕКСТа. Следует отметить, что аксиому ПЕЧАТЬ можно рассматри¬ вать как пример организации цикла обхождения (или пере¬ бора) с помощью цикла с возвратом. Так как первая версия аксиомы ПЕЧАТЬ кончается FALSE, то Пролог, пытаясь найти истинное значение аксиомы, перебирает все составляющие от¬ ношения КОНТЕКСТ и их печатает. Когда в отношении КОН¬ ТЕКСТ не останется элементов, то Пролог передает управление второй версии аксиомы ПЕЧАТЬ, которая сразу успешно завер¬ шается. Третия версия аксиомы ЗАПРОСА получает управление в случае, когда цель не может быть достигнута, и выдает соот¬ ветствующее сообщение на печать. Управление от аксиомы ЗАПРОСА получают аксиомы ТО, которые передают управление аксиомам ЕСЛИ. Первая версия аксиомы ЕСЛИ передает управление аксиоме ПРОВЕРКА, которая проверяет наличие атрибута в КОНТЕК СТЕ; в случае успеха осуществляется сравнение значений атри бута в КОНТЕКСТЕ (*ЗНАЧЕНИЕА) и в правиле (>ЦЗНАЧЕ НИЕ). Результат сравнения возвращается как значение аксио мы ЕСЛИ. Если атрибута в КОНТЕКСТЕ нет, то управление получает вторая версия аксиомы ЕСЛИ, которая, запуская аксиомы ТО, осуществляет поиск атрибута в части ТО правил; если такого правила нет, то получает управление третья вер сия аксиомы ЕСЛИ, передающая управление аксиоме ДИА ЛОГ. Выше была приведена упрощенная версия аксиомы ДИА ЛОГ, предназначенная для проведения испытаний блока логи ческого вывода, полная версия аксиомы ДИАЛОГ будет при ведена в п. 4.3. Аксиома ДИАЛОГ по значению переменной ^АТРИБУТ осуществляет поиск соответствующей подсказки, печать под сказки, ввод ответа пользователя. Атрибут и его значение, полу ченное от пользователя, записываются в КОНТЕКСТ. В каче 160
стве значения номера правила при этом записывается 0, как признак ответа пользователя. Функция SLASH перед вызовом аксиомы ДИАЛОГ в третьей версии аксиомы ЕСЛИ нужна для того, чтобы при неудаче по¬ иска подсказки прекратить поиск других версий аксиомы ЕСЛИ. Таким образом, постепенно усложняя текст программы, мы получили реализацию блока логического вывода, при этом раз¬ работали внутреннее представление для подсказок и для правил. Приведенные тексты программ на Прологе полностью готовы для проведения испытаний блока логического вывода. Запуск испытаний осуществляется с помощью ЗАПРОСА. Результаты испытаний можно проверить по тестовому примеру, приведен¬ ному в табл. 1.5. 4.3. РЕАЛИЗАЦИЯ БЛОКА ПОЯСНЕНИЙ И ЯЗЫКА ПОЛЬЗОВАТЕЛЯ Как уже неоднократно упоминалось, обращение к блоку объяснений может быть осуществлено перед ответом пользова¬ теля на подсказку. Поэтому в соответствии с синтаксическими диаграммами рис. 1.11 изменим текст аксиомы ДИАЛОГ, при¬ веденной в п. 4.2, приведем дополнительные аксиомы: +ДИАЛОГ(*АТРИБУТ,*ЗНАЧЕНИЕ,*СЛЕД) -ПОДСКАЗКИ(*АТРИБУТ,*ТЕКСТ)-PRINT(*ТЕКСТ) -REPEAT -PRINT('ЕСЛИ БУДЕТЕ ОТВЕЧАТЬ, ТО ВВЕДИТЕ #') -PRINT("ЕСЛИ БУДЕТЕ СПРАШИВАТЬ, ТО ВВЕДИТЕ ? ') -INWORD(*РЕЖИМ) - -ОБРАБОТКА(*РЕЖИМ,*АТРИБУТ,*ЗНАЧЕНИЕ,*СЛЕД)# В процессе работы аксиомы ДИАЛОГ осуществляется поиск текста подсказки для заданного атрибута и начинается (преди¬ катом REPEAT) цикл диалога, в начале которого у пользова¬ теля запрашивается режим диалога, т. е. режим ответов или ре¬ жим вопросов, после чего управление передается аксиоме ОБ¬ РАБОТКА: •г* +ОБРАБОТКА(' #',*АТРИБУТ,«ЗНАЧЕНИЕ,«СЛЕД) -PRINT('ОТВЕЧАЙТЕ ')-INWORD(«ОТВЕТ) -ADDAX(КОНТЕКСТ(«АТРИБУТ,«ОТВЕТ, 0) ) -SLASH(ДИАЛОГ)-EQ(«ЗНАЧЕНИЕ,«ОТВЕТ)# +ОВРАБОТКА(' ?',«АТРИБУТ,«ЗНАЧЕНИЕ,«СЛЕД) -ОБЬЯСНЕНИЯ(«АТРИБУТ,«ЗНАЧЕНИЕ,«СЛЕД) -ПОДСКАЗКИ(«АТРИБУТ,«ТЕКСТ)-PRINT(«ТЕКСТ) -ОБРАБОТКА(' #' ,«АТРИБУТ,«ЗНАЧЕНИЕ,«СЛЕД)# +ОБРАБОТКА(«ЛЮБОЙ,«АТРИБУТ,«ЗНАЧЕНИЕ,«СЛЕД) -PRINT('НЕВЕРНЫЙ СИМВОЛ ')-OUTPUT(«ЛЮБОЙ) -/-FALSE# г И в. Э. Балтрашевич 161
Аксиома ОБРАБОТКА имеет два режима. Если пользователь в качестве указателя режима в процессе выполнения аксиомы ДИАЛОГ ввел символ 41=1 то выполняется (первая версия аксиомы ОБРАБОТКА) режим получения значения атрибута от пользователя, запись его в КОНТЕКСТ и выход из диалога со значением, определяемым сравнением значений атрибута в пра¬ виле и атрибута, заданного пользователем. Если пользователь в качестве указателя режима ввел сим¬ вол?, то выполняется (вторая версия аксиомы ОБРАБОТКА) режим объяснений, после которого повторяется подсказка и осу¬ ществляется обработка в режиме получения ответа от пользова¬ теля. Если же пользователь не правильно задал режим обработки^ то срабатывает третья версия аксиомы ОБРАБОТКА, которая выдает соответствующие сообщения и, заканчиваясь значением FALSE, позволяет стандартной аксиоме REPEAT в аксиоме ДИАЛОГ повторить цикл запроса режима. Действие аксиомы ОБЪЯСНЕНИЯ сводится к запуску аксиомы ПОЧЕМУ. Если вызов аксиомы ПОЧЕМУ заканчива¬ ется неудачно, то управление получает вторая версия аксиомы ОБЪЯСНЕНИЯ, которая завершает режим объяснений: ♦ОБЬЯСНЕНИЯ(*АТРИБУТ,*ЗНАЧЕНИЕ,*СЛЕД) -ПОЧЕМУ(*АТРИБУТ,*ЗНАЧЕНИЕ,*СЛЕД)# ♦ОБЪЯСНЕНИЯ(*АТРИБУТ,*ЗНАЧЕНИЕ,*СЛЕД)# Аксиома ПОЧЕМУ организует цикл перебора следа вывода. Если след пуст (NIL), т. е. по аналогии с п. 1.4 стек целей пуст,, то на вопрос ПОЧЕМУ печатается сообщение «Вы этого хотели сами», если список СЛЕД не пуст, то из него выбирается номер первого правила и производится печать этого правила. При сле¬ дующем вопросе ПОЧЕМУ происходит рекурсивное обращение к аксиоме ПОЧЕМУ, но уже с остатком следа: ♦ПОЧЕМУ(*АТРИБУТ,*ЗНАЧЕНИЕf NIL) -PRINT('ВЫ ЭТОГО ХОТЕЛИ САМИ')# ♦ПОЧЕМУ(*АТРИБУТ,*ЗНАЧЕНИЕ,*НОМЕР.*СЛЕД) -ПЕЧАТЬПРАВИЛА(*НОМЕР)-ВОПРОСЫ -ПОЧЕМУ(*АТРИБУТ,^ЗНАЧЕНИЕ,*СЛЕД)# Описание аксиом, обеспечивающих режим вопросов, приве¬ дено ниже: 162
♦ВОПРОСЫ-REPEAT -PRINT('ЖДУ ВОПРОСОВ [ПОЧЕМУ,КАК,НЕТ] ') -INWORD ( *ВОПРОС) -ВОПРОС ( ^ВОПРОС) W# ♦ВОПРОС (ПОЧЕМУ) # ♦ВОПРОС (НЕТ) -SLASH(ПОЧЕМУ) -FALSE# ♦ВОПРОС(КАК) -PRINT('ЗАДАЙТЕ НАЗВАНИЕ АТРИБУТА ') -INWORD ( * АТРИБУТ) -КАК( * АТРИБУТ) -/-FALSE# ♦ВОПРОС(*ЛЮБОЙ)-PRINT('НЕВЕРНЫЙ СИМВОЛ ') -OUTPUT(*ЛЮБОЙ)-/-FALSE# ♦КАК (* АТРИБУТ) -КОНТЕКСТ(*АТРИБУТ,*ЗНАЧЕНИЕ,*НОМЕР) -СООБЩЕНИЕ(*НОМЕР)# ♦КАК ( * АТРИБУТ) -ПОИСКПР АВИЛА ( * АТРИБУТ, * ЗНАЧЕНИЕ, *НОМЕР) -PRINT('МОЖЕТ БУДЕТ ИСПОЛЬЗОВАНО ПРАВИЛО ') -OUTPUT(*НОМЕР) -NEWLINE-ПЕЧАТЬПРАВИЛА(*НОМЕР)# ♦КАК (* АТРИБУТ) -PRINT ('ИНФОРМАЦИЯ МОЖЕТ БЫТЬ ЗАДАНА ПОЛЬЗОВАТЕЛЕМ')# ♦СООБЩЕНИЕ(0) -PRINT('ИНФОРМАЦИЯ ВВОДИЛАСЬ ПОЛЬЗОВАТЕЛЕМ')# ♦СООБЩЕНИЕ(*НОМЕР) -PRINT('БЫЛО ИСПОЛЬЗОВАНО ПРАВИЛО ') -OUTPUT(*НОМЕР) -NEWLINE-nE4ATbnPABHHA(*НОМЕР)# Первый вариант аксиомы КАК пытается найти интересую¬ щий пользователя атрибут в КОНТЕКСТЕ. В случае успеха вы¬ дается сообщение, зависящее от номера правила, под действием которого были записаны в КОНТЕКСТ атрибут и его значение. Если номер равен нулю, то согласно п. 1.4 это значит, что инфор¬ мация вводилась пользователем. При любом другом номере рас¬ печатывается правило с найденным номером. Второй вариант аксиомы КАК запускается в случае неудачи поиска атрибута в КОНТЕКСТЕ для того, чтобы найти правило, в части ТО которого имеется заданный атрибут. В случае успеха выдается сообщение «может будет использовано правило», печа¬ тается номер и текст правила. Третий вариант аксиомы КАК включается в случае неудачи поиска в КОНТЕКСТЕ и среди правил; он выдает сообщение о том, что значение атрибута может быть задано только поль¬ зователем. Перед тем как привести описания аксиом ПОИСК-ПРА¬ ВИЛА и ПЕЧАТЬ^ ПРАВИЛ А, выберем внутреннее представ¬ ление для правил предметной области, используемых при реали¬ зации блока объяснений. Структура должна быть определена с учетом действий, которые над ней должны быть произведены. Как следует из вышеизложенного, нам необходимы доступ U1* 163
+ПРАВИЛА(1,(ЕСЛИ-КЛАСС=ГОЛОСЕМЯННЫЕ). (И-ФОРМАЛИСТА-ЧЕШУЕОБРАЗНАЯ).NIL, (ТО-СЕМЕЙСТВО=КИПАРИСОВЫЕ).NIL)# +ПРАВИЛА(2, (ЕСЛИ-КЛАСС-ГОЛОСЕМЯННЫЕ). (И-ФОРМАЛИСТА-ИГЛОПОДОБНАЯ). (И-КОНФИГУРАЦИЯ-ХАОТИЧЕСКАЯ).NIL, (ТО-СЕМЕЙСТВО=СОСНОВЫЕ).NIL)# +ПРАВИЛА(3,(ЕСЛИ-КЛАСС=ГОЛОСЕМЯННЫЕ). (И-ФОРМАЛИСТА-ИГЛОПОДОБНАЯ). (И-КОНФИГУРАЦИЯ-ДВАРОВНЫХРЯДА). (И-СЕРЕБРИСТАЯПОЛОСА=ДА).NIL, (ТО-СЕМЕЙСТВО-СОСНОВЫЕ).NIL)# +ПРАВИЛА(4,(ЕСЛИ-КЛАСС-ГОЛОСЕМЯННЫЕ). (И-ФОРМАЛИСТА-ИГЛОПОДОБНАЯ). (И-КОНФИГУРАЦИЯ-ДВАРОВНЫХРЯДА). (И-СЕРЕВРИСТАЯПОЛОСА-НЕТ).NIL, (ТО-СЕМЕЙСТВО=БОЛОТНЫЙ_КИПАРИС).NIL)# +ПРАВИЛА(5,(ЕСЛИ-ТИП-ДЕРЕВЬЯ). (И-ШИРОКАЯ_И_ПЛОСКАЯ=ДА).NIL, (ТО-КЛАСС-ПОКРЫТОСЕМЯННЫЕ).NIL)# +ПРАВИЛА(б,(ЕСЛИ-ТИП-ДЕРЕВЬЯ). (И-ШИРОКАЯ_И_ПЛОСКАЯ=НЕТ).NIL, (ТО-КЛАСС-ГОЛОСЕМЯННЫЕ).NIL)# +ПРАВИЛА(7,(ЕСЛИ-СТЕБЕЛЬ=ЗЕЛЁНЫЙ).NIL, (ТО-ТИП-ТРАВЯНИСТЫЕ).NIL)# +ПРАВИЛА(8,(ЕСЛИ-СТЕБЕЛЬ-ДРЕВЕСНЫЙ). (И-ПОЛОЖЕНИЕ-СТЕЛЮЩЕЕСЯ).NIL, (ТО-ТИП-ЛИАНЫ).NIL)# +ПРАВИЛА(9,(ЕСЛИ-СТЕБЕЛЬ-ДРЕВЕСНЫЙ). (И-ПОЛОЖЕНИЕ-ПРЯМОСТОЯЩЕЕ). (И-ОДИН_ОСНОВНОЙ_СТВОЛ=ДА).NIL, (ТО-ТИП-ДЕРЕВЬЯ).NIL)# +ПРАВИЛА(10,(ЕСЛИ-СТЕБЕЛЬ-ДРЕВЕСНЫЙ) (И-ПОЛОЖЕНИЕ-ПРЯМОСТОЯЩЕЕ). (И-ОДИН_ОСНОВНОЙ_СТВОЛ=НЕТ).NIL, (ТО-ТИП-КУСТАРНИКОВЫЕ).NIL)# к правилу по его номеру, доступ к правилу по атрибуту и зна¬ чению в части ТО, печать атрибутов и их значений отдельно в части ЕСЛИ и в части ТО. Для удовлетворения всех этих тре¬ бований было решено использовать следующую структуру: ПРАВИЛА (*Номер, *ЕСЛИ, *ТО), причем части ЕСЛИ и ТО будут организованы в виде списков из структурированных элементов. Для организации структурированных элементов используем оператор «—» с приоритетом 4, описываемый следующим об¬ разом: OPERATOR *S—*S = *S, 4) и стандартный оператор «•» с приоритетом 3. 164
В процессе рассуждений об организации логического вывода В п. 4.2 мы пришли к выводу, что знания о правилах предмет¬ ной области, полученные от эксперта, должны быть представ¬ лены в виде аксиом ТО. Эти правила управляют логическим вы¬ водом решения конкретной задачи, заданной пользователем. Средства Пролога не позволяют проводить над этими прави¬ лами какие-то действия, связанные с их печатью и доступом к отдельным частям для распечатывания. Поэтому было введено отношение ПРАВИЛА, в котором те же правила предметной области, полученные от эксперта, будут представлены в виде, удобном для их обработки в блоке объяснений. Текст отноше¬ ния ПРАВИЛА, т. е. внутреннее представление правил для ис¬ пользования при объяснениях, приведен на стр. 164. С учетом выбранного представления правил, можно реализо¬ вать оставшиеся аксиомы ПОИСКПРАВИЛА и ПЕЧАТЬПРА- ВИЛА +ПОИСКПРАВИЛА(*АТРИБУТ,*ЗНАЧЕНИЕ,*НОМЕР) -ПРАВИЛА(*НОМЕР,*ЕСЛИ, (*СЛ0В0-*АТРИБУТ=*ЗНАЧЕНИЕ).*Т0)# +ПЕЧАТЫ1РАВИЛА(‘НОМЕР)-ПРАВИЛА(‘НОМЕР,‘ЕСЛИ,*ТО) -PRINT('ПРАВИЛО ')-OUTPUT(‘НОМЕР) -OUTPUT(' ГЛАСИТ:')-ПЕЧАТЬСПИСКА(‘ЕСЛИ) -NEWSTRING-ПЕЧАТЬСПИСКА(*ТО)# +ПЕЧАТЬПРАВИЛА(‘НОМЕР)-PRINT('ТАКОГО ПРАВИЛА НЕТ')# +ПЕЧАТЬСПИСКА(NIL)# +ПЕЧАТЬСПИСКА((‘СЛОВО-*АТРИБУТ=*ЗНАЧЕНИЕ).‘СПИСОК) -PRINT(‘СЛОВО)-OUTTAB -ПЕЧАТЬАТРИБУТА(‘АТРИБУТ)-OUTTAB -OUTPUT(‘ЗНАЧЕНИЕ) -ПЕЧАТЬСПИСКА(‘СПИСОК)# +ПЕЧАТБАТРИБУТА(‘АТРИБУТ)-ПЕРЕВОДЫ(‘АТРИБУТ,‘ТЕКСТ) -OUTPUT(‘ТЕКСТ)-OUTPUT('[')-OUTPUT(‘АТРИБУТ) -OUTPUT(']')# +ПЕЧАТБАТРИБУТА(‘АТРИБУТ)-OUTPUT(‘АТРИБУТ)# Аксиома ПОИСКПРАВИЛА осуществляет поиск правила, у которого в части ТО имеется заданный атрибут, после этого переменные ^НОМЕР и ^ЗНАЧЕНИЕ примут соответствую¬ щие этому правилу значения. Аксиома ПЕЧАТЬПРАВИЛА осуществляет поиск правила с заданным номером и последовательно распечатывает части ЕСЛИ и ТО найденного правила с помощью аксиомы ПЕЧАТЬ СПИСКА. Если правило с указанным номером отсутствует, та запускается второй вариант аксиомы ПЕЧАТЬПРАВИЛА, вы¬ дающий соответствующее сообщение. Аксиома ПЕЧАТЬСПИСКА осуществляет обхождение всего списка с остановкой при пустом (NIL) значении списка. При 165
этом выделяются и распечатываются все компоненты структу¬ рированных элементов списка. Печать атрибута осуществляется соответствующей аксиомой. Аксиома ПЕЧАТЬАТРИБУТА пытается найти текст пе¬ ревода для заданного атрибута и в случае успеха печатает пе¬ ревод и в квадратных скобках название атрибута, а в случае неудачи поиска перевода распечатывает просто название атри¬ бута. Точное название атрибута, как уже отмечалось выше, нужно для формирования вопроса КАК. Аксиома ПЕЧАТЬАТ¬ РИБУТА использует отношение ПЕРЕВОДЫ, структура кото¬ рого выбрана по аналогии со структурой отношения ПОД¬ СКАЗКИ (см. п. 4.2): ♦ПЕРЕВОДЫ(СТЕБЕЛЬ,'СТЕБЕЛЬ РАСТЕНИЯ')# ♦ПЕРЕВОДЫ(ПОЛОЖЕНИЕ,'ПОЛОЖЕНИЕ СТЕБЛЯ')# ♦ПЕРЕВОДЫ(одиносновнойствол, 'РАСТЕНИЕ (НЕ)ИМЕЕТ ОДИН ОСНОВНОЙ СТВОЛ')# ♦ПЕРЕВОДЫ(ТИП,'ТИП РАСТЕНИЯ')# ♦ПЕРЕВОДЫ(СЕМЕЙСТВО,'СЕМЕЙСТВО РАСТЕНИЯ')# ♦ПЕРЕВОДЫ(ШИРОКАЯИПЛОСКАЯ, 'ФОРМА ЛИСТЬЕВ - (НЕ)ШИРОКАЯ И (НЕ)ПЛОСКАЯ')# ♦ПЕРЕВОДЫ(КЛАСС,'КЛАСС РАСТЕНИЯ')# ♦ПЕРЕВОДЫ(ФОРМАЛИСТА,'ФОРЦА ЛИСТА')# ♦ПЕРЕВОДЫ(КОНФИГУРАЦИЯ, 'КОНФИГУРАЦИЯ РАСПОЛОЖЕНИЯ ИГЛ ВДОЛЬ ВЕТВИ')# ♦ПЕРЕВОДЫ(СЕРЕБРИСТАЯПОЛОСА, 'СНИЗУ ИГЛЫ ИМЕЕТСЯ (ОТСУТСТВУЕТ) СЕРЕБРИСТАЯ ПОЛОСА')# Итак, мы завершили реализацию блока пояснений и языка пользователя на Прологе. Для проведения испытаний разрабо¬ танных аксиом необходимо удалить из памяти упрощенный ва¬ риант аксиомы ДИАЛОГ и ввести разработанные аксиомы. Запуск системы осуществляется с помощью ЗАПРОСА. Испытание блока пояснений фактически сводится к испыта¬ нию всей экспертной системы (пока не являющейся инструмен¬ тальной). После проверки системы на примере из области ботаники ее можно проверить на нашем втором примере из области лингви¬ стики. Однако поскольку разработанная нами система не явля¬ ется инструментальной вследствие отсутствия компилятора с языка внешнего представления знаний, нам придется составить новые аксиомы (отношения) ТО, ПОДСКАЗКИ, ПЕРЕВОДЫ и ПРАВИЛА в соответствии с приведенными выше. Фактически мы должны задать внутреннее представление знаний. Но так как базовой машиной является Пролог-машина, это представление имеет довольно высокий уровень, т. е. уро¬ вень максимально приближенный к эксперту, и фактически очень мало отличается от языка эксперта. 166
4.4. РЕАЛИЗАЦИЯ ЯЗЫКА ЭКСПЕРТА В процессе реализаии блока логического вывода и блока по¬ яснений мы разработали структуру внутреннего представления внаний, т. е. структуру представления правил, используемых при логическом выводе, в виде аксиом ТО (см. п. 4.2), структуру ПРАВИЛА для представления правил при использовании в блоке пояснений (см. п. 4.3), структуры ПОДСКАЗКИ и ПЕ¬ РЕВОДЫ для представления подсказок (см. п. 4.2) и переводов (см. п. 4.3). Синтаксические диаграммы языка эксперта т. е. внешнего представления знаний, приведены на рис. 1.6. Реализуем ком¬ пилятор в соответствии с этими синтаксическими диаграммами, внеся незначительное непринципиальное упрощение: не будем использовать предикат «—» между атрибутами и их значе¬ ниями в правилах. На рис. 1.6 фактически приведено внешнее представление знаний для реализуемого компилятора, при условии, что будут удалены символы «—» из правил. Предположим, что внешнее представление знаний записано в некотором файле. Таким образом, задачей разрабатываемого компилятора яв¬ ляется синтаксическая проверка и преобразование внешнего представления знаний, построенных в соответствии с рис. 1.6, во внутреннее представление в виде аксиом ТО, ПОДСКАЗКИ, ПЕРЕВОДЫ и ПРАВИЛА. Ниже приведены подготовительные аксиомы. OPERATOR(,*S-*S=*S,4) -(-КОМПИЛЯТОР - Р RI NT ( ' ВВ ЕДИТЕ ИМЯ ФАЙЛА СО ЗНАНИЯМИ ') -INWORD(*Х)-INOPEN(*Х)-BSWITCH « -BBOfl-CSWITCH-INCLOSE# +ВВОД-АНАЛИЗ # +ВВОД# +AHAnH3-REPEAT-TW0# -l-TWO-ПРЕДЛОЖЕНИЕ-/-FALSE# +TWO-SLASH (АНАЛИЗ)-FALSE# -(•ПРЕДЛОЖЕНИЕ-INWORD( *Х) -Р(*Х)# Аксиома КОМПИЛЯТОР запрашивает имя файла с внеш¬ ним представлением знаний (программой на языке эксперта), открывает его, вызывает аксиому ВВОД и после ее успешного выполнения закрывает файл. Аксиома ВВОД вызывает аксиому АНАЛИЗ, которая с по¬ мощью REPEAT зацикливает аксиому ПРЕДЛОЖЕНИЕ до конца файла с исходными данными. Аксиома ПРЕДЛОЖЕНИЕ вводит первое слово очередного предложения языка эксперта и передает управление аксиоме Р С введенным словом в качестве параметра: 167
+Р(ПОДСКАЗКА)-/-ПОДСКАЗКА# +Р(ПЕРЕВОД)-/-ПЕРЕВОД# +Р(‘НОМЕР)-NUM(‘НОМЕР)-/-ПРАВИЛО(‘НОМЕР)# +Р(‘ЛЮБОЙ)-ОШИБКА(‘ЛЮБОЙ)# Если первым словом предложения является подсказка, то происходит вызов аксиомы ПОДСКАЗКА; если первым словом предложения является перевод, то происходит вызов аксиомы ПЕРЕВОД; если первым словом предложения является число, то вызывается аксиома ПРАВИЛО с введенным номером в ка¬ честве параметра; если первым словом является любое дру¬ гое слово, то вызывается аксиома ОШИБКА. Таким образом, структура аксиомы Р реализует действия, аналогичные опера¬ торам Паскаля IF ... THEN ... ELSE IF... THEN ... ELSE IF... Аксиома ПЕРЕВОД получает управление, если предложе¬ ние языка эксперта начинается со слова перевод, и производит ввод атрибута, переход на новую строку файла, ввод текста пе¬ ревода, формирование аксиомы ПЕРЕВОДЫ и запись ее в базу данных с помощью ADDAX: +ПЕРЕВОД-INWORD(‘АТРИБУТ)-NEWSTRING-INSTRING(‘ТЕКСТ) -ADDAX(ПЕРЕВОД^(*АТРИБУТ,‘ТЕКСТ))# Аксиома ПОДСКАЗКА получает управление, если предло¬ жение языка эксперта начинается со слова подсказка, и про¬ изводит ввод атрибута, переход на новую строку файла, ввод текста подсказки, формирование аксиомы ПОДСКАЗКИ и запись ее в базу данных с помощью ADDAX: +П0ДСКАЗКА-INWORD(‘АТРИБУТ)-NEWSTRING-INSTRING(‘ТЕКСТ) -ADDAX(ПОДСКАЗКИ(‘АТРИБУТ,‘ТЕКСТ))# Аксиома ПРАВИЛО получает управление, если предложе¬ ние языка эксперта начинается с номера, и производит ввод очередного слова, которым может быть либо ЕСЛИ, либо ТО и запусакет аксиому Р1 с введенным словом и номером в каче¬ стве параметра: -►ПРАВИЛО(‘НОМЕР)-INWORD(*Х)-Р1(*Х,‘НОМЕР,NIL,NIL,‘СЛЕД)# Аксиома Р1 фактически начинает анализ и обработку пра¬ вила. В результате обработки правила должна быть получена соответствующая аксиома ТО и соответствующая аксиома (или строка отношения) ПРАВИЛА. В процессе обработки правила будущая аксиома ТО будет копиться в виде списка СПИСОКТО, который после окончания 168
обработки правила с помощью ADDAX будет преобразован в аксиому со стандартной структурой. Как уже отмечалось выше, отношение ПРАВИЛА имеет Структуру ПРАВИЛА (*НОМЕР, *ЕСЛИ, *ТО) Причем ЕСЛИ и ТО представлены в виде списков соответствую¬ щих частей правил. Часть ТО фактически будет состоять из од¬ ного элемента списка, а список для части ЕСЛИ может быть большим, для его накопления будет использован список СПИ- СОКПР. Перед началом обработки списки СПИСОКТО и СПИСОКПР должны быть пустыми. Поэтому при вызове ак¬ сиомы Р1 на месте параметров, соответствующих этим спискам, стоят NIL. Кроме того, при формировании аксиомы ТО надо Предусмотреть переменную для организации следа вывода, что и сделано при вызове аксиомы Р1: +Р1(ЕСЛИ,*НОМЕР,*СПИСОКТО,*СПИСОКПР,*СЛЕД) -INWORD(*АТРИБУТ) -INWORD(*ЗНАЧЕНИЕ)-NEWSTRING-INWORD(*Y)-/ _P2(*Y,‘НОМЕР, ЕСЛИ(‘АТРИБУТ,‘ЗНАЧЕНИЕ,‘НОМЕР.‘СЛЕД).‘СПИСОКТО (ЕСЛИ-*АТРИБУТ=*ЗНАЧЕНИЕ).‘СПИСОКПР,‘СЛЕД)# +Р1(ТО,‘НОМЕР,* СПИСОКТО,* СПИСОКПР,* СЛЕД) -INWORD(‘АТРИБУТ)-INWORD(‘ЗНАЧЕНИЕ)-NEWSTRING-/ -ДОБАВИТЬВКОНЕЦ(ТО(‘АТРИБУТ,‘ЗНАЧЕНИЕ,‘СЛЕД). ‘СПИСОКТО, ADDAX(КОНТЕКСТ(‘АТРИБУТ,‘ЗНАЧЕНИЕ,‘НОМЕР)), ‘СПИСОКА) -NEWLINE-OUTLIST(‘СПИСОКА)-NEWLINE -ADDAX(‘СПИСОКА) -NEWLINE-OUTLIST(‘СПИСОКПР)-NEWLINE -ADDAX(ПРАВИЛА(‘НОМЕР,‘СПИСОКПР, (ТО-*АТРИБУТ=‘ЗНАЧЕНИЕ).NIL))# ♦Р1(*Х,‘НОМЕР,‘СПИСОКТО,‘СПИСОКПР,‘СЛЕД)-ОШИБКА(*Х)# Первая версия аксиомы Р1 получает управление, если за номером в правиле стоит слово ЕСЛИ. В процессе выполнения аксиомы происходит ввод атрибута и его значения, перевод на Новую строку и ввод первого слова следующей строки, которым может быть либо И, либо ТО. После этого осуществляется за¬ пуск аксиомы Р2 с введенным словом в качестве первого пара¬ метра. При вызове аксиомы Р2 происходит соответствующее наращивание списков СПИСОКТО и СПИСОКПР. Вторая версия аксиомы Р1 получает управление, если за номером в правиле стоит слово ТО. В процессе выполнения ак¬ сиомы происходит ввод атрибута и его значения и переход на Новую строку. После этого с помощью аксиомы ДОБАВИТЬ- ВКОНЕЦ осуществляется доформирование списка СПИСОКТО 169
во вспомогательном списке СПИСОКА, и с помощью ADDAX этот список преобразуется в аксиому ТО и записывается в базу данных Пролога. В заключение происходит доформирование и запись в базу данных с помощью ADD АХ аксиомы ПРАВИЛА. Третья версия аксиомы Р1 получает управление при любом ошибочном слове в правиле после номера и вызывает аксиому ОШИБКА. Аксиома ДОБАВИТЬВКОНЕЦ осуществляет добавление элемента списка, стоящего на месте второго параметра, к списку, стоящему на месте первого параметра, результирую¬ щий список получается на месте третьего параметра: +ДОБАВИТЬВКОНЕЦ(NIL,*ЭЛЕМЕНТ,*ЭЛЕМЕНТ.NIL)-/# +ДОБАВИТЬВКОНЕЦ(*Х.*СПИСОК,‘ЭЛЕМЕНТ,*Х.‘СПИСОКА) -ДОБАВИТЬВКОНЕЦ(‘СПИСОК,‘ЭЛЕМЕНТ,‘СПИСОКА)# Аксиома ОШИБКА распечатывает ошибочный символ и за¬ канчивает работу компилятора: +ОШИБКА(*Х)-PRINT('ОШИБКА ')-OUTPUT(*Х) -SLASH(КОМПИЛЯТОР)-FALSE# Описание аксиомы Р2 имеет вид +Р2(ТО,‘НОМЕР,‘СПИСОКТО,‘СПИСОКПР,‘СЛЕД)-/ -Р1(ТО,‘НОМЕР,‘СПИСОКТО,‘СПИСОКПР,‘СЛЕД)# +Р2('И',‘НОМЕР,‘СПИСОКТО,‘СПИСОКПР,‘СЛЕД) -INWORD(‘АТРИБУТ)-INWORD(‘ЗНАЧЕНИЕ)-NEWSTRING-/ -ДОБАВИТЬВКОНЕЦ(‘СПИСОКТО, ЕСЛИ(‘АТРИБУТ,‘ЗНАЧЕНИЕ,‘НОМЕР.‘СЛЕД),‘СПИСОКА) -ДОБАВИТЬВКОНЕЦ(‘СПИСОКПР, ('И'-*АТРИБУТ=*ЗНАЧЕНИЕ),‘СПИСОКБ) -INWORD(*Х) -Р2(*Х,‘НОМЕР,‘СПИСОКА,‘СПИСОКБ,‘СЛЕД)# +Р2(*Х,‘НОМЕР,‘СПИСОКТО,‘СПИСОКПР,‘СЛЕД)-ОШИБКА(*Х)# Первая версия аксиомы Р2 получает управление, если сле¬ дующая строка правила начинается со слова ТО, в этом слу¬ чае происходит запуск аксиомы Р1 с теми же параметрами. Вторая версия аксиомы Р2 получает управление, если сле¬ дующая строка правила начинается со слова И. В этом случае производится ввод атрибута и его значения и переход на но¬ вую строку файла исходных данных. После этого с помощью аксиомы ДОБАВИТЬВКОНЕЦ происходит соответствующее доформирование списков СПИСОКТО и СПИСОКПР во вспо¬ могательные списки СПИСОКА и СПИСОКБ соответственно. 170
В заключение производится ввод первого слова (И или ТО) следующей строки и запуск аксиомы Р2 с соответствующим па¬ раметром. Третья версия аксиомы Р2 получает управление, если сле¬ дующая строка правила начинается с любого символа, кроме разрешенного. В этом случае осуществляется вызов аксиомы ОШИБКА. Запуск компилятора осуществляется аксиомой ЗАПРОС, ко¬ торая после успешной работы аксиомы КОМПИЛЯТОР с по¬ мощью системных процедур SAVE сохраняет полученные ак¬ сиомы ТО, ПРАВИЛА, ПЕРЕВОДЫ и ПОДСКАЗКИ: +ЗАПР0С-КОМПИЛЯТОР-SAVE(ПРАВИЛА)-SAVE(ТО) -SAVE(ПЕРЕВОДЫ)-SAVE(ПОДСКАЗКИ)# +3AnP0C-PRINT('ОШИБКА В КОМПИЛЯТОРЕ')# Для испытания компилятора надо, как указывалось выше, подготовить файл с внешним представлением знаний, запустить компилятор с помощью аксиомы ЗАПРОС и после завершения его работы с помощью сервисных средств системы ПРОЛОГ просмотреть содержимое аксиом ПОДСКАЗКИ, ТО, ПРА¬ ВИЛА и ПЕРЕВОДЫ, которое должно совпадать с приведен¬ ными выше описаниями. Текст программы интерпретации растений (см. п. 1.5) дол¬ жен иметь вид 1 ЕСЛИ КЛАСС ГОЛОСЕМЯННЫЕ И ФОРМАЛИСТА ЧЕШУЕОБРАЗНАЯ ТО СЕМЕЙСТВО КИПАРИСОВЫЕ 2 ЕСЛИ КЛАСС ГОЛОСЕМЯННЫЕ И ФОРМАЛИСТА ИГЛОПОДОБНАЯ И КОНФИГУРАЦИЯ ХАОТИЧЕСКАЯ ТО СЕМЕЙСТВО СОСНОВЫЕ 10 ЕСЛИ СТЕБЕЛЬ ДРЕВЕСНЫЙ И ПОЛОЖЕНИЕ ПРЯМОСТОЯЩЕЕ И ОДИНОСНОВНОЙСТВОЛ НЕТ ТО ТИП КУСТАРНИКОВЫЕ ПОДСКАЗКА СТЕБЕЛЬ КАКОЙ СТЕБЕЛЬ У РАСТЕНИЯ - ДРЕВЕСНЫЙ ИЛИ ЗЕЛЕНЫЙ? ПОДСКАЗКА СЕРЕБРИСТАЯПОЛОСА ИМЕЕТСЯ ЛИ СЕРЕБРИСТАЯ ПОЛОСА СНИЗУ ИГЛЫ (ДА ИЛИ НЕТ)9 ПЕРЕВОД СТЕБЕЛЬ СТЕБЕЛЬ РАСТЕНИЯ ПЕРЕВОД СЕРЕБРИСТАЯПОЛОСА СНИЗУ ИГЛЫ ИМЕЕТСЯ (ОТСУТСТВУЕТ) СЕРЕБРИСТАЯ ПОЛОСА 171
4.5. ОСНОВНАЯ ПРОГРАММА ИНСТРУМЕНТАЛЬНОЙ ЭКСПЕРТНОЙ СИСТЕМЫ В параграфе 4.4 был реализован компилятор, преобразую¬ щий программу, записанную на языке эксперта, во внутреннее представление знаний, структура которого была получена в п. 4.2 и п. 4.3. Запуск компилятора осуществляется с по¬ мощью аксиомы ЗАПРОС. Блок логического вывода, исполь¬ зующий блок пояснений, запускается с помощью ЗАПРОСА. При этом предполагается, что внутреннее представление знаний уже сформировано. Если мы создадим аксиому ВЫВОД вида + ВЫВОД—ЗАПРОС—ЗАПРОСА# и с ее помощью будем запускать систему, то вначале пройдет компиляция, а потом логический вывод для цели заданной пользователем в процессе диалога. Если пользователю потребуется решить задачу из той же предметной области, т. е. без Смены содержимого базы знаний, то он может запустить систему с помощью ЗАПРОСА. Теперь мы можем подвести итоги реализации инструмен¬ тальной экспертной системы на Прологе и наметить некоторые перспективы развития реализации. В процессе постепенного усложнения решения задачи ин¬ терпретации для конкретной предметной области были вы¬ браны структуры данных для внутреннего представления знаний. Для подсказок и переводов были выбраны отношения ПОД¬ СКАЗКИ (см. п. 4.2) и ПЕРЕВОДЫ (см. п. 4.3) с элементами атомарной и строковой структуры. Для представления правил, предназначенных для использо¬ вания в блоке пояснений, выбрано отношение ПРАВИЛА (см. п. 4.3), один элемент которого должен принимать числовое, зна¬ чение, а в качестве двух других элементов отношения исполь¬ зуются списки со структурированными элементами. Для представления правил, применяемых при управлении логическим выводом, используются аксиомы ТО с двумя пара¬ метрами (см. п. 4.2), которые в свою очередь используют двух¬ элементные отношения ЕСЛИ. Характерной особенностью Пролога является наличие двух равноправных семантик. Предложение Пролога можно тракто¬ вать как декларативное описание некоторых свойств и как опи¬ сание процедур. Так, например для того чтобы отношение ЕСЛИ при конкретном атрибуте и его значении было истин¬ ным надо, чтобы при соответствующем атрибуте и его значении было истинным либо отношение ПРОВЕРКА, либо отноше¬ 172
ние ТО, которое в свою очередь требует выполнения ряда процедур ЕСЛИ, либо должна выполняться процедура ДИА¬ ЛОГ. При реализации экспертной системы на Паскале и ЛИСПе мы много сил тратили на организацию поиска по образцу и ор¬ ганизацию возвратов. В Прологе же эти действия заложены в его управляющую структуру, что приводит к значительно меньшему объему программистской работы. При разработке аксиом неоднократно подчеркивалась про¬ стота организации либо циклов поиска, либо циклов перебора. Организация циклов на Прологе не требует специальных зна¬ ний из области вычислительной техники, связанных с необходи¬ мостью индексации и знания операторов цикла, как при ис¬ пользовании Паскаля. Использование обратного вывода, лежащего в основе управ¬ ляющей структуры Пролога, приводит к необходимости повтора запросов атрибутов у пользователя. Чтобы устранить этот не¬ достаток, пришлось ввести отношение КОНТЕКСТ, эквивалент¬ ное стеку фактов при реализации на Паскале и ЛИСПе, т. е. обратный вывод был дополнен прямым выводом. Поскольку обратный вывод лежит в основе управляющей структуры Пролога, то доступ к аналогу стека целей для про¬ граммиста закрыт. Пришлось проводить формирование соот¬ ветствующего списка, так как для организации объяснений ну¬ жен след процесса вывода. Рассмотрим возможные пути улучшения реализации экс¬ пертной системы и экспериментирования с ней. 1. Изменить структуру отношения ПРАВИЛА, устранив списочные структуры для представления частей ЕСЛИ и ТО правила взамен, используя отношения с элементами типа слово. 2. Откорректировать процедуры компиляции с учетом вы¬ шеуказанных изменений отношения ПРАВИЛА. 3. Снабдить компилятор более подробной диагностикой воз¬ можных ошибок. 4. Откорректировать блок объяснений так, чтобы при ответе на вопрос КАК использовался не только атрибут, но и его зна¬ чение. Так как правила предметной области для организации вывода и печати разнесены по разным отношениям, то система ответа на вопрос КАК, использующая в качестве аргумента только атрибут, может привести к печати запрещенного в про¬ цессе логического вывода правила. 5. Расширить возможности языка пользователя за счет до¬ полнительных команд пользователя. 6. Ввести дружественную проверку на допустимость значе¬ ний атрибутов, задаваемых пользователем. 173
5. ПУТИ РАСШИРЕНИЯ ВОЗМОЖНОСТЕЙ ЭКСПЕРТНОЙ СИСТЕМЫ 5.1. ИСПОЛЬЗОВАНИЕ В КАЧЕСТВЕ АТРИБУТОВ ИМЕН ПРОЦЕДУР До сих пор мы рассматривали в качестве знаний правила и подсказки, которые позволяли пользователю легко и точна отвечать на поставленные вопросы, т. е. задавать значения атри¬ бутов. Но часто для того чтобы ответить на вопрос о значении атрибута, надо провести некоторые действия, например, связан¬ ные с расчетами или обработкой списков и т. п., т. е. использо¬ вать какие-то более глубокие знания. Знания, связанные с этими действиями, могут быть реализованы в виде процедур, и хоте¬ лось бы в экспертной системе иметь возможность при опреде¬ лении значений некоторых атрибутов использовать процедуры. Предположим, что перед пользователем имеются предложе¬ ния языка эксперта типа «подсказка» и «перевод». Как и раньше, будем считать, что пользователь со структурой предло¬ жений не знаком. А задача перед ним стоит следующая: для любого взятого наугад предложения определить тип предложе¬ ния или языка и организовать список подсказок или переводов. Будучи решенной эта задача может пригодиться, например, для демонстрации работы составных частей экспертной системы. Если мы предполагаем, что пользователь не знаком со струк¬ турой интерпретируемых предложений, то он не знаком и с ор¬ ганизацией списков. Поэтому пользователь сможет решить эту задачу только с помощью эксперта или его машинного замени¬ теля, т. е. с помощью экспертной системы. Перед тем как продолжить наши рассуждения, нам надо вы¬ брать язык реализации экспертной системы из освоенных нами языков: Паскаля, ЛИСПа или Пролога Что касается Пролога, то вопросы использования подсоединенных процедур и выбора языка реализации процедур специфичны для разных реализа¬ ций Пролога и поэтому мы этим вопросом заниматься не будем. Остается выбрать между Паскалем и ЛИСПом. Поскольку тек¬ сты программ на ЛИСПе значительно короче, а нам пока надо только разобраться с концепцией использования процедур в ка¬ честве атрибутов, а не строить коммерческую систему, то пред¬ ставляется целесообразным рассмотрение возможностей реали¬ зации на базе языка ЛИСП. В п. 5.3 мы дадим пример коммер¬ ческой системы, которая уже будет реализована на Паскале, точнее на TURBO PASCAL, для персональных машин типа IBM PC. Продолжим рассуждения о задаче, стоящей перед пользо¬ вателем. Для решения подобных задач эксперт должен не 174
только задать вопросы, с помощью ответов на которые он смо¬ жет определить тип предложения, но он должен выполнить еще некоторые дополнительные действия по организации списков на основании своих глубинных знаний. Предположим, что на- <5ор (первый) процедур, составляющих глубинные знания, мо¬ жет быть представлен на языке ЛИСП в следующем виде: (DEF НАЧ_УСТАНОВКА( LAMBDA () (PROG( ) (SETQ ПОДСКАЗКИ1 (SETQ ПЕРЕВОДЫ1 NIL)) (RETURN 'ДА] (DEF СЛОВО(LAMBDA()(PROG() (PRINT'(ЗАДАЙТЕ ПРИЗНАК(ПЕРВОЕ СЛОВО)))(ТЕRPR) (RETURN(CAR(READ] ( DEF АТРИБУТ (LAMBDA ( ) (PROG ( ) (PRINT'(ЗАДАЙТЕ АТРИБУТ))(ТЕRPR) (COND ((SETQ АТРИБУТИК(CAR(READ)))(RETURN 'ДА)) (T(RETURN 'НЕТ] (DEF ТЕКСТ(LAMBDA()(PROG() (PRINT '(ЗАДАЙТЕ ТЕКСТ))(ТЕRPR) (COND ((SETQ ТЕКСТИК(READ))(RETURN 'ДА)) (T(RETURN 'НЕТ] (DEF ЗАПИСЬ_П0ДСКАЗКИ(1АМВ0А( ) (SETQ ПОДСКАЗКИ1 (CONS(LIST АТРИБУТИК ТЕКСТИК)ПОДСКАЗКИ1] (DEF ЗАПИСЬ__ПЕРЕВ0ДА(LAMBDA( ) (SETQ ПЕРЕВОДЫ1 (CONS(LIST АТРИБУТИК ТЕКСТИК) ПЕРЕВОДЫ1] (DEF ПЕЧАТЬ(LAMBDA()(PROG() (PRINT'(ПОДСКАЗКИ))(PRINT ПОДСКАЗКИ1)(TERPR) (PRINT '(ПЕРЕВОДЫ))(PRINT ПЕРЕВОДЫ1)(TERPR) (RETURN 'ДА] Знания эксперта, с помощью которых можно интерпретиро¬ вать предложения с целью определения типа предложения, вы¬ раженные с помощью первой программы интерпретации пред¬ ложений, приведены ниже. При этом в качестве языка эксперта будем использовать упрощенный язык (см. п. 3.2), т. е. в на¬ чале идет S-выражение, содержащее все правила, потом — под¬ сказки и переводы, см. стр. 176. Будем называть знания эксперта, управляющие процессом интерпретации, поверхностными. В конце программы на языке эксперта приведен список атрибутов, являющихся функциями. Знания, которые используются в экспертных системах, при¬ нято разделять на поверхностные и глубинные. Поверхностные знания обычно задают с помощью правил ЕСЛИ... ТО и ис¬ пользуют для управления процессом решения задачи. Глубин¬ ные знания описывают знания, свойственные глубоким деталь¬ ным процессам, характерным для конкретной предметной об- 175
( (1( (НАЧ_УСТАНОВКА ДА) (СЛОВО ПОДСКАЗКА) (АТРИБУТ ДА) (ТЕКСТ ДА))((ПРЕДЛОЖЕНИЕ ПОДСКАЗКА) (ЗАПИСЬ_П0ДСКАЗКИ)(ПЕЧАТЬ))) (2 ((НАЧ_УСТАНОВКА ДА) (СЛОВО ПЕРЕВОД) (АТРИБУТ ДА) (ТЕКСТ ДА))((ПРЕДЛОЖЕНИЕ ПЕРЕВОД) (ЗАПИСЬ_ПЕРЕВОДА)(ПЕЧАТЬ))) (3 ((НАЧ_УСТАНОВКА ДА) ) ((ПРЕДЛОЖЕНИЕ ОШИБОЧНОЕ] ((СЛОВО(ПРЕДЛОЖЕНИЕ НАЧИНАЕТСЯ СО СЛОВА)) (АТРИБУТ(ПРИСУТСТВУЕТ АТРИБУТ)) (ТЕКСТ(ИМЕЕТСЯ СТРОКА ТЕКСТА)) (ПРЕДЛОЖЕНИЕ(ТИП ПРЕДЛОЖЕНИЯ] (НАЧ УСТАНОВКА СЛОВО АТРИБУТ ТЕКСТ ЗАПИСЬ_ПОДСКАЗКИ ЗАПИСЬ_ПЕРЕВОДА ПЕЧАТЬ] ласти. Для представления глубинных знаний используются семантические сети, фреймы и процедуры, которые можно рас¬ сматривать как откомпилированные сети. Сети обладают мень¬ шей степенью свободы, чем правила ЕСЛИ... ТО, так как они в значительной степени учитывают особенности предметной об¬ ласти, но зато работа с ними проходит быстрее. Процедуры, описывающие различные процессы предметной области, для организации полной модели предметной области должны обмениваться между собой информацией, структура и содержание которой характерны для конкретной предметной области. Эти структуры данных являются глобальными и пред¬ ставляют процесс функционирования модели. В литературе по¬ добного типа данные называют «доской объявлений». Их можно вывести на экран дисплея, и пользователь сможет наблюдать за процессом функционирования. Здесь просматривается ана¬ логия с базой данных экспертной системы, состоящей из стека целей, стека фактов и списка пассивных правил и используемой при организации логического вывода, т. е. процесса взаимодей¬ ствия правил продукций, обмен информацией между которыми и осуществлялся через базу данных, которую раньше также на¬ зывали либо «доской объявлений», либо «классной доской». Мы будем под «доской объявлений» понимать базу данных, через которую будут осуществлять обмен информацией процедуры, описывающие глубинные процессы предметной области. На рис. 5.1 приведена модифицированная структурная схема инструментальной экспертной системы. Преобразователь глубинных знаний предназначен для пере¬ вода внешнего представления глубинных знаний в их внутрен¬ нее представление в виде процедур или функций языка, на ко¬ тором реализована экспертная система. Можно отметить, что возможно глубинные знания эксперт когда-то описывал как по¬ верхностные с помощью правил продукций; с помощью анало¬ гичной экспертной системы они были проверены, и потом была 176
12 в. Э. Балтрашевич 177 Рис. 5.1. Структурная схема инструментальной экспертной системы
проведена компиляция знаний на язык реализации экспертной системы, в результате чего были получены тексты используе¬ мых функций. Кратко опишем работу экспертной системы при использова¬ нии вышеописанных глубинных и поверхностных знаний. Пред¬ положим, что целью, стоящей перед пользователем, является определение типа конкретного предложения. Тогда в качестве основной цели для экспертной системы он должен задать ПРЕДЛОЖЕНИЕ. По этой цели находят правило номер один и начинают его оценивание. Атрибут НАЧ-УСТАНОВКА объ¬ является целью, этому атрибуту не соответствует ни правило (в части ТО которого должен быть этот атрибут), ни подсказка (в нашем примере их вообще нет), но- соответствует имя функ¬ ции. Управление должно передаться этой функции, которая подготовит (очистит) глобальные структуры данных (списки) ПОДСКАЗКИ1 и ПЕРЕВОДЫ 1. Заметим, что эти имена вы¬ браны такими, поскольку имена ПОДСКАЗКИ и ПЕРЕВОДЫ заняты при реализации самой экспертной системы (см. гл. 3). После окончания своей работы функция НАЧ_УСТАНОВКА принимает значение ДА, которое должно быть помещено в стек фактов (вместе с именем атрибута). Так как значение атрибута, выданное функцией ему соответствующей, совпадает со значе¬ нием атрибута в правиле, то далее целью объявляется атрибут СЛОВО. По аналогичным причинам будет запущена функция СЛОВО, в процессе работы которой пользователь получает за¬ прос на ввод первого слова интерпретируемого предложения и должен ввести это слово (либо ПОДСКАЗКА, либо ПЕРЕ¬ ВОД). Введенное пользователем слово становится значением функции СЛОВО и соответствующего атрибута в стеке фактов. В зависимости от значения атрибута СЛОВО далее будет «ра¬ ботать» либо правило один, либо правило два. Предположим, что пользователь ответил ПОДСКАЗКА, тогда правило один не запрещается, а продолжает оцениваться. Целью объявляется атрибут АТРИБУТ, а управление получает соответствующая ему функция АТРИБУТ, которая запрашивает у пользователя атрибут, проверяет его значение и в зависимости от результата проверки функция принимает значение или ДА, или НЕТ. Упро¬ щенная проверка атрибута фактически сводится к проверке его наличия. Предположим, что в качестве атрибута пользователь ввел слово СТЕБЕЛЬ, т. е. функция АТРИБУТ примет значе¬ ние ДА, и оценка правила продолжится. Целью будет объявлен атрибут ТЕКСТ. Так как и для него нет ни правила, ни под¬ сказки, определяющих его значение, а есть функция, то она и получит управление. Функция ТЕКСТ запрашивает текст и в за¬ висимости от его проверки (проверки наличия) принимает зна¬ чение ДА или НЕТ. Предположим, что пользователь ввел текст подсказки, соответствующий атрибуту СТЕБЕЛЬ, тогда атри¬ 178
бут ТЕКСТ получает значение ДА, правило один принимает 5начение ИСТИНА, основная цель—ПРЕДЛОЖЕНИЕ — полу- ( ает значение ПОДСКАЗКА, но в части ТО предложения после атрибута и его значения, определяемого правилом, записаны (еще два атрибута, соответствующие обращениям к функциям. (Поскольку на оценку правила они влияния не оказывают, а для Модели предметной области важен сам факт их выполнения, то эти атрибуты записаны без соответствующих им значений. Функция ЗАПИСЬ-ПОДСКАЗКИ добавляет в начало соот¬ ветствующего списка ПОДСКАЗКИ 1 новую подсказку. Полу¬ ченный список является также значением функции. Очевидно, что если бы функции присвоить значение ДА, то соответствую¬ щий ей атрибут со значением ДА можно было бы включать В часть ЕСЛИ правила. Функция ПЕЧАТЬ осуществляет вывод списков, входящих в состав «доски объявлений» на экран дис¬ плея как глубинный результат решения задачи. Из приведенных рассуждений следует, что часть функций могут выдавать значения, влияющие на порядок срабатывания правил (функции СЛОВО, АТРИБУТ, ТЕКСТ), а соответствую¬ щие им атрибуты должны быть включены в часть ЕСЛИ пра¬ вила. Для других функций (НАЧ-УСТАНОВКА, ЗАПИСЬ-- ПОДСКАЗКИ, ЗАПИСЬ_ПЕРЕВОДА, ПЕЧАТЬ) важен сам факт их выполнения, и на порядок выполнения правил они не влияют. Соответствующие им атрибуты могут быть включены и в часть ЕСЛИ (со значением ДА) и в часть ТО. Рассмотрим вторую программу интерпретации предложений, аналогичную первой, но в ней атрибут НАЧ-УСТАНОВКА вы¬ несен в часть ТО нового первого правила с пустой частью ЕСЛИ. ((1( ) ( (НАЧАЛО ДА) (НАЧ_УСТАНОВКА)) ) (2 ((НАЧАЛО ДА) (СЛОВО ПОДСКАЗКА) (АТРИБУТ ДА) (ТЕКСТ ДА)) ((ПРЕДЛОЖЕНИЕ ПОДСКАЗКА) (ЗАПИСЬ_ПОДСКАЗКИ) (ПЕЧАТЬ) )) (3((НАЧАЛО ДА)(СЛОВО ПЕРЕВОД)(АТРИБУТ ДА)(ТЕКСТ ДА)) ((ПРЕДЛОЖЕНИЕ ПЕРЕВОД)(ЗАПИСЬ_ПЕРЕВ0ДА)(ПЕЧАТЬ))) (4((НАЧАЛО ДА))((ПРЕДЛОЖЕНИЕ ОШИБОЧНОЕ))) (5((ПРЕДЛОЖЕНИЕ ПОДСКАЗКА))((ЯЗЫК ЭКСПЕРТА))) (б((ПРЕДЛОЖЕНИЕ ПЕРЕВОД))((ЯЗЫК ЭКСПЕРТА] ( 1 ( ] (НАЧ-УСТАНОВКА СЛОВО АТРИБУТ ТЕКСТ ЗАПИСЬ_П0ДСКАЗКИ ЗАПИСЬ_ПЕРЕВ0ДА ПЕЧАТЬ] Поскольку при решении задачи интерпретации предложе¬ ний и построения списков пользователь фактически только вво¬ дит соответствующие части предложения, а всю задачу факти¬ чески решает система, то труд пользователя при решении по¬ добных задач можно автоматизировать. Для этого надо запи¬ сать анализируемые предложения в файл, например III.LSP, а процедуры, соответствующие глубинным знаниям, настроить 12* 179
на чтение из этого файла. Пользователю можно отвести упраи ляющие (задание основной цели) и контролирующие функции Второй набор глубинных знаний, обеспечивающих обра ботку файла III.LSP, можно представить в виде (DEF НАЧ_УСТАНОВКА(LAMBDA()(PROG() (SETQ П0ДСКАЗКИ1 (SETQ ПЕРЕВОДЫ1 NIL)) (INFILE 'III) (RETURN 'ДА] (DEF СЛОВО(LAMBDA()(PROG() (PRINT(CAR(READ III)))(TERPR)(RETURN 'ДА] (DEF АТРИБУТ(LAMBDA() (COND ((SETQ АТРИБУТИК(CAR(READ III))) 'ДА) (T 'НЕТ] (DEF ТЕКСТ(LAMBDA() (COND ((SETQ ТЕКСТИК(READ III)) 'ДА) (T 'НЕТ] (DEF ЗАПИСЬ_П0ДСКАЗКИ(LAMBDA() (SETQ ПОДСКАЗКИ1 (CONS(LIST АТРИВУТИК ТЕКСТИК)П0ДСКАЗКИ1] (DEF ЗАПИСЬ_ПЕРЕВ0ДА(LAMBDA() (SETQ ПЕРЕВОДЫ1 (CONS(LIST АТРИБУТИК ТЕКСТИК) ПЕРЕВОДЫ1] (DEF ПЕЧАТЬ(LAMBDA()(PROG() (PRINT'(ПОДСКАЗКИ))(PRINT ПОДСКАЗКИ1)(TERPR) (PRINT ' (ПЕРЕВОДЫ) ) (PRINT ПЕРЕВОДЫ!.) (TERPR) (RETURN 'ДА] Третья программа интерпретации предложений, управляю щая обработкой файла III.LSP, может иметь вид ((1( )((НАЧАЛО ДА){НАЧ_УСТАНОВКА))) и (2((НАЧАЛО ДА)(СЛОВО ДА)(ПОДСКАЗКА ДА)(АТРИБУТ ДА) (ТЕКСТ ДА)) ((ПРЕДЛОЖЕНИЕ ПОДСКАЗКА)(ЗАПИСЬ_П0ДСКАЗКИ)(ПЕЧАТЬ))) (3((НАЧАЛО ДА)(СЛОВО ДА)(ПЕРЕВОД ДА)(АТРИБУТ ДА) (ТЕКСТ ДА)) ((ПРЕДЛОЖЕНИЕ ПЕРЕВОД)(ЗАПИСЬ_ПЕРЕВОДА)(ПЕЧАТЬ))) (4((НАЧАЛО ДА)(СЛОВО ДА)(ПЕРЕВОД НЕТ)) ((ПРЕДЛОЖЕНИЕ ОШИБОЧНОЕ))) (5((ПРЕДЛОЖЕНИЕ ПрДСКАЗКА))((ЯЗЫК ЭКСПЕРТА))) (б((ПРЕДЛОЖЕНИЕ ПЕРЕВОД))((ЯЗЫК ЭКСПЕРТА] ((ПОДСКАЗКА (ПРЕДЛОЖЕНИЕ НАЧИНАЕТСЯ СО СЛОВА ПОДСКАЗКА?(ДА/НЕТ))) (ПЕРЕВОД (ПРЕДЛОЖЕНИЕ НАЧИНАЕТСЯ СО СЛОВА ПЕРЕВОД?(ДА/НЕТ] ( ) (НАЧ_УСТАНОВКА СЛОВО АТРИБУТ ТЕКСТ ЗАПИСЬ_П0ДСКАЗКИ ЗАПИСЬ_ПЕРЕВ0ДА ПЕЧАТЬ] Файл исходных данных III.LSP может содержать следую¬ щие данные: 180
(ПЕРЕВОД) (ФАЙЛ) (НАЗНАЧЕН ФАЙЛ ВВОДА) (подсказка)(конец)(Кончать анализ?) (ПЕРЕВОД) (КОНЕЦ) (КОНЁЦ АНАЛИЗА) (ПЕРЕВОД) (СЛОВО) (ПРЕДЛОЖЕНИЕ НАЧИНАЕТСЯ СО СЛОВА) Заметим, что функция, соответствующая атрибуту СЛОВО, Вводит первое слово предложения и распечатывает его на дис¬ плее для контроля пользователем. Значение этой функции Всегда ДА, так что атрибут, ей соответствующий, можно ста¬ вить и в часть ТО правила. Атрибутам ПОДСКАЗКА и ПЕРЕВОД соответствуют тек¬ сты подсказок, на которые пользователь, учитывая значение, Выведенное функцией СЛОВО, может ответить ДА или НЕТ, И в зависимости от этого сработает одно или другое правило. Читателю предлагается в качестве упражнения расширить описание поверхностных знаний для более полной диагностики возможных ошибок в анализируемых предложениях. В рассматриваемых примерах возможен анализ одного пред¬ ложения; для проведения анализа другого предложения нужно перезапустить систему, так как пока в системе не предусмот¬ рена организация циклов на языке эксперта (см. п. 5.2.). Представляется очевидным, что в файле III.LSP фактически Записаны знания некоторого нового эксперта на языке эксперта. Вся наша система, состоящая из инструментальной ЭС, напол¬ ненной поверхностными и глубинными знаниями, выполняет роль компилятора языка абстрактного эксперта, преобразую¬ щего внешнее представление знаний (файл III.LSP) в струк¬ туры данных (списки переводов и подсказок), входящие в со¬ став «доски объявлений». Если же еще добавить процедуру, реализующую блок логического вывода и использующую полу¬ ченные структуры данных из «доски объявлений», то мы полу¬ чим новую инструментальную ЭС, т. е. еще один уровень вир¬ туальной машины (см. рис. 1.5). Этот процесс надстройки вир¬ туальных машин можно продолжить и далее. Очевидно, что меняя содержимое файла III.LSP, мы можем менять предмет¬ ную область, например вводить знания из области ботаники или зоологии. Из вышеприведенного ясно, что существуют различные ре¬ жимы взаимодействия процедур с системой и пользователем. 1. Для системы важен сам факт выполнения процедуры, ко¬ торая в свою очередь всегда выдает значение ДА. Атрибуты, соответствующие этим процедурам, могут помещаться как в часть ЕСЛИ (со значением ДА), так и в часть ТО (без зна¬ чения). Примером может служить функция НАЧ-УСТАНОВКА В первой и во второй программе интерпертации предложений. 181
2. Ответ процедуры влияет на порядок срабатывания пра вил; атрибуты, соответствующие этим процедурам, должны включаться в часть ЕСЛИ правил (функция СЛОВО в первой программе). 3. Процедуры могут выдавать сообщения на «доску объяв¬ лений». Эти сообщения анализируются пользователем, и им принимается решение, влияющее на дальнейший ход работы системы (функция СЛОВО в третьей программе). 4. Очевидно, что возможен вариант, при котором пользова¬ тель выдает какое-то значение атрибута, оно анализируется со¬ ответствующей проверяющей процедурой, и решение этой про¬ цедуры может влиять на ход процесса вывода. Естественно* что в том случае, когда ответ проверяющей процедуры влияет на ход процесса вывода, соответствующий атрибут со своим зна¬ чением должен быть включен в часть ЕСЛИ. Этот вариант по¬ дробно будет рассмотрен в п. 5.3. В пределе вариант, при котором значение атрибута опреде¬ ляется с помощью процедуры и сразу записывается в стек фак¬ тов, минуя пользователя, ведет к полностью автоматическим системам логического вывода (или принятия решения) без вме¬ шательства человека. Участие человека можно организовать с помощью атрибутов, которые либо не используют процедур, либо используют процедуры в другом режиме. Рассмотрим особенности реализации инструментальной экс¬ пертной системы, позволяющей использовать в качестве атри¬ бутов имена процедур на языке ЛИСП. Рассмотрение начнем с блока логического вывода. Алгоритм логического вывода изменится следующим образом. После вы¬ явления текущей цели в вершине стека целей в первой версии системы проводился поиск разрешенного правила с целью в части ТО, в случае неудачи проводился поиск подсказки. В новой версии алгоритма в случае неудачи поиска правила перед поиском подсказки осуществляется поиск процедуры, т. е. проводится проверка, не является ли целевой атрибут именем одной из возможных процедур (в случае ЛИСПа — функций), и при успешной проверке осуществляется запуск этой про¬ цедуры. После обработки процедуры проводится фиксация этого факта в стеке фактов и выталкивание цели из стека це¬ лей; если при этом стек целей оказывается пустым, то прово¬ дится установка признака ГОТОВНОСТЬ. Как уже отмечалось, атрибуты, соответствующие процедурам, могут помещаться не только в часть ЕСЛИ, но и в часть ТО правила после атрибута и значения, определяемых правилом, поэтому коррекции дол¬ жна подвергнуться функция, обрабатывающая истинное пра¬ вило. Проведем необходимую коррекцию функций, описанных в п. 3.3. 182
В текст откорректированной основной функции включены переменная ФУНКЦИИ и соответствующая функция чтения списка имен функций из файла INPI: f DEF ЭС (LAMBDA( ) (PROG(ГОТОВНОСТЬ ПАССИВНЫЕ_ПРАВИЛА СТЕК_ЦЕЛЕЙ СТЕК_ФАКТОВ ОСНОВНАЯ_ЦЕЛЬ ПРАВИЛА ПОДСКАЗКИ ФУНКЦИИ ПЕРЕВОДЫ) (INFILE 'INP1) (SETQ ОСНОВНАЯ_ЦЕЛЬ(ПОЛУЧИТЬ_ОСНОВНУЮ_ЦЕЛЬ)) (SETQ ПРАВИЛА (READ INP1)) (SETQ ПОДСКАЗКИ (READ INPI)) (SETQ ПЕРЕВОДЫ (READ INPI)) (SETQ ФУНКЦИИ (READ INPI)) (CLOSE INPI) (ВЫВОД ГОТОВНОСТЬ ОСНОВНАЯ_ЦЕЛЬ) (RETURN T] В текст функции ВЫВОД между функциями осуществляю¬ щими поиск и обработку правил, а также поиск и обработку подсказок, включена функция ПОИСК-И-ОБРАБОТКА- ФУНКЦИИ: (DEF ВЫВОД(LAMBDA(ГОТОВНОСТЬ ЦЕЛЬ ) (COND (ГОТОВНОСТЬ(ВЫДАЧА_РЕЗУЛЬТАТА ОСНОВНАЯ_ЦЕЛЬ)) (Т(COND ((ПОИСК_И_ОБРАБОТКА_ПРАВИЛА (ПРАВИЛО ЦЕЛЬ ПРАВИЛА))) ((ПОИСК_И_ОБРАБОТКА_ФУНКЦИИ ЦЕЛЬ ФУНКЦИИ)) ((0ТВЕТ_НА_П0ДСКАЗКУ ЦЕЛЬ (ПОДСКАЗКА ЦЕЛЬ ПОДСКАЗКИ))) (T(SETQ ГОТОВНОСТЬ Т))) (ВЫВОД ГОТОВНОСТЬ(ПОДЦЕЛЬ СТЕК_ЦЕЛЕЙ) ] В конце откорректированной функции ПРАВИЛО-ИСТИНА добавлен вызов новой функции ВЫПОЛНЕНИЕ-ПРОЦЕДУР, в качестве аргумента которой передается остаток ПРАВИЛО- ТО, в котором могут содержаться вызовы процедур: (DEF ПРАВИЛО_ИСТИНА (LAMBDA (ЗНАЧЕНИЕ_ПРАВИЛА ПРАВИЛО_ТО) (COND ((AND (АТОМ ЗНАЧЕНИЕ_ПРАВИЛА) (EQ ЗНАЧЕНИЕ_ПРАВИЛА 'ДА)) (SETQ СТЕК_ФАКТОВ (CONS(CONS(CAR ПРАВИЛО ТО) (CAR(CADR ПРАВИЛО_ТО))) СТЕК_ФАКТОВ)) (SETQ СТЕК_ЦЕЛЕЙ(CDR СТЕК_ЦЕЛЕИ)) (COND ((NULL СТЕК_ЦЕЛЕЙ)(SETQ ГОТОВНОСТЬ Т)) (Т Т)) (ВЫПОЛНЕНИЁ_ПРОЦЕДУР (CDR(CADR ПРАВИЛО ТО)))) (Т NIL] “ 183
Описание рекурсивной функции ВЫПОЛНЕНИЕ ПРО¬ ЦЕДУР имеет вид (DEF ВЫПОЛНЕНИЕ_ПРОЦЕДУР (LAMBDA(ПРОЦЕДУРЫ) (COND ((NULL ПРОЦЕДУРЫ) Т) (Т(ЕVAL (CAR ПРОЦЕДУРЫ))(ВЫПОЛНЕНИЕ_ПРОЦЕДУР (CDR ПРОЦЕДУРЫ] Если список ПРОЦЕДУРЫ пуст, то функция ВЫПОЛНЕ¬ НИЕ-ПРОЦЕДУР принимает значение Т и свою работу закан¬ чивает. Если список не пуст, то с помощью функции EVAL про¬ исходит запуск первой функции в списке и рекурсивный вызов функции ВЫПОЛНЕНИЕ-ПРОЦЕДУР с остатком списка ПРОЦЕДУРЫ в качестве аргумента. Функция ПОИСК-И-ОБРАБОТКА-ФУНКЦИИ вызывается функцией ВЫВОД. Если список функций пуст или атрибут, т. е. цель, не входит в список функций, то функция ПОИСК- И-ОБРАБОТКА-ФУНКЦИИ принимает значение NIL, что ис¬ пользуется функцией ВЫВОД для включения следующего этапа поиска. Если же с помощью стандартной функции MEM¬ BER установлено, что атрибут входит в список функций, то вы¬ зывается функция ОБРАБОТКА-ФУНКЦИИ: (DEF ПОИСК_И_ОБРАБОТКА_ФУНКЦИИ(LAMBDA(АТРИБУТ ФУНКЦИИ) (COND ((NULL ФУНКЦИИ)NIL) ((MEMBER АТРИБУТ ФУНКЦИИ) (ОБРАБОТКА_ФУНКЦИИ АТРИБУТ)) (Т NIL] Для организации функции ОБРАБОТКА-ФУНКЦИИ ис¬ пользуется PROG-выражение, так как последовательно надо обработать и стек фактов и стек целей. В стек фактов записы¬ ваются атрибут, его значение, полученное с помощью соответ¬ ствующей ему функции, запускаемой стандартной функцией EVAL, а также номер —1, являющийся признаком того, что значение данного атрибута определено с помощью функции: (DEF ОБРАБОТКА_ФУНКЦИИ(LAMBDA(АТРИБУТ)(PROG() (SETQ СТЕК_ФАКТОВ(CONS(CONS -1(LIST АТРИБУТ (EVAL(LIST АТРИБУТ)))) СТЕК_ФАКТОВ)) (SETQ СТЕК_ЦЕПЕЙ(CDR СТЕК_ЦЕЛЕЙ)) (COND ((NULL СТЕК_ЦЕПЕЙ)(SETQ ГОТОВНОСТЬ T)) (Т Т)) (RETURN Т] Далее в процессе выполнения функции ОБРАБОТКА- ФУНКЦИИ производится выталкивание верхнего элемента из стека целей и, если стек целей оказывается пустым, устанавли¬ 184
вается признак готовности. На этом коррекцию блока логиче¬ ского вывода закончим. Теперь проведем коррекцию компилятора. Откорректированные описания функций ПРОВЕРКА, КОМ¬ ПИЛЯЦИЯ И ПРОВЕРКА_ЧАСТИ_ТО принимают вид (DBF nPOBEPKA(LAMBDA() (PROG(ПРАВИЛА ПОДСКАЗКИ ПЕРЕВОДЫ ФУНКЦИИ) (INFILE 'INPA) (ВВ0Д_ЗНАНИЙ (READ INPA)) (CLOSE INPA) (PRINT 'ПРАВИЛА)(PRINT ПРАВИЛА)(TERPR) (PRINT 'ПОДСКАЗКИ)(PRINT ПОДСКАЗКИ)(TERPR) (PRINT 'ПЕРЕВОДЫ)(PRINT ПЕРЕВОДЫ)(TERPR) (PRINT 'ФУНКЦИИ)(PRINT ФУНКЦИИ)(TERPR) (RETURN T] (DEF КОМПИЛЯЦИЯ(LAMBDA(ПРЕДЛОЖЕНИЕ) (COND ((EQ (CAR ПРЕДЛОЖЕНИЕ) 'ПОДСКАЗКА) (COND ((ПРОВЕРКА_АТРИБУТА(CAR(CADR ПРЕДЛОЖЕНИЕ)) 'ПОДСКАЗКА)) ((ПРОВЕРКА_ТЕКСТА(CADR(CADR ПРЕДЛОЖЕНИЕ)) 'ПОДСКАЗКА)) ((ЗАПИСЬ_ПОДСКАЗКИ (CADR ПРЕДЛОЖЕНИЕ))))) ((EQ (CAR ПРЕДЛОЖЕНИЕ) 'ПЕРЕВОД) (COND ((ПРОВЕРКА_АТРИБУТА(CAR(CADR ПРЕДЛОЖЕНИЕ)) 'ПЕРЕВОД)) ((ПРОВЕРКА_ТЕКСТА(CADR(CADR ПРЕДЛОЖЕНИЕ)) 'ПЕРЕВОД)) ((ЗАПИСЬ_ПЕРЕВОДА(CADR ПРЕДЛОЖЕНИЕ))))) ((EQ(CAR ПРЕДЛОЖЕНИЕ) 'ФУНКЦИИ) (COND ((ПРОВЕРКА_ФУНКЦИЙ(CADR ПРЕДЛОЖЕНИЕ))) ((ЗАПИСЬ_ФУНКЦИЙ(CADR ПРЕДЛОЖЕНИЕ)J))) ((NUMBERP(CAR ПРЕДЛОЖЕНИЕ)) (COND ((ПРОВЕРКА_ЧАСТИ_ЕСЛИ(CADR ПРЕДЛОЖЕНИЕ))) ((ПРОВЕРКА_ЧАСТИ_ТО (CAR(CDDR ПРЕДЛОЖЕНИЕ)))) ((ЗАПИСЬ_ПРАВИЛА ПРЕДЛОЖЕНИЕ )))) (Т(PRINT '(ОШИБКА В ПЕРВОМ СЛОВЕ ПРЕДЛОЖЕНИЯ)) (PRINT ПРЕДЛОЖЕНИЕ)(TERPR)Т] ( DBF ПРОВЕРКА_ЧАСТИ_ТО(LAMBDA(ЧАСТЬ_ТО) (COND ((ПРОВЕРКА_АТРИБУТА(CAAR ЧАСТЬ_ТО) 'ПРАВИЛО)) ((ПР0ВЕРКА_ЗНАЧЕНИЯ(CAR(CDAR ЧАСТЬ_ТО)))) ((ПРОВЕРКА_ВЫ30В0В_ФУНКЦИЙ(CDR ЧАСТЬ_ТО))) (Т NIL] 185
Рассмотрим рекурсивную функцию ПРОВЕРКА-ВЫЗО ВОВ_ФУНКЦИИ: ;DEF ПРОВЕРКА_ВЫЗОВОВ_ФУНКЦИЙ(LAMBDA(СПИСОК) (COND ((NULL СПИСОК)NIL) (T(COND ((ATOM(CAR СПИСОК)) (PRINT'(ОШИБКА В ВЫЗОВАХ ФУНКЦИЙ В ПРАВИЛЕ)) (TERPR)T) (Т(ПРОВЕРКА_ВЫ30В0В_ФУНКЦИЙ(CDR СПИСОК] Если список функций пуст, то функция ПРОВЕРКА-ВЫЗО- ВОВ_ФУНКЦИИ получает значение NIL; иначе начинается проверка. Как видно из рис. 5.2, каждое имя функции в части ТО правила должно быть заключено в скобки. Интересующийся читатель может провести соответствующую коррекцию синтак¬ сических диаграмм (см. рис. 3.1). Каждый элемент списка функций не может быть атомом, поэтому в этом случае функ¬ ция ПРОВЕРКА_ВЫЗОВОВ_ФУНКЦИИ производит печать соответствующего сообщения и принимает значение Т. Если проверка очередного элемента списка функций прошла ус¬ пешно, то происходит рекурсивное обращение к функции ПРО ВЕРКА_ВЫЗОВОВ_ФУНКЦИИ с остатком списка функций. Описание функции ПРОВЕРКА-ФУНКЦИЙ имеет вид (DEF ПРОВЕРКА_ФУНКЦИЙ(LAMBDA(ФУНКЦИИ) (COND ((NULL ФУНКЦИИ)NIL) (T(COND ((ATOM (CAR ФУНКЦИИ))(ПРОВЕРКА_ФУНКЦИЙ (CDR ФУНКЦИИ))) (T(PRINT '(ОШИБКА В ФУНКЦИЯХ))(TERPR)T] > Функция ЗАПИСЬ-ФУНКЦИИ добавляет новые имена функций в список функций: (DEF ЗАПИСЬ_ФУНКЦИЙ(LAMBDA(ИМЕНА_ФУНКЦИЙ) (PROG() (SETQ ФУНКЦИИ(APPEND ФУНКЦИИ ИМЕНА_ФУНКЦИЙ))(RETURN Т| В качестве примера приведем ряд предложений на расши¬ ренном языке эксперта: (1( )((НАЧАЛО ДА)(НАЧ УСТАНОВКА))) (ПОДСКАЗКА “ (ЧИСЛО (ПРЕДЛОЖЕНИЕ НАЧИНАЕТСЯ С ЧИСЛА?(ДА/НЕТП (ФУНКЦИИ(СЛОВО НАЧ_УСТАНОВКА)) ' * 1 ’ (ПЕРЕВОД(ЧИСЛО(ПРЕДЛОЖЕНИЕ НАЧИНАЕТСЯ С ЧИСЛА))) 186
ЛИСП позволяет легко запускать функции по имени атри¬ бута, Паскаль же этого не позволяет. В Паскале можно каждому атрибуту поставить в соответствие номер и, если надо, Лимя обслуживающей его функции. С помощью оператора CASE !иожно по номеру атрибута легко запустить соответствующую рму процедуру, как это было показано при реализации языка рользователя (см. п. 2.5). Смена же имен процедур приводит к необходимости перекомпиляции модуля, содержащего указан¬ ный оператор CASE. Таким образом, завершена коррекция всех блоков и мы по¬ лучили инструментальную экспертную систему, позволяющую использовать процедуры в качестве атрибутов. Кратко обсудим порядок смены наполнения системы зна¬ ниями. Если предположить, что описание инструментальной экс¬ пертной системы находится в файле ES.LSP, то раз загрузив его в ЛИСП-систему, можно о нем больше не думать. При смене же наполнения знаниями надо загружать в ЛИСП-си¬ стему файл с описанием функций, определяющих глубинные знания, и подготовить файл с поверхностными знаниями, кото¬ рый будет обрабатываться инструментальной экспертной систе¬ мой после вызова функции -*(ИЭС). В общем случае вопрос стыковки глубинных знаний и экс¬ пертной системы зависит от языка, на котором реализована система. При использовании ЛИСПа, как указывалось, файл с функ¬ циями, реализующими глубинные знания, просто вводится в ЛИСП-систему. Если же использовать Паскаль, то глубинные знания можно подключать при трансляции, используя оператор INCLUDE, либо при сборке при условии раздельной компиляции. Пример описания глубинных знаний с использованием языка Паскаль будет рассмотрен в п. 5.3. Во всех предыдущих рассуждениях предполагалось, что глу¬ бинные знания и экспертная система записаны на одном и том же языке. 5.2. ОРГАНИЗАЦИЯ ЦИКЛОВ НА ЯЗЫКЕ ЭКСПЕРТА Как известно из теоремы структуризации, для того чтобы реализовать любой вычислительный процесс, надо иметь воз¬ можность реализовать три вида базовых вычислительных про¬ цессов: линейный, ветвящийся и циклический. В нашей реали¬ зации эксперт задает свои знания на языке эксперта с помощью 187
правил ЕСЛИ... ТО, поэтому рассмотрим возможность реалп зации вышеуказанных трех процессов на этом языке. Очевидно что линейный процесс задается частью ЕСЛИ правила, в кото рой действия, составляющие линейный процесс, соединены зна ком И. Для реализации ветвящихся процессов можно исполь зовать правила с одинаковой частью ТО и разными частями ЕСЛИ. Теперь возникает вопрос о возможности реализации циклического вычислительного процесса, до этого такая воз можность не предусматривалась. Отсутствие циклов ограничивало возможности нашей си стемы. Во всех рассмотренных примерах система интерпрети ровала одно предложение (или одно растение) и, чтобы про анализировать другое предложение, нужно было перезапустит!, систему, т. е. фактически очистить стек фактов. С другой стороны, в п. 1.1 описывается задача интерпрета ции предложений языка эксперта и языка пользователя. Од нако это неполная интерпретация, что особенно хорошо видно на предложениях языка эксперта, поскольку в этом случае ана лизируются только первые слова предложений. Это объясни ется опять же отсутствием циклов. Например, структура строк предложений типа «правило» фактически одинакова, но при отсутствии циклов нам бы при шлось вводить разные атрибуты для элементов всех строк, а так как число строк в предложениях типа правило не огра ничено, то практически реализовать полную интерпретацию предложений невозможно. Если же у нас будет возможность организации циклов, то для строки анализируемого предложения можно ввести необхо димые атрибуты, проверить строку и этот процесс зациклить по всем строкам, т. е. повторно использовать выделенные атри буты. Для того чтобы в процессе работы экспертной системы можно было повторно использовать атрибуты, необходимо либо организовать удаление этих атрибутов из стека фактов, либо выделить дополнительный стек фактов для очередной подцели. Рассмотрим первый вариант организации циклов за счет удаления части атрибутов и их значений из стека фактов. Чтобы в общем случае удалить из стека фактов любое число атрибутов, можно в стек фактов ввести какой-то вспомогатель ный атрибут, который будет последним в числе удаляемых ат¬ рибутов. Но так как значение каждого атрибута определяется либо правилом, либо процедурой, либо ответом пользователя, то будем этот вспомогательный атрибут определять с помощью дополнительного правила с пустой частью ЕСЛИ, т. е. в виде факта. Следует подчеркнуть, что введение вспомогательного атри¬ бута* не обязательно*, та» как можно: использовать и основной 188
атрибут, являющийся последним в группе удаляемых атрибу¬ тов, но для большей наглядности будем использовать вспомо¬ гательный атрибут (или атрибуты) под названием ФЛАГ. i Кроме того, следует отметить, что для реализации удаления атрибутов из списка (множества) фактов особенно удобной яв¬ ляется используемая нами организация этого списка в виде ртека. Перейдем к рассмотрению реализации организации циклов. Так как порядком выполнения правил продукции управляет блок логического вывода, то необходимо расширить его воз¬ можности. В универсальном языке Пролог, реализующем логи¬ ческий вывод, эта проблема решена за счет использования или рекурсии или стандартного предиката REPEAT (см. п. 4.1). Использование циклов в реализации логического вывода на базе языка Паскаль будет продемонстрировано в п. 5.3. Здесь же мы рассмотрим варианты реализации циклов на базе языка ЛИСП. Удаление атрибутов из стека фактов реализуется функцией ГАШЕНИЕ, аргументом которой является последний из уда¬ ляемых атрибутов: (DEF ГАШЕНИЕ(LAMBDA(ПАРАМЕТР) (COND ((NULL СТЕК__ФАКТОВ)NIL) ((EQ(CAR(CDAR СТЕК_ФАКТОВ))ПАРАМЕТР) (SETQ ПАССИВНЫЕ_ПРАВИЛА NIL) (SETQ СТЕК_ФАКТОВ(CDR СТЕК_ФАКТОВ))) (T(SETQ СТЕК_ФАКТОВ(CDR СТЕК_ФАКТОВ)) (ГАШЕНИЕ ПАРАМЕТР] Рекурсивная функция ГАШЕНИЕ реализуется с помощью функции COND. Если стек фактов пуст, то функция ГАШЕНИЕ завершает работу. Если в вершине стека фактов находится ат¬ рибут, совпадающий с аргументом, т. е. с последним удаляемым атрибутом, то происходит удаление верхнего элемента стека фактов, состоящего из номера правила, атрибута и его значе¬ ния; далее производится разрешение запрещенных правил и завершение работы функции ГАШЕНИЕ. Если же в вершине стека фактов не находится атрибут, совпадающий с аргументом функции, то происходит удаление верхнего элемента стека фак¬ тов и рекурсивное обращение к функции ГАШЕНИЕ. Функция ГАШЕНИЕ является системной функцией и дол¬ жна быть включена в текст основной программы, реализующей экспертную систему. Очевидно, что обращение к функции ГАШЕНИЕ должно помещаться в часть ТО соответствующего правила. 189
Итак, после реализации возможности использования циклоп на языке эксперта можно расширить возможности примеров программ, рассмотренных в п. 5.1. Рассмотрим первую программу интерпретации предложений, являющуюся расширением третьей программы интерпретации предложений из п. 5.1, которая управляет обработкой предло жений типа «перевод» и «подсказка» и построением соответст вующих списков: ((1 ( ) ( (НАЧАЛО ДА) (НАЧ_УСТАНОВКА)) ) (2( (НАЧАЛО ДА) (ФЛАГ ДА) (СЛОВО ДА)(ПОДСКАЗКА ДА) (АТРИБУТ ДА)(ТЕКСТ ДА)) ( (ПРЕДЛОЖЕНИЕ ПОДСКАЗКА) (ЗАПИСЬ_П0ДСКАЗКИ) (ПЕЧАТЬ) ) ) (3( (НАЧАЛО ДА) (СЛОВО ДА) (ПЕРЕВОД ДА) (АТРИБУТ ДА) (ТЕКСТ ДА)) ((ПРЕДЛОЖЕНИЕ ПЕРЕВОД)(ЗАПИСЬ_ПЕРЕВ0ДА)(ПЕЧАТЬ))) (4((НАЧАЛО ДА)(СЛОВО ДА)(ПЕРЕВОД НЕТ)) ((ПРЕДЛОЖЕНИЕ ОШИБОЧНОЕ))) (5((ПРЕДЛОЖЕНИЕ ПОДСКАЗКА))((ЯЗЫК ЭКСПЕРТА))) (б((ПРЕДЛОЖЕНИЕ ПЕРЕВОД))((ЯЗЫК ЭКСПЕРТА))) (7 ((СИНТ__АНАЛИЗ ДА) ) ( (РАБОТА ДА) ) ) (8((ЯЗЫК ЭКСПЕРТА)(КОНЕЦ ДА))((СИНТ_АНАЛИЗ ДА))) (9((ЯЗЫК ЭКСПЕРТА)(КОНЕЦ НЕТ)) ((СИНТ_АНАЛИЗ НЕТ)(ГАШЕНИЕ 'ФЛАГ))) (10( ) ( (ФЛАГ ДА] ((КОНЕЦ(КОНЧАТЬ АНАЛИЗ?(ДА/НЕТ))) (ПОДСКАЗКА (ПРЕДЛОЖЕНИЕ НАЧИНАЕТСЯ СО СЛОВА ПОДСКАЗКА? (ДА/НЕТ) ) ) (ПЕРЕВОД (ПРЕДЛОЖЕНИЕ НАЧИНАЕТСЯ СО СЛОВА ПЕРЕВОД?(ДА/НЕТ] ( 1 (НАЧ—УСТАНОВКА СЛОВО АТРИБУТ ТЕКСТ ЗАПИСЬ_ПОДСКАЗКИ ЗАПИСЬ^ПЕРЕВОДА ПЕЧАТЬ] В качестве глубинных знаний используем второй набор глу бинных знаний из п. 5.1. В текст программы интерпретации (по сравнению с п. 5.1) добавлены правила 8, 9 и 10, позволяющие без перезапуска си стемы проводить анализ любого числа предложений, записанные в файле III.LSP. Решение о конце анализа принимается поль зователем в ответ на вопрос о значении атрибута КОНЕЦ по соответствующей этому атрибуту подсказке. Циклический ре жим устанавливается при задании пользователем основной цели РАБОТА. Как видно из текста программы, при задании поль зователем основной цели ПРЕДЛОЖЕНИЕ или ЯЗЫК буде! проводиться анализ (интерпретация) одного предложения с целью определения типа предложения или типа языка соот ветственно. Ниже приведена вторая программа на языке экспер та полной интерпретации предложений языка эксперта и поль зователя: 190
((1((ВВ0Д_СЛаВА ДА)(ЧИСЛО ДА)(ВВОД_СЛЕД_СЛОВА ДА) (ЧАСТЬ_ЕСЛИ ДА)(ЧАСТЬ_ТО ДА)) ((ПРЕДЛОЖЕНИЕ ПРАВИЛО))) (2((СЛОВО ЕСЛИ)(ФЛАГ1 ДА)(ВЫРАЖЕНИЕ ДА)) ((ЧАСТЬ_ЕСЛИ ДА))) (3((СЛОВО ТО))((ЧАСТЬ_ЕСЛИ ДА))) (4((АТРИБУТ ДА)(ПРЕДИКАТ ДА)(ЗНАЧЕНИЕ ДА) (КОНЕЦ_СТРОКИ ДА))((СТРОКА ДА))) (5((СТРОКА ДА)(СЛЕД_СЛОВО ТО))((ВЫРАЖЕНИЕ ДА))) (6((СТРОКА ДА)(СЛЕДСЛОВО И)) ((ВЫРАЖЕНИЕ НЕТ)(ГАШЕНИЕ 'ФЛАГ1))) (7((СЛОВО ТО)(СТРОКА ДА))((ЧАСТЬТО ДА))) (8((СЛЕД_СПОВО ТО)(СТРОКА1 ДА))((ЧАСТЬ_ТО ДА))) (9 ((АТРИБУТ1 ДА)(ПРЕДИКАТ1 ДА)(ЗНАЧЕНИЕ 1 ДА) (КОНЕЦ_СТРОКИ1 ДА))((СТРОКА1 ДА))) (10()((ФЛАГ1 ДА))) (11((ВВОД_СЛОВА ДА)(ЧИСЛО НЕТ)(СЛОВО ПОДСКАЗКА) (АТРИБУТ ДА)(КОНЕЦ_СТРОКИ ДА)(ТЕКСТ ДА)) ((ПРЕДЛОЖЕНИЕ ПОДСКАЗКА))) (12((ВВОД_СЛОВА ДА)(ЧИСЛО НЕТ)(СЛОВО ПЕРЕВОД) (АТРИБУТ ДА)(КОНЕЦСТРОКИ ДА)(ТЕКСТ ДА)) ((ПРЕДЛОЖЕНИЕ ПЕРЕВОД))) (13((СЛОВО #)(ЗНАЧЕНИЕ ДА))((ПРЕДЛОЖЕНИЕ ОТВЕТ))) (14((СЛОВО ?)(СЛЕД_СЛОВО ПОЧЕМУ)) ((ПРЕДЛОЖЕНИЕ ВОПРОС))) (15((СЛОВО ?)(СЛЕД_СЛОВО КАК)(АТРИБУТ ДА)) ((ПРЕДЛОЖЕНИЕ ВОПРОС))) (16((ПРЕДЛОЖЕНИЕ ПРАВИЛО))((ЯЗЫК (17((ПРЕДЛОЖЕНИЕ (18((ПРЕДЛОЖЕНИЕ (19((ПРЕДЛОЖЕНИЕ (20((ПРЕДЛОЖЕНИЕ ЭКСПЕРТА))) ПЕРЕВОД))((ЯЗЫК ЭКСПЕРТА))) ПОДСКАЗКА))((ЯЗЫК ЭКСПЕРТА))) ОТВЕТ))((ЯЗЫК ПОЛЬЗОВАТЕЛЯ))) ВОПРОС))((ЯЗЫК ПОЛЬЗОВАТЕЛЯ))) (21((ФЛАГ2 ДА)(СИНТ_АНАЛИЗ ДА))((ВЫВОД ДА))) (22((ЯЗЫК ЭКСПЕРТА)(КОНЕЦ ДА))((СИНТ_АНАЛИЗ ДА)); (23((ЯЗЫК ЭКСПЕРТА)(КОНЕЦ НЕТ)) ((СИНТАНАЛИЗ НЕТ)(ГАШЕНИЕ 'ФЛАГ2))) (24()((ФЛАГ2 ДА] ((ВВОД_СЛОВА (ВЫ ВЫДЕЛИЛИ ПЕРВОЕ СЛОВО В ПРЕДЛОЖЕНИИ?(ДА/НЕТ))) (ЧИСЛО(ВЫДЕЛЕННОЕ СЛОВО ЯВЛЯЕТСЯ ЧИСЛОМ?(ДА/НЕТ))) (ВВОД_СПЕД_СЛОВА (ВЫ ВЫДЕЛИЛИ ОЧЕРЕДНОЕ СЛОВО В ПРЕДЛОЖЕНИИ?(ДА/НЕТ))) (СЛОВО(ВВЕДИТЕ ВЫДЕЛЕННОЕ СЛОВО)) {СЛЕД_СПОВО(ВЫДЕЛИТЕ И ВВЕДИТЕ ОЧЕРЕДНОЕ СЛОВО)) (АТРИБУТ(СЛЕДУЮЩИМ СЛОВОМ ЯВЛЯЕТСЯ АТРИБУТ?(ДА/НЕТ))) (АТРИБУТ1(СЛЕДУЮЩИМ СЛОВОМ ЯВЛЯЕТСЯ АТРИБУТ?(ДА/НЕТ))) (ПРЕДИКАТ (СЛЕДУЮЩИМ СЛОВОМ ЯВЛЯЕТСЯ ПРЕДИКАТ?(ДА/НЕТ))) (ПРЕДИКАТ1 (СЛЕДУЮЩИМ СЛОВОМ ЯВЛЯЕТСЯ ПРЕДИКАТ?(ДА/НЕТ))) (ЗНАЧЕНИЕ (СЛЕДУЮЩИМ СЛОВОМ ЯВЛЯЕТСЯ ЗНАЧЕНИЕ АТРИБУТА?(ДА/НЕТ))) 191
(ЗНАЧЕНИЕ1 (СЛЕДУЮЩИМ СЛОВОМ ЯВЛЯЕТСЯ ЗНАЧЕНИЕ АТРИБУТА?(ДА/НЕТ))) (КОНЕЦ_СТРОКИ(НА ЭТОМ СТРОКА КОНЧАЕТСЯ?(ДА/НЕТ))) (КОНЕЦ_СТРОКИ1(НА ЭТОМ СТРОКА КОНЧАЕТСЯ?(ДА/НЕТ))) (ТЕКСТ(ИМЕТСЯ ЛИ СТРОКА ТЕКСТА?(ДА/НЕТ))) (КОНЕЦ(КОНЧАТЬ АНАЛИЗ?(ДА/НЕТ] ((ВВОД_СЛОВА(ВВОД ОЧЕРЕДНОГО СЛОВА)) (ЧИСЛО(СЛОВО ЯВЛЯЕТСЯ ЧИСЛОМ)) (ВВОД_СЛЕД_СЛОВА(ВВОД ОЧЕРЕДНОГО СЛОВА)) (АТРИБУТ(ПРИСУТСТВУЕТ АТРИБУТ)) (СЛОВО(ОЧЕРЕДНОЕ СЛОВО)) (СЛЕД_СЛОВО(ОЧЕРЕДНОЕ СЛОВО)) (ТЕКСТ(ИМЕЕТСЯ СТРОКА ТЕКСТА)) (КОНЕЦ(КОНЕЦ АНАЛИЗА)) (ЗНАЧЕНИЕ(ПРИСУТСТВУЕТ ЗНАЧЕНИЕ АТРИБУТА)) (ПРЕДИКАТ(ИМЕЕТСЯ ПРЕДИКАТ] ПС Число строк в анализируемых предложениях типа «пра вило», соединенных словом И, может быть любым за счет ис пользования цикла с параметром ФЛАГ1. Цикл с параметром ФЛАГ2 позволяет проводить анализ нескольких предложении Образцы правильных возможных предложений приведены в табл. 1.1. Заметим, что подробный анализ программы показывает, чт<- вместо вспомогательного атрибута ФЛАГ1 можно использо вать основной атрибут АТРИБУТ, а вместо вспомогательного атрибута ФЛАГ2 — основной атрибут ВВОД-СЛОВА. Выход из цикла с параметром ФЛАГ1 осуществляется при появлении строки анализируемого предложения, начинающейся со слова ТО. Выход из цикла с параметром ФЛАГ2 осуществляется гю указанию пользователя в ответ на запрос системы о значении атрибута КОНЕЦ. Как видно из программы, для проведения анализа несколь ких предложений должна быть поставлена цель ВЫВОД. При задании цели ЯЗЫК или ПРЕДЛОЖЕНИЕ будет про изведено определение соответствующего типа для одного прел ложения. Если к поверхностным знаниям, представленным во второй программе добавить соответствующие глубинные знания, ю можно получить внутреннее представление знаний, внешне представление которых является входными данными для про граммы (по аналогии с файлом III.LSP). Как уже ранее отмечалось, реализованные нами компиля торы (например, в п. 2.3) можно рассматривать как откомпп лированные поверхностные знания, представленные во второй программе, и соответствующие глубинные знания. В результат этой компиляции получена процедура ПРЕДЛОЖЕНИЕ (см 192
п. 2.3), которую можно в свою очередь рассматривать как реа¬ лизацию глубинных знаний при организации работы инструмен¬ тальной экспертной системы. Теперь перейдем к реализации второго варианта организа¬ ции циклов за счет выделения нового стека фактов при уста¬ новлении новой цели. Как известно, при реализации рекурсии происходит выделение дополнительной памяти, что ограничи¬ вает пока использование рекурсии на машинах с небольшим объемом оперативной памяти. Таким образом, проведем реа¬ лизацию циклов на языке эксперта с помощью рекурсии. Начнем рассмотрение с функции ЭСР: (DEF ЭСР{LAMBDAQ (PROG(CTEKJUEЛЕИ ПРАВИЛА ПОДСКАЗКИ ФУНКЦИИ) (INFILE 'IESR) (SETQ ПРАВИЛА (READ IESR)) (SETQ ПОДСКАЗКИ (READ IESR)) (SETQ ФУНКЦИИ (READ IESR)) (CLOSE IESR) (PRINT (ЗНАЧЕНИЕ_ЦЕЛИ 0(ОСНОВНАЯ_ЦЕЛЬ)))(TERPR) (RETURN T] Функция ЭСР (экспертная система рекурсивная) открывает файл с внешним описанием знаний т. е. с описанием правил, подсказок и имен функций, исключая переводы. Для внешнего представления поверхностных знаний используем упрощен¬ ный вариант языка эксперта, описанный в п. 3.2, т. е. все зна¬ ния задаются в виде трех S-выражений, соответствующих пра¬ вилам, подсказкам и именам функций. Функция ЭСР вводит правила, подсказки и имена функций из файла IESR. LSP, предварительно открыв его с последующим закрытием. Далее осуществляется печать значения цели, полученной с помощью функции ЗНАЧЕНИЕ-ЦЕЛИ, в качестве аргументов которой используется ноль (признак задания атрибута пользователем) и основная цель, полученная с помощью соответствующей функции. Функция ОСНОВНАЯ-ЦЕЛЬ осуществляет ввод основной цели, задаваемой пользователем, с соответствующей подсказ¬ кой: (DEF ОСНОВНАЯ-ЦЕЛЬ(LAMBDA()(PROG() (PRINT '(ЗАДАЙТЕ ОСНОВНУЮ ЦЕЛЬ))(TERPR) (RETURN(CAR(READ] Функция ЗНАЧЕНИЕ-ЦЕЛИ оформлена в виде PROG-вы- ражения для задания и начального очищения списков ПАС- СИВНЫЕ-ПРАВИЛА и СТЕК-ФАКТОВ. В качестве значения 13 в. Э. Балтрашевич 193
функции ЗНАЧЕНИЕ-ЦЕЛИ возвращается значение функцш CON'D, которая организует гетерархический принцип управле ния. Каждая из входящих в функцию COND функций прове ряет возможность своего включения и в случае неудачи выдаем значение NIL, которое позволяет функции COND передать уп¬ равление следующей функции. Отладочная функция REPORT (см. п. 3.3) позволяет проанализировать текущее состояние си стемы вывода решения: (DEF ЗНАЧЕНИЕ_ЦЕЛИ(LAMBDA (НОМЕР АТРИБУТ) (PROG(ПАССИВНЫЕ_ПРАВИЛА СТЕК_ФАКТОВ) (RETURN (COND ((ФИКСАЦИЯ_ЦЕЛИ НОМЕР АТРИБУТ)) ((ПОИСК_И_ОБРАБОТКА_ПРАВИЛА (ПРАВИЛО АТРИБУТ ПРАВИЛА))) ((ПОИСК_И_ОБРАБОТКА_ФУНКЦИИ АТРИБУТ ФУНКЦИИ)) ((ЗАПРОС_ПОЛЬЗОВАТЕЛЯ (ПОДСКАЗКА АТРИБУТ ПОДСКАЗКИ))) ((REPORT '(НЕТ НИ ПРАВИЛА НИ ФУНКЦИЙ НИ ПОДСКАЗКИ Из описания функции ЗНАЧЕНИЕ-ЦЕЛИ виден алгоритм вывода. В начале осуществляется фиксация (запоминание) в стеке целей текущей цели, после этого осуществляется поиск и обработка правила, если правило не найдено, то осуществля¬ ется поиск и обработка функции; если функция не найдена, то происходит запрос пользователя; если и подсказка не най¬ дена, то управление передается отладочной функции REPORT, с помощью которой можно проверить содержимое базы знаний. Функция ФИКСАЦИЯ-ЦЕЛИ производит запись цели и номера правила, установившего эту цель, в стек целей. Функ¬ ция ФИКСАЦИЯ-ЦЕЛИ всегда принимает значение NIL, что позволяет ей всегда выполняться при выполнении функции ЗНАЧЕНИЕ_ЦЕЛИ и не запрещать выполнение остальных функций, используемых функцией ЗНАЧЕНИЕ-ЦЕЛИ: (DEF ФИКСАЦИЯ_ЦЕЛИ(11АМВОА( НОМЕР АТРИБУТ)(PROG( ) (SETQ СТЕК_ЦЕЛЕИ(CONS(LIST НОМЕР АТРИБУТ)СТЕК ЦЕЛЕЙ)) (RETURN NIL] _ Следует особо подчеркнуть, что для реализации рассматри¬ ваемого логического вывода, использующего рекурсию, стек целей не нужен, так как он автоматически реализуется меха¬ низмом рекурсии. Мы же используем список СТЕК-ЦЕЛЕЙ фактически в качестве следа вывода, необходимого для орга¬ низации объяснений. 194
В рассмотренных ранее реализациях логического вывода на Паскале и ЛИСПе текущая подцель заносилась в стек целей, Правило, установившее эту подцель, объявлялось неопределен¬ ным и его обработка завершалась. На следующем цикле вы¬ вода текущая подцель выбиралась из стека целей. В рассматри¬ ваемой же реализации правила могут иметь только два значе- ВИя: истина или ложь. Поэтому при появлении текущей подцели Вразу происходит рекурсивный вызов функций, определяющих §начение этой цели, и затем либо оценка правила будет продол¬ жена, либо правило будет считатся ложным. Рекурсивная функция ПОИСК-И-ОБРАБОТКА-ПРАВИЛА вызывается функцией ЗНАЧЕНИЕ-ЦЕЛИ и в качестве аргу¬ мента получает правило, найденное с помощью функции ПРА¬ ВИЛО. Если правило не найдено, то функция ПОИСК-И-ОБРА- ВОТКА“ПРАВИЛА получает значение NIL и заканчивает ра¬ боту. , Если же правило найдено, то с помощью функции ЗНА¬ ЧЕНИЕ-ПРАВИЛА осуществляется его оценка; если правило Имеет значение ЛОЖЬ (т. е. NIL), то осуществляется запрет Правила с помощью соответствующей функции и поиск другого Правила с помощью рекурсивного обращения к функции ПОИСК-И-ОБРАБОТКА-ПР АВИЛА. Если значение правила истинно (т. е. Т), то запускается функция ПРАВИЛО-ИСТИНА: (DEF ПОИСК_И_ОБРАБОТКА_ПРАВИЛА (LAMBDA (ПРАВИЛО) (COND ((NULL ПРАВИЛО)NIL) (T(COND ((NULL(ЗНАЧЕНИЕ_ПРАВИЛА(ПРАВИЛ0_ЕСЛИ ПРАВИЛО))) (COND ((ЗАПРЕТ_ПРАВИЛА ПРАВИЛО)) (Т(П0ИСК_И_0БРАБОТКА_ПРАВИЛА (ПРАВИЛО АТРИБУТ ПРАВИЛА))))) (Т(ПРАВИЛО_ИСТИНА ПРАВИЛО] Функция ЗАПРЕТ-ПРАВИЛА включает номер ложного Правила в список ПАССИВНЫЕ-ПРАВИЛА и всегда получает Значение NIL, что позволяет при выполнении функции ПО- ИСК-И-ОБРАБОТКА-ПРАВИЛА после выполнения функции ЗАПРЕТ-ПРАВИЛА всегда включать рекурсивное обращение К функции ПОИСК-И_ОБРАБОТКА_ПРАВИЛА: (DEF ЗАЛРЕТ_ПРАВИЛА (LAMBDA (ПРАВИЛО) (PROG ( ) (SETQ ПАССИВНЫЕ_ПРАВИЛА (CONS(CAR ПРАВИЛО)ПАССИВНЫЕ ПРАВИЛА)) (RETURN NIL] “ 18* 195
Функция ПРАВИЛО-ИСТИНА формирует вспомогательную переменную ПРАВИЛО-ТО, состоящую из номера правила и части ТО правила, выталкивает из стека целей верхний эле мент и запускает функцию ВЫПОЛНЕНИЕ-ПРОЦЕДУР, по редавая ей вызовы функций, стоящие в конце части ТО. В ка честве своего значения функция ПРАВИЛО-ИСТИНА выдае: значение атрибута, стоящего в части ТО правила: (DEF ПРАВИЛО_ИСТИНА(LAMBDA(ПРАВИЛО)(PROG(ПРАВИЛО ТО) (SETQ ПРАВИЛО_ТО(LIST(CAR ПРАВИЛО) (CAR(CDDR ПРАВИЛО)))) (SETQ СТЕК_ЦЕЛЕЙ(CDR СТЕК_ЦЕЛЕЙ)) (ВЫПОЛНЕНИЕ_ПРОЦЕДУР(CDR(CADR ПРАВИЛО_ТО))) (RETURN(CAR(CDAR(CADR ПРАВИЛО_ТО] Функция ЗАПРОС-ПОЛЬЗОВАТЕЛЯ запускается функ цией ЗНАЧЕНИЕ-ЦЕЛИ и получает в качестве своего аргу мента значение подсказки, найденное с помощью функции ПОДСКАЗКА. Если подсказка найдена, то запускается функ ция ПОЛУЧИТЬ_ОТВЕТ, в противном случае функция ЗА ПРОС_ПОЛЬЗОВАТЕЛЯ принимает значение NIL и завер шает работу: (DEF ЗАЛРОС_ПОЛЬЗОВАТЕЛЯ(LAMBDA(ПОДСКАЗКА) ^ (COND (ПОДСКАЗКА(ПОЛУЧИТЬ_ОТВЕТ АТРИБУТ ПОДСКАЗКА)) (Т NIL] Функция ПОЛУЧИТЬ-ОТВЕТ оформлена в виде PROG-вы ражения и осуществляет печать подсказки и выталкивание верхнего элемента стека целей, так как соответствующая под цель достигнута. В качестве своего значения функция ПОЛУ ЧИТЬ_ОТВЕТ выдает значение атрибута, заданное пользова телем: (DEF ПОЛУЧИТЬ_ОТВЕТ(LAMBDA(АТРИБУТ ПОДСКАЗКА)(PROGП (PRINT ПОДСКАЗКА)(TERPR) (SETQ СТЕК_ЦЕЛЕЙ(CDR СТЕК_ЦЕЛЕЙ)) (RETURN(CAR(READ] Функция ЗНАЧЕНИЕ-ПРАВИЛА в случае пустой части ЕСЛИ правила выдает значение Т, являющееся признаком того, что правило истинно. Если же часть ЕСЛИ правила не пуста, то включается функция ОЦЕНКА-ПРАВИЛА, в качестве аргу ментов которой передаются элемент стека фактов, содержащий 196
оцениваемый атрибут, найденный с помощью функции НАЙТИ К часть ЕСЛИ правила: (DEF. ЗНАЧЕНИЕ_ПР АВИЛА (LAMBDA(ПРАВИЛО_ЕСЛИ) (COND ((NULL(CADR ПРАВИЛО_ЕСЛИ))Т) (Т (ОЦЕ HKA_JI РАВИЛА (НАЙТИ (CAAR (С ADR ПРАВИЛ 0_Е С ЛИ) ) СТЕК_ФАКТОВ) ПРАВИЛО__ЕСЛИ ] Функция ОЦЕНКА-ПРАВИЛА работает в зависимости от Наличия оцениваемого атрибута в стеке фактов: (DEF ОЦЕ НКА_ПРАВИЛА (LAMBDA (ЭЛЕМЕНТ_СТЕКА_ФАКТОВ ПРАВИЛО__ЕСЛИ) (COND (ЭЛЕМЕНТ_СТЕКА__ФАКТОВ (COND ( (EQ(CAR(CDAR(CADR ПРАВИЛО_ЕСЛИ) )) (CAR(CDDR ЭЛЕМЕНТ_СТЕКА_ФАКТОВ))) (ЗНАЧЕНИЕ_ПРАВИЛА(Ы8Т(CAR ПРАВИЛО_ЕСЛИ) (CDR(CADR ПРАВИЛО^ЕСЛИ))))) (Т NIL))) (T(COND ( (ФИКСАЦИЯ_ЗНАЧЕНИЯ_П0ДЦЕЛИ ПРАВИЛО_ЕСЛИ) ) ((EQ(СADR(CDAR СТЕК_ФАКТОВ)) (CAR(CDAR(CADR ПРАВИЛО_ЕСЛИ)))) (ЗНАЧЕНИЕ_ПРАВИЛА( LIST (CAR ПРАВИЛО_ЕСЛИ) (CDR(CADR ПРАВИЛО_ЕСЛИ))))) (Т NIL] Если оцениваемый атрибут части ЕСЛИ правила имеется в стеке фактов, т. е. значение ЭЛЕМЕНТА_СТЕКА_ФАКТОВ отлично от NIL, то производится сравнение значения атрибута В правиле и в стеке фактов. В случае равенства значений атри¬ бутов управление передается функции ЗНАЧЕНИЕ-ПРАВИЛА С неоцененной частью ЕСЛИ правила в качестве аргумента. Если же значение атрибута в правиле не совпадает со значе¬ нием атрибута в стеке фактов, то оцениваемое правило имеет Значение ложь и функция ОЦЕНКА-ПРАВИЛА принимает зна¬ чение NIL и завершает свою работу. Если же оцениваемый атрибут части ЕСЛИ правила отсут¬ ствует в стеке фактов, то производится фиксация его в качестве цели и запись значения этой цели в вершину стека фактов С помощью функции ФИКСАЦИЯ-ЗНАЧЕНИЯ-ПОДЦЕЛИ. После этого производится сравнение значения атрибута в пра¬ виле и в вершине стека фактов. В случае равенства значений 197
атрибутов управление передается функции ЗНАЧЕНИЕ-ПРЛ ВИЛА с неоцененной частью ЕСЛИ правила в качестве арг> мента. Если же значение атрибута в правиле не совпадает со значением атрибута в стеке фактов, то оцениваемое правило имеет значение ложь и функция ОЦЕНКА-ПРАВИЛА принн мает значение NIL и завершает свою работу. Функция ФИКСАЦИЯ-ЗНАЧЕНИЯ-ПОДЦЕЛИ записывав в вершину стека фактов номер правила, которое устанавливаем атрибут целью, сам атрибут и его значение, определяемое с по мощью функции ЗНАЧЕНИЕ-ЦЕЛИ: OEF ФИКСАЦИЯ_ЗНАЧЕНИЯ_П0ДЦЕЛИ(LAMBDA(ПРАВИЛО ЕСЛИ) (PROG() “ (SETQ СТЕК_ФАКТОВ(CONS(LIST(CAR ПРАВИЛО ЕСЛИ) (CAAR(CADR ПРАВИЛО_ЕСЛИ)) (ЗНАЧЕНИЕ_ЦЕЛИ(CAR ПРАВИЛО_ЕСЛИ) (CAAR(CADR ПРАВИЛО ЕСЛИ))))СТЕК ФАКТОВ)) (RETURN NIL] - Таким образом, в данной реализации оценка значения пра вила производится с помощью двух взаимнорекурсивных функ Ций ЗНАЧЕНИЕ-ПРАВИЛА и ОЦЕНКА-ПРАВИЛА. Кроме того, значение цели и значение правила также определяются с помощью взаимнорекурсивных функций. Здесь можно прове сти аналогию с реализацией на Прологе, где в аксиомы ТО входил вызов аксиом ЕСЛИ, а в аксиомы ЕСЛИ входил вызон аксиом ТО. Из проведенного анализа данной реализации следует, чте в данном случае правила принимают только два значения: либо ложь (NIL), либо истина (Т) (в отличие от предыдущих реа лизаций, где правила имели три значения: истина, ложь и не определено). Функция ОБРАБОТКА-ФУНКЦИИ запускается функцией ПОИСК-И_ОБРАБОТКА_ФУНКЦИИ при условии, что най дена функция, соответствующая целевому атрибуту. В процесс* работы функции ОБРАБОТКА-ФУНКЦИИ производится уда ление верхнего элемента стека целей. В качестве своего значс ния функция ОБРАБОТКА-ФУНКЦИИ получает значенш функции, соответствующее целевому атрибуту, которое опреде ляется в результате запуска этой функции с помощью стан дартной функции EVAL. Напомним, что в реализациях на ЛИСПе атрибут и имя соответствующей ему функции совпа дают: (DEF ОрРАБОТКА_ФУНКЦИИ(LAMBDA(АТРИБУТ)(PROG() (SETQ СТЕК_ЦЕЛЕЙ(CDR СТЕК_ЦЕЛЕЙ)) (RETURN(EVAL(LIST АТРИБУТ] 198
Остальные функции, используемые в рекурсивной реализа¬ ции логического вывода, были описаны ранее: рекурсивная функция ПРАВИЛО, функция ПРАВИЛО-ЕСЛИ, рекурсивная функция НАЙТИ, функция ПОДСКАЗКА — в п. 3.2; отладоч¬ ная функция REPORT — в п. 3.3; рекурсивная функция ВЫ¬ ПОЛНЕНИЕ-ПРОЦЕДУР и функция ПОИСК-И-ОБРА- БОТКА-ФУНКЦИИ —в п. 5.1. В качестве примера использования рекурсии для организа¬ ции циклов рассмотрим третью программу интерпретации пред¬ ложений, а именно предложений типа «правило»: <(1((ВВОД_СЛОВА ДА)(ЧИСЛО ДА)(ВВОД_СЛЕД_СЛОВА ДА) (ПРАВИЛ01 ДА))((ПРЕДЛОЖЕНИЕ ПРАВИЛО))) (2((СЛОВО ЕСЛИ)(ВЫРАЖЕНИЕ ДА)(СТРОКА ДА)) ((ПРАВИЛО1 ДА))) (3((СЛОВО ТО)(СТРОКА ДА))((ПРАВИЛО1 ДА))) <4((АТРИБУТ ДА)(ПРЕДИКАТ ДА)(ЗНАЧЕНИЕ ДА) (КОНЕЦ_СТРОКИ ДА))((СТРОКА ДА))) <5((СТРОКА ДА)(СЛЕД_СЛОВО ТО))((ВЫРАЖЕНИЕ ДА))) <б((СТРОКА ДА)(СЛЕД_СЛОВО И)(ВЫРАЖЕНИЕ ДА)) ((ВЫРАЖЕНИЕ ДА] ((ВВОД_СЛОВА (ВЫ ВЫДЕЛИЛИ ПЕРВОЕ СЛОВО В ПРЕДЛОЖЕНИИ?(ДА/НЕТ))) (ЧИСЛО(ВЫДЕЛЕННОЕ СЛОВО ЯВЛЯЕТСЯ ЧИСЛОМ?(ДА/НЕТ))) (ВВОД_СЛЕД_СЛОВА (ВЫ ВЫДЕЛИЛИ ОЧЕРЕДНОЕ СЛОВО В ПРЕДЛОЖЕНИИ?(ДА/НЕТ))) (СЛОВО(ВВЕДИТЕ ВЫДЕЛЕННОЕ СЛОВО)) (СЛЕД_СЛОВО(ВЫДЕЛИТЕ И ВВЕДИТЕ ОЧЕРЕДНОЕ СЛОВО)) (АТРИБУТ(СЛЕДУЮЩИМ СЛОВОМ ЯВЛЯЕТСЯ АТРИБУТ?(ДА/НЕТ))) (ПРЕДИКАТ(СЛЕДУЮЩИМ СЛОВОМ ЯВЛЯЕТСЯ ПРЕДИКАТ?(ДА/НЕТ))) (ЗНАЧЕНИЕ (СЛЕДУЮЩИМ СЛОВОМ ЯВЛЯЕТСЯ ЗНАЧЕНИЕ АТРИБУТА?(ДА/НЕТ))) (КОНЕЦ_СТРОКИ(НА ЭТОМ СТРОКА КОНЧАЕТСЯ?(ДА/НЕТ] П В шестом правиле, определяющем значение атрибута ВЫ¬ РАЖЕНИЕ, атрибут ВЫРАЖЕНИЕ используется и в части ЕСЛИ правила, что приводит к рекурсивному вызову правила, определяющего значения атрибута ВЫРАЖЕНИЕ (правило 5 или 6), и позволяет интерпретировать предложения с любым числом строк части ЕСЛИ, соединенных словом И. Выход из цикла осуществляется с помощью правила 5 при появлении строки анализируемого предложения, начинающейся со слова ТО. Примеры анализируемых предложений типа «правило» приведены в табл. 1.1. При запуске программы интерпертации пользователь должен задать целью ПРЕДЛОЖЕНИЕ. В качестве второго примера рассмотрим четвертую про¬ грамму интерпертации любого числа предложений типа «под¬ сказка» или «перевод» языка эксперта с параллельным созда- 199
нием списков подсказок, и переводов с помощью первого на бора глубинных знаний, приведенного в п. 5.1: ((1( )((НАЧАЛО ДА)(НАЧ_УСТАНОВКА))) (2 ((СЛОВО ПОДСКАЗКА) (АТРИБУТ ДА) (ТЕКСТ ДА)) ((ПРЕДЛОЖЕНИЕ ПОДСКАЗКА)(ЗАПИСЬ_П0ДСКАЗКИ)(ПЕЧАТЬ))) (3((СЛОВО ПЕРЕВОД)(АТРИБУТ ДА)(ТЕКСТ ДА)) ((ПРЕДЛОЖЕНИЕ ПЕРЕВОД)(ЗАПИСЬ_ПЕРЕВ0ДА)(ПЕЧАТЬ))) (4()((ПРЕДЛОЖЕНИЕ ОШИБОЧНОЕ))) (5((ПРЕДЛОЖЕНИЕ ПОДСКАЗКА))((ЯЗЫК ЭКСПЕРТА))) (б((ПРЕДЛОЖЕНИЕ ПЕРЕВОД))((ЯЗЫК ЭКСПЕРТА))) ( 7 ( (НАЧАЛО ДА) (СИНТ_АНАЛИЗ ДА) ) ( (РАБОТА ДА) ) ) (8((ЯЗЫК ЭКСПЕРТА)(КОНЕЦ ДА))((СИНТ_АНАЛИЗ ДА))) (9((ЯЗЫК ЭКСПЕРТА)(КОНЕЦ НЕТ)(СИНТ_АНАЛИЗ ДА)) ((СИНТ_АНАЛИЗ ДА] ((КОНЕЦ(КОНЧАТЬ АНАЛИЗ ?(ДА/НЕТ] (НАЧ^УСТАНОВКА СЛОВО АТРИБУТ ТЕКСТ ЗАПИСЬ_ПОДСКАЗКИ ЗАПИСЬ_ПЕРЕВОДА ПЕЧАТЬ ] В девятом правиле, определяющем значение атрибута СИНТ-АНАЛИЗ (синтаксический анализ), атрибут СИНТ_ АНАЛИЗ используется и в части ЕСЛИ правила, что приводит к рекурсивному вызову правила, определяющего значение атри¬ бута СИНТ-АНАЛИЗ (правило 8 или 9), и позволяет прово¬ дить анализ нескольких предложений. Выход из цикла осуще¬ ствляется правилом 8 при принятии атрибутом КОНЕЦ зна¬ чения НЕТ. Значение атрибута КОНЕЦ задается пользовате¬ лем в ответ на соответствующую подсказку. Анализ нескольких предложений осуществляется при задании пользователем цели РАБОТА. При задании пользователем цели ПРЕДЛОЖЕНИЕ или ЯЗЫК проводится интерпретация одного предложения с целью определения типа предложения или типа языка, к ко¬ торому относится интерпретируемое предложение. Примеры анализируемых предложений типа подсказка или перевод при¬ ведены в табл. 1.1. Очевидно, что знания, приведенные в четвертой программе и в соответствующем наборе процедур, определяют новый ком¬ пилятор части языка эксперта, осуществляющий преобразова¬ ние внешнего представления знаний, приведенных в табл. 1.1, во внутреннее представление в виде списков ПОДСКАЗКИ1 и ПЕРЕВОДЫ1. В заключение следует подчеркнуть, что рекурсивная реали¬ зация логического вывода представляет большой интерес и способствует лучшему пониманию процесса логического вы¬ вода. Представляется полезным в качестве упражнения реали¬ зовать рекурсивный вывод на Паскале, так как в ЛИСПе рекурсия используется и для реализации циклов, поэтому за¬ 200
труднительно отличить, где рекурсия необходима по смыслу* А где в качестве реализации простого цикла. В реализации же на Паскале можно выделить цикл пере- вора правил (и подсказок) и цикл оценки правила. Так, по¬ лезным упражнением будет реализация процедуры ВЫВОД Как рекурсивной, т. е. циклы по правилам и внутри правила Останутся, но при появлении атрибута, значение которого не¬ известно, сразу должно происходить рекурсивное обращение К процедуре ВЫВОД с новой целью. С другой стороны, как было показано, организация циклов На языке эксперта также может быть реализована либо с по¬ мощью рекурсии, либо без рекурсии. Представляет интерес А качестве упражнений рассмотреть различные комбинации ре¬ ализации логического вывода (с рекурсией или без рекурсии) К циклов на языке эксперта (с рекурсией или без рекурсии). Ранее мы фактически рассмотрели вариант реализации циклов На языке эксперта без рекурсии и реализацию логического вы¬ вода также без рекурсии. Затем мы рассмотрели рекурсивную Организацию и циклов и логического вывода. Особо следует подчеркнуть, что при всех реализациях ло¬ гического вывода необходимо проводить коррекцию блока объ¬ яснений. 5.3. АВТОМАТИЗИРОВАННАЯ ОБУЧАЮЩАЯ СИСТЕМА НА БАЗЕ ИНСТРУМЕНТАЛЬНОЙ ЭКСПЕРТНОЙ СИСТЕМЫ Как отмечалось в п. 5.1, разные варианты взаимодействия Ответов процедур и пользователя приводят к разным режимам работы экспертной системы: автоматическому, при котором от¬ вет процедуры записывается в базу данных экспертной си¬ стемы (в стек фактов), минуя пользователя; рекомендующему, при котором ответ процедуры является рекомендацией пользо¬ вателю, а окончательный ответ определяется пользователем; I контролирующему, при котором ответ пользователя проверя- | стся процедурой. Примеры использования первых двух режи¬ мов были даны в п. 5.1. Здесь же мы рассмотрим возможности [ реализации контролирующего режима, который может найти 1 Широкое применение при обучении. | Рассмотрим необходимые модификации экспертной системы ! для использования ее в качестве базы для создания автомати- !Ированной обучающей системы (АОС). При этом режиме зна¬ чение атрибута задается пользователем, а процедура прове¬ ряет правильность ответа пользователя. В случае ошибки (в зависимости от желания пользователя) система либо про- I СТО повторяет запрос, либо выдает подсказку (пояснение). 201
В процессе работы системы фиксируется число ошибок обучя емого при определении каждого атрибута и число подсказок Эти числа учитываются при оценке знаний обучаемого. Напомним, что поверхностные знания предметной области описываются с помощью языка эксперта, а для представления глубинных знаний мы используем процедуры, записанные ня языке реализации экспертной системы. Структуры данных, описывающие концептуальную модель предметной области, об разуют «доску объявлений», с помощью которой происходи! обмен информацией между процедурами, описывающими глу бинные знания, а также между моделью предметной области и пользователем. Рассмотрим требования к структуре данных для атрибутов, выдвигаемых разрабатываемой АОС. В рассмотренных раней версиях экспертной системы с каждым атрибутом были свя заны тексты подсказки и перевода. Текст перевода использовался для замены имени атрибута при поясняющей распечатке правил при ответе на вопросы КАК и ПОЧЕМУ. Параметр ПЕРЕВОД должен остаться и в нашем случае Что касается текста подсказки, то ранее он фактически состоял из вопроса о значении атрибута и из возможных ответов ни данный вопрос. Очевидно что в обучающей системе этот пара метр должен быть разделен на два, т. е. на ВОПРОС и ПОЯС НЕНИЕ. Так как значение атрибута, заданное обучаемым, должно быть проверено и для этой проверки используется процедура, то среди параметров атрибута должен быть параметр, содер жащий имя процедуры. Как уже указывалось, при работе АО( подсчитывается число ошибок при определении значения атрн бута, поэтому может быть полезен параметр, содержащий но мер атрибута. В общем случае значения атрибутов могут быть разных типов (целые, вещественные, строковые и т. д.), поэтому при реализации на языках типа Паскаль должен быть параметр, указывающий тип атрибута. Для объединения разных типов атрибутов в один объединен ный тип можно использовать запись с вариантами (см. п. 2.1). Ключ варианта определяет тип значения атрибута в конкретном случае. При использовании процедур, проверяющих ответы пользо вателя, возможны два режима. При первом режиме в стек фактов записывается ДА как признак правильности задания значения атрибута. При втором режиме в стек фактов записы вается проверенный ответ пользователя, по которому происхо дит ветвление в процессе, описанном поверхностными знани ями. Поэтому среди параметров атрибута должен быть при¬ 202
знак записи ответа пользователя. При истинном значении этого Признака в стек фактов записывается ответ пользователя, иначе Записывается ДА как признак правильности задания значения атрибута. Таким образом, атрибут может иметь следующие пара¬ метры: перевод, вопрос, пояснение (варианты ответов), имя Обслуживающей процедуры, номер атрибута, признак типа от¬ пета и признак записи ответа. Можно сказать, что для описа¬ ния атрибута должен использоваться фрейм, т. е. деклара¬ тивно-процедурная структура данных, содержащая различные поля (слоты). В предыдущих версиях экспертной системы организация диалога пользователя с системой осуществляется процедурой ПОЛУЧИТЬ_ОТВЕТ, которая распечатывает значение под¬ сказки и получает от пользователя значение атрибута. Перед выдачей ответа пользователь может задать экспертной системе вопросы типа ПОЧЕМУ и КАК. Таким образом, процедура ПОЛУЧИТЬ-ОТВЕТ имеет два режима работы: режим полу¬ чения ответа и режим объяснений. Рассмотрим необходимые изменения этой процедуры для организации обучающей системы. Кроме вышеописанных дей¬ ствий в АОС необходимо обеспечить режим помощи, при кото¬ ром должны быть даны пояснения по определению значений конкретного атрибута, при этом должен быть зафиксирован факт помощи. После этого система входит в цикл проверки, признаком окончания которого является правильный ответ обу¬ чаемого на заданный вопрос. С учетом имеющихся пояснений пользователь в принципе всегда сможет дать правильный ответ. В начале цикла проверки повторяется вопрос о значении атрибута, и пользователь (обучаемый) должен задать значе¬ ние атрибута. При получении ответа пользователя при разра¬ ботке АОС на языках типа Паскаль необходимо учитывать, что ответы пользователя могут быть разных типов. Далее производится проверка правильности заданного зна¬ чения атрибута. Для этого запускается проверяющая процедура, имя которой указано в соответствующем параметре атри¬ бута. При успешной проверке пользователю выдается поощритель¬ ное сообщение, иначе фиксируется факт ошибки и у пользова¬ теля (обучаемого) спрашивается, знает ли он, какое значение должен иметь атрибут. В случае положительного ответа (т. е. ошибка обусловлена небрежностью ввода) пользователю вы¬ дается рекомендация не отвлекаться от работы, иначе выда¬ ется пояснение об определении значения атрибута и фиксиру¬ ется факт помощи. При получении правильного ответа, в за¬ висимости от значения признака записи ответа, в стек фактов 203
в качестве значения атрибута записывается либо ответ поль¬ зователя, либо значение ДА. Для реализации этой системы выбран язык Паскаль, так как этот язык, из рассмотренных нами, позволяет наиболее полно использовать возможности современных машин. При заполнении АОС знаниями о конкретной предметной области эксперт должен описать управляющие процессы в форме поверхностных знаний на языке эксперта в отдельном файле. Глубинные знания и структуры данных, описывающие «доску объявлений», должны быть описаны в другом файле по правилам описания внешних модулей языка Паскаль. Воз¬ можность замены этих файлов для других предметных обла¬ стей делает разработанную АОС фактически инструментальной АОС. Пример реализации инструментальной экспертной системы для АОС с использованием языка TURBO PASCAL приведен в прил. 2. Версия TURBO PASCAL выбрана в связи с тем, что она получила большое распространение на персональных ЭВМ, в частности на персональных ЭВМ типа IBM PC, на которых реализация АОС прошла опытные испытания. Основные использованные при реализации АОС отличия TURBO PASCAL от версии, описанной в п. 2.1, сводятся к сле¬ дующему. 1. Введен дополнительный предопределенный тип данных STRING для представления строк символов, содержащих пере¬ менное число символов. Максимальная длина строки должна быть указана для каждой STRING-переменной. Тип STRING— это структурный тип, во многом похожий на ARRAY OF CHAR. Основное отличие — число символов в строке изменяется от О до указанной при описании верхней границы, в то время как для массива число элементов в нем фиксировано. В элементе STRING-переменной с индексом 0 хранится фактическая длина строки. 2. Область действия метки — тот блок, в котором она опи¬ сана, т. е. нельзя входить (выходить) в процедуру (из проце¬ дуры) по метке. При реализации экспертной системы в п. 2.1 использовалась метка для аварийного завершения программы, теперь придется вводить признак ERROR. 3. Отсутствуют процедуры GET и PUT для работы с фай¬ лами, В п. 2.3 процедура GET использовалась при реализации компилятора для заглядывания вперед на один символ. 4. Разрешено использование так называемых окон для раз¬ деления экрана дисплея на части в целях вывода разной ин¬ формации. Имеется ряд процедур, поддерживающих работу с окнами: FRAMEWINDOW (...)—для задания рамки окна с подза¬ головком; 204
WINDOW (...)—для задания самого окна; CLRSCR— очистка экрана.и др. Все эти процедуры входят в пакет TPCRT, который дол¬ жен быть подключен в начале программы с помощью дирек¬ тивы USES. В приведенной в приложении реализации одно окно будет использовано для «доски объявлений», второе — для диалога пользователя с экспертной системой. 5. Разрешено использование директивы INCLUDE для под¬ ключения частей программы, записанных в другом файле. С помощью этой директивы мы будем подсоединять файл с описанием глубинных знаний (>fcSI имя файла ^с). 6. Запрещено использование букв русского алфавита в иден¬ тификаторах. Программа из приложения разрабатывалась аналогично программе из гл. 2, но с использованием мнемоники, близкой к английской, и с учетом вышеприведенных особенностей языка TURBO PASCAL. Кратко рассмотрим особенности реализации АОС. Синтаксические диаграммы языка эксперта приведены на рис. 5.2. Из синтаксических диаграмм для правил видно, что в части ТО после атрибута и его значения могут идти имена процедур и их параметры, соединенные символом И. Структуры данных в основном соответствуют структурам данных программы, приведенной в гл. 2. Дополнительно вве¬ дены следующие типы: DOMEN — записи с вариантами — для реализации ответов пользователя разных типов: INTEGER, REAL, WORD; EROR — массив записей с двумя полями — для сбора ста¬ тистики ошибок (поле TXT предназначено для наименования ошибки, поле I—для числа ошибок). Вариант FALSE типа ITEM предназначен для формирова¬ ния списка атрибутов. Поля записи имеют следующие назна¬ чения: QUEST-PTR — указатель на текст вопроса; ANSWER-PTR — указатель на текст ответа (подсказки); TRANS-PTR — указатель на текст перевода; NAME-PROC — имя процедуры; NUMBER — номер атрибута; KIND — признак типа ответа; SIGN — признак записи ответа. В основной программе используются следующие основные переменные: MAS-RULE — массив правил; FREE — список свободной памяти; ATTR-LIST — список атрибутов. 205
Пробило ^ Вопрос От бет Перевод Номер атрибута Номер -^—QEcniT)- Условие (ТГ)— Вывод -( Вопрос ^— Атрибут Текст (еоЬтГ^ -(Подсказка Атрибут —(еоЬ• Текст ~ ^е~оЬ ( Перевод )— Атрибут Условие Т~ еоЬть Текст —(еоЬть I Цисрра Выражение —(еоЬть Выражемие Атрибут -Л^у-Значение— —Атрибут Лексема Имя процедуры Параметры Номер Имя атрибута процедурь/ Признак типа ответа Признак записи —(еоЬть)- Om Serna Вывод Выражение —Имя процедуры —(^—Параметр —(е о 1тъ у ® word Признак типа ответа -(integery Признак записи ответа real Yes 9 Рис. 5.2. Синтаксические диаграммы языка эксперта АОС 206
В процедуре INFER, реализующей логический вывод, ис¬ пользуются следующие основные переменные: MAIN-GOAL — основная цель; ACTIVE-RULE — активные правила; FACT-LIST, GOAL-LIST — стек фактов и стек целей соот¬ ветственно; DONE — признак готовности. Назначение процедур поясняется приведенными в тексте Программы комментариями. При реализации процедуры SENTENCE, реализующей син¬ таксические диаграммы (см. рис. 5.2), большое внимание было уделено диагностике возможных ошибок в программе экс¬ перта. При реализации процедуры INFER в основную программу были добавлены следующие процедуры. Процедура RETFLAG, эквивалентная функции ГАШЕНИЕ (см. п. 5.2); предназначена для реализации циклов на языке эксперта; Процедура ERRPRINT; предназначена для итоговой печати Сообщений об ошибках. Процедура ERRPRINT соответствует атрибуту с первым номером, а процедура RETFLAG — атрибуту со вторым номе¬ ром, поэтому атрибуты, которые использует эксперт, могут Иметь номера, начиная с 3. Процедура EVAL-PROC приводится во внешнем файле глу¬ бинных знаний и предназначена для запуска процедур, связан¬ ных с атрибутом по номеру атрибута. Процедура TRUE-RULE аналогична процедуре ПРА¬ ВИЛО-ИСТИННО (см. п. 2.4), но расширена для реализации Запуска процедур, указанных в части ТО правила по анало¬ гии с функцией ПРАВИЛО-ИСТИНА (см. п. 5.1). Принципиальные отличия данной реализации от приведен¬ ных ранее заключены в процедуре получения ответа от поль¬ зователя (GET — ANSWER), которая в качестве вспомогатель¬ ных использует процедуру QUESTION (вопрос) и процедуру VERIFY (проверка). Процедура QUESTION обеспечивает печать вопроса поль- Ювателя и в зависимости от желания пользователя осуществ¬ ляет или подсказку, или ответы на вопросы КАК и ПОЧЕМУ, Напуская процедуру EXPLANATION (объяснения). Основу процедуры VERIFY составляет цикл ввода ответа Пользователя о значении атрибута и проверка ответа соответ¬ ствующей атрибуту процедурой. Признаком окончания цикла Является правильный ответ пользователя. В начале процедуры VERIFY в зависимости от значения Признака типа ответа KIND атрибута осуществляется ввод от¬ вета необходимого типа и запись его в соответствующее поле 207
переменной ANSWER, которая является входным параметром процедуры EVAL-PROC. Процедура EVAL-PROC запускаем проверяющую процедуру по номеру атрибута. При правильном ответе пользователя все проверяющие процедуры выдают зна чение ДА. Процедура GET-ANSWER получает управление, если в<> фрейме, соответствующем атрибуту, либо поле вопроса не пу сто, либо имеется имя обслуживающей процедуры. Если поле вопроса пусто, а имя процедуры есть, то это ре жим использования имен процедур в качестве атрибутов, par смотренный в п. 5.1. В этом случае с помощью процедуры EVAL-PROC осуществляется запуск процедуры, соответству ющей атрибуту, т. е. происходит так называемый «виртуаль ный» диалог (в отличие от реального диалога при присутствии вопроса). В поле номера правила соответствующего элемента стека фактов записывается—1 как признак того, что значение ai рибута определялось процедурой. Если поле вопроса не пусто, а имя процедуры отсутствуем то это наш основной режим, рассмотренный в предыдущп главах. В этом случае в ответ на заданный системой вопро» осуществляется обычный ввод ответа пользователя о значении атрибута. Если же во фрейме имеется и вопрос и имя процедуры, этот режим соответствует режиму обучения, и в этом случаи производится запуск процедур QUESTION и VERIFY. Посл> этого в зависимости от значения признака записи ответ.' (SIGN) в стек фактов в качестве значения атрибута будет за писан ответ пользователя или ДА. В режиме реального диалога, т. е. при наличии вопроса г." фрейме, соответствующем атрибуту, в поле номера правила со ответствующего элемента стека фактов, как и преж/е записывается значение 0 в качестве признака ответа пользе вателя. При создании конкретной АОС, комбинируя различные за полнения слотов фрейма, можно использовать различные р« жимы работы АОС при обработке конкретного атрибута. Из вышеизложенного следует, что рассматриваемая нами реализация является расширением всех предыдущих, так к;н она позволяет использовать имена процедур в качестве атри бутов в правилах языка эксперта и использовать циклы и ■ языке эксперта. В качестве упрощенного примера использования АОС ра< смотрим систему, позволяющую обучать (и контролирован ) пользователя структуре предложений ПОДСКАЗКА и ПЕР1 ВОД языка эксперта. В ответ на просьбу пользователя о п< мощи система распечатывает ответ на соответствующий п* 208
■рос. То же самое система сможет сделать по желанию поль¬ зователя при совершении им ошибки, т. е. при неправильном ■свете на вопрос. С помощью задания вопросов КАК и ПОЧЕМУ пользова¬ тель может проследить всю структуру изучаемых предло¬ жений. Программа обучения структуре предложений типа «под¬ сказка» и «перевод» языка эксперта, записанная на языке экс¬ перта, имеет вид 1 ЕСЛИ ПЕНАТЫ - ДА <ВК> И СЛ0В01 - ДА И АТРИБУТ - ДА <ВК> И КОНЕЦ_СТРОКИ - ДА ц твист — ДА ТО ЗАПРОС1 - ПРЕДЛ0ЖЕНИЕ_П0ДСКАЗКА И ПЕЧАТЬ - HETJIAPAMETPA <ВК> И ОШИБКИ - НЕТ_ПАРАМЕТРА 2 ЕСЛИ ПЕНАТЫ - ДА <ВК> И СЛОВО2 - ДА И АТРИБУТ - ДА <ВК> И КОНЕЦСТРОКИ - ДА И ТЕКСТ - ДА ТО ЗАПР0С2 - ПРЕДЛОЖЕНИЕ_ПЕРЕВОД Й ПЕЧАТЬ - НЕТ <ВК> И ОШИБКИ - НЕТ ВОПРОС СЛОВО1 С КАКОГО СЛОВА НАЧИНАЕТСЯ ПРЕДЛОЖЕНИЕ(?) ВОПРОС СЛ0В02 С КАКОГО СЛОВА НАЧИНАЕТСЯ ПРЕДЛОЖЕНИЕ(?) ВОПРОС АТРИБУТ ВВЕДИТЕ СЛЕДУЮЩИЙ ЭЛЕМЕНТ СТРУКТУРЫ ПРЕДЛОЖЕНИЯ ВОПРОС КОНЕЦ_СТРОКИ ВВЕДИТЕ СЛЕДУЮЩИЙ ЭЛЕМЕНТ СТРУКТУРЫ ПРЕДЛОЖЕНИЯ ВОПРОС ТЕКСТ ВВЕДИТЕ СЛЕДУЮЩИЙ ЭЛЕМЕНТ СТРУКТУРЫ ПРЕДЛОЖЕНИЯ ПАРАМЕТРЫ ОШИБКИ <ВК> 1 ERRPRINT WORD NO ПАРАМЕТРЫ СЛОВО1 <ВК> 3 SLOWOl WORD NO ПАРАМЕТРЫ СЛ0В02 <ВК> 4 SL0W02 WORD NO ПАРАМЕТРЫ АТРИБУТ <ВК> 5 ATR WORD NO ПАРАМЕТРЫ КОНЕЦ_СТРОКИ <ВК> б END_LINE WORD NO ПАРАМЕТРЫ ТЕКСТ <ВК> 7 READJTEXT WORD NO ПАРАМЕТРЫ ПЕНАТЫ <ВК> 8 PRINT 1 WORD NO ПАРАМЕТРЫ ПЕЧАТЬ2 <ВК> 9 PRINT2 WORD NO ПАРАМЕТРЫ ПЕЧАТЬ <ВК> 10 PRINT WORD NO ПОДСКАЗКА СЛОВО1 <ВК> СО СЛОВА ПОДСКАЗКА ПОДСКАЗКА СЛ0В02 <ВК> СО СЛОВА ПЕРЕВОД ПОДСКАЗКА АТРИБУТ ,КОТОРЫЙ ДОЛЖЕН БЫТЬ АТРИБУТОМ ПРЕДМЕТНОЙ ОБЛАСТИ ПОДСКАЗКА КОНЕЦСТРОКИ .КОТОРЫЙ ДОЛЖЕН БЫТЬ КЛАВИШЕЙ [<ВК>] ПОДСКАЗКА ТЕКСТ , КОТОРЫЙ ДОЛЖЕН БЫТЬ ТЕКСТОМ ПЕРЕВОД СЛОВО1 <ВК> СЛУЖЕБНОЕ СЛОВО ПЕРЕВОД СЛ0В02 <ВК> СЛУЖЕБНОЕ СЛОВО 14 В. Э. Балтрашевнч 209
Описание соответствующих глубинных знаний можно пред ставить в виде PROCEDURE EVAL_PROC(NUMBER:INTEGER; PAR:DOMEN; VAR VALsWORD); PROCEDURE SLOWOl(INP sWORD; VAR VALsWORD); BEGIN IP INP='ПОДСКАЗКА' THEN VAL: = 'HA' ELSE VALs ='НЕТ'; END; PROCEDURE SL0W02(INP:WORD; VAR VAL:WORD); BEGIN IF INP“'ПЕРЕВОД' THEN VAL:='ДА' ELSE VALs ='НЕТ'; END; PROCEDURE ATR(INP:WORD; VAR VAL!WORD); BEGIN IF INP[0]=CHR(0) THEN VALs ='НЕТ' ELSE VALs='HA'f END; PROCEDURE END_LINE(INPSWORD; VAR VALsWORD); BEGIN IF INP[0]-CHR(0) THEN VALs ='ДА' ELSE VALs='HET'p END; PROCEDURE READ_TEXT(INPsWORD; VAR VALsWORD); BEGIN IF INP[0]=CHR(0) THEN VALs ='НЕТ' ELSE VALt-'W'; END; PROCEDURE PRINT1; BEGIN WRITELN('ВЫ РАБОТАЕТЕ С ПРЕДЛОЖЕНИЕМ 'ТИПА ПОДСКАЗКА'); END; PROCEDURE PRINT2; BEGIN WRITELN('ВЫ РАБОТАЕТЕ С ПРЕДЛОЖЕНИЕМ ТИПА ПЕРЕВОД' ); END; PROCEDURE PRINT; i BEGIN WRITELN('СТРУКТУРА ПРЕДЛОЖЕНИЯ ВЕРНА'); END; BEGIN(*EVAL_PROC*) WINDOW(3,3,77,14); VAL s =' ДА'; CASE NUMBER OF 3 s SLOWOl(PAR.DW,VAL); 4 SSL0W02(PAR.DW,VAL); 5sATR(PAR.DW,VAL); 6 sEND_LINE(PAR.DW,VAL); 7sREAD_TEXT(PAR.DW,VAL); 8:BEGIN CLRSCR; PRINT1; END; 9sBEGIN CLRSCR; PRINT2; END; lOsBEGIN CLRSCR; PRINT; END; END(*CASE*); ** WINDOW(3,17,77,24); CLRSCR; END(*EVAL_PROC *); 210
Если пользователь хочет изучать структуру предложения типа «ПОДСКАЗКА» или хочет проконтролировать свои зна¬ ния о структуре предложений этого типа, он должен задать системе цель ЗАПРОС 1. Если же пользователь хочет изучать структуру предложения типа «перевод», он должен задать Цель ЗАПРОС 2. Предложения, составляемые пользователем, должны относиться к какой-то предметной области. Проверяющие процедуры ATR и READ-TEXT проверяют только наличие атрибута и текста соответственно. При этом используется тот факт, что в TURBO PASCAL в STRING-ne- ременных в элементе с индексом ноль хранится длина строки. Структура основной программы должна быть представлена в виде Program аос(input, output); CONST NWORD = 30; TYPE WORD = PACKED ARRAY [1..NWORD] OF CHAR; TIPS = (INTEG, REL, WRD); DOMEN = RECORD CASE KIND: TIPS OF INTEG; (DI: INTEGER); REL: (DR: REAL); WRD: (DW: WORD); END; <* ОПИСАНИЯ СТРУКТУР ДАННЫХ, ОБРАЗУЮЩИХ МОДЕЛЬ ПРЕДМЕТНОЙ ОБЛАСТИ *) PROCEDURE EVAL_PROC(NUMBER: INTEGER; PAR: DOMEN; VAR VAL: WORD); (* ОПИСАНИЯ ПРОЦЕДУР ПРЕДМЕТНОЙ ОБЛАСТИ *) BEGIN (* EVAL_PROC *) CASE NUMBER OF 3: (* ВЫЗОВ I-ОЙ ПРОЦЕДУРЫ ПРЕДМЕТНОЙ ОБЛАСТИ *) END (* CASE *); END (* EVAL_PROC *); PROCEDURE ИНСТРУМЕНТАЛЬНАЯ_ЗКСПЕРТНАЯ_СИСТЕМА; EXTERNAL; BEGIN (* AOC *) ИНСТРУМЕНТАЛЬНАЯ_ЗКСПЕРТНАЯ_СИСТЕМА; END. Вся структура AOC может рассматриваться как модель предметной области, заданная структурами данных и проце¬ дурами, к которой добавляется внешняя процедура, реализую¬ щая инструментальную ЭС. Один из возможных вариантов программы с подсоедине¬ нием файлов приведен ниже: 14* 211
PROGRAM АОС(INPUT, OUTPUT); USES TPCRT; CONST NWORD=30; TYPE WORD=STRING[NWORD]; TIPS=(INTEG, REL, WRD); DOMEN= RECORD CASE KIND:TIPS OP INTEG:(DIsINTEGER); REL:(DR:REAL); WRD:(DW:WORD); END; (*$I EVALPROC.PAS *) (‘МОДЕЛЬ ПРЕДМЕТНОЙ ОБЛАСТИ*) (*$I IES.PAS *) (‘ИНСТРУМЕНТАЛЬНАЯ ЭС‘) BEGIN < IES END. Тело основной программы — это вызов инструментальной ЭС, которая, используя поверхностные знания, заданные на языке эксперта в отдельном файле, осуществляет логический вывод конкретного решения и обеспечивает возможность объ¬ яснений и помощи. В традиционных программах глубинные про¬ цессы задаются процедурами, а поверхностный процесс задается телом основной программы. Используя традиционную програм¬ му, пользователь практически не может понять ее работу, так как он не может из какой-либо точки программы проследить историю ее работы и узнать возможные пути дальнейшей ра¬ боты. Если программист и включит в эту программу различные трассировки, то они будут специфичны для конкретной про¬ граммы. При разработке новой программы трассировки нужно организовывать заново. Запись же тела основной программы на языке эксперта позволяет пользователю с помощью вопро¬ сов ПОЧЕМУ и КАК познать процесс работы основной про¬ граммы, режим же помощи АОС напоминает пользователю (при контроле знаний пользователя) суть глубинных процессов, описанных процедурами. В качестве примера использования раз¬ работанной системы в обычном режиме, т. е. без обучения и без использования имен процедур в качестве атрибутов, но с ис¬ пользованием циклов, приведем программу интерпретации пред¬ ложений языков эксперта и пользователя, сооттветствующую второй программе из п. 5.2 (см. стр. 213). Описание соответствующих глубинных знаний состоит фак¬ тически из замещающего модуля PROCEDURE EVAL PROC(NUMBER«INTEGER* PARjDOMEN* VAR VAL:WORD)} BEGIN VAL:«'ДА'; , END(*EVAL_PROC *)* 212
ПАРАМЕТРЫ ГАШЕНИЕ 2 RETFLAG WORD NO 1 ЕСЛИ ВВОД_СЛОВА - ДА <ВК> И ЧИСЛО - ДА И ВВОД_СЛЕД_СЛОВА - ДА <ВК> И ЧАСТЬ_ЕСЛИ - ДА И ЧАСТЬ_ТО - ДА <ВК> ТО ПРЕДЛОЖЕНИЕ - ПРАВИЛО 2 ЕСЛИ СЛОВО - ЕСЛИ <ВК> И ФЛАГ1 - ДА И ВЫРАЖЕНИЕ - ДА <ВК> ТО ЧАСТЬ_ЕСЛИ - ДА 3 ЕСЛИ СЛОВО - ТО <ВК> ТО ЧАСТЬ_ЕСЛИ - ДА 4 ЕСЛИ АТРИБУТ - ДА <ВК> И ПРЕДИКАТ - ДА И ЗНАЧЕНИЕ - ДА <ВК> И КОНЕЦ_СТРОКИ - ДА ТО СТРОКА - ДА 5 ЕСЛИ СТРОКА - ДА <ВК> И СЛЕД_СЛОВО - ТО ТО ВЫРАЖЕНИЕ - ДА 6 ЕСЛИ СТРОКА - ДА <ВК> И СЛЕД_СЛОВО - И ТО ВЫРАЖЕНИЕ - ДА <ВК> И ГАШЕНИЕ - ФЛАГ1 7 ЕСЛИ СЛОВО - ТО <ВК> И СТРОКА - ДА ТО ЧАСТЬ_ТО - ДА 8 ЕСЛИ СЛЕД_СЛОВО - ТО <ВК> И СТРОКА1 - ДА ТО ЧАСТЬ_ТО - ДА 9 ЕСЛИ АТРИБУТ1 - ДА <ВК> И ПРЕДИКАТ1 - ДА И ЗНАЧЕНИЕ1 - ДА <ВК> И КОНЕЦ_СТРОКИ1 - ДА ТО СТРОКА1 - ДА 10 ТО ФЛАГ1 - ДА 11 ЕСЛИ ВВОД_СЛОВА - ДА <ВК> И ЧИСЛО - НЕТ И СЛОВО - ПОДСКАЗКА <ВК> И АТРИБУТ - ДА И КОНЕЦ_СТРОКИ - ДА <ВК> И ТЕКСТ - ДА ТО ПРЕДЛОЖЕНИЕ - ПОДСКАЗКА 20 ЕСЛИ ПРЕДЛОЖЕНИЕ - ВОПРОС ТО ЯЗЫК - ПОЛЬЗОВАТЕЛЯ 21 ЕСЛИ ФЛАГ2 - ДА <ВК> И СИНТ_АНАЛИЗ - ДА ТО ВЫВОД - ДА 22 ЕСЛИ ЯЗЫК - ЭКСПЕРТА <ВК> И КОНЕЦ - ДА ТО СИНТ_АНАЛИЗ - ДА 23 ЕСЛИ ЯЗЫК - ЭКСПЕРТА <ВК> И КОНЕЦ - НЕТ ТО СИНТ_АНАЛИЗ - НЕТ <ВК> И ГАШЕНИЕ - ФЛАГ2 24 ТО ФЛАГ2 - ДА ВОПРОС ВВОД_СЛОВА ВЫ ВЫДЕЛИЛИ ПЕРВОЕ СЛОВО В ПРЕДЛОЖЕНИИ?(ДА/НЕТ) ВОПРОС ЧИСЛО ВЫДЕЛЕННОЕ СЛОВО ЯВЛЯЕТСЯ ЧИСЛОМ?(ДА/НЕТ) ВОПРОС КОНЕЦ КОНЧАТЬ АНАЛИЗ?(ДА/НЕТ) ПЕРЕВОД ВВОД_СЛОВА ВВОД ОЧЕРЕДНОГО СЛОВА ПЕРЕВОД ЧИСЛО СЛОВО ЯВЛЯЕТСЯ ЧИСЛОМ ПЕРЕВОД ПРЕДИКАТ ИМЕЕТСЯ ПРЕДИКАТ 213
Если пользователь в качестве основной дели задает ПРЕД ЛОЖЕНИЕ или ЯЗЫК, то будет проведена интерпретация одного предложения в целях определения типа этого предложе ния или определения типа языка, к которому относится интер претируемое предложение. Если же пользователь задает целью ВЫВОД, то он сможет провести интерпретацию нескольких предложений. Окончание анализа задается пользователем в от вет на соответствующий вопрос. В этой программе в предло жениях ВОПРОС объединены тексты вопроса и подсказки, т. е. ответа. Вторая программа интерпретации предложений типои «подсказка» и «перевод» с построением списка атрибутов пред ставлена в виде 1 ЕСЛИ НАЧ_УСТАНОВКА - ДА <ВК> И ФАЙЛ - ДА И ФЛАГ - ДА <ВК> И СЛОВО - ПОДСКАЗКА И АТРИБУТ - ДА <ВК> И КОНЕЦ_СТРОКИ - ДА И ТЕКСТ - ДА <ВК> ТО ПРЕДЛОЖЕНИЕ - ПОДСКАЗКА И ЗАПИСЬ_П0ДСКАЗКИ - НЕТ <ВК> И ПЕЧАТЬ - НЕТ 2 ЕСЛИ НАЧ_УСТАНОВКА - ДА <ВК> И ФАЙЛ - ДА И СЛОВО - ПЕРЕВОД <ВК> И АТРИБУТ - ДА И КОНЕЦ_СТРОКИ - ДА <ВК> И ТЕКСТ - ДА ТО ПРЕДЛОЖЕНИЕ - ПЕРЕВОД <ВК> И ЗАПИСЬПЕРЕВОДА - НЕТ И ПЕЧАТЬ - НЕ Т_ПАРАМЕ ТРА 3 ЕСЛИ НАЧ_УСТАНОВКА - ДА <ВК> И ФАЙЛ - ДА ТО ПРЕДЛОЖЕНИЕ - ОШИБОЧНОЕ(ПО ПЕРВОМУ_СЛОВУ) ПЕРЕВОД ФАЙЛ <ВК> НАЗНАЧЕН ФАЙЛ ВВОДА ПЕРЕВОД СЛОВО <ВК> ПРЕДЛОЖЕНИЕ НАЧИНАЕТСЯ СО СЛОВА ПЕРЕВОД АТРИБУТ <ВК> ПРИСУТСТВУЕТ АТРИБУТ ПЕРЕВОД КОНЕЦ_СТРОКИ <ВК> НА ЭТОМ СТРОКА КОНЧАЕТСЯ ПЕРЕВОД ТЕКСТ <ВК> ИМЕЕТСЯ СТРОКА ТЕКСТА ПЕРЕВОД ПРЕДЛОЖЕНИЕ <ВК> ТИП ПРЕДЛОЖЕНИЯ ПАРАМЕТРЫ НАЧ_УСТАНОВКА <ВК> 3 INITIAL WORD NO ПАРАМЕТРЫ ФАЙЛ <ВК> 4 FILES WORD NO ПАРАМЕТРЫ СЛОВО <ВК> 5 PRISNAK WORD NO ПАРАМЕТРЫ АТРИБУТ <ВК> б ATR WORD NO ПАРАМЕТРЫ КОНЕЦ_СТРОКИ <ВК> 7 END_LINE WORD NO ПАРАМЕТРЫ ТЕКСТ <ВК> 8 READ_TEXT WORD NO ПАРАМЕТРЫ ЗАПИСЬ_П0ДСКАЗКИ <ВК> 9 WRITE_PROMPT WORD NO ПАРАМЕТРЫ ЗАПИСЬ_ПЕРЕВ0ДА <ВК> 10 WRITE_TRANS WORD NO ПАРАМЕТРЫ ПЕЧАТЬ <ВК> 11 PRINT_LIST WORD NO 4 ЕСЛИ ПРЕДЛОЖЕНИЕ - ПОДСКАЗКА <ВК> ТО ЯЗЫК - ЭКСПЕРТА 5 ЕСЛИ ПРЕДЛОЖЕНИЕ - ПЕРЕВОД <ВК> ТО' ЯЗЫК - ЭКСПЕРТА 6 ЕСЛИ СИНТ_АНАЛИЗ - ДА <ВК> ТО РАБОТА - ДА 7 ЕСЛИ ЯЗЫК - ЭКСПЕРТА <ВК> И КОНЕЦ - ДА ТО СИНТ_АНАЛИЗ - ДА 8 ЕСЛИ ЯЗЫК - ЭКСПЕРТА <ВК> И КОНЕЦ - НЕТ ТО СИНТ_АНАЛИЗ - НЕТ <ВК> И ВОЗВРАТ - ФЛАГ 9 ТО ФЛАГ - ДА ПЕРЕВОД КОНЕЦ <ВК> КОНЕЦ АНАЛИЗА ВОПРОС КОНЕЦ <ВК> КОНЧАТЬ АНАЛИЗ?(ДА/НЕТ) ПАРАМЕТРЫ ВОЗВРАТ <ВК> 2 RETFLAG WORD NO 214
Описание соответствующих глубинных знаний имеет вид CONST NSTRING=80; ТУРЕ STRING1=STRING[NSTRING]; STRING_PTR1=~STRING_REC1; STRING_RECl=RECORD INFOsSTRING!; NEXT_LINE s STRING_PTR1; END; ITEM_PTR1= ЛITEM1; ITEMl=RECORD NEXT:ITEM_PTR1; ATTR:WORD; PROMPT_PTR,TRANS_PTRs STRING_PTR1; END; VAR ATTR_LISTlsITEM_PTRl; INTsTEXT; CHlsWORD; ATTRlsWORD; LINEIs STRING1; PROCEDURE EVAL_PROC(NUMBER:INTEGER; PARsDOMEN; VAR VAL:WORD); PROCEDURE READWORD(VAR INPsTEXT; VAR AsWORD); VAR JS1..NWORD; CHsCHAR; BEGIN REPEAT READ(INP,CH); UNTIL CH<>' '; Js=l; A[J]:=CH; WHILE (A[J]<>' ') AND NOT(EOLN(INP)) AND(J<NWORD) DO BEGIN J:=J+1;READ(INP»A[J]); END; IF EOLN(INP) THEN A[0]:=CHR(J) ELSE A[0]s=CHR(J-l); END; PROCEDURE NAJT1(VAR NAJ:ITEM_PTR1; LIST:ITEM_PTR1; KLsWORD); BEGIN IF LIST“NIL THEN NAJ:="NIL ELSE IF KL=LIST~.ATTR THEN NAJ:=LIST ELSE NAJT1(NAJ,LIST~.NEXT,KL); END(*NAJT1*); PROCEDURE PUSH2(VAR LIST:ITEM_PTR1; ATTRsWORD); VAR Q:ITEM_PTR1; BEGIN NEW(Q); (Г . ATTR: =ATTR; Q-4 . PROMPT_PTR: =NIL; (Г .TRANS_PTR:=NIL; O'4. NEXT: “LIST; LIST:=Q; END(*PUSH2*); PROCEDURE INITIAL(VAR LIST:ITEM_PTR1);. BEGIN LIST:=NIL; END; PROCEDURE FILES(VAR CHsWORD; VAR INTsTEXT); BEGIN WRITE('ЗАДАЙТЕ ИМЯ ФАЙЛА С ИСХОДНЫМИ ДАННЫМИ '); READLN(CH); ASSIGN(JNT,CH); 'RESET(INT); <END(*FILES*); PROCEDURE PRISNAK(CHsWORD; VAR INTsTEXT; VAR VALsWORD)? 21
BEGIN IF CH-'CON' THEN WRIТЕ('ЗАДАЙТЕ ПРИЗНАК ')} READWORD(INT,VAL); END(*PRISNAK*); PROCEDURE PRISNAK1(CHsWORD; VAR INTsTEXT); VAR VALsWORD; BEGIN IF CH='CON' THEN WRITELN('РАБОТА ДОЛЖНА ИДТИ HE С ТЕРМИНАЛОМ'); READWORD(INT,VAL); WRITELN('ПРИЗНАК 's40,VAL); END(*PRISNAK1*); PROCEDURE ATR(CH:WORD; VAR INTsTEXT; VAR ATTRsWORD; VAR VALSWORD); BEGIN IF CH='CON' THEN BEGIN WRITE('ЗАДАЙТЕ АТРИБУТ '); READWORD(INT,ATTR); VAL:='HA'; END ELSE IF EOLN(INT) THEN VAL:='НЕТ' ELSE BEGIN VALs ='ДА'; READWORD(INT,ATTR); END; END(*ATR*); PROCEDURE END_LINE(CHsWORD; VAR INTsTEXT; VAR VALsWORD); BEGIN IF CH='CON' THEN BEGIN WRITE('ЗАДАЙТЕ КОНЕЦ СТРОКИ '); VAL;-'ДА'; END ELSE IF EOLN(INT) THEN VALs ='ДА' ELSE VALs ='НЕТ'; READLN(INT); END(*END_LINE*); PROCEDURE READ_TEXT(CHsWORD; VAR INTsTEXT; VAR LINEsSTRING1; VAR VALsWORD); BEGIN IF CH-'CON' THEN BEGIN WRITELN('ЗАДАЙТЕ ТЕКСТ'); READLN(INT,LINE) VAL S ='ДА'; END ELSE IF EOLN(INT) THEN VAL s ='НЕТ' ELSE BEGIN VAL;-'ДА'; READLN(INT,LINE); END; END(*READ_TEXT*); PROCEDURE WRITE_PROMPT(ATTRsWORD; LINEsSTRING1; VAR LIST;ITEM_PTR1); VAR PTRsITEM_PTR1; PsSTRING_PTRI; ' BEGIN NEW(P); PA.INFOS-LINE; NAJTI(PTR,LIST,ATTR); IF PTR-NIL THEN BEGIN PUSH2(LIST,ATTR); PTRs-LIST; END; PTR-4 . PROMPT_PTR s =P ; END(*WRITE_PROMPT*); PROCEDURE WRITETRANS(ATTRsWORD? LINEsSTRING1; VAR LIST sITEM_PTR1); VAR PTRsITEM_PTRl; PsSTRING_PTRl; ^ 216
BEGIN NEW(P); Рл.INFO:=LINE; NAJTl(PTR,LIST,ATTR); IF PTR=NIL THEN BEGIN PUSH2(LIST,ATTR); PTR:=LIST; END; PTR^.TRANS_PTR:=P; END(*WRITE_TRANS*); PROCEDURE PRINT_LIST(P:ITEM_PTRI)} BEGIN IF PoNIL THEN WITH Рл DO BEGIN WRITELN('АТРИБУТ:',ATTR); WRITELN('ПОДСКАЗКА:'); IF PROMPT_PTR<>NIL THEN WRITELN(PROMPT_PTR~.INFO); WRITELN('ПЕРЕВОД:'); IF TRANS_PTR<>NIL THEN WRITELN(TRANS_PTR'* . INFO) ; PRINT_LIST(P~.NEXT); END; END(*PRINT_LIST*); BEGIN(*EVAL_PROC *) WINDOW(3,3,77,14); VAL:='ДА'; CASE NUMBER OF 3:INITIAL(ATTR_LIST1); 4:BEGIN CLRSCR; FILES(CHI,INT); END; 5:BEGIN CLRSCR; PRISNAK(CH1,INT,VAL); END; 6:BEGIN CLRSCR; ATR(CH1,INT,ATTRl,VAL); END; 7:BEGIN CLRSCR; END_LINE(CH1,INT,VAL); END; 8:BEGIN CLRSCR; READ_TEXT(CH1,INT,LINE1,VAL); END; 9:WRITE_PROMPT(ATTR1,LINE1,ATTR_LIST1); 10:WRITE_TRANS(ATTR1,LINE1,ATTR_LIST1); 11:BEGIN CLRSCR; PRINT_LIST(ATTR_LIST1); END; 12:BEGIN CLRSCR; PRISNAK1(CH1,INT); END; END(*CASE*); WINDOW(3,17,77,24); CLRSCR; END(* EVAL_PROC *); Перед описанием процедур приведено описание используе¬ мых структур данных, составляющих «доску объявлений». Эта задача для интерпретации одного предложения уже описыва¬ лась в п. 5.1. Исходные данные для рассматриваемой про¬ граммы, т. е. предложения типов «подсказка» и «перевод» для конкретной предметной области, могут задаваться пользовате¬ лем с терминала или браться из какого-либо файла, например III. TXT, содержимое которого может иметь вид ПЕРЕВОД ФАЙЛ НАЗНАЧЕН ФАЙЛ ВВОДА ПОДСКАЗКА КОНЕЦ КОНЧАТЬ АНАЛИЗ ПЕРЕВОД КОНЕЦ КОНЕЦ АНАЛИЗА ПОДСКАЗКА ФАЙЛ ФАЙЛ ДАННЫХ 217
Если пользователь будет задавать исходные данные с тер минала, то по запросу системы «задайте имя файла с исход ными данными» для машин IBM PC надо ответить CON, что является признаком терминала. При задании цели РАБОТА пользователь сможет провести интерпретацию нескольких пред ложений. Конец анализа задается пользователем. При задании цели ПРЕДЛОЖЕНИЕ или ЯЗЫК будет проводиться анализ одного предложения. В конце работы на «доске объявлений» будет распечатан список атрибутов, содержащий введенные подсказки и переводы для введенных атрибутов. Напомним (см. рис. 5.2), что при описании правил в части ТО после атрибута и его значения в следующих строках ни месте атрибута записывается имя процедуры, а на месте зна чения атрибута записывается параметр процедуры, при отсут ствии которого можно писать любое синтаксически правильное слово, в частности, в программе используется слово НЕТ. Читателю предлагается в качестве упражнения изменить синтаксис части ТО правила на тот, который ему больше нра вится. Например, имена процедур могут записываться чере запятую, а если процедура должна использовать параметры, то они могут быть указаны в скобках. Реализация этих измг нений уже не должна вызывать затруднений. Ниже приведена третья программа интерпретации предло жений типа «подсказка» или «перевод», соответствующая третьей программе из п. 5.1 (см. стр. 219). В качестве глубинных знаний используются знания для вто рой программы. Работа третьей программы имеет смысл при вводе исходных данных из внешнего файла. Отличие этой про граммы от второй программы фактически заключено в опредг лении значения атрибута СЛОВО в правилах. Во второй про грамме значение атрибута СЛОВО определялось с помощью процедуры PRISNAK, которая вводила первое слово интерпрс тируемого предложения (ПОДСКАЗКА или ПЕРЕВОД) и вы давала его в качестве своего выходного параметра VAL, зил чение которого записывалось далее в стек фактов (процедуром GET—ANSWER). В третьей программе значение атрибут.! СЛОВО определяется с помощью процедуры PRISNAK1, кото рая вводит первое слово интерпретируемого предложения м выдает его на экран дисплея в качестве сообщения пользовл телю. В качестве значения атрибута СЛОВО в стек фактов за писывается слово ДА. Значение первого слова интерпретируй мого предложения задается системе пользователем в ответ пь вопрос, соответствующий атрибуту ПОДСКАЗКА или ПЕР1 ВОД. Следует отметить, что в рассмотренном случае пользовл тель обрабатывает ответ процедуры в противоположность выше приведенному режиму обучения, при котором процедура обрабл тывает ответ пользователя. В режиме обучения фрейм одной* 218
1 ТО НАЧАЛО - ДА И НАЧ_УСТАНОВКА - НЕТ <ВК> И ФАЙЛ - НЕТ 2 ЕСЛИ НАЧАЛО - ДА <ВК> И ФЛАГ - ДА <ВК> И СЛОВО - ДА И ПОДСКАЗКА - ДА <ВК> И АТРИБУТ - ДА И КОНЕЦ_СТРОКИ - ДА <ВК> И ТЕКСТ - ДА ТО ПРЕДЛОЖЕНИЕ - ПОДСКАЗКА И ЗАПИСЬ_П0ДСКАЗКИ - НЕТ <ВК> И ПЕЧАТЬ - НЕТ 3 ЕСЛИ НАЧАЛО - ДА <ВК> И СЛОВО - ДА И ПОДСКАЗКА - НЕТ <ВК> И ПЕРЕВОД - ДА И АТРИБУТ - ДА <ВК> И КОНЕЦ_СТРОКИ - ДА И ТЕКСТ - ДА ТО ПРЕДЛОЖЕНИЕ - ПЕРЕВОД <ВК> И ЗАПИСЬ_ПЕРЕВ0ДА - НЕТ И ПЕЧАТЬ - НЕТ 4 ЕСЛИ НАЧАЛО - ДА <ВК> И СЛОВО - ДА И ПЕРЕВОД - НЕТ ТО ПРЕДЛОЖЕНИЕ - ОШИБОЧНОЕ ПЕРЕВОД ФАЙЛ <ВК> НАЗНАЧЕН ФАЙЛ ВВОДА ПЕРЕВОД СЛОВО <ВК> ПРЕДЛОЖЕНИЕ НАЧИНАЕТСЯ СО СЛОВА ПЕРЕВОД АТРИБУТ <ВК> ПРИСУТСТВУЕТ АТРИБУТ ПЕРЕВОД КОНЕЦ_СТРОКИ <ВК> НА ЭТОМ СТРОКА КОНЧАЕТСЯ ПЕРЕВОД ТЕКСТ <ВК> ИМЕЕТСЯ СТРОКА ТЕКСТА ПЕРЕВОД ПРЕДЛОЖЕНИЕ <ВК> ТИП ПРЕДЛОЖЕНИЯ ПАРАМЕТРЫ НАЧ_УСТАНОВКА <ВК> 3 INITIAL WORD NO ПАРАМЕТРЫ ФАЙЛ <ВК> 4 FILES WORD NO ПАРАМЕТРЫ СЛОВО <ВК> 12 PRISNAK1 WORD YES ПАРАМЕТРЫ АТРИБУТ <ВК> б ATR WORD YES ПАРАМЕТРЫ КОНЕЦ_СТРОКИ <ВК> 7 END_LINE WORD YES ПАРАМЕТРЫ ТЕКСТ <ВК> 8 READJTEXT WORD YES ПАРАМЕТРЫ 3АПИСЬ_П0ДСКАЗКИ <ВК> 9 WRITE_PROMPT WORD NO ПАРАМЕТРЫ ЗАПИСЬ_ПЕРЕВ0ДА <ВК> 10 WRITEJTRANS WORD NO ПАРАМЕТРЫ ПЕЧАТЬ <ВК> 11 PRINT_LIST WORD NO 5 ЕСЛИ ПРЕДЛОЖЕНИЕ - ПОДСКАЗКА <ВК> ТО ЯЗЫК - ЭКСПЕРТА 6 ЕСЛИ ПРЕДЛОЖЕНИЕ - ПЕРЕВОД <ВК> ТО ЯЗЫК - ЭКСПЕРТА 7 ЕСЛИ СИНТ_АНАЛИЗ - ДА <ВК> ТО РАБОТА - ДА 8 ЕСЛИ ЯЗЫК - ЭКСПЕРТА <ВК> И КОНЕЦ - ДА ТО СИНТ_АНАЛИЗ - ДА 9 ЕСЛИ ЯЗЫК - ЭКСПЕРТА <ВК> И КОНЕЦ - НЕТ ТО СИНТ_АНАЛИЗ - НЕТ <ВК> И ВОЗВРАТ - ФЛАГ 10 ТО ФЛАГ - ДА ПЕРЕВОД КОНЕЦ <ВК> КОНЕЦ АНАЛИЗА ВОПРОС КОНЕЦ <ВК> КОНЧАТЬ АНАЛИЗ?(ДА/НЕТ) ПАРАМЕТРЫ ВОЗВРАТ <ВК> 2 RETFLAG WORD NO ВОПРОС ПОДСКАЗКА ПРЕДЛОЖЕНИЕ НАЧИНАЕТСЯ СО СЛОВА ПОДСКАЗКА?(ДА/НЕТ) ВОПРОС ПЕРЕВОД ПРЕДЛОЖЕНИЕ НАЧИНАЕТСЯ СО СЛОВА ПЕРЕВОД/(ДА/НЕТ) атрибута определял и вопрос пользователю и имя проверяю¬ щей процедуры. В рассмотренном же случае имя процедуры задается во фрейме одного атрибута, а вопрос задается во фрейме второго атрибута. Можно их объединить в одном фрейме, но тогда придется задать еще один параметр во 219
фрейме атрибута, в котором должно определяться кто кого об рабатывает: либо процедура — ответ пользователя, либо поль¬ зователь — ответ процедуры. В заключение отметим, что, как видно из описания про¬ цедуры GET-ANSWER, при пустом поле вопроса, т. е. при вир¬ туальном диалоге, значения параметров, определяющих значе¬ ния признака типа ответа и признака типа записи ответа, в связи с отсутствием ответа безразличны, но должны быть син¬ таксически правильными. Как уже отмечалось, программу ин¬ терпретации предложений языка абстрактного эксперта с парал¬ лельным созданием списков, записанную на языке эксперта, можно рассматривать как один из вариантов реализации блока преобразования знаний из внешней формы представления во внутреннюю. Эта задача в п. 2.3 решалась с помощью про¬ цедуры КОМПИЛЯЦИЯ, которую можно рассматривать как пример результата компиляции знаний, представленных в про¬ дукционной форме, в процедурную форму, т. е. более эффектив¬ ную, но менее удобную для коррекции и для организации объяс¬ нений форму представления знаний. Очевидно, что аналогично могут быть реализованы и дру¬ гие блоки ЭС: блок логического вывода и блок объяснений. Один из возможных вариантов реализации блока логиче¬ ского вывода на языке эксперта приведен ниже: Г 1 ЕСЛИ ЗНАНИЯ - ВВЕДЕНЫ И БАЗА_ДАННЫХ - ОЧИЩЕНА И ЦЕЛЬ - ЗАДАНА И ВЫВОД - ДА ТО ЗАПРОС - ДА И ПЕЧАТЬ_ЗНАЧЕНИЯ_ЦЕЛИ - ДА 2 ЕСЛИ ВЫВОД - НЕТ ТО ЗАПРОС - ДА И ПЕЧАТЬ_СООБЩЕНИЯ - ДА 3 ЕСЛИ ФЛАГ - ДА И ПОДЦЕЛЬ_ВЫБРАНА - ДА И ПОДЦЕЛЬ - ОБРАБОТАНА ТО ВЫВОД - НЕОПРЕДЕЛЕН И ВОЗВРАТ - ФЛАГ 4 ЕСЛИ ПОДЦЕЛЬ_ВЫБРАНА - НЕТ ТО ВЫВОД - ДА 5 ЕСЛИ ПОДЦЕЛЬ - НЕОБРАБОТАНА ТО ВЫВОД - НЕТ 6 ЕСЛИ ПРАВИЛО_НАЙДЕНО - ДА И ПРАВИЛО - ОБРАБОТАНО ТО ПОДЦЕЛЬ - ОБРАБОТАНА 7 ЕСЛИ ПРАВИЛО_НАЙДЕНО - НЕТ И ПРОЦЕДУРА_НАЙДЕНА - ДА И ПРОЦЕДУРА - ОБРАБОТАНА ТО ПОДЦЕЛЬ - ОБРАБОТАНА 8 ЕСЛИ ПРОЦЕДУРА_НАЙДЕНА - НЕТ И ПОДСКАЗКА - НАЙДЕНА И ОТВЕТ - ПОЛУЧЕН ТО ПОДЦЕЛЬ - ОБРАБОТАНА 9 ЕСЛИ ПОДСКАЗКА - НЕНАЙДЕНА ТО ПОДЦЕЛЬ - НЕОБРАБОТАНА 10 ЕСЛИ ЗНАЧЕНИЕ_ПРАВИЛА - ИСТИНА И ФАКТ - ЗАПИСАН ТО ПРАВИЛО - ОБРАБОТАНО 11 ЕСЛИ ЗНАЧЕНИЕПРАВИЛА - ЛОЖНО И ЗАПРЕТ_ПРАВИЛА - ПРОВЕДЕН ТО ПРАВИЛО - ОБРАБОТАНО 12 ЕСЛИ ЗНАЧЕНИЕПРАВИЛА - НЕОПРЕДЕЛЕНО И ПОДЦЕЛЬ_ЗАПИСАНА - ДА ТО ПРАВИЛО - ОБРАБОТАНО 13 ТО ФЛАГ - ДА 220
Основной целью в этом примере является атрибут ЗАПРОС. Атрибуты, значения которых не определяются с помощью при¬ веденных правил, определяются соответствующими процеду¬ рами, действия которых поясняются названиями процедур и значений атрибутов. Так, например, значение атрибута ЗНА¬ НИЯ определяется процедурой КОМПИЛЯЦИЯ. Очевидно, что значение атрибута ЗНАНИЯ может быть определено и с помощью правил, как указывалось в программе интерпрета¬ ции предложений языка эксперта. Следует отметить, что запись процесса вывода на языке эксперта приближается к описанию этого процесса на естест¬ венном языке. Читателю предлагается в качестве упражнения дать описа¬ ние соответствующих глубинных знаний, используя приведен¬ ные выше процедурные реализации блока логического вывода (см. п. 2.4). В приведенной реализации блока логического вывода пред¬ полагается, что значение атрибута ОТВЕТ получается с по¬ мощью процедуры ПОЛУЧИТЬ_ОТВЕТ. Но очевидно, что зна¬ чение этого атрибута может быть получено и с помощью пра¬ вил продукций. Для этого нужно записать реализацию блока объяснений на языке эксперта (см. стр. 222). Сообщения, используемые в приведенной программе, имеют следующие значения: 1 — Вы этого хотели сами; 2 — фраза обосновывалась процедурой <имя процедуры>; 3 — фраза обосновывалась пользователем; 4 — было использовано правило <правило>; 5—может будет использоваться правило <правило>; 6 — будет использована процедура <имя процедуры>; 7 — значение атрибута может определить только пользова¬ тель. Соответствующие глубинные знания легко формируются из приведенной выше процедурной реализации блока объяснений (см. п. 2.5). Итак, мы получили новый уровень инструментальной ЭС, все блоки которой могут быть описаны на языке эксперта, функции транслятора с которого исполняет базовая инструмен¬ тальная ЭС. Используя блок объяснений базовой ЭС, разра¬ ботчик программ, описывающих процесс логического вывода и процесс объяснений на языке эксперта, может их легко отла¬ дить, а пользователь этих блоков может их изучить. Применяя различные варианты задания атрибутов, можно создать различ¬ ные АОС, позволяющие изучать функционирование ЭС в раз¬ личных режимах. Описание процессов функционирования раз¬ личных блоков ЭС на языке эксперта позволяет легко изме¬ нять эти процессы. Меняя содержимое блока объяснений, мо- 221
14 ЕСЛИ РЕЖИМ - ОТВЕТ И ВВ0Д_И_ЗАП0МИНАНИЕ_0ТВЕТА - ПРОВЕДЕНЫ ТО ОТВЕТ - ПОЛУЧЕН 15 ЕСЛИ РЕЖИМ - ОБЪЯСНЕНИЯ И ВОПРОСЫ - ОТСУТСТВУЮТ И ВВ0Д_И_ЗАП0МИНАНИЕ_0ТВЕТА - ПРОВЕДЕНЫ ТО ОТВЕТ - ПОЛУЧЕН 16 ЕСЛИ ФЛАГ1 - ДА И ВОПРОС - ПОЧЕМУ И ПОЧЕМУ - ОБРАБОТАН ТО ВОПРОСЫ - МОГУТ_БЫТЬ И ВОЗВРАТ - ФЛАГ1 17 ЕСЛИ ВОПРОС - КАК И КАК - ОБРАБОТАН ТО ВОПРОСЫ - МОГУТ_БЫТЬ И ВОЗВРАТ - ФЛАГ1 18 ЕСЛИ ВОПРОС - НЕТ ТО ВОПРОСЫ - ОТСУТСТВУЮТ 19 ЕСЛИ ВОПРОС - ПОЧЕМУ И СТЕК_ЦЕЛЕЙ - ПУСТ ТО ПОЧЕМУ - ОБРАБОТАН И СООБЩЕНИЕ - 1 20 ЕСЛИ ВОПРОС - ПОЧЕМУ И СТЕК_ЦЕЛЕЙ - НЕПУСТ И ПЕЧАТЬ_ПРАВИЛА - ПРОВЕДЕНА ТО ПОЧЕМУ - ОБРАБОТАН 21 ЕСЛИ ВОПРОС - КАК И АТРИБУТ - ЗАДАН И АТРИБУТ_ФАКТ -ДА И ПОЯСНЕНИЯ - ДАНЫ ТО КАК - ОБРАБОТАН 22 ЕСЛИ НОМЕР_ПРАВИЛА - <0 ТО ПОЯСНЕНИЯ - ДАНЫ И СООБЩЕНИЕ - 2 23 ЕСЛИ НОМЕР_ПРАВИЛА - =0 ТО ПОЯСНЕНИЯ - ДАНЫ И СООБЩЕНИЕ - 3 24 ЕСЛИ НОМЕР_ПРАВИЛА - >0 ТО ПОЯСНЕНИЯ - ДАНЫ И СООБЩЕНИЕ - 4 25 ЕСЛИ ВОПРОС - КАК И АТРИБУТ - ЗАДАН И АТРИБУТ_ФАКТ - НЕТ И СООТВЕТСТВУЮЩЕЕ_ПРАВИЛО - НАЙДЕНО ТО КАК - ОБРАБОТАН И СООБЩЕНИЕ - 5 26 ЕСЛИ ВОПРОС - КАК И АТРИБУТ - ЗАДАН И АТРИБУТ_ФАКТ - НЕТ И СООТВЕТСТВУЮЩЕЕ_ПРАВИЛО - НЕНАЙДЕНО И СООТВЕТСТВУЮЩАЯ_ПРОЦЕДУРА - НАЙДЕНА ТО КАК - ОБРАБОТАН И СООБЩЕНИЕ - 6 '27 ЕСЛИ ВОПРОС - КАК ТО КАК - ОБРАБОТАН И СООБЩЕНИЕ - 7 28 ТО ФЛАГ1 - ДА жно получить различные системы объяснений (отладки) про¬ грамм, записанных на языке эксперта. В заключение можно отметить, что автором была проведена реализация экспертной системы для решения задачи интерпре¬ тации, т. е. построения описаний ситуаций по наблюдаемым данным для различных предметных областей. Интерпретирую¬ щая система объясняет наблюдаемые данные, приписывая им символьный смысл, описывающий ситуацию или состояние си¬ стемы, обусловливающие эти данные. 222
Экспертная система была реализована при следующих ог¬ раничениях: 1) данные и знания должны быть надежными; 2) данные и знания должны быть неизменными; 3) простран¬ ство возможных решений должно быть небольшим. Первое требование состоит в том, чтобы данные и знания не содержали ошибки и не были «зашумлены». Под ошибкой в нашем случае можно понимать семантически неправильный ответ, а под «зашумлением» — орфографические ошибки при ответе. Помимо надежности данных необходима надежность знаний. Применяя надежные знания, не приходится заботиться об их согласованности или корректности. Систематическое при¬ менение надежных знаний не может привести к ложным, при¬ близительным или условным заключениям. Главным преиму¬ ществом использования надежных данных и надежных знаний является монотонность системы. В системе с простейшей струк¬ турой (гл. 2—4) память представляет собой монотонную базу данных, к которой заключения просто добавляются по мере их получения в системе вывода. Нет необходимости предусматри¬ вать средства для удаления фактов при получении новой ин¬ формации. Достаточно построить одну линию рассуждения, т. е. не возникает необходимости в поиске многих аргументов, подтверждающих потенциальные заключения. Если в какой-то момент применимы сразу несколько правил вывода, то поря¬ док их применения не имеет значения. Второе требование позволяет избежать работы с данными, зависящими от времени. Это значит, что нет необходимости за¬ ботиться о том, что с ходом времени факты могут измениться. Требование небольшого размера пространства поиска озна¬ чает, что не нужно предпринимать заранее каких-либо мер для учета ограниченности вычислительных ресурсов. Проведенная реализация экспертной системы базировалась на вычислительном формализме, известном под названием «си¬ стема продукций». При реализации были применены поиск ре¬ шения (при использовании представления задачи в простран¬ стве состояний) и логический вывод (при использовании ис¬ числения предикатов). Как было показано, реализованная экспертная система при¬ меняется как для решения задачи интерпретации, так и для решения задачи диагностики. Диагностика — это процесс по¬ иска неисправности в системе (или определение стадии «забо¬ левания» в «живой» системе), основанной на интерпретации данных. Кроме задач диагностики на решении задач интерпре¬ тации базируется также и класс задач мониторинга, т. е. срав¬ нения наблюдений с критическими точками плана. Мониторинг означает непрерывную интерпретацию сигналов и выдачу опо¬ вещений при возникновении ситуаций, требующих вмешатель¬ ства. Система мониторинга является частью диагностической 223
системы, работающей при условаи^ что расвнанаше. крлтя ческих ситуаций осуществляется - .в рдо ^жт*-***. вре мени. Реализованная в экспертной системе.дешшжность ис¬ пользования процедур позволяет проводить ставнику системы с различными внешними устройствами, контролирующими ход различных процессов. Возможность организации циклов позво¬ ляет контролировать изменяющиеся данные. Экспертная система реализована как -инструментальная, т. е. позволяющая производить смену наполнения базы знаний. Для этого разработан и реализован язык эксперта. Анализ ра¬ боты системы проводился при использовании знаний из двух различных предметных областей: из области ботаники и из области лингвистики. Использование в качестве примеров ре¬ шения задачи интерпретации интерпретации предложений языка эксперта и языка пользователя, как представляется, спо¬ собствует лучшему пониманию принципов работы экспертной системы. Кроме того, использование в качестве примеров ин¬ терпретации этих предложений позволило наиболее естественно показать необходимость организации циклов на языке эксперта и использования имен процедур в качестве атрибутов предло жений того же языка. Таким образом, было продемонстриро¬ вано эволюционное развитие экспертных систем, переходящих от решения простых задач ко всё более сложным. Реализация системы проводилась с помощью языков раз¬ личных классов, использующих различные структуры данных, действия и управляющие структуры. Использование при реа¬ лизации логического вывода на языках Паскаль и ЛИСП об ратного вывода с поиском по образцу в глубину с возвратом должно облегчить читателю понимание программ на языке Пролог, так как его управляющая структура базируется на этой же стратегии вывода. Можно выразить надежду, что в результате прочтения книги читатель смог составить пред¬ ставление об этих языках и сможет проводить обоснованный выбор языка программирования для решения своих конкрет¬ ных задач при конкретных ограничениях. Что касается направ лений дальнейших разработок реализованной экспертной си¬ стемы, то некоторые из них были представлены в заключитель ных параграфах гл. 2—4. 224
ПРИЛОЖЕНИЕ 1 СИНТАКСИЧЕСКИЕ ДИАГРАММЫ ЯЗЫКА ПАСКАЛЬ Целое дез знака I -( Цифра > ) Рис. П.1.2 Рис. П.1.3 Константа 5ез знака ^— ч 4*0—С^Р— Рис. П.1.4 Константный идентификатор [ Число дез знака 15 В. Э. Валтрашевнч 225
Рис. 17.1.6 Рис. П.1.7 226
Выражение 4Простое выражение] [Простое выражен и е\—' Рис. ПАЛО 16* Рис. П.1.11 227
Простой тип ——— Идентификатор типа —7—Ч Идентификатор | ^ с ■о J | Констант\ -^) •^Константс1\ Рис. П.1.12 Тип ^ _ ,/Г\ „ Идентификатор 1 ^ л типа Простой тип [- ^{jiaclteAj-— *— <-( array >»(Г)-Н <file ) »( set ) Ф- Простой тип :ун°о —»j Тип Тип -0— *\ Простой тип | ^ *(j:scor(f) -j Список попей | ^ endy~ Рис. ПЛАЗ Список попей ■ф- ч" тазе ^у*\идентисринатор\^^У*\ т G>— ^Идентификатору 1 ■€ИЕ Т Идентификатор >Оч типа м; Константа -1— 4D-CK Список по пей| •Ч2У 228 Рис. П.1.14
Оператор Целое fed знака Ь9 *\ Переменная 1Ь-®—ч Выражение Идентификатор функции Идентификатор Ж(Т\ процедуры <•> Выражение Идентификатор процедуры г -~(beyiny Т~ L. Оператор О *(етьЛу- Оператор -^^elsey*- Оператор|-> Выражение Константа —'у^ Оператор <—*(whitey-*- Выражение ——■» Оператор ^^(repeaty- -о- Переменная С* Выражение Оператор +(do) ^Оператор »(goto у Целое fe3 знака Рис. ПА .15 229
<ЕН!> ■—©* on sty—Идентификатор | +£=)—~^Константа <*(type)—-у^Йдентиср и кат ор I -{Целое без знакаf ^—(уаг )—^-*{И8енти<рила/лор\-~у^(Т)—т- Тип~\- О- ' ФН1 Ф блок ф '^(procedurey+tfl дентификатор |—^Список параметроВ\- ^ЛГГN _ {ИдентисриА .1 Список _ /т\ _ Идентификатор '*+\FuncV-b07ij-*‘ кат0р параметров ч2/ типа '^^ерьпУ--г~\Оператор [- —о— Рис. П.1.16 Программа (^™Ня™ГГ Н=НР ■о Рис. П.1.17 230
ПРИЛОЖЕНИЕ 2 PROCEDURE IES; (^ИНСТРУМЕНТАЛЬНАЯ ЭС*) CONST NSTRING=80; NRULE=140; (*ЧИСЛО ПРАВИЛ*) NERR=20; (*ЧИСЛО ФИКСИРУЕМЫХ ОШИБОК*) TYPE STRING1 = STRING [NSTRING]; COUNTER=—1 .. NRULE; STRING_PTR=f STRING-REC; STRING-REC= RECORD INFO : STRING1; NEXT-LINE : STRING-PTR; END; I TEM_PTR=f I ТЕМ; I TEM= RECORD NEXT : I TEM-PTR; ATTR : WORD; CASE KINDI : BOOLEAN OF TRUE : (VAL : WORD; RULE-NO : COUNTER); FALSE: (QUEST PTR, ANSWER-PTR, TRANS-PTR : STRING-PTR; NAME-PROC : WORD; NUMBER : INTEGER; KIND: TIPS; SIGN : BOOLEAN); END; TABLE_RULE = ARRAYfCOUNTER, 1 .. 2] OF I TEM-PTR; EROR= ARRAY[O .. NERR] OF RECORD TXT: STRING1; I : INTEGER; END; VAR MAS-RULE : TABLE-RULE; FREE, ATTR_LIST : I TEM-PTR; INP : TEXT; I : COUNTER; ERROR : BOOLEAN; CH:WORD; ERR : EROR; PROCEDURE RETFLAG(VAL: WORD; VAR VALl:WORD); (*ГАШЕНИЕ СТЕКА ФАКТОВ ДО VAL ВКЛЮЧИТЕЛЬНО*) VAR I : INTEGER; BEGIN VAL1 : = VAL; REPEAT POP (FAST-LIST, FREE); UNTIL (FACT_LIST=NIL) OR (FACT_LISTf.ATTR = VAL); IF F ACT-LISTf. ATTR = VAL THEN POP (FAST-LIST, FREE); FOR I : = 1 TO NRULE DO ACTIVE-RULE [I] : = TRUE; END (*RETFLAG*); PROCEDURE ERRPRINT (ERR: EROR); (*ПЕЧАТЬ СООБЩЕНИЯ ОБ ОШИБКАХ*) VAR SUM : INTEGER; 1:0.. NERR; CH : CHAR; NOTE : REAL; BEGIN WRITELN(‘РЕЗУЛЬТАТЫ РАБОТЫ’); SUM: = 0; FOR I : = 1 TO NERR DO SUM: = SUM+ERR[1].I; WRITELN (‘ЧИСЛО ПОДСКАЗОК’, ERR[0].I); WRITELN (‘ОБЩЕЕ ЧИСЛО ОШИБОК’, SUM); 231
REPEAT WRITE (‘ВАС ИНТЕРЕСУЕТ БОЛЕЕ ПОДРОБНАЯ’. ‘ИНФОРМАЦИЯ? [ДА/НЕТ] ’); READLN (СН); UNTIL СН IN [‘Д\ ‘Н']; IF СН=‘Д’ THEN FOR I: — 1 ТО NERR DO IF ERR[I]Л>0 THEN WRITELN(ERR[I].TXT : 50, ERR[I]T : 5); WRITE (‘ОЦЕНИТЕ СВОЮ ДЕЯТЕЛЬНОСТЬ [2 .. 5]=’); READLN (NOTE) ; WRITELN(‘ПУСТЬ ЭТА ОЦЕНКА БУДЕТ НА ВАШЕЙ СОВЕСТИ’); END (*ERRPRINT*); PROCEDURE GET_ANSWER(PTR : I TEM-PTR; VAR FACT-LIST, GOAL-LIST: I TEM-PTR; VAR ERR: EROR); (*ПОЛУЧЕНИЕ ОТВЕТА ОТ ПОЛЬЗОВАТЕЛЯ*) VAR VALUE : WORD; NUMB : INTEGER; ANSWER : DOMEN; PROCEDURE QUESTION(PTR : I TEM-PTR; VAR ERR : EROR); (^ВОПРОС*) VAR CH : WORD; BEGIN WRITELN (‘ВОПРОС : ’); WRITELN (PTRf.QUEST-PTRfJNEO); REPEAT WRITELN (‘ЕСЛИ БУДЕТЕ ОТВЕЧАТЬ, TO ВВЕДИТЕ <BK>’); WRITELN (‘ЕСЛИ НУЖНА ПОДСКАЗКА, ТО ВВЕДИТЕ Н’); WRITE (‘ЕСЛИ БУДЕТЕ СПРАШИВАТЬ’, ‘[ПОЧЕМУ, КАК], ТО ВВЕДИТЕ ?’); READLN (СН); IF СН=‘Н’ THEN REPEAT ERR[0]Л : - ERR[0] Л+1; WRITE (PTRf.QUEST-PTR f TNFO); IF PTRf.ANSWER-PTR < > NIL THEN WRITELN(PTRf.ANSWER-PTRflNFO) ELSE WRITELN (‘НА ЭТОТ ВОПРОС ПОДСКАЗКИ НЕТ’); WRITE ('ПОНЯТНО [ДА/НЕТ]’); READLN (СН); UNTIL СН < > ‘НЕТ; ELSE IF СН = ‘?’ THEN EXPLANATION(WHY-PTR); UNTIL NOT(CH=‘H’) OR (SH=‘?’)); WRITELN (‘ВОПРОС;’); WRITELN (PTRf.QUEST_PTRf .INFO); END (^QUESTION*); PROCEDURE VERIFY(PTR : I TEM-PTR; VAR ANSWER : DOMEN; VAR ERR: EROR); (^ПРОВЕРКА*) CONST С1='ОТВЕЧАИТЕ’; VAR P : BOOLEAN; SH : CHAR; VAL : WORD; BEGIN P : = FALSE; ANSWER.KIND : = PTRf.KIND; 232
WHILE NOT (P) DO BEGIN CASE PTRf .KIND OF INTEG: BEGIN WRITE(C1, ‘(INTEGER) =’); READLN (ANSWER.DI); END; REL : BEGIN WRITE(C1, <(REAL) = ’); READLN (ANSWER.DR); END; WRD-.BEGIN WRITE(C1, ‘(WORD)=’); READLN (ANSWER.DW); END; END; CASE PTRf.NUMBER OF 1: BEGIN CLRSCR; VAL : - ‘ДА’; ERRPRINT(ERR); END; 2 : RETFLAG (ANSWER.DW, VAL) ; ELSE EVAL_PROC(PTR.NUMBER, ANSWER, VAL); END; p : = VAL = ‘ДА’; (*ПРИ ПРАВИЛЬНОМ ОТВЕТЕ ПРОЦЕДУРЫ ВЫДАЮТ ДА*) IF Р THEN WRITELN(‘M0 Л ОД ЧИН А’) ELSE BEGIN REPEAT WRITE (‘ВЫ ЗНАЕТЕ КАК ОТВЕЧАТЬ [ДА/НЕТ]’); READLN (СН); UNTIL СН IN [‘Д\ ‘Н’1; IF СН = ‘Д’ THEN WRITELN (‘ТОГДА ДУМАЙТЕ О РАБОТЕ, А НЕ О...’) ELSE BEGIN WRITELN (PTRf .QUEST-JPTRf.INFO, PTRf .ANSWER.PTRf.INFO); ERR [PTRf.NUMBER] Л : = ERR [PTRf.NUMBER].I + 1; END; QUESTION(PTR, ERR); END; END; END (^VERIFY*); BEGIN (*GET-ANSWER*) IF PTRf.QUEST-PTR-NIL THEN BEGIN ANSWER.KIND : = WRD; ANSWER.DW : = GOAL-LISTf.VAL; NUMB : «= —1; CASE PTRf .NUMBER OF 1: BEGIN CLRSCR; EGGPRINT(ERR); END; 2 : RETFLAG (ANSWER.DW, VALUE) ; ELSE EVAL^PROC(PTR.NUMBER, ANSWER, VALUE); END(*CASE*); 233
END ELSE BEGIN QUESTION(PTR, ERR); IF PTRf .NAME-P ROC = ‘НЕТ’ THEN BEGIN WRITE (‘ОТВЕЧАЙТЕ (WORD) =’); READLN(VALUE); NUMB : = 0; END ELSE BEGIN VERIFY(PTR, ANSWER, ERR); IF PTRf.SIGN THEN VALUE : = ANSWER.DW ELSE VALUE : = ‘ДА’; NUMB : = 0; END; END; PUSH (FACT-LIST, FREE, GOAL-LISTfATTR, VALUE, NUMB); POP (GOAL-LIST, FREE); IF GOAL_LIST=NIL THEN DONE : = TRUE; END (*GET_ANSWER1*); BEGIN (*IES*) CLRSCR; FRAMEWINDOW(2, 2, 78, 15, 27, 40, ‘ПРЕДМЕТНАЯ ОБЛАСТЬ’); FRAMEWINDOW(2, 16, 78, 25, 27, 40, ‘ДИАЛОГ’); WINDOW(3, 17, 77, 24); FOR I: = 1 TO NRULE DO BEGIN MAS-RULE [I, 1] : = NIL; MAS_RULE[I, 2] ; = NIL; END; ATTR-LIST; = NIL; FREE : = NIL; WRITE (‘ЗАДАЙТЕ ИМЯ ФАЙЛА С ВНЕШНИМ’, ‘ПРЕДСТАВЛЕНИЕМ ЗНАНИИ’); READLN (СН); ASSIGN(ШР, СН); RESET (INP); ERROR : - FALSE; READWORD (INP, CH); WHILE NOT (EOF (INP)) AND (NOT ERROR) DO SENTENCE (INP, CH, MAS-RULE, ATTR-LIST, ERROR); CLOSE (INP); IF NOT (ERROR) THEN INFER (MAS-RULE, ATTR_LI$T); WRITELN(‘КОНЕЦ ЗАДАЧИ’); END(*IES*);
СПИСОК ЛИТЕРАТУРЫ 1. Ван Тассел Д. Стиль, разработка, эффективность, отладка н испытание программ: Пер. с аигл.— JVL: Мир, 1985,— 332 с. 2. Вирт Н. Алгоритмы+структуры данных=программы: Пер. с англ.— М.: Мир, 1985.—406 с. 3. Грогоио П. Программирование на языке Паскаль.— М.: Мнр, 1982.— 384 с. 4. Яеисеи К-, Вирт Н. Паскаль. Руководство для пользователя н описа¬ ние языка.— М.: Финансы и статистика, 1982.— 151 с. 5. Клоксин У., Меллиш К- Программирование на языке Пролог.— М.: Мир, 1987.—336 с. 6. Лавров С. С., Снлагадзе П. С. Автоматическая обработка данных. Язык ЛИСП н его реализация.— М.: Наука, 1978.— 176 с. 7. Лаврова Е. С., Медынцев А. Л., Симуин М. Л. Система программиро¬ вания Пролог-СМ. Описание языка. Руководство программиста.— Л.: ЛЭТИ, 1985.—56 с. (Индекс ЦФАП 516027.00138—01 33 01.) 8. Лаврова Е. С., Медынцев А. Л., Симуин М. Л. Возможности применения н перспективы развитии языка Пролог//ЭВМ в проектировании и про¬ изводстве вып. 3.— Л.: Машиностроение, 1987.— С. 49—60. 9. Липский В. Комбинаторика для программистов: Пер. с польск. — М.: Мир, 1988.— 213 с. 10. Логическое программирование: Пер. с англ, и фр. Под ред. В. Н. Ага¬ фонова.— М.: Мир, 1988.—368 с. 11. Маурер У. Введение в программирование на языке ЛИСП: Пер, с англ.— М.: Мир, 1976.— 104 с. 12. Мендельсон Э. Введение в математическую логику.— М.: Наука, 1984.— 319 с. 13. Нильсон Н. Принципы искусственного интеллекта: Пер. с англ.— М.: Радио н связь, 1985.— 376 с. 14. Новиков П. С. Элементы математической логики.— М.: Наука, 1973.— 399 с. 15. Попов Э. П. Экспертные системы: Решение неформализованных задач в диалоге с ЭВМ.— М.: Наука, 1987.— 284 с. 16. Построение экспертных систем. Пер. с англ./Под ред. Ф. Хейеса — Рота, Д. Уотермана, Д. Лената.— М.: Мир, 1987.—441 с. 17. Пратт Т. Языки программирования: разработка н реализация. Пер. с англ.— М.: Мнр, 1979.— 574 с. 18. Реальность и прогнозы искусственного интеллекта: Сб. статей; Пер. с аигл./Под ред. В. Л. Стефанюка. — М.: Мир, 1987.— 247 с. 19. Робототехника и гибкие автоматизированные производства. В 9-ти кн. Кн. 6. Техническая имитация интеллекта: Учеб, пособие для втузов/ В. М. Назаретов, Д. П. Ким; Под ред. И. М. Макарова.— М.: Высш. шк., 1986.— 144 с. 20. Сойер Б., Фостер Д. Л. Программирование экспертных систем на Пас¬ кале.— М.: Финансы и статистика, 1990.—191 с. 21. Таиенбаум Э. Многоуровневая организация ЭВМ: Пер. с англ.—М.: Мир., 1979.—547 с. 22. Уинстон П. Искусственный интеллект: Пер. с англ.— М.: Мир, 1980.— 519 с. 235
23. Уотермен Д. Руководство по экспертным системам: Пер. с англ.— М Мир, 1989.— 388 с. 24. Хантер Р. Проектирование и конструирование компиляторов: Пер с аигл.— М.: Мир, 1984.— 232 с. 26. Хендерсон П. Функциональное программирование. Применение и реалп зация: Пер. с аигл.— М.: Мир, 1983.— 349 с. 26. Хоггер К. Введение в логическое программирование: Пер. с англ.— М Мир, 1988.— 348 с. 27. Экспертные системы. Принципы работы и примеры: Пер. с англ./А. Бру книг, П. Джонс, Ф. Кокс и др.; Под ред. Р. Форсайта.— М.: Ради<* и связь, 1987.— 224 с. 28. Элти Дж., Кумбс М. Экспертные системы: концепции и примеры.— М Финансы и статистика, 1987.— 191 с.
ОГЛАВЛЕНИЕ Предисловие 3 1. Назначение, состав и функционирование экспертной системы . . 5 1.1. Назначение, особенности функционирования и структурная схема инструментальной экспертной системы — 1.2. Язык эксперта 25 1.3. Блок логического вывода 33 1.4. Блок пояснений и язык пользователя 48 1.5. Описание функционирования экспертной системы 52 2. Реализация экспертной системы на языке Паскаль 57 2.1. Краткое описание языка Паскаль — 2.2. Выбор структур данных 72 2.3. Реализация языка эксперта 79 2.4. Реализация логического вывода 94 2.5. Реализация блока объяснений и языка пользователя 2.6. Основная программа инструментальной экспертной системы . . .100 3. Реализация экспертной системы на языке ЛИСП 102 3.1. Краткая характеристика языка ЛИСП — 3.2. Выбор структур данных 1103.3. Реализация логического вывода 118 3.4. Реализация блока объяснений и языка пользователя 129 3.5. Реализация языка эксперта 134 3.6. Основная программа инструментальной экспертной системы . . .139 4. Реализация экспертной системы на языке Пролог 141 4.1. Краткая характеристика языка Пролог — 4.2. Реализация логического вывода 149 4.3. Реализация блока пояснений и языка пользователя 161 4.4. Реализация языка эксперта 167 4.5. Основная программа инструментальной экспертной системы . . . 172 5. Пути расширения возможностей экспертной системы 174 5.1. Использование в качестве атрибутов имен процедур — 5.2. Организация циклов иа языке эксперта 187 5.3. Автоматизированная обучающая система на базе инструменталь¬ ной экспертной системы 201 Приложение 1. Синтаксические диаграммы языка Паскаль . . . 225 Приложение 2. Программа инструментальной экспертной системы 231 Список литературы 235 237
В 1992 году издательство «Политехника» выпустило в свет книгу Д. Лоуренса «Сыновья и любовники. Флейта Аарона» В книгу вошли два романа известного английского писателя Девида Герберта Лоуренса — страстного проповедника идей фрейдизма. Напряженное повествование, глубокий психологический анализ сделали произведения Лоуренса популярными во всем мире... Герои его романов—яркие личности которые любят жизнь и ищут гармонии в отношениях между мужчиной и женщиной, что по мнению автора, является центральной проблемой чело¬ веческой жизни. Книга рассчитана на самый широкий круг читателей.
ПРОИЗВОДСТВЕННОЕ ИЗДАНИЕ Балтрашевич Владимир Эдуардович РЕАЛИЗАЦИЯ ИНСТРУМЕНТАЛЬНОЙ ЭКСПЕРТНОЙ СИСТЕМЫ Редактор Г. А. Ходченко. Переплет художника А. Ф. Каширских. Художест венный редактор А. Я. Волкогонова. Технический редактор Е. Б. Спрукт Корректоры Я. Г. Иванова, 3. С. Романова ИБ № 77 Сдано в набор 10.12.91. Подписано в печать 22.02.93. Формат 6OX88V1*. Бумага тип Гарнитура литературная. Печать высокая. Уел. печ. л. 15,0. Уел. кр.-отт. 15,0. Уч.-нзд. л. 16,47. Тираж 230 экз. Заказ № 1168. Издательство «Политехника», 191011, Санкт-Петербург, Инженерная ул., 6. Государственная типография № 4 г. Санкт-Петербурга Министерства печати ■ ниформл цня Российской Федерации. 191126, Санкт-Петербург, Социалистическая ул., 14.
Издательство «Политехника», оставляя за собой традиционную тематику (наука, техника, производство), планирует в то же время расширить круг тем: издавать научно-популярную, на¬ учно-фантастическую и другую литературу, освещать нетради¬ ционные взгляды на факты, догадки, гипотезы в различных отраслях деятельности человека. Издательство приглашает к сотрудничеству на разных условиях (заказные издания, совместные издания и др.) и принимает заказы на платную рекламу — как в виде отдельных выпусков, так и на страницах своих изданий. Издательство <гПолитехника» купит бумагу на договорных условиях. Издательство рекомендует читателям и представителям всех заинтересованных организаций своевременно оформлять заказы на книги издательства <гПолитехника» в местных книжных магазинах.