6.7. Формирование составных целевых утверждений

В правилах и вопросах вида X:-Y или ?-Y терм, появляющийся на месте Y, может состоять из единственного целевого утверждения либо представлять конъюнкцию целевых утверждений или их дизъюнкцию. Более того, можно употреблять в качестве целевых утверждений переменные и успешно доказывать согласованность целевого утверждения, когда целевое утверждение в действительности не согласуется, используя для этого предикат not. Предикаты, представленные в этом разделе, позволяют реализовать эти сложные способы выражения целевых утверждений.

Конъюнкция целей

Функтор ',' (запятая) определяет конъюнкцию целевых утверждений. Этот функтор был введен в гл. 1. Если X и Y – целевые утверждения, то целевое утверждение X, Y согласуется с базой данных, если согласуется X и Y. Если X согласуется и затем Y не согласуется, то делается попытка найти новое доказательство согласованности для X. Если X не согласуется, то не согласуется и конъюнкция в целом. Это и составляет суть механизма возврата. Функтор Y является встроенным и определен как левоассоциативный инфиксный оператор, так что X, Y, Z эквивалентно (X,Y),Z.

Дизъюнкция целей

Функтор ';' определяет дизъюнкцию (означающую или) целевых утверждений. Если X и Y – целевые утверждения, то целевое утверждение X; Y согласуется с базой данных, если согласуется X или Y. Если X не согласуется, то делается попытка доказать согласованность Y. Если и Y не согласуется, то не согласуется и дизъюнкция в целом. Мы можем использовать функтор ';' для того, чтобы выразить альтернативы в пределах одного утверждения. Например, будем считать, что некоторый объект является человеком, если этот объект – либо Адам либо Ева или если у объекта есть мать. Мы можем выразить это в одном правиле следующим образом:

человек(Х):- (Х=адам; Х = ева; мать(Х,Y)).

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

';' (Х = адам, ';'(Х=ева,мать(Х, Y)))

Таким образом, первая возможность соответствует тому, что X – это адам. Вторая возможность включает две альтернативы: X это ева или у X есть мать

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

человек(адам).

человек(ева).

человек(Х):- мать(Х,Y).

Этот вариант более традиционен и, возможно, проще для чтения. Для многих Пролог-систем он может быть более эффективным по сравнению с использованием ';'.

Результатом отсечения является невозможность изменить выбор альтернатив, обусловленных наличием дизъюнкций, сделанный с момента сопоставления с правилом, содержащим отсечение (см. гл. 4). Вследствие этого имеется ряд случаев, когда программа, содержащая отсечения, не может быть преобразована в обычную программу без использования дизъюнкций. Однако в общем случае не рекомендуется чрезмерно часто использовать ';'. В качестве предостережения отсылаем вас к гл. 8, где показано, как необдуманное использование ';' затрудняет понимание программ.

call(X)

Предполагается, что X конкретизирован термом, который может быть интерпретирован как целевое утверждение. Целевое утверждение саll(X) считается согласованным, если попытка доказать согласованность X завершается успехом. Целевое утверждение call(X) не согласуется с базой данных, если попытка доказать согласованность X заканчивается неудачей. На первый взгляд этот предикат может показаться излишним, поскольку, естественно, возникает вопрос: почему аргумент call не может быть записан непосредственно как целевое утверждение? Например, целевое утверждение

…, саll(принадлежит(а,Х)),…

всегда может быть заменено следующим:

…, принадлежит(a,X),…

Однако если мы создаем целевые утверждения, используя предикат '=..' или ему подобные, то возможны обращения к целевым утверждениям, функторы которых неизвестны на момент ввода программы в Пролог-систему. Так, например, в определении предиката consult в разд. 7.13 нам надо иметь возможность рассматривать любой терм, прочитанный после ?-, как целевое утверждение. Предполагая, что Р, Х и Y конкретизированы функтором и аргументами соответственно, можно использовать call следующим образом:

…, Z =… [P,X,Y], call(Z),…

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

…, P(X,Y),…

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

not(X)

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

Чем отличаются следующие два вопроса?

/* 1 */?- принадлежит(Х,[а,b,с]), write(X).

/* 2 */?- not(not(принадлежит(Х,[а,b,с]))), write(X).

Может показаться, что между ними нет никакой разницы, так как в запросе 2 принадлежит(Х,[а,b,с,]) согласуется, поэтому not(принадлежит(Х,[а,b,с,])) не согласуется и not(not(принадлежит(Х,[а,b,с]))) согласуется. Это правильно лишь отчасти. В результате первого вопроса будет напечатан атом 'а', а в результате второго – неконкретизированная переменная. Рассмотрим, что происходит при попытке доказать согласованность первого целевого утверждения из второго вопроса:

1. Целевое утверждение принадлежит согласуется, и X конкретизируется значением а.

2 Предпринимается попытка доказать согласованность первого целевого утверждения not, которая заканчивается неудачей, так как целевое утверждение принадлежит, являющееся его аргументом, согласуется с базой данных. Теперь вспомним, что, когда целевое утверждение не согласуется, все конкретизированные переменные, такие как X в нашем примере, должны теперь «забыть», что они обозначали до сих пор. Следовательно, X становится неконкретизированной.

3. Предпринимается попытка доказать второе целевое утверждение not, и эта попытка заканчивается успехом, так как его аргумент (not(принадлежит(…))) не согласован. Переменная X остается неконкретизированной.


Перейти на страницу:
Изменить размер шрифта: