Рис. 4.9. Схема работы интерпретатора Пролог
Ниже рассмотрим последовательность операций работы интерпретатора, введя следующие обозначения: В - вопрос БД пользователя или вопрос, полученный посредством фактов и правил; Н - найден факт или правило в БД; У - фраза в предыдущей строке; В унифицируется с фразой в строке Н; П переименование переменных. В квадратных скобках указаны точки возврата, откуда начинается поиск, когда соответствующая подцель разрешена:
В дед (Х,Y)
Н дед (Х,Y) :- отец(X,Z), отец(Z,Y)
П дед (Х1,Y1) :- отец(X1,Z1), отец(Z1,Y1)
У дед (Х,Y) :- отец(X,Z), отец(Z,Y) [TB0]
X=X1,Y=Y1
В отец(X1,Z1)
Н отец(алексей, владимир)
У дед (ал,Y1) :- отец(алексей,Z1), отец(алексей,Y1) [TB1] Х1= алексей , Y1=владимир
В отец(владимир,Y1)
Н Здесь интерпретатор заходит в тупик, так как в БД нет фраз с первым аргументом "владимир". Интерпретатор возвращается в TBO, т е. содержимое стека восстанавливается:
В отец(X1,Z1)
Н отец(андрей, алексей)
У дед (ан,Y1) :- отец(андрей, алексей), отец(ал,Y1) [TB0]
Х1=андрей, Z1=алексей
В отец(алексей,Y1)
Н отец(алексей, владимир)
У дед (андрей, владимир) :-
отец(андрей, алексей), отец (алексей, владимир)
Y1=владимир
Правило «дед» разрешено, следовательно, выходим на TB0.
Предикат "отсечение". Специальное средство "отсечение" в Прологе позволяет обходить (не просматривать) при возврате некоторые цели. Во-первых, программа, включающая отсечение, работает быстрее, так как не рассматриваются цели, ничего нового не дающие для решения. Во-вторых, такая программа занимает меньше места в памяти, так как нет необходимости запоминать точки возврата, чтобы обойти ненужные цели.
Рассмотрим более детально процесс отсечения. Мы знаем, что для получения решения нужно проанализировать, как минимум, одну цель, т.е. найти в БД один факт. Также известно, что если правило является конъюнкцией целей, то для получения решения требуется просмотреть, как минимум, две цели. В Прологе это происходит следующим образом:
1) разрешается (если возможно) первая цель для первого соответствующего факта;
2) разрешается (если возможно) вторая цель для всех соответствующих фактов;
3) далее интерпретатор возвращается назад по цепочке целей, как только все факты удовлетворили (или не удовлетворили) второй цели.
С помощью встроенного предиката "!" (восклицательный знак) - средства "отсечения" - можно воспрепятствовать движению назад.
Например, на запрос
отец(Х,Y),!.
Пролог находит первое решение:
X = a, Y = b и переходит ко второй цели, которая указывает, что невозможно возвращаться назад, и процесс прекращается.
Пусть имеется четыре цели:
цель-1 ,цель-2,! ,цель-3,цель-4.
Пролог последовательно анализирует одну за другой четыре цели, а затем: возвращается назад, как только нет решения для цели-4; возвращается назад, как только нет решения для це-ли-3 (или вновь направляется вперед к цели-4 в случае, если имеется решение для цели-3); после этого интерпретатор останавливается на предикате "!", т.е. возвращение к цели-2 и цели-1 невозможно.
Приведем примеры применения предиката "!".
Рассмотрим следующую программу на Прологе:
отец(а,b).
отец(b,c).
отец(c,d).
предок(Х,Y) :- отец(Х,Y). /* 1-е правило X,Y */
предок(Х,Y) :-
отец(X,Z), /* 2-е правило, 1-я цель: Х,Z,*/
предок(Z,Y). /* 2-е правило, 2-я цель:",Z,Y.*/
Последовательность выполнения операций следующая:
1-е правило: a,b
X=a,Y=b
1-е правило: b,c
X=b,Y=c
1-е правило: c,d
X=c,Y=d
2-е правило 1-я цель: а,b
1-е правило: b,c
2-е правило 2-я цель: b,c
X=a,Y=c
2-е правило 1-цель: b,c
1-е правило: c,d
2-е правило 2-я цель: c,d
2-е правило 2-я цель: b,d
X=a,Y=d
На запрос
!, отец(X,Y), отец(Y,Z) получим
X=a, Y=b, Z=c
X=b, Y=c, Z=d
отец(Х,Y),!,отец(Y,Z)
получим
X=a, Y=b, Z=c
Предикат "ложь". В Прологе имеется встроенный предикат "fail", который всегда указывает на ложь, т.е. на тупик в процессе анализа целей. Этот предикат полезен в том случае, когда необходимо получить все решения некоторой более ранней цели, прежде чем переходить к анализу последующих целей (обычно Пролог находит первое решение первой цели, а затем последующих целей). Вопрос заключается в том, как пройти к последующим целям, если предикат "fail" систематически осуществляет возврат. Например, на запрос отец(Х,Y), write(X,Y), nl, fail, мать(Z,Y). высвечиваются имена всех отцов и нет возможности достичь предиката "мать". Это можно сделать с помощью логической операции ИЛИ, используя которую можно сказать: ИЛИ имеется следующий факт "отец" ИЛИ осуществляется переход к следующей цели".
Арифметические, логические операции и операции отношения.
Рассмотрим следующую БД:
predicates
дopoгa(symbol, symbol, integer)
cвязь(symbol, symbol, integer)
clauses
дорога(минск, москва, 750).
дорога(москва, свердповск, 1668).
дорога(свердловск, новосибирск, 1675).
связь(Отправление, Прибытие, Расстояние) :-
дорога(Отправление, Прибытие, Расстояние).
связь(Отправление, Прибытие, Расстояние) :-
дорога(Отправление,Транзит,Расстояние1),
связь(Транзит,Прибытие,Расстояние2),
Расстояние = Расстояние1 + Расстояние2.
Введем запрос:
связь(минск,Прибытие,Расстояние)
и получим расстояния от Минска до других городов:
Прибытие=москва, Расстояние=750
Прибытие=свердловск, Расстояние=2418
Прибытие=новосибирск, Расстояние=4093
связь(минск,новосибирск,Расстояние).
Для получения ответа использована арифметическая операция "+".
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.