Пролог, подразумевающий отрицательный предикат

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

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

4 ответов


предложение "если P, то не Q" логически эквивалентно отрицательному предложению "не P или не Q". Как таковой это Horn пункт без положительного литерала и как применение соответствия положений доказательства теоремы SLD и Horn, может быть представлен в программировании Prolog как предложение цели или "запрос":

?- P, Q.

давайте вернемся к этой идее в минуту.

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

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

?- not((P,Q)).

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

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


вы когда-нибудь слышали о cut in Prolog?

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

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

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

это означает, что цель не может быть доказана, а не цель ложна. Может быть, это Пролог И Вырезать ссылка будет полезной.


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

(P -> \+ Q),

обратите внимание, что, как правило, \+ будет реализовывать то, что известно как отрицание как неудача, т. е. подцель/выражение \+ Q будет успешным iff 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) как вы можете хотеть (с точки зрения "правила") не просто, как вы описываете, однако потенциальный Хак:

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

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


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

P -> ~Q

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

P -> (Q -> ff).

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

P & Q -> ff.

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

G |- A -> B

отвечает, временно добавляя A в программу prolog 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) Дейл Миллер, Nadathur Гопалан, Фрэнк Пфеннинга, Андре Scedrov