Пролог подразумевает отрицательный предикат
Как я могу написать следующее правило в PROLOG: , если P, а не Q
Я понимаю, что вы можете легко написать, если P тогда Q предикаты, такие как q(X) :- p(X)
, но как вы можете отменить предикат q/1
? Я не хочу определять новые предикаты с другой семантикой, например non_q/1
.
Ответы
Ответ 1
Предложение "если P, а не Q" логически эквивалентно отрицательному предложению "не P ИЛИ не Q". Таким образом, это предложение Хорна без положительного литерала и как применение соответствия доказательств теоремы SLD и предложений Хорна, может быть представлено в Пролог-программирование как предложение цели или "запрос":
?- P, Q.
Вернемся к этой идее через минуту.
Но предложение цели, возможно, не такое представление, которое вы имеете в виду. Факты и правила, составляющие базу знаний "Пролог", являются определенными положениями, т.е. Предложениями Хорна, каждая из которых имеет ровно один положительный литерал. "Если P, а не Q", не имеет положительного литерала, поэтому в этом смысле он не может быть представлен (как определенный пункт).
Вышеуказанное предложение цели "спрашивает", если оба доказательства P и Q могут быть доказаны. В Prolog содержится понятие "отрицание как сбой", поэтому более естественным способом "спросить" будет ли "не P ИЛИ не Q":
?- not((P,Q)).
Тогда мы получим успех, если либо P, либо Q не удастся, и сбой, если оба успеха.
Однако, если ваша цель - утверждать отрицание чего-то в базе знаний, Prolog, естественно, не поддерживает это. В зависимости от вашего приложения может быть разумный способ обойти синтаксис Prolog и выполнить то, что необходимо (всегда есть необоснованный способ сделать это, как вы намекали, как с предикатом non_q),.
Ответ 2
Вы когда-нибудь слышали о сокращении Prolog?
Во всяком случае, я мало знаю о стандарте Prolog, но в SWI-Prolog символ \+
означает отрицание. Я знаю, что ему не нужно работать в каждом интерпретаторе Prolog.
Вы можете сделать отрицание предиката с помощью пролога. Предикат определяется следующим образом:
not(Goal) :- call(Goal),!,fail.
not(Goal).
Это означает, что цель не может быть доказана, а не цель.
Возможно, эта ссылка Prolog and Cut будет полезна.
Ответ 3
"... если P, а не Q", можно представить через предикат ->
if-then control-flow (например, 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)
, как вам может захотеть (в терминах "правила" ) не является простой, как вы описали, однако потенциальный взлом:
q(X) :- p(X), !, fail.
Это определение будет отражать только то, что q(X)
будет терпеть неудачу для всех X
, где p(X)
преуспеет, если он утверждается перед любыми другими предложениями q(X)
, но может быть не идеальным.
Ответ 4
Вы можете использовать минимальную логику для определения отрицательной головки. В минимальной логике
~ 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)
Дейл Миллер, Гопалан Надатур, Фрэнк Пфеннинг, Андре Себеров