Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ПРОЛОГ.doc
Скачиваний:
3
Добавлен:
21.11.2019
Размер:
311.81 Кб
Скачать

4. Простенькая экспертная система

Задача этой главы заключается в том, чтобы проиллюстрировать использование Пролога для создания игрушечной экспертной системы.

Игрушечная эс «Кто чем увлекается?»

Мы хотим создать систему, которая отвечала бы на вопросы, сформулированные на русском языке, на тему увлечений (hobby) действующих лиц.

Начнем с простейшего варианта.

В простейшем варианте нам следует создать элементарную базу фактов типа увлечение(Кто,Что). Все вербальные варианты запросов система проинтерпретирует так:

1) если в тексте вопроса присутствует значение «Кто» (Петров, Сидоров,...), следует выдать все значения «Что»;

2) если в тексте вопоса присутствует значение «Что», следует выдать все значения «Кто»;

3) если в тексте запроса присутствуют «Что» и «Кто», то система интерпретирует запрос, как «Увлекается ли Кто Что?».

Ответ: «Да» или «Нет» в зависимости от содержания элементарной базы знаний.

В таком простейшем варианте ЭС (с единственным видом отношения между субъектом и объектом) можно не утруждать пользователя формулированием запроса в полном виде, играя в понимание, а предоставить ему возможность выбрать тип запроса и заполнить соответствующие поля.

Алгоритм обработки запросов очень прост. В самом сложном случае, когда их типы заранее не определены (через меню выбора типа), каждое слово запроса проверяется на принадлежность типам «Кто» или «Что» и, в зависимости от результата, формулируется ответ. «Закодируем» алгоритм обработки строки-запроса Запрос, полагая, что база знаний содержится в файле «hobbyNew.dbs».

Программа завершает работу, если в ответ на ее вопрос write(«Есть вопросы? (Д|Н|д|н)»), пользователь ответит 'Н' или 'н'. Предикат repeat используется в разделе goal для организации цикла по обработке вопросов.

domains

кто=symbol

что=symbol

facts - f1

увлечение(кто,что)

кто(кто)

что(что)

predicates

nondeterm repeat

nondeterm ответить(symbol)

ответить_что(кто)

ответить_кто(что)

анализ_КтоЧто(symbol)

спросить

goal

consult("hobbyNew.dbs",f1),

repeat,

спросить,

retractall(кто(_)),

retractall(что(_)),

write("Есть вопросы? (Д|Н)"),

readchar(ДаНет),

ДаНет='Н',exit().

clauses

repeat.

repeat:-repeat.

ответить(""):-

кто(Кто),

что(Что),

увлечение(Кто,Что),!,

write("Да");

кто(Кто),

что(Что),

not(увлечение(Кто,Что)),!,

write("Нет");

кто(Кто),

not(что(_)),!,

write(Кто,".Хобби:"),nl,

ответить_что(Кто);

что(Что),

not(кто(_)),!,

write(Что," является увлечением для:"),nl,

ответить_кто(Что);

!,write("Не понял"),nl.

ответить(Запрос):-

fronttoken(Запрос,Лексема,Остаток),!,

анализ_КтоЧто(Лексема),

ответить(Остаток).

анализ_КтоЧто(Лексема):-

увлечение(Лексема,_),!, assert(кто(Лексема));

увлечение(_,Лексема),!, assert(что(Лексема));

!.

ответить_кто(Что):-

увлечение(Кто,Что),

write(Кто),nl,

fail.

ответить_кто(_).

ответить_что(Кто):-

увлечение(Кто,Что),

write(Что),nl,

fail.

ответить_что(_).

спросить:-

write("Введите Ваш вопрос:"),nl,

readln(Вопрос),

ответить(Вопрос),!;

!.

Теперь усложним задачу с целью дать возможность пользователю формулировать вопрос грамматически правильно, а также для того, чтобы вводить любые виды отношений. Факты мы приведем к универсальному виду f(объект1,отношение,объект2), а также введем синонимы для имен объектов и отношений. В данном случае под термином синоним будем понимать как грамматическое видоизменение слова, так и другое слово, которое мы считаем семантически эквивалентным исходному.

