Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
пособие_Пролог_часть1.doc
Скачиваний:
31
Добавлен:
13.11.2019
Размер:
1.36 Mб
Скачать

4.2.3 Механизм поиска с возвратом.

Для того, чтобы представить работу механизма автоматического возврата удобно воспользоваться понятием маркера. Маркер отмечает текущее утверждение в программе, сопоставимое с целью. Для каждой цели в запросе Прологсистема создает свой собственный маркер, который будем обозначать значком “”. Маркеры могут передвигаться только вперед. Однако, когда цель начинает согласовываться сначала, соответствующий маркер устанавливается на первое утверждение, заголовок которого совпадает с именем предикатацели.

Рассмотрим этот процесс на примере. Пусть программа «Однокурсники» содержит следующие утверждения:

(1) student_course(X,Y):student(X,K1), student(Y,K2),X\=Y,K1=K2.

(2) student(‘Иванов’,1).

  1. student(‘Петров’,4).

  2. student(‘Сидоров’,2).

(5) student(‘Кузнецов’,4).

Пусть требуется согласовать запрос:

? student_course(X,Y).

Этот запрос сопоставим с первым утверждением, которое является правилом, поэтому производится редукция цели, и текущая резольвента примет вид:

ТР: student(X,K1), student(Y,K2),X\=Y,K1=K2.

Создадим маркер 1 для первой цели в резольвенте student(X,K1) и маркер 2 для второй цели в резольвенте student(Y,K2).

При просмотре фактов student в программе маркеры будут передвигаться следующим образом:

(2) student(‘Иванов’,1). 1 2 (no) 2 (no)

(3) student(‘Петров’,4). 2 (no) 1 2 (no)

(4) student(‘Сидоров’,2). 2 (no) 2 (no)

(5) student(‘Кузнецов’,4). 2 (no) 2 (yes)

возврат 1-й цели успешный

вывод

при подстановке {X=‘Петров’; Y=‘Кузнецов’}.

Таким образом, ответ на запрос будет выдан в следующем виде:

? student_course(X,Y).

X=‘Петров’

Y=‘Кузнецов’ >

Получив решение, Прологсистема предлагает пользователю решить, нужно ли искать другие решения. При нажатии клавиши «;» интерпретатор Пролога выполняет возврат на первую цель и переставляет маркер 1 на предложение 3 программы, а маркер 2 на первое предложение.

(2) student(‘Иванов’,1). 2 (no) 2 (no)

(3) student(‘Петров’,4). 2 (no) 2(yes) (4) student(‘Сидоров’,2). 1 2 (no)

(5) student(‘Кузнецов’,4). 2 (no) 1 возврат 1-й цели успешный

вывод

при подстановке {X=‘Петров’; Y=‘Кузнецов’}.

Не найдя второкурсников, кроме Сидорова система сама производит возврат и переставляет маркер 1 на предложение 4 программы, а маркер 2 на первое предложение.

Таким образом, ответ на запрос будет выдан в следующем виде:

? student_course(X,Y).

X=‘Кузнецов’

Y=‘Петров’

 >;

Если отказаться от этого решения, то система должна будет переставить маркер 1 на предложение, следующее за пятым предложением программы, но поскольку все предложения программы исчерпаны, а маркер 1 может передвигаться только вперед, вычисление запроса завершается, сообщением “no”, которое означает, что больше решений нет.

5. Рекурсивное программирование на языке Пролог.

5.1 Рекурсивные правила.

Рекурсия в логическом программировании применяется в двух случаях:

  • если отношение описывается с помощью такого же отношения;

  • когда сложный объект (структура) сам является частью однотипного, сложного объекта.

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

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

В общем случае рекурсивная процедура имеет следующий вид:

<заголовок рекурсивного правила>:<предикат условия выхода>, <предикаты>.

<заголовок рекурсивного правила >:<предикаты>,

<заголовок рекурсивного правила >,<предикаты>.

<заголовок рекурсивного правила >:<предикаты>,

<заголовок рекурсивного правила >,<предикаты>.

…………………………………………..

<заголовок рекурсивного правила >:<предикаты>,

<заголовок рекурсивного правила >,<предикаты>.

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

Чтобы обеспечить проверку условий завершения рекурсивных вызовов, рекомендуется нерекурсивное правило с условием выхода записывать перед рекурсивными правилами.

Рассмотрим примеры рекурсивных процедур.

Пример 1. Программа определения суммы ряда натуральных чисел.

sum_series(1,1).

sum_series(N,S):N>0,Next is N-1, sum_series(Next,S1),

S is N+S1.

?  sum_series(6,S).

S=21.

YES

Пример 2. Программа генерации ряда натуральных чисел от N до 20.

write_number (20) :write(20).

write_number(N): N<20,write(N),nl,Next is N-1, write_number (Next).

? write_number(15).

15

16

17

18

19

20

YES