Скачиваний:
62
Добавлен:
01.05.2014
Размер:
346.11 Кб
Скачать

11.3. Отрицание

Использование зеленого отсечения не влияет на декларативное значение про­грамм на Прологе. Однако с учетом процедурного поведения отсечение может быть в ограниченной мере использовано для выражения безрезультатной информации.

Отсечение является основой реализации в Прологе ограниченной формы отрица­ния, называемой отрицание как безуспешное выполнение. Программа 11-о задает стандартное определение отношения not (Goal), которое истинно, если цель Goal не выполнена. Она основана на использовании метапеременной и системного предика­та fail, который никогда не выполняется (т.е. отсутствуют определяющие его предложения). Конъюнкция отсечения и предиката fail представляет комбинацию “omceченue-fail”. Мы употребляем not как префиксный оператор.

notX

Х недоказуемо.

not XX, X,!. fail.

not X

Программа 11.6. Отрицание как безуспешное выполнение.

Рассмотрим, как работает программа 11.6 при поиске ответа на вопрос not G? Применяется первое правило, и использование метапеременной задает обращение к цели G. Если цель G выполнена, то мы сталкиваемся с отсечением. В вычислении фиксируется выбор первого правила, и цель not не выполнена. "Если цель G не выполнена, то применяется второе правило программы 11.6, приводящее к успеш­ному вычислению. Следовательно, цель notG не выполнена, если выполнена цель G, и наоборот.

Для того чтобы программа 11.6 функционировала должным образом, требуется именно такой порядок правил. Здесь мы сталкиваемся с новой, не всегда желатель­ной ситуацией в программировании на Прологе. До сих пор порядок правил влиял только на порядок появления решений. Теперь порядок правил может изменить значение программы. Процедуры, в которых порядок правил является критическим в этом смысле, следует рассматривать как единый объект, а не как набор отдельных предложений.

Остановка вычислений цели not G зависит от остановки вычислений цели G. Если вычисления цели G остановятся, то остановятся и вычисления цели notG. Если вычисления цели G не остановятся, то вычисления цели notG могут остановиться или не остановиться в зависимости от того, будет ли в дереве поиска найдена успешная вершина, прежде чем вычисление пойдет по бесконечной ветви. Рассмот­рим незавершающуюся программу:

женаты (авраам, сара).

женаты (X,Y)  женаты (Y,X).

Решение вопроса not женаты (авраам, сара)?. приведет к остановке (безуспешного) вычисления, хотя решение вопроса женаты (авраам. сара)? не останавливается.

Значение отношения not, определяемого в программе 11.6, отличается от строго­го логического отрицания. Нельзя также сказать, что программа реализует полное и точное определение отрицания как безуспешного выполнения в смысле теории гл. 5.

Неполнота такой реализации проистекает от неполноты реализации в Прологе вычислительной модели логического программирования. В логическом программи­ровании отрицание как безуспешное выполнение определяется в терминах дерева конечного безуспешного поиска. Вычисления в Прологе не гарантируют нахождение такого дерева, даже если оно существует. Имеются цели, которые могут быть не выполнены при подобном отрицании, однако решение этих целей в соответствии с правилом вычислений в Прологе не останавливается. Например, решение вопроса not(p(X),q(X))? приводит к незавершающейся работе программы

В действительности Пролог-10 использует предикат \ +, а не not, но это не должно вводить в заблуждение. Прим. перев.

p(s(X))р(Х).

q(a).

Вопрос можно решить, если выбрать сначала цель q(X), так как этот выбор приводит к дереву конечного безуспешного поиска.

Неадекватность программы 11.6 связана также с порядком обхода дерева поис­ка, что проявляется в случае использования отношения not в конъюнкции с другими целями. Рассмотрим использование отношения not в определении предиката не-женатый_студент (X) для кого-то, кто и студент, и не женат. Определение приведено в программе 5.1:

неженатый студент (X)  not женат (X), студент (X).

студент (билл.)

женат(джо).

Решение вопроса неженатый­_студент (X)?. с использованием приведенных сведений безуспешно, несмотря на то что решение Х = билл логически следует из правила и двух фактов. Это связано с тем, что цель not женат (X) не выполнена из-за решения X = джо. В данном случае проблема может быть устранена перестановкой целей в теле правила.

Аналогичным примером является вопрос not(X = l),X = 2?, который, несмотря на то что он верен, приводит к безуспешному вычислению.

Как показывают приведенные выше примеры, реализация отрицания как безус­пешного выполнения с помощью комбинации “отсечение-fail” приводит к некор­ректной работе для неосновных целей. В большинстве стандартных реализации языка Пролог ответственность за то, что под отрицанием находятся основные цели, ложится на программиста. Проверка может выполняться или при статическом анализе программы, или в процессе вычислений с помощью предиката ground, описанного в программе 10,4.

Предикат not очень полезен. С его помощью можно вводить интересные понятия. Рассмотрим, например, предикат disjoint (Xs.Ys), выполненный, если списки Xs и Ys не имеют общих элементов. Этот предикат можно задать следующим образом:

disjoint(Xs,Ys)  not(member(Z, Xs),member(Z, Ys)).

В программах, приведенных в книге, встретятся и другие примеры применения предиката not.

Комбинация “отсечение-fail”, использованная в программе 11.6, имеет и более общее применение. Она позволяет прервать вычисление на ранней стадии. В предложении, содержащем “отсечение-fail”, утверждается, что поиск не должен быть (и не будет) продолжен.

Некоторые отсечения в комбинации “отсечение-fail” являются зелеными отсече­ниями. Это означает, что значение программы не изменится, если удалить предло­жение, содержащее данную комбинацию. Рассмотрим в качестве примера програм­му 10.4, определяющую предикат ground. Можно добавить правило, сокращающее поиск и не влияющее на значение программы:

ground (Term)  var(Term),!, fail.

Использование отсечения в программе 11.6, задающей предикат not, является красным, а не зеленым. Работа программы после удаления отсечения будет отличаться от требуемой.

Комбинац1ия “отсечение-fail” применяется и при реализации других системных предикатов, использующих отрицание. Например, программа 11.7 дает простую реализацию предиката  с помощью унификации и комбинации “отсечений-fail”, а не с помощью бесконечной таблицы. Данная программа также работает правильно лишь для основных целей.

X Y-

X и У неунифицируемы.

Х  Х  !, fail. Х  Y.

Программа 11.7. Реализация отношения 

Изобретательность, хорошее понимание алгоритма унификации и процесса вычисления в Прологе позволяют строить интересные определения многих метало­гических предикатов. Уровень требуемых ухищрений можно оценить, рассмотрев программу, определяющую предикат same_var (X, Y). Этот предикат выполнен в том случае, если Х и Y- одна .и та же переменная, в противном случае он ложен.

Same_var(foo,Y)var(Y),!,fai. Same_var(X,Y)var(X),var(Y).

Довод в пользу правильности определения: “Если аргументы предиката Same_vаг -одна и та же переменная, то сопоставление значения foo аргументу Х приведет к такому же сопоставлению и для второго аргумента, так что первое правило будет неприменимо. Применение второго правила приведет к успешному решению. Если какой-либо из аргументов не является переменной, то оба правила неприменимы. Если аргументы - различные переменные, то первое правило приве­дет к безуспешному вычислению, а отсечение воспрепятствует рассмотрению вто­рого правила” (O'Keef, 1983).

Упражнения к разд. 113

1. Определите предикат \ = =, используя предикат == = и конструкцию отсечение-fail”.

2. Определите предикат nonvar, используя предикат var и конструкцию “отсечение - fail”.

Соседние файлы в папке 1-13