При данной организации БЗ и приведенном ниже алгороитме обработки запроса, имена объектов и отношений,множества синонимов различных отношений и множество синонимов различных объектов не должны пересекаться. Например, если есть факты

ф("кирилл","хобби","шахматы")},

ф("кирилл","любить","татьяна")},

соб("татьяна",["татьяну",...])

сот("хобби",["нравится","увлекается","любит","любить"])

сот("любить",["любит"])

то на вопрос: "кирилл любит татьяну" Вы получите ответ "Нет!", поскольку в качестве имени отношения будет выбрано "хобби".

Состав базы знаний.

ф("кирилл","хобби","хоккей")

ф("петров","хобби","лыжи")

ф("ирина","хобби","кино")

ф("татьяна","хобби","гимнастика")

ф("кирилл","хобби","гимнастика")

ф("петров","любить","ирина")

ф("ирина","любить","кирилл")

ф("кирилл","любить","татьяна")

соб("кирилл",["кириллу","кириллом","кирилла","кирилле"])

соб("петров",["петрову","петровым","петрова","петрове"])

соб("ирина",["ирине","ириной","ирины","ирину"])

соб("гимнастика",["гимнастикой","гимнастики","гимнастикой",

"гимнастике","гимнастику"])

соб("татьяна",["татьяне","татьяной","татьяны","татьяну"])

сот("хобби",["нравится","увлекается"])

сот("любить",["любит"])

Текст программы.

domains

список=symbol*

facts - f1

ф(symbol,symbol,symbol)

соб(symbol,список)

сот(symbol,список)

кто(symbol)

что(symbol)

отн(symbol)

временно(symbol)

predicates

nondeterm repeat

nondeterm ответить(symbol)

ответ1(symbol,symbol,symbol)

ответ2(symbol,symbol)

ответ3(symbol,symbol)

ответ4(symbol)

ответ5(symbol,symbol)

ответ6(symbol)

ответ7(symbol)

анализ_КтоОтношениеЧто(symbol)

nondeterm поиск_кто(symbol)

nondeterm поиск_что(symbol)

nondeterm поиск_отношения(symbol)

искать_синоним_кто(symbol)

искать_синоним_отношения(symbol)

искать_синоним_что(symbol)

загрузить_список(список)

спросить

goal

consult("hobbyNew2.dbs",f1),

repeat,

спросить,

retractall(кто(_)),

retractall(что(_)),

retractall(отн(_)),

write("Есть вопросы? (Д|Н)"),

readchar(ДаНет),

ДаНет='Н',!,exit().

clauses

repeat.

repeat:-repeat.

ответить(""):-

кто(Кто),

что(Что),

отн(Отношение),!,

ответ1(Кто,Отношение,Что);

кто(Кто),

что(Что),

not(отн(_)),ф(Кто,_,Что),!,

ответ2(Кто,Что);

кто(Кто),

отн(Отношение),

not(что(_)),!,

ответ3(Кто,Отношение);

кто(Кто),

not(отн(_)),

not(что(_)),!,

ответ4(Кто);

not(кто(_)),

отн(Отношение),

что(Что),!,

ответ5(Отношение,Что);

not(кто(_)),

отн(Отношение),

not(что(_)),!,

ответ6(Отношение);

not(кто(_)),

not(отн(_)),

что(Что),!,

ответ7(Что);

!,write("Не понял"),nl.

ответить(Запрос):-

fronttoken(Запрос,Лексема,Остаток),

анализ_КтоОтношениеЧто(Лексема),

ответить(Остаток).

анализ_КтоОтношениеЧто(Лексема):-

поиск_кто(Лексема),!;

поиск_отношения(Лексема),!;

поиск_что(Лексема),!;

!.

поиск_кто(Лексема):-

not(кто(_)),

ф(Лексема,_,_),!,assert(кто(Лексема));

