- •Введение.
- •Фундаментальные подходы к познанию ис.
- •Синергетический подход.
- •Информационный подход.
- •Знания.
- •Свойства знаний.
- •Классификация знаний.
- •Модели представления знаний в сии.
- •Предикатная модель представления знаний.
- •Редукционная модель представления знаний.
- •Процедурные модели представления знаний.
- •Специальные модели представления знаний. Семантические сети.
- •Фреймовая модель представления знаний.
- •Экспертные системы в сии.
- •Архитектуры экспертной системы как сии.
- •Функциональная схема экспертной системы.
- •Технология разработки экспертных систем.
- •Общий обзор языка prolog на примере конкретной программы.
- •Пример программы.
- •Рекурсивное определение правил.
- •Поиск Пролог-системой ответа на вопрос.
- •Декларативный и процедурный смысл программы.
- •Декларативная семантика Пролог-системы.
- •Процедурная семантика Пролог-программы.
- •Порядок предложений и целей.
- •Списки.
- •Операции над списками.
- •1) Принадлежность к списку.
- •2) Добавление элемента.
- •3) Удаление элемента.
- •4) Сцепление (конкатенация) списков.
- •Управление перебором в Пролог-системе.
- •Решение головоломок методом «образовать и проверить».
Управление перебором в Пролог-системе.
Предикат отсечения ! – обозначение.
В процессе достижения целей Пролог-система осуществляет автоматический перебор вариантов, делая возврат при неуспехе какого-либо из них. Такой перебор – полезный механизм, который освобождает пользователя от необходимости программировать его самому. С другой стороны неограниченный перебор может стать источником неэффективности программы. Поэтому иногда его следует ограничить или исключить полностью. Для этого в Прологе используется конструкция отсечение.
Пример.
Добавим:
отец (“Том”,”Боб”).
отец (“Том”,”Лиз”).
отец (“Боб”,”Пат”).
отец (“Боб”,”Энн”).
И отношение дед:
дед (X,Y) :- отец (Z,Y), отец (X,Z).
Вопрос:
? дед (Х,”Боб”).
Шаги вычисления:
Y=”Боб” отец (Z, ”Боб”), отец (X,Z).
Z=”Том” отец (X,”Том”).
отец (X,”Том”).
Fail – происходит возврат.
Чтобы остановить работу механизма возврата, после доказательства 1 цели в теле правила «дед» ставится предикат отсечения.
дед (X,Y) :- отец (Z,Y), !, отец (X,Z).
Не могут быть пересогласованы цели, стоящие до отсечения, даже если они включают и головную часть.
Предикат fail – неуспех, true – успех. Это 2 предиката для управления перебором.
Предикат fail всегда терпит неудачу, true – заканчивается успешно.
Пример.
«Энн встречается со всеми своими родственницами, кроме Лиз».
встречается (“Энн”, Х) :- X=”Лиз”, !, fail.
встречается (“Энн”, Х) :- женщина (Х).
различны (Х, Х) :- !, fail.
различны (_, _).
различны (Х, Y) :- X=Y, !, fail; true.
Предикат repeat. Это цель, которая всегда успешна и всегда может быть пересогласована при возврате.
имя :- repeat, nl, write (“Имя:”), readln(X), встречается (“Энн”, X).
nl – перемещение позиции ввода к началу текущей строки.
readln(X) – чтение
write(X) – вывод.
Решение головоломок методом «образовать и проверить».
Метод «образовать и проверить» - это общий приём, используемый при проектировании алгоритмов и программ. Суть его состоит в том, что один процесс или программа генерирует множество предполагаемых решений задачи, а другой процесс или программа проверяет эти предполагаемые решения, пытаясь найти те из них, которые действительно являются решениями задачи. Используя вычислительную модель Пролога, легко создавать логические программы, реализующие этот метод. Обычно такие программы содержат конъюнкцию двух целей, одна из которых действует как генератор предполагаемых решений, а вторая проверяет, являются ли эти решения приемлимыми:
find(X) :- generate(X), test(X).
Такая Пролог-программа действует подобно обычной процедурной программе, выполняющей генерацию вариантов и их проверку. Процесс продолжается итерационно до тех пор, пока при успешной проверке не будет найдено решение с характерными свойствами или генератор не исчерпает все альтернативные решения.
Однако, программисту нет необходимости интересоваться циклом «образовать и проверить». Он может рассматривать этот метод более абстрактно, как пример недетерминированного программирования. В качестве генератора обычно используется программа для предиката принадлежности:
member (X, [X|H]). /*предикат принадлежности
member (X, [_|H]) :- member (X,H).
Этот предикат порождает множество решений.
На вопрос ? member (X, [a,b,c]) будут даны в требуемой последовательности решения X=a X=b X=c.
Таким образом, предикат member можно использовать в программах, реализующих метод «образовать и проверить» для недетерминированного выбора корректного элемента из некоторого списка.
В качестве примера рассмотрим решение следующей логической головоломки:
Три друга заняли 1, 2 и 3 места в соревнованиях универсиады. Друзья – из разных стран, их зовут по-разному и любят они разные виды спорта. Известно, что:
Майкл предпочитает баскетбол и играет лучше, чем американец.
Англичанин Саймон играет лучше теннисиста.
Игрок в крикет занял первое место.
Необходимо ответить на вопросы:
Кто является австралийцем?
Каким спортом занимается Ричард?
Подобные головоломки легко решаются посредством конкретизации значений подходящей структуры данных и выделения значения, приводящего к решению. Каждый ключ к разгадке преобразуется в факт относительно структуры данных. Это может быть сделано с использованием абстракции данных до определения точной формы структуры данных.
Проанализируем первый ключ к разгадке: «Майкл предпочитает баскетбол и играет лучше, чем американец». Очевидно. Речь идёт о двух разных людях. Одного зовут Майклом и он занимается баскетболом, в то время как второй – американец. Кроме того, Майкл лучше играет в баскетбол, чем американец.
Предположим, что Friends – это структура данных, подлежащая конкретизации, тогда наш ключ может быть выражен следующей конъюнкцией целей:
play_best (Man1, Man2, Friends), /*играет лучше
name (Man1, “Майкл”), /*имя 1-го мужчины
sport (Man1, “Баскетбол”), /*Майкл предпочитает баскетбол
country (Man2, “Американец”), /*2-ой мужчина – американец.
Аналогично второй ключ можно представить конъюнкцией целей:
play_best (Man1, Man2, Friends),
name (Man1, “Саймон”),
country (Man1, “Англичанин”),
sport (Man2, “Теннис”),
Наконец, третий ключ к разгадке выразится следующим образом:
first (Friends, Man), /*первый
sport (Man, “Крикет”),
Базовая программа для решения головоломок имеет вид:
решить_головоломку (головоломка(Ключи,Вопросы,Решения)) :-
решить(Ключи),
решить (Вопросы).
решить ([Ключ|Ключи]) :-
Ключ,
решить (Ключи).
решить ([]).
Всё, что делает эта программа – это последовательное решение каждого ключа и вопроса, которые представляются как цели Пролога и выполняются с использованием метапеременных.
Ключи и вопросы для нашего примера в программе №2. Но сначала рассмотрим структуру, представляемую ключами, для решения этой головоломки.
Каждый человек имеет 3 атрибута и может быть представлен структурой:
friend (Name, Country, Sport) /*друг (Имя, Страна, Спорт)
Есть три друга, распределение которых в итоге соревнований имеет существенное значение. Это наводит на мысль выбрать в качестве структуры данных для решения задачи упорядоченную последовательность из 3-х элементов, то есть список:
[friend(N1,C1,S1), friend(N2,C2,S2), friend(N3,C3,S3)]
Программа №2:
puzzle :- /*головоломка
structure (Struct), /*структура
key (Stuct), /*ключи
question (Struct, Name, Sport), /*вопросы
solution (Name, Sport). /*решение
structure([friend(_,_,_), friend(_,_,_), friend(_,_,_)]).
key (Friends) :-
play_best (Man1Kl1, Man2Kl1, Friends), /*ключ1
name (Man1Kl1, ”Майкл”),
sport (Man1Kl1, ”Баскетбол”),
country (Man2Kl1, “Американец”),
play_best (Man1Kl2, Man2Kl2, Friends), /*ключ2
name (Man1Kl2, ”Саймон”),
country (Man1Kl2, “Англичанин”),
sport (Man2Kl2, ”Теннис”),
first (Friends, ManKl3), /*ключ3
sport (ManKl3, ”Крикет”).
question (Friends, Name, Sport) :-
member (Man1, Friends), /*вопрос1
name (Man1, Name),
country (Man1, “Австралиец”),
member (Man2, Friends), /*вопрос2
name (Man2, “Ричард”),
sport (Man2, Sport),
solution (Name, Sport) :-
write (“Австралийца зовут ”), write (Name), nl,
write (“Ричард играет в ”), write (Sport).
play_best (A, B, [A,B,C]). /* играет лучше
play_best (A, C, [A,B,C]).
play_best (B, C, [A,B,C]).
name (friend (A, B, C), A). /*имя
country (friend (A, B, C), B). /*страна
sport (friend (A, B, C), C). /*спорт
first ([G|H], G). /*первый
member (X, [X|H]).
member (X, [_|H]) :- member (X, H).
Каждая из целей play_best и member имеет дело с людьми, а остальные цели обращаются к атрибутам людей. Какие функции они выполняют – генерацию или проверку, зависит от того, конкретизированы из аргументы или нет.
Задание; пользуясь изложенным выше методом, написать программу решения головоломки Эйнштейна:
В пяти домах, окрашенных в разные цвета, обитают мужчины разных национальностей. Они держат разных животных, предпочитают разные напитки и курят сигареты разных марок. Известно, что:
Англичанин живёт в красном доме.
У испанца есть собака.
Кофе пьют в зелёном доме.
Украинец пьёт чай.
Зелёный дом – первый по правую руку от дома цвета слоновой кости.
Курильщик «Уинстона» держит улиток.
Сигареты «Кул» курят в жёлтом доме.
Молоко пьют в среднем доме.
Норвежец живёт в крайнем слева доме.
Мужчина, курящий «Честерфилд», живёт в доме, соседним с домом мужчины, у которого есть лиса.
Сигареты «Кул» курят в доме, соседним с домом, где имеется лошадь.
Мужчина, предпочитающий «Лайки Страйк», пьёт апельсиновый сок.
Японец курит сигареты «Парламент».
Норвежец живёт в доме рядом с голубым домом.
Вопросы:
У кого есть зебра?
Кто пьёт воду?
man (Country, Color, Animal, Sigaret, Napitok).
