Пролог, подразумевающий отрицательный предикат - PullRequest
12 голосов
/ 13 июня 2011

Как я могу написать следующее правило в PROLOG: , если P, то не Q

Я понимаю, что вы можете легко написать , если P, тогда Q :q(X) :- p(X), но как можно отрицать предикат q/1?Я не хочу определять новые предикаты с другой семантикой, такой как non_q/1.

Ответы [ 4 ]

13 голосов
/ 13 июня 2011

Предложение «если P, то не Q» логически эквивалентно отрицательному предложению «не P ИЛИ не Q».Таким образом, это условие Хорна без положительного литерала, и как приложение соответствия доказательства теоремы SLD и предложений Хорна, может быть представлено в программировании на Прологе в качестве предложения цели или «запроса»:

?- P, Q.

Вернемся к этой идее через минуту.

Но пункт цели, возможно, не тот тип репрезентации, который вы имеете в виду.Факты и правила, которые составляют «базу знаний» Пролога, представляют собой определенные положения, то есть предложения Хорна, каждый из которых содержит только один положительный литерал.«Если P, то не Q» не имеет положительного литерала, поэтому в этом смысле он не может быть представлен (как определенное предложение).

Вышеуказанное предложение цели «спрашивает», могут ли оба P и Q быть доказаны.В Прологе есть понятие «отрицание как неудача», поэтому более естественный способ «спросить», имеет ли «не Р ИЛИ не Q», будет:

?- not((P,Q)).

Тогда мы получим успех, если либо Р, либоQ терпит неудачу, и неудача, если оба успешны.

Однако, если ваша цель состоит в том, чтобы утверждать отрицание чего-либо в базе знаний, Пролог, естественно, не поддерживает это.В зависимости от вашего приложения, может быть разумный способ обойти синтаксис Prolog и выполнить то, что необходимо (всегда есть необоснованный способ сделать это, как вы уже намекали, как с предикатом non_q ).

6 голосов
/ 13 июня 2011

Вы когда-нибудь слышали о разрезе в Прологе?

В любом случае, я мало что знаю о стандарте Пролога, но в SWI-Prolog символ \+ означает отрицание. Я знаю, что это не должно работать в каждом переводчике Пролога.

Вы можете сделать отрицание предиката с помощью разреза Пролога. Предикат определяется как:

not(Goal) :- call(Goal),!,fail.
not(Goal). 

Это означает, что цель не может быть доказана, а цель не является ложной. Может быть, эта Prolog & Cut ссылка будет полезна.

2 голосов
/ 14 июня 2011

"... если P, а не Q" может быть представлено с помощью предиката потока управления if-then -> (например, GNU ) вместе с \+ оператор отрицания (или «недоказуемости») (например, GNU ) следующим образом:

(P -> \+ Q),

Обратите внимание, что обычно \+ реализует то, что известно как отрицание-а-отказ ;то есть подцель / выражение \+ Q будет успешным, если Q не может.Обратите внимание, что оценка Q в \+ не повлияет на привязки любых переменных, присутствующих в выражении Q при выполнении.

Например, рассмотрим:

foo(a).
bar(b).

Учитывая эти факты, справедливо следующее:

foo(a) -> \+ bar(a). % succeeds, as bar(a) is not provable.
foo(a) -> \+ bar(b). % fails, as bar(b) is provable.
foo(a) -> \+ bar(X). % fails, as bar(X) is provable; note that X remains unbound.
foo(X) -> \+ bar(X). % succeeds, as bar(X) where X unified to 'a' isn't provable.

Реализация чего-то похожего на \+ q(X) :- p(X) так, как вы хотите (с точки зрения «правила»), не так проста, как вы описываете, однако потенциальный взломis:

q(X) :- p(X), !, fail.

Это определение будет отражать только намерение, что q(X) потерпит неудачу для всех X, где p(X) завершится успешно, если заявлено до любых других пунктовq(X), но не может быть идеальным.

0 голосов
/ 14 июня 2011

Вы можете использовать минимальную логику, чтобы определить отрицательную голову. В минимальной логике ~ A можно рассматривать как A -> ff. Таким образом, следующее

P -> ~Q

Можно рассматривать как:

P -> (Q -> ff).

Теперь, если мы возьмем следующее тождество (A -> (B -> C)) = (A & B -> C), мы видим, что вышеупомянутое эквивалентно:

P & Q -> ff.

Теперь есть одна проблема, как мы можем задавать отрицательные запросы? Есть один способ использовать минимальную логику, которая отличается от отрицания как отказ. По идее, это запрос вида:

G |- A -> B

временно добавляется A в программу пролога G, а затем пытаясь решить B, т.е. делать следующее:

G, A |- B

Теперь давайте обратимся к нотации Пролога, покажем, что p, а p -> ~ q подразумевает ~ q, выполняя (минимальную логику) программу Prolog. Пролог программы:

p.
ff :- p, q.

И запрос:

?- q -: ff.

Сначала нам нужно определить новое связующее (-:) / 2. Быстрое решение выглядит следующим образом:

(A -: B) :- (assert(A); retract(A), fail), B, (retract(A); assert(A), fail).

Здесь вы видите реализацию этого минимального логического отрицания в SWI Prolog:

Welcome to SWI-Prolog (Multi-threaded, 64 bits, Version 5.10.4)
Copyright (c) 1990-2011 University of Amsterdam, VU Amsterdam

1 ?- [user].
:- op(1200,xfy,-:).
|: (A -: B) :- (assertz(A); retract(A), fail), B, (retract(A); assertz(A), fail).
|: p.
|: ff :- p, q.
|:
% user://1 compiled 0.02 sec, 1,832 bytes
true.

2 ?- q -: ff.
true .

С наилучшими пожеланиями

Ссылка: Унифицированные доказательства как основа логического программирования (1989) Дейл Миллер, Гопалан Надатур, Фрэнк Пфеннинг, Андре Счедров

...