Пролог, подразумевающий отрицательный предикат
как я могу написать следующее правило в прологе: если 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