Пролог и искусственный интеллект
Пролог может использоваться в области обработки естественного языка. Можно создать программу имитирующую разговор психотерапевта с пациентом. Такая программа пытается сопоставить вводимые пользователем ответы с имеющимися у неё шаблонами, если это удается, то шаблон отвечает. Алгоритм программы:
1. Попросит человека описать имеющуюся у него проблему
2. Прочитает строку с клавиатуры
3. Попытается подобрать шаблон, которому соответствует введенная человеком строка
4. Если удалось, выдаст соответствующий шаблону ответ
5. Если не удалось, попросит продолжить рассказ.
6. Переход к пункту 2 и продолжаем процесс.
Возможно написать более совершенную программу, для этого требуется увеличивать количество шаблонов и организовывать разные реакции на некоторые шаблоны с использованием случайных чисел.
Экспертная система – программа, которая заменяет эксперта в какой-либо области.
Построим классификационную экспертную систему, которая пытается угадать загаданное человеком животное. Если загаданное человеком животное окажется неизвестно программе, то она дополняет свою базу знаний новой информацией. В связи с этим по окончании работы программы эта база знаний сохраняется в файле. А при начале работы база знаний считывается из файла в оперативную память. При этом можно использовать внутренние или динамические базы данных. Представим правила, определяющие животных в виде фактов. Рассмотрим два предиката внутренней базы данных, которые позволяют хранить информацию о животных. Первый предназначен для хранений характеристик животных. У него два аргумента – номер свойства и словесное описание.
cond(1,"кормит детенышей молоком").
cond(2,"имеет перья").
cond(3,"плавает").
cond(4,"ест мясо").
cond(5,"имеет копыта").
cond(6,"летает").
Второй предикат хранит описания животных. Аргументы: название животного и список, элементами которого являются номера свойств, присущих данному животному.
rule("гепард",[1,4,8,10]).
rule("тигр",[1,4,8,9]).
rule("жираф",[1,5,8,10,12,13]).
rule("зебра",[1,5,8,9,11]).
rule("страус",[2,14]).
По сути дела, в виде фактов записаны правила. Например, правило: "если животное кормит детенышей молоком, имеет копыта, пятна, длинную шею и ноги, то это жираф", записано в виде rule("жираф", [1,5,11,13,14]).
Вторая база будет хранить ответы человека.cond_is(N,'1') /* если загаданное животное имеет свойство
с номером N */
cond_is(N,'2') /* если загаданное животное не имеет
свойства с номером N */
Knowledge – база знаний.
dialog – ответы человека.
Процесс отгадывания задуманного животного:
1. Последовательно перебираются животные, имеющиеся в базе знаний.
2. Если загаданное животное обладает всеми характеристиками, известного программе животного делается вывод о том, кто был загадан.
3. Если не удается сопоставить загаданному животному ни одно из животных, имеющихся в базе знаний, производится дополнение базы. Для этого используется предикат animals.
animals:–
rule(X,L),
check(L),
nl,write("Я думаю это ",X),
nl,write("Я прав? (1 — да, 2 — нет)"),
read_true_char(C),C='1',!.
animals:–
nl,write("Я не знаю, что это за животное"),nl,
nl,write("Давайте добавим его в мою базу
знаний."),nl,
update.
check - осуществляет проверку свойств, номера которых входят в список, указанный в качестве его аргумента.
check([H|T]):–
test_cond(H),
check(T).
check([]).
test_cond - проверяет наличие у загаданного животного свойства с номером, указанным в качестве его аргумента.
test_cond(H):–
cond_is(H,'1'),!. /* в базе имеется
информация о наличии
данного свойства */
test_cond(H):–
cond_is(H,'2'),!,
fail. /* в базе имеется информация
об отсутствии данного свойства */
test_cond(H):– /* в базе нет никакой информации о данном
свойстве, получаем ее у человека */
cond(H,S),
nl,write("Оно ",S,"? (1 — да, 2 — нет)"),
read_true_char(A),
assert(cond_is(H,A)),
test_cond(H).
Предикат read_true_char осуществляет проверку нажатой пользователем клавиши, и если она отлична от '1' или '2', выводит соответствующее сообщение и повторно считывает символ с клавиатуры.
read_true_char(C):–
readchar(C1),
test(C1,C).
test(C,C):–
'1'<=C,C<='2',!.
test(_,C):–
write("Нажмите 1 или 2!"),nl,
readchar(C1),
test(C1,C).
Предикат Update осуществляет добавление новой информации в базу знаний, читает название нового животного, затем с помощью предиката add_cnd формирует список номеров свойств загаданного животного, добавляет соответствующий в базу знаний и сохраняет её.
update:–
nl,write("Введите название животного:"),
readln(S),
add_cond(L), /* указываем свойства животного */
assert(rule(S,L),knowledge),
/* добавляем информацию в базу
знаний*/
save("animals.ddb",knowledge)
/* сохраняем базу знаний в файл */.
add_cond – выводит уже имеющуюся информацию о свойствах загаданного животного и спрашивает, известно ли еще что-либо о животном. В случае необходимости добавляет новые характеристики.
add_cond(L):–
cond_is(_,'1'),!,
/* имеется информация о свойствах
животного */
nl,write("О нем известно, что оно: "),
print_cond(1,[],L1),
/* вывод имеющейся информации
о животном */
nl,write("Известно ли о нем еще что-нибудь?
(1 — да, 2 — нет)"),
read_true_char(C),
read_cond(C,L1,L).
add_cond(L):–
read_cond('1',[],L).
Read_cond - используя предикат ex_cond, добавляет в список номера свойств, уже имеющихся в базе; используя предикат new_cond, добавляет в список номера новых свойств, а также описания самих свойств — в базу знаний.
read_cond('1',L,L2):–
ex_cond(1,L,L1,N),
new_cond(N,L1,L2),!.
read_cond(_,L,L):–!.
Полный вариант программы.
DOMAINS
i=integer
s=string
c=char
li=i* /* список целых чисел */
DATABASE — knowledge
cond(i,s) /* свойства животных */
rule(s,li) /* описания животных */
DATABASE — dialog
cond_is(i,c) /* номер условия; '1' — имеет место,
'2' — не имеет места у загаданного
животного */
PREDICATES
start
animals /* отгадывает животное */
check(li) /* добавляет в базу информацию о новом
животном */
test_cond(i) /* проверяет, обладает ли загаданное
животное свойством с данным номером */
update /* добавляет в базу информацию о новом животном */
add_cond(li) /* возвращает список, состоящий из номеров
свойств, имеющихся у нового животного */
print_cond(i,li,li) /* добавляет в список номера свойств,
относительно которых уже были даны
утвердительные ответы */
read_cond(c,li,li) /* добавляет в список номера свойств,
о которых еще не спрашивалось */
ex_cond(i,li,li,i) /* добавляет в список номера имеющихся
в базе свойств, которыми обладает
новое животное */
wr_cond(c,i,li,li)
new_cond(i,li,li) /* добавляет в список номера новых
свойств, которыми обладает новое
животное, а также добавляет описания
новых свойств в базу знаний */
read_true_char(c) /* с помощью предиката test читает
символ с клавиатуры, пока он
не окажется равен '1' или '2'*/
test(c,c) /* добивается, чтобы пользователь нажал один
из символов, '1' или '2' */
CLAUSES
start:–
consult("animals.ddb",knowledge),
/* загружаем в базу информацию
из базы знаний */
write("Загадайте животное, а я попытаюсь его
отгадать"),nl,
animals, /* попытка отгадать загаданное животное */
retractall(_,dialog), /* очищаем текущую
информацию */
retractall(_,knowledge),
/* очищаем информацию об известных
животных и свойствах */
nl,nl,write("Хотите еще раз сыграть? (1 — Да,
2 — Нет)"),
read_true_char(C),
C='1',!,start.
start:–
nl,nl,write("Всего доброго! До новых встреч"),
readchar(_).
animals:–
rule(X,L),
check(L),
nl,write("Я думаю, это ",X),
nl,write("Я прав? (1 — да, 2 — нет)"),
read_true_char(C),C='1',!.
animals:–
nl,write("Я не знаю, что это за животное"),nl,
nl,write("Давайте добавим его в мою базу знаний."),nl,
update.
update:–
nl,write("Введите название животного:"),
readln(S),
add_cond(L), /* указываем свойства животного */
assert(rule(S,L),knowledge), /* добавляем информацию
в базу знаний*/
save("animals.ddb",knowledge) /* сохраняем базу
знаний в файл */.
add_cond(L):–
cond_is(_,'1'),!, /* имеется информация
о свойствах животного */
nl,write("О нем известно, что оно: "),
print_cond(1,[],L1),
/* вывод имеющейся о животном
информации */
nl,write("Известно ли о нем еще что-нибудь?
(1 — да, 2 — нет)"),
read_true_char(C),
read_cond(C,L1,L).
add_cond(L):–
read_cond('1',[],L).
print_cond(H,L,L):–
not(cond(H,_)),!.
print_cond(H,L,L1):–
cond_is(H,'1'),!,
cond(H,T),
H1=H+1,
nl,write(T),
print_cond(H1,[H L],L1).
print_cond(H,L,L1):–
H1=H+1,
print_cond(H1,L,L1).
read_cond('1',L,L2):–
ex_cond(1,L,L1,N),
new_cond(N,L1,L2),!.
read_cond(_,L,L):–!.
ex_cond(N,L,L,N):–
not(cond(N,_)),!.
ex_cond(N,L,L1,N2):–
cond_is(N,_),!,
N1=N+1,
ex_cond(N1,L,L1,N2).
ex_cond(N,L,L1,N2):–
cond(N,S),
nl,write("Оно ",S,"? (1 — да, 2 — нет)"),
read_true_char(A),
wr_cond(A,N,L,L2),
N1=N+1,
ex_cond(N1,L2,L1,N2).
wr_cond('1',N,L,[N L]):–!.
wr_cond('2',_,L,L):–!.
new_cond(N,L,L1):–
nl,write("Есть еще свойства? (1 — да,
2– нет)"),
read_true_char(A),
A='1',!,
nl,write("Укажите новое свойство,
которым обладает животное"),
nl,write("в виде 'оно <описание
нового свойства>'"), readln(S),
assertz(cond(N,S)),
/* добавление нового свойства
в базу знаний */
N1=N+1,
new_cond(N1,[N L],L1).
new_cond(_,L,L).
check([HT]):–
test_cond(H),
check(T).
check([]).
test_cond(H):-
cond_is(H,'1'),!. /* в базе имеется информация
о наличии свойства */
test_cond(H):–
cond_is(H,'2'),!,
fail. /* в базе имеется информация
об отсутствии свойства */
test_cond(H):– /* в базе нет никакой информации о данном
свойстве, получаем ее у человека */
cond(H,S),
nl,write("Оно ",S,"? (1 — да, 2 — нет)"),
read_true_char(A),
assert(cond_is(H,A)),
test_cond(H).
read_true_char(C):–
readchar(C1),
test(C1,C).
test(C,C):–
'1'<=C,C<='2',!.
test(_,C):–
write("Нажмите 1 или 2!"),nl,
readchar(C1),
test(C1,C).
GOAL
start.
В идеале экспертная система должна уметь объяснять свое решение, а так же почему она задаёт тот или иной вопрос.