not(кто(_)),искать_синоним_кто(Лексема),!;!,fail.

поиск_отношения(Лексема):-

not(отн(_)),

ф(_,Лексема,_),!,assert(отн(Лексема));

not(отн(_)),искать_синоним_отношения(Лексема),!;!,fail.

поиск_что(Лексема):-

not(что(_)),

ф(_,_,Лексема),!,assert(что(Лексема));

not(что(_)),искать_синоним_что(Лексема),!;!,fail.

искать_синоним_кто(Лексема):-

соб(Кто,СписокКто),

загрузить_список(СписокКто),

временно(Лексема),!,

retractall(временно(_)),assert(кто(Кто));

fail.

искать_синоним_кто(_):-retractall(временно(_)),!,fail.

искать_синоним_отношения(Лексема):-

сот(Отн,СписокОтн),

загрузить_список(СписокОтн),

временно(Лексема),!,

retractall(временно(_)),assert(отн(Отн));

fail.

искать_синоним_отношения(_):-retractall(временно(_)),!,fail.

искать_синоним_что(Лексема):-

соб(Что,СписокЧто),

загрузить_список(СписокЧто),

временно(Лексема),!,

retractall(временно(_)),assert(что(Что));

fail.

искать_синоним_что(_):-retractall(временно(_)),!,fail.

загрузить_список([]).

загрузить_список([H|T]):-

assert(временно(H)),загрузить_список(T).

ответ1(Кто,Отношение,Что):-

ф(Кто,Отношение,Что),!,

write("otvet1"),nl,

write("Да."),nl;!,write("Нет."),nl.

ответ2(Кто,Что):-

ф(Кто,Отношение,Что),

write("otvet2"),nl,

write(Кто," ",Отношение," ",Что),nl,

fail.

ответ2(_,_).

ответ3(Кто,Отношение):-

ф(Кто,Отношение,Что),

write("otvet3"),nl,

write(Кто," ",Отношение," ",Что),nl,

fail.

ответ3(_,_).

ответ4(Кто):-

ф(Кто,Отношение,Что),

write("otvet4"),nl,

write(Кто," ",Отношение," ",Что),nl,

fail.

ответ4(_).

ответ5(Отношение,Что):-

ф(Кто,Отношение,Что),

write("otvet5"),nl,

write(Кто," ",Отношение," ",Что),nl,

fail.

ответ5(_,_).

ответ6(Отношение):-

ф(Кто,Отношение,Что),

write("otvet6"),nl,

write(Кто," ",Отношение," ",Что),nl,

fail.

ответ6(_).

ответ7(Что):-

ф(Кто,Отношение,Что),

write("otvet7"),nl,

write(Кто," ",Отношение," ",Что),nl,

fail.

ответ7(_).

спросить:-

write("Введите Ваш вопрос:"),nl,

readln(Вопрос),

upper_lower(Вопрос,Q),

ответить(Q),!;

!.

Протокол сеанса с системой (знак '?' опущен, а также опущены вопросы системы в отношении продолжения диалога):

Любит ли Кирилл Татьяну

otvet1

Да.

Любит ли Татьяна Кирилла

Нет.

В каких отношениях находятся Петров и Ирина

otvet2

петров любить ирина

Кого любит Ирина

otvet3

ирина любить кирилл

Как относится Татьяна к гимнастике

otvet2

татьяна хобби гимнастика

Все о Петрове

otvet4

петров хобби лыжи

otvet4

петров любить ирина

Кто любит кино

Есть вопросы? (Д|Н)Введите Ваш вопрос:

Чьим хобби является кино

otvet5

ирина хобби кино

Кто чем увлекается

otvet6

кирилл хобби хоккей

otvet6

петров хобби лыжи

otvet6

ирина хобби кино

otvet6

татьяна хобби гимнастика

otvet6

кирилл хобби гимнастика

Кто занимается гимнастикой

Есть вопросы? (Д|Н)Введите Ваш вопрос:

(Комментарий: в синонимах нет слова гимнастикой)