私が直面している問題は少し些細なことです。 Prologではなくlogicalを使用したいのですが、not/1
は私が欲しいものではありません:
course(ai).
course(pl).
course(os).
have(X,Y) :- course(X),course(Y),not(X = Y).
私はクエリ:
have(X,Y), write(X-Y), nl , fail.
そして、私は望む結果を得られません:(
not(X = Y)
の代わりに、_\+ X = Y
_または_X \= Y
_を記述する必要があります。ただし、代わりにdif(X,Y)
を使用することを検討してください。 _dif/2
_は、B、SWI、YAP、SICStusに存在します。違いを確認するには:
_?- X = b, dif(a, X).
X = b.
?- X = b, \+ a = X.
X = b.
_
これまでのところ、すべてがうまくいくようです。しかし、2つの目標の順序を単純に交換する場合はどうでしょうか。
_?- \+ a = X, X = b.
false.
?- dif(a, X), X = b.
X = b.
_
_(\+)/1
_は、_a = X
_に答えがあるため、目標_\+ a = X
_が失敗するため、異なる結果が得られます。
したがって、_(\+)/1
_は否定ではなく、この時点で証明できないことを意味します。
安全な近似 of _dif/2
_もISO Prologで可能です。
SWI-PrologとGNU Prologの両方で、以下が機能するはずです。
have(X, Y) :- course(X), course(Y), X \= Y.
SWI-Prologでは、dif/2
。これは、述語の前半で使用できるため、より便利です。
have(X, Y) :- dif(X, Y), course(X), course(Y).
上記のユーザー「false」による回答の補助として、つまり.
「not(X = Y)の代わりに\ + X = Yと書く必要があります」
これにより、次のような印象が得られます。
a。 「not」と「\ +」は異なるものです
b。\+は機能しますが、notは機能しません。
私の理解では、「not」と「\ +」は同等ですが、最新のPrologプログラムでは\ +が好まれます。なぜなら、より直感的な感覚を伝えるからです。具体的には、「not」は不注意なコーダーに「真ではない」ことを示唆する場合がありますが、「\ +」は「証明可能でない」ことを示唆します。 Prologでは、「not」は「失敗としての否定」の例ですが、\ +を使用すると、特定のルールで正確にアサートされていることをプログラマーに明確にすることができます。したがって、「not」を使用できます(ほとんどのPL実装は下位互換性のために保持します)が、慣用的な現代のPLプログラマーになるには、おそらく\ +を使用することをお勧めします。
Samuel Kaminの book の第8章prologを読んで、ここにも適合するこのソリューションを見つけ、cut
の使用方法を説明します。
カットは、バックトラックが許可されていない場所を示すことをプログラマに許可することにより、プログラマが計算をさらに制御できるようにする方法です。具体的には、カットは感嘆符(!)として書き込まれます。これは、次のような句の右側のゴールとして発生します。
_G :- H, !, R.
_
この節が、G 統一 である目標gを満たすように選択されているとします。 Hを満たすための試みが行われます。成功した場合、Rが証明されます。 Rの証明が成功した場合、gが証明されます;この場合、カットには再生する部分がありません。 ただし、Rの証明が失敗した場合、バックトラックしてHを再証明しようとするのではなくカットの結果、ゴールgはすぐに失敗します;これは、gに適用される可能性のある句がさらにある場合でも発生します。例は、not-equalsの定義です。
_equals(X, X).
not-equals(X, Y) :- equals(X, Y), !, fail.
not-equals(X, Y).
_
not-equals(X, Y)
は、XがYと等しくない場合は成功し、等しい場合は失敗します。この目標を達成しようとする場合、XとYは グラウンドエクスプレッション (つまり、自由変数がない)にバインドする必要があります。
あなたが言ったように、OP、これは簡単です。
試して
course(ai).
course(pl).
course(os).
have(X,Y) :- course(X), course(Y), X \== Y).
これで述部が修正されます。
数学的に言い換えると、一歩先を見ると、おそらく(n [〜#〜] c [〜#〜] 2)(n [〜 #〜] p [〜#〜] 2)述語が現在提供しているもの-置換ではなく組み合わせ、選択の選択肢の配置ではなく選択の選択肢。これが私が思うことです。
これがあなたが望むものであれば、私はあなたが試してみることをお勧めします
course(ai).
course(pl).
course(os).
have(X,Y) :- course(X), course(Y), X @< Y).
これにより、重複した逆の結果が防止されます。
@<
は、原子的により小さいことを意味します。 <
は整数用、@<
はアトム用です。