PROLOGで次のルールを書くにはどうすればよいですか? pの場合はQではありません
Pの場合はQq(X) :- p(X)
のような述語を簡単に記述できることは理解していますが、q/1
述語をどのように否定できますか? non_q/1
のような他のセマンティクスで新しい述語を定義したくありません。
「ifPthen not Q」という節は、「not P OR not Q」」という負の節と論理的に同等です。したがって、正の値がない ホーン節 です。リテラルであり、SLD定理証明とホーン節の対応のアプリケーションとして、Prologプログラミングではゴール節または「クエリ」として表すことができます。
?- P, Q.
すぐにこのアイデアに戻りましょう。
しかし、ゴール条項はおそらくあなたが考えているような表現ではありません。 Prologの「知識ベース」を構成する事実と規則は明確な節です。つまり、ホーン節はそれぞれ1つの正のリテラルを持っています。 「IfPthen not Q」には正のリテラルがないため、この意味で(明確な句として)表すことはできません。
上記の目標節は、PとQの両方を証明できるかどうかを「尋ねます」。 Prologは「失敗としての否定」の概念を提供するので、「P OR Qではない」が成り立つかどうかを尋ねる」より自然な方法は次のようになります。
?- not((P,Q)).
次に、PまたはQのいずれかが失敗した場合は成功し、両方が成功した場合は失敗します。
しかし、あなたの目的が知識ベースの否定をアサートすることである場合、Prologは当然これをサポートしません。アプリケーションによっては、Prolog構文を回避し、必要なことを達成するための合理的な方法がある場合があります(non_qのように示唆したように、それを行うには常に不合理な方法があります述語)。
Prologのカットについて聞いたことがありますか?
とにかく私はProlog標準についてあまり知りませんが、SWI-Prologでは記号\+
は否定を意味します。私はそれがすべてのPrologの通訳者で働く必要はないことを知っています。
Prologのカットで述語否定を行うことができます。述語は次のように定義されます。
not(Goal) :- call(Goal),!,fail.
not(Goal).
それは、目標が間違っているのではなく、目標を証明できないことを意味します。多分これ Prolog&Cut リンクが役に立つでしょう。
"... if P then not Q"は、_->
_ if-then制御フロー述語(例:- [〜#〜] gnu [〜#〜] )、および_\+
_否定(または '証明不可能')演算子(例: [〜#〜] gnu [ 〜#〜] )、次のように:
_(P -> \+ Q),
_
通常、_\+
_は negation-as-failure として知られているものを実装することに注意してください。つまり、サブゴール/式_\+ 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)
は、アサートされた場合beforeq(X)
の他の句ですが、理想的ではない場合があります。
最小限のロジックを使用して、負のヘッドを定義できます。最小限のロジックでは、〜AはA-> ffと見なすことができます。したがって、次の
P -> ~Q
次のように表示できます。
P -> (Q -> ff).
ここで、次のID(A->(B-> C))=(A&B-> C)をとると、上記は次と同等であることがわかります。
P & Q -> ff.
ここで1つの問題があります。どうすれば否定的な質問をすることができますか?失敗としての否定とは異なる最小限のロジックを利用する方法が1つあります。アイデアは、次の形式のクエリです。
G |- A -> B
は、一時的にAをプロローグプログラムGに追加し、次にBを解決しようとすることによって答えられます。つまり、次のようにします。
G, A |- B
ここで、Prolog表記に目を向けましょう。pを示します。p-> 〜qは、(最小ロジックの)Prologプログラムを実行することによって〜qを意味します。プロローグプログラムは次のとおりです。
p.
ff :- p, q.
そして、クエリは次のとおりです。
?- q -: ff.
まず、新しい接続(-:)/2を定義する必要があります。簡単な解決策は次のとおりです。
(A -: B) :- (assert(A); retract(A), fail), B, (retract(A); assert(A), fail).
ここに、SWIPrologでのこの最小限の論理否定の実現が示されています。
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)、Dale Miller、Gopalan Nadathur、Frank Pfenning、Andre Scedrov