Почему двойное отрицание не связывает в Прологе

Скажем, у меня есть следующая теория:

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).

и вам нужен способ исключить это из ваших семейных дел.

Надеюсь, это поможет.

Другие вопросы по тегам