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

5.2 Метод отсечения и отката – оо

Использование предиката cut

В случае, когда надо иметь доступ только к определенной части данных, Пролог использует встроенный предикат cut (!)-отсечение.

Его вычисление всегда успешно. Этот предикат заставляет внутренние унификационные подпрограммы убрать все указатели отката, установленные во время попытки вычислить текущую подцель – то есть он прерывает поиск с возвратом. Через cut невозможно вернуться (совершить откат). Отсечение обычно помещается в теле правила.

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

5.2.1.Влияние предиката cut на составную цель

Пусть cut является одной из подцелей составной цели.

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

Пример:

goal: a(X), b(Y), !, c(X,Y,Z).

При выполнении этой цели компилятор пройдет через предикат cut только в том случае, если и подцель a(X), и подцель b(Y) окажутся уже успешными.

После того как предикат cut окажется обработан, компилятор не сможет вернуться назад для повторного рассмотрения подцелей “a” и “b”, если подцель”c” потерпит неудачу при текущем значении переменных X и Y.

Эта составная цель не обладает декларативным смыслом. Но с процедурной точки зрения ее можно прочесть так:

взять значение переменной X из подцели “a” и значение переменной Y из подцели “b” а затем выполнить подцель c(X,Y,Z).

5.2.2.Влияние предиката cut на процедуру

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

Листинг 5.2. Программа, в которой нет предиката cut

predicates

a(symbol)

d(symbol)

clauses

a(“1”):-

write(“один”).

a(X):-

d(X),

write(“два”).

a(“3”):-

write(“три”).

d(“2a”).

d(“2b”).

Возьмем цель goal: a(N).

В соответствии с представленной схемой получаем все четыре решения:

1) один, N=1;

2) два, N=2a;

3) два, N=2b;

4) три,N=3.

Изменим программу, вставим предикат cut между двумя подцелями правила a(X) и проанализируем, что произойдет в результате выполнения программы, которая будет запущена той же самой целью goal:a{N).

Листинг 5.3.Программа с предикатом cut

predicates

a(symbol)

d(symbol)

clauses

a(“1”):-

write(“один”).

a(X):-

d(X),

!,

write(“два”).

a(“3”):-

write(“три”).

d(“2a”).

d(“2b”).

В результате получим только два ответа:

1) один, N=1;

2) два, N=2.

3) система ‘заморозила’ все альтернативы, стоящие до cut,и лишила тем самым возможности вернуться к подцели d(X),чтобы воспользоваться веткой d(“2b”).

4) отбросила все утверждения процедуры a , стоящие после утверждения с предикатом cut.(то есть перейти к утверждению a(“3”) –невозможно)

Использование предиката cut позволило отбросить части пространства поиска.

Рассмотрим еще один пример.

Листинг 5.4.Программа, использующая cut для того, чтобы сделать процедуру детерминированной

predicates

x(integer)

clauses

x(1):-

!,

write(“a, b, c”),nl.

x(2):-

!,

write(“c”),nl.

x(_):-

Write(“ изучаем предикат cut.”).

Предикат сut позволяет сделать процедуру детерминированной.

Предикат cut предотвращает поиск с возвратом к следующим предложениям. Это отменяет точки отката, увеличивая эффективность выполнения программы. Конструкция очень похожа на switch(case).Для каждой цели существует своя веточка, которая единственная и будет работать при совпадении цели с головой именно этой веточки.

Обратите внимание: условие проверки записывается в заголовке правила(x(1), x(2) и так далее, а не в теле: x(Y):- Y=1,!,a, b, c.)- это увеличивает эффективность работы программы и упрощает чтение.