Почему двойное отрицание не связывает в Прологе
Скажем, у меня есть следующая теория:
a(X) :- \+ b(X).
b(X) :- \+ c(X).
c(a).
Это просто говорит, что правда, что, конечно, правильно, a(X)
верно, потому что нет b(X)
(с отрицанием как конечный провал). Так как есть только b(X)
если нет c(X)
и у нас есть c(a)
Можно сказать, что это правда. Мне было интересно, однако, почему Пролог не дает ответ X = a
? Скажем, например, я ввожу некоторую семантику:
noOrphan(X) :- \+ orphan(X).
orphan(X) :- \+ parent(_,X).
parent(david,michael).
Конечно, если я сделаю запрос noOrphan(michael)
, это приведет к true
а также noOrphan(david)
в false
(так как я не определил родителя для david
)., но мне было интересно, почему не существует активного способа определить, какие лица (michael
, david
...) принадлежат noOrphan/1
связь?
Это, вероятно, является результатом механизма обратного отслеживания Пролога, но Пролог может поддерживать состояние, которое подтверждает, если кто-то ищет в позитивном пути (0,2,4,...) глубокие отрицания или отрицательный путь (1,3,5,...) отрицания глубокие.
2 ответа
Давайте начнем с чего-то более простого. Сказать \+ X = Y
, Здесь отрицательная цель - это предопределенный встроенный предикат. Так что все еще яснее X
а также Y
должно быть по-другому. Тем не мение, \+ X = Y
не удается, потому что X = Y
преуспевает. Так что не осталось и следа, при каких точных условиях цель провалилась.
Таким образом, \+ \+ X = Y
выдает пустой ответ, а не ожидаемый X = Y
, Смотрите этот ответ для более.
Учитывая, что такие простые запросы уже показывают проблемы, вы не можете ожидать слишком много определенных пользователем целей, таких как ваша.
В общем случае вам придется сначала пересмотреть то, что вы на самом деле подразумеваете под отрицанием. Ответ гораздо сложнее, чем кажется на первый взгляд. Подумай о программе p :- \+ p.
должен p
Успех или неудача? Должен p
быть правдой или нет? Здесь на самом деле есть две модели, которые больше не вписываются в взгляд Пролога на использование минимальной модели. Соображения, как это открыло новые ветви для логического программирования, такие как программирование набора ответов (ASP).
Но давайте придерживаться Пролога. Отрицание может использоваться только в очень ограниченных контекстах, например, когда цель достаточно конкретизирована, а определение стратифицировано. К сожалению, нет общепринятых критериев безопасного выполнения отрицательной цели. Мы могли бы подождать, пока цель не станет переменной свободной (наземной), но это довольно часто означает, что нам приходится ждать слишком долго - на жаргоне: отрицательные цели колеблются.
Таким образом, общее отрицание не очень хорошо сочетается с программами чистого Пролога. Сердце Пролога на самом деле является чистым, монотонным подмножеством языка. В пределах ограничительной части Пролога (или его соответствующих расширений) отрицание может работать довольно хорошо.
Я мог бы неправильно понять вопрос, и я не понимаю последний абзац.
Во всяком случае, существует совершенно достоверный способ определить, какие люди не являются сиротами. В своем примере вы забыли рассказать компьютеру кое-что, что вы знаете, а именно:
person(michael).
person(david).
% and a few more
person(anna).
person(emilia).
not_orphan(X) :- \+ orphan(X).
orphan(X) :- person(X), \+ parent(_, X).
parent(david, michael).
parent(anna, david).
?- orphan(X).
X = anna ;
X = emilia.
?- not_orphan(X).
X = michael ;
X = david ;
false.
Я не знаю, как именно вы хотите определить "сироту", так как это определение определенно немного странно, но это не главное.
В заключение: вы не можете ожидать, что Пролог знает, что michael
а также david
и все остальные люди, если вы не заявите это явно. Вы также должны четко заявить, что orphan
или же not_orphan
отношения, которые относятся только к людям. Мир, который вы моделируете, также может иметь:
furniture(red_sofa).
furniture(kitchen_table).
abstract_concept(love).
emotion(disbelief).
и вам нужен способ исключить это из ваших семейных дел.
Надеюсь, это поможет.