Good_standard( francesco)
reasonable СRestaurant) ;- ftРесторан с приемлемымиценами
not expensiveCRestaurant}. i - это недорогой ресторан! Если после ввода этой программы будет задан вопрос ?- 9ood_etaadard( X), reasonable £ X).
для определения того, какие рестораны характеризуютсявысоким уровнем обслуживания и приемлемыми ценами, то система Prolog ответит X = francesco
Если же будет задан, на первый взгляд, такой же вопрос ?- reasonable ( X) , good_atandard ( х). то система Prolog ответит
II:
Рекомендуем читателю выполнить трассировку программы, чтобы понять причины получения разных ответов. Ключевая разница между обоими вопросами состоит в том, что в первом случае при выполнении терма reasonable ( X} переменная х уже конкретизирована, а во втором случае — еще не конкретизирована. В качестве общей рекомендации можно указать следующее: оператор not Goal выполняется безопасно, если переменные в цели Goalуже конкретизированы ко времени вызова цели notGoal. Б противном случае могут быть получены непредсказуемые результатыпо причинам, описанным ниже.
Проблема, связанная с кеконкретизировашзымиотрицаемыми целями, является результатом неблагоприятного изменения квантификациипеременных при использовании отрицания как недостижения цели. При обычной интерпретации в системе Prolog вопрос ?- expensive! X).
означает: "Существует ли такой X, что цель expensive { X) является истинной? Если да, то каков этот X?" Поэтому к X применяется квантор существования. В соответствии с этим система Prolog отвечает, что X = jeanluis. Но вопрос
?-not expensive ( X).
не интерпретируется так: "Существует ли такой X, что достигается цель notexpensive (X! ?" Если бы это было действительно так, то можно было рассчитывать на получение ответа X = francesco.Но Prolog отвечает "по", поскольку при использовании отрицания как недостижения цели квантор существования заменяется квантором всеобщности. Вопрос nor. expensive1!X) интерпретируется следующим образом: not iсуществует X, такой, что достигаетсяцель expensive (К))
Это равносильно следующему утверждению: Для всех X утверждение expensive (XJ является ложным
134 Часть I. Язык Prolog
В этой главе подробно рассматриваются проблемы, связанные с использованием оператора отсечения, которые также косвенно касаются и оператора not. Автор поставил перед собой задачу предупредить читателей о необходимости соблюдать осторожность при работе с оператором отсечения, а ие полностью отказаться от его применения. Оператор отсечения является полезным и часто необходимым. Кроме того, сложности, аналогичные тем, которые связаны с использованием оператора отсечения в языке Prolog, часто наблюдаются и при разработке программ на других языках.
Резюме
• Оператор отсечения позволяет предотвратить перебор с возвратами. Он ис
пользуется, во-первых, для повышения эффективности программ, а во-вторых,
для усиления выразительной мощи языка.
• Повышение эффективности достигается благодаря тому, что системе Prolog можно явно передать указание (с помощью оператора отсечения), что не нужно проверять альтернативные цели, о которых заранее известно, что попытка их достижения окончится неудачей.
• Оператор отсечения позволяет сформулировать взаимоисключающие заключения с помощью правил, имеющих следующую форму:
если Условие, то Заключение 1, в противном случае Заключение2
• Оператор отсечения позволяет ввести в программу конструкцию отрицания как недостижения цели; оператор not Goal определяется как неудача при достижении цели Goal.
• В программе иногда возникает необходимость в использовании двухспециаль ных целей, true и fail; первая всегда достигается, а последняя никогда не достигается.
• Имеются также некоторые предпосылки, препятствующие использованию оператора отсечения, связанные с тем, что вставка оператора отсечения может нарушить соответствие между декларативным и процедурным значениями программы. Поэтому признаком хорошего стиля программирования является соблюдение осторожности при использовании оператора отсечения и отказ от его применения без достаточных оснований.
• Определение оператора not как недостижения цели не полностью соответствует понятию отрицания в математической логике. Поэтому использование оператора not также требует особой осторожности.