Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Основы программирования на языке Turbo Prolog.doc
Скачиваний:
56
Добавлен:
09.11.2019
Размер:
563.2 Кб
Скачать

3. Встроенный предикат fail

Предикат fail вызывает неудачное завершение правила, в результате чего внутренние унификационные процедуры выполняют возврат в предыдущую подцель и пытаются найти для нее другое решение.

С помощью этого предиката можно заставить систему находить все решения и для внутренней цели.

Goal

sister(ann,X),write(“Ann — сестра “,X),

nl, fail

Дойдя до предиката fail, система будет осуществлять возврат к предикату sister и будет находить для Х новое значение. В конечном итоге цель так и не будет согласована, но при попытках ее доказать будут напечатаны все, для кого ann — сестра.

Для того, чтобы заставить систему выдавать еще и обоих родителей ann, запрос нужно составить так:

Goal

(sister(ann,X), write(”Ann- сестра ”,X), nl;

pearent(X,ann), write(X,” — родитель Ann”)),

fail

Или так:

Goal

sister(ann,X), write(”Ann-сестра ”,X),nl,fail;

pearent(X,ann), fail

4. Сокращенные варианты внутренних запросов

В предыдущих примерах запросы строились из цепочек взимосвязанных предикатов. В случае, когда какой-либо запрос нужно повторить несколько раз, разумно предусмотреть возможность не задавать всякий раз одни и те же условия. В Турбо-Прологе эта задача решается конструированием правил, не содержащих в себе данных, т.е. правил нулевой арности. Задача, таким образом, сводится к написанию сокращенного варианта запроса. Пояснить только что сказанное можно на следующем примере:

Goal

who_is_the_sister ,fail

who_is_the_sister:-

sister(X,Y),

write(X,”- сестра ”,Y),nl.

Для определения всех родственников девушки составим запрос:

Goal

family,fail

И следующие правила:

family:-

write(” Tell me girl, please ”),nl,

readln(X),

family_of_girl(X).

family_of_girl(Girl):- % сестры Girl

sister(X, Girl),

write(X,”- сестра”), nl.

family_of_girl(Girl):- % мать Girl

mother(X,Girl),

write(X,”- мать”),nl.

Аналогично составляются правила для определения братьев и отца.

При разработке программы такой способ записи цели более предпочтителен, так как он упрощает процедуру запросов.

Упражнение 2.1.

Модифицируйте программу «Родственники» из примера 1.2 главы 1 так, чтобы печатались все родственники девушки по имени Бэт.

5. Использование в запросах анонимных переменных

Пусть потребовалось узнать имена всех лиц, имеющих сестер, причем имена сестер нас не интересуют.

Goal

write(”Имеют сестер: ”),nl, sister(_,X),

write(X), nl, fail.

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

6. Механизм возврата

Турбо-Пролог пытается вычислить цель при помощи сопоставления цели с утверждениями базы данных. Сопоставление выполняется СЛЕВА НАПРАВО, причем, в процессе доказательства основной цели, Турбо-Пролог сам генерирует подцели. Некоторые сопоставления подцелей с какими-то утверждениями, вероятно, будут неуспешными.

Поэтому Турбо-Прологу требуется способ запоминания точек, в которые он может вернуться, чтобы продолжить альтернативные попытки найти решение. Прежде чем выбрать один из возможных путей доказательства подцели, Турбо-Пролог фактически помещает в программу «указатель».

Указатель определяет точку, в которую может быть выполнен возврат, если текущая попытка будет неуспешной. По мере того, как Турбо-Пролог успешно заканчивает свои попытки вычисления подцелей слева направо, указатели возврата расставляются во всех точках, которые могут привести к альтернативному решению.

Если некоторая подцель оказывается неуспешной, то Турбо-Пролог возвращается влево и останавливается у ближайшего указателя возврата. С этой точки Турбо-Пролог начинает попытку найти другое решение для неуспешной цели.

До тех пор, пока следующая цель на данном уровне не будет успешной, Турбо-Пролог будет повторять возврат к ближайшему указателю возврата. Эти попытки выполняются внутренними подпрограммами унификации и механизмом возврата. Окончательным результатом будет либо успешное, либо неуспешное вычисление цели. Рассмотрим механизм возврата на примере программы 2.1.

/* Программа 2.1 «РОДСТВЕННИКИ».

Назначение: демонстрация механизма возврата */

domains

name=symbol

predicates

pearent(name,name)

feminin(name)

male(name)

sister(name,name)

clauses

pearent(mary,bob).

(2) pearent(mary,beth).

(1) pearent(tom,beth).

(4)(5) pearent(tom,bob).

(6) pearent(tom,liz).

(7) pearent(bob,ann).

pearent(bob,pat).

pearent(pat,jim).

feminin(mary).

feminin(beth).

(3) feminin(liz).

feminin(ann).

feminin(pat).

male(tom).

male(bob).

male(jim).

sister(X,Y):-

pearent(Z,X),

pearent(Z,Y),

feminin(X),

X<>Y .

/* Конец программы */

Будем вычислять цель

Goal: sister(beth,X)

Первым правилом, сопоставимым с нашей целью, является правило sister(X,Y). Так как других утверждений для предиката sister нет, то нет и альтернативных путей. Поэтому указатель возврата не ставится, а система генерирует первую подцель pearent(Z,beth). Эта подцель успешно согласуется с фактом pearent(mary,beth). Так как для предиката pearent есть другие утверждения, то указатель возврата (1) устанавливается на факт, следующий за фактом pearent(mary,beth).

Затем система генерирует подцель pearent(mary,Y) и начинает просматривать сначала всю базу данных. Первым утверждением, согласующим данную подцель, будет pearent(mary,bob). Указатель возврата (2) при этом устанавливается на следующее за ним утверждение pearent(mary,beth). Подцели feminin(beth) и beth<>bob успешно согласуются, цель вычисляется со значением X=bob.

Так как для feminin есть другие утверждения, то указатель возврата (3) устанавливается на feminin(liz) и к нему возвращается система, пытаясь передоказать feminin(beth). Передоказать его не удается, указатель (3) снимается, а система возвращается на указатель (2). X означивается beth, успешно доказывается feminin(beth), но beth<>beth неуспешно.Так как для pearent(mary,_) больше утверждений нет, то возвращаемся на (1). Цель pearent(tom,beth) успешно согласуется, на следующее утверждение устанавливается указатель (4), система генерирует подцель pearent(tom,Y).

Эта цель успешно доказывается с Y=beth, указатель (5) устанавливается на pearent(tom,bob), и к нему мы возвращаемся, потерпев неудачу при доказательстве beth<>beth. (5) снимается, на pearent(tom,liz) устанавливается (6). Так как beth<>bob цель успешно доказывается (получаем повторно X=bob) и возвращаемся на (6). Y получает значение liz, указатель (7) устанавливается на pearent(bob,ann). Успешно получив решение X=liz, возвращаемся на (7), потерпев неудачу, возвращаемся еще на шаг назад — на (4). bob не согласуется с beth, больше указателей нет, выходим из системы.