
использовании оператор goto иногда позволяет программисту более просто решить
задачу. Аналогично обстоят дела с оператором отсечения в Прологе. Несмотря на то,
что его применение приводит часто к трудно предсказуемым
действиям,
он позволяет
резко сократить перебор вариантов и упростить программу.
Рассмотрим принцип работы предиката
'!'
на следующем примере. Даны
утверждения базы.
p(Z)
:- pl(Z) ,p2(Z) , !,p3(Z) .
p(Z)
:-
p4(Z)
.
К данной базе задан вопрос.
Сначала р(Х) согласуется с первым утверждением базы, и правая часть
pl(Z),p2(Z),!,p3(Z) становится целевым утверждением. Теперь начинают
согласовываться предикаты pl(Z) и p2(Z) по обычным правилам, и если согласование
хотя бы одного из них прошло неудачно, то происходит возвращение к исходному
предикату p(Z), который согласуется с новым утверждением
p(Z)>
p4(Z), и целевым
предикатом становится p4(Z).
Предикат отсечения начинает работать при удачном согласовании pl(Z) и p2(Z).
В этот момент происходит
переход
через отсечение слева направо, и полученное
решение для
pl(Z)
и p2(Z) замораживается. Предикат p3(Z) согласуется по обычным
правилам, и все полученные решения, которых может не быть, выводятся.
После окончания согласования p3(Z) выполняется откат к предыдущей цели, т.е.
происходит переход через отсечение справа налево. При этом прекращается поиск
новых решений для pl(Z) и p2(Z) и кроме этого, прекращается также согласование и
исходного утверждения p(Z), поэтому в данном случае p4(Z) не становится целевым
утверждением. Согласование p(Z) по второму правилу произойдет только в том случае,
если не будет перехода через отсечение слава направо, т.е. если цель pl(Z),p2(Z) не
удастся согласовать ни разу.
Другими словами, без использования отсечения база выглядела бы следующим
образом:
p(Z) :- pl(Z) ,p2(Z) ,p3(Z) .
p(Z)
:-
not
(pi
(Z) ,p2(Z) ) ,p4(Z) .
Последний вариант обладает одним неоспоримым преимуществом перед
вариантом, использующим отсечение: в нем можно изменять порядок правил в базе без
потери смысла. Если поменять порядок строк в исходной базе, то предикат p4(Z) будет
согласовываться всегда, независимо от результата согласования pl(Z),p2(Z):
p(Z)
:-
p4(Z)
.
p(Z) :-
pl(Z),p2(Z)
, !,p3(Z) .
113