0

PROLOG の学習を開始しましたが、非常に基本的な例に問題があります。私は SWI PROLOG を使用しており、コードは次のとおりです。

is_true(a).
is_true(c).
is_true(d).
is_false(b).
is_false(e).

and(A,B) :- is_true(A),is_true(B).
nand(A,B) :- \+(and(A,B)).

それで:

[imanol@I56106 prolog]$ swipl
Welcome to SWI-Prolog (Multi-threaded, 64 bits, Version 6.6.4)
Copyright (c) 1990-2013 University of Amsterdam, VU Amsterdam
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software,
and you are welcome to redistribute it under certain conditions.
Please visit http://www.swi-prolog.org for details.

For help, use ?- help(Topic). or ?- apropos(Word).

?- consult(test).
% test compiled 0.00 sec, 8 clauses
true.

?- and(a,X).
X = a ;
X = c ;
X = d.

すべてが素晴らしい ATM です。私は、A=a の目標と (A,B) に適合するすべての可能な値を PROLOG にバックトラックさせました。しかし、目標 nand(A,B) を試してみると:

?- nand(a,X).
false.

目標が不可能だと考えているか、後戻りしないかのどちらかであり、その理由はまったくわかりません。:/

誰かが私が間違っていることを知っていますか?

前もって感謝します。

PS:私も試しました:

nand(A,B) :- not(and(A,B)).

そして、それは同じ結果をもたらします。

編集:私の質問が一部の人にとって不可解であることを確認してください:

PROLOG に、and(A,B) を満たさない変数 A と B の値のリストを提供してもらいたい

EDIT2:PROLOGが教えてくれることを期待しています:

?- nand(a,X).
    X = e ;
    X = b.
4

2 に答える 2

1

SWI-Prolog のドキュメントから:

「……『Goal』が証明できないなら真……」

つまり、失敗し\+(and(A, B))た場合にのみ成功and(A, B)します。つまり、 の解決策がある場合and(A, B)\+(and(A, B))は失敗します。

and(a, X)私が見たところ、 との両方に解決策がありand(A, B)ます。

として明示的に宣言されていない引数のクエリを試してくださいis_true/1

「失敗としての否定」と「閉じた世界の仮定」をググってみてください。どちらにも、読む価値のあるウィキペディアの記事があります。

ブール論理と Prolog を混在させる場合は注意してください。彼らは同じ仮定をしていません。

あなたの問題に:論理変数がたくさんあります。それらのいくつかは真実であり、いくつかは間違っています。真理値表を計算できるようにしたいと考えています。出力列がtrueand(A, B)の場合は成功し、それ以外の場合は失敗します。この時点で、すでに 2 つの異なる概念を混同しています。

  1. 論理 TRUE および FALSE
  2. プロローグの成功と失敗

これは実際には十分に間違っているので、反対することをお勧めします。その代わり:

and(f, f, f).
and(f, t, f).
and(t, f, f).
and(t, t, t).

not(t, f).
not(f, t).

nand(A, B, R) :- and(A, B, R0), not(R0, R).

val(a, t). val(c, t). val(d, t).
val(b, f). val(e, f).

solve(and(A, B), R) :- val(A, VA), val(B, VB), and(VA, VB, R).
% solve(nand...) as exercise

等々。

次に、より有益なクエリを作成できます。

?- solve(and(a, c), R).
R = t.

?- solve(and(a, X), R).
X = a,
R = t ;
X = c,
R = t ;
X = d,
R = t ;
X = b,
R = f ;
X = e,
R = f ;
false.

?- solve(nand(a, X), R).
X = a,
R = f ;
X = c,
R = f ;
X = d,
R = f ;
X = b,
R = t ;
X = e,
R = t ;
false.
于 2015-03-05T15:42:21.993 に答える
1

単純なアプローチは、有効な変数に対して成功する述語を導入することです。したがって、既存の述語に次を追加します。

is_valid(X) :- is_true(X) ; is_false(X).

次に、nand/2述語はそのドメイン内で機能し、可能な値の宇宙を制限できます。そうでなければ、\+ and(A, B)の失敗を判断するためにどの値を選択すればよいかわかりませんand(A, B):

nand(A, B) :- is_valid(A), is_valid(B), \+ and(A, B).

| ?- nand(a, X).

X = b ? ;

X = e ? ;

no

別の言い方をすれば、テスト可能なオプションを生成するis_valid/1手段を提供します。nand/2\+ and(A, B)

この「宇宙の限定」をand/2:などの他の述語に合理的に適用するand(A, B) :- is_valid(A), is_valid(B), is_true(A), is_true(B).こともできますが、これは冗長であることがわかります。

于 2015-03-05T19:23:23.193 に答える