4

次の目標を見てください (Markus Triska の clpfd で swi-prolog を使用しています)。

result(Input,Result) :-
    Input #> 10,
    Result=decline.
result(Input,Result) :-
    Input in 0..20,
    Result=offer.

可能なクエリは次のようになります。

?- result(15,B).
B = decline ;
B = offer.

注文または何らかの解決策の優先順位を追加したいと考えています。「辞退」が に対する有効な応答でInput=15ある場合、2 番目の目標はもはや考慮されるべきではないため、それB=declineは解決策であり、 ではありませんB=offer

を追加できることはわかっています!/0が、その逆は機能しません。この述語に対して考えられるすべての答えを教えてください。

この例を考えると、 aResult=offerは に対してのみ真であるべきInput 0..10です。

述語内の順序を考慮しようとするとき、私はあまりにも命令的であると考えていますか?

4

4 に答える 4

8

ここにはいくつかの問題があります。まず、最も明白なものから始めましょう。

モデリングの問題

関係があります (result/2はおそらく最適な名前ではありません)。この関係は、いつdecline、いつoffer真になるべきかをモデル化する必要があります。プログラムを読む前に、Prolog に次のように質問します。

?- 結果 (X、辞退)、結果 (X、オファー)。
11..20 の X ;
間違い。

したがって、11 から 20 までの値については、関係があいまいです。決定を下したい場合は、まずこの関係を修正してください。実際には、私はから始めます

  • 関係であることを明確にする関係のより良い名前
  • 命令的な言い回しがない(好きInputまたは命令)
  • (=)/2よりコンパクトな定式化では、プログラムにそれほど多くの目標は必要ありません。代わりに、次のように記述できます。
heigth_decision(私、辞退) :-
   私は #< 10。

CLP における答えと成功 vs. ソリューション

そして、もっと根本的な問題がもう一つあります。これまでに与えられたすべてのSO回答はこの側面を完全に無視しているため、これは実際にははるかに深刻です。それは答えと成功の概念であり、一方で解決策の概念です。

Prolog でクエリを実行すると、返されるのは答えです。そのような答えには、L = [_,_]無限に多くの解を含む答えのように、解が含まれる場合があります。または、回答に のようなソリューションが 1 つだけ含まれる場合もありますDecision = decline。しかし、 のような制約を使用している場合は、その間にさらに多くのことがありますlibrary(clpfd)

これで有限数の解を得ることができます:

?- abs(X) #< 3.
X in -2..2.

または無限に多く:

?- X #> Y.
Y#=<X+ -1.

しかし、1 つのように見えない、正確に 1 つのソリューションを取得することもできます。

?- 2^X #= 1.
2^X#=1.

繰り返しますが、整数の解は 1 つしかありませんが、Prolog の場合、これは複雑すぎます。返されたのは、次のような回答でした。はい、この細字がすべて true である限り、すべて true です

さらに悪いことに、解決策が含まれていない回答が返されることがあります。

?- X^X#=0.
X^X#=0。

Prolog が十分に賢ければ、答えはfalse. しかし、決定不可能な問題を簡単に定式化できるという理由だけで、必ずしもそれほどスマートであるとは限りません。このような回答は、不一致と呼ばれることがあります。ドイツ語の概念Scheinlösung (〜偽の解決策ですが、否定的な意味合いは少ない) は、この考えをよりよく伝えています。

したがって、回答には解決策が含まれる場合がありますが、一部の回答には解決策がまったく含まれていません。このため、目標の成功を解決策の存在と見なすことはできません。つまり、(;)/2 – if-then-else、once/1、または !/0 として何らかのコミットを示唆するすべての SO 回答は、成功を解決策と見なす場合、すべて正しくありません。これを確認するには、次のように試してください。

?- X^X#=0, 結果(X,辞退).
X in 11..sup、
X^X#=0;
間違い。

?- X^X#=0, 結果(X,オファー).
X で 0..20、
X^X#=0。

では、どうすれば何かを確信できるようになるのでしょうか?

  • 目標の失敗に頼ることができます。

  • を試すことはできますがlabeling/2、これは有限領域でしか機能しません。

  • とを使用call_residue_vars/2copy_term/3て、「ぶらぶらしている」制約があるかどうかを判断できます。

  • 残念ながら、回答の変数に関係のない制約を隠す SWI のトップレベルに完全に依存することはできません。それらを正しく表示できるのは SICStus だけです。

于 2012-11-23T16:46:35.000 に答える
1

私を困惑させるのは、「逆はうまくいかない」と言うときです。なぜあなたは逆に行きたいのですか?

これは決定論的検索の明確なケースであり、Prologでそれを行う方法はカットです。最初のルールが満たされている場合は、他のブランチを開いたままにしないでください。または、チェックする範囲を相互に排他的にすることもできます。

ただいじり回しているだけでなく、何か深刻なことを実装しようとしている場合は、優先度の高いルールと遠隔反応ルールを読むことをお勧めします。Prologの上に構築されたフレームワークを見つけることができるはずです。これは、車輪の再発明をしなくても問題を解決するために使用できます。

于 2012-11-22T15:08:39.073 に答える
0

ここでは、建設的否定からのいくつかのアイデアが役立ちます。

仮説

論理的なカットを行う簡単な方法があります。制約は通常完全否定であるため、特に制約の場合。したがって、制約 C がある場合、通常、次のプロパティを持つ制約 C' を見つけることができます。

C' <=> ~C

次のように読み取れる 2 つの句の間で優先順位を課すには:

p :- C, q.
p :- r

次の手順を実行してください。

p :- C, q.
p :- C', r.

制約ソルバーが具体化された否定を提供する場合、(#\)/1 そのための演算子を定義することさえできます:

:- op(1050,xfy,#?).
:- op(1100,xfy,#:).
(A #? B #: C) :- (A, B); (#\ A, C).

そして、次のように書きます。

p :- C #? q #: r.

この戦略をあなたの例に適用しましょう:

現在、コードは次のようになっています。

result(Input, Result) :-
    Input #> 10,
    Result = decline.
result(Input, Result) :-
    Input in 0..20,
    Result = offer.

次に、次の操作を行います。

result(Input, Result) :-
    Input #> 10,
    Result = decline.
result(Input, Result) :-
    Input #=< 10, Input in 0..20,
    Result = offer.

実行例を次に示します。

?- result(15, X).
X = decline ;
false.

?- result(8, X).
X = offer.

(#?)/2CLP(FD) ライブラリが具体化をサポートしているため、たとえば SWI-Prolog でこれを使用できるようになりました。(#:)/2CLP(FD) ライブラリを参照し、上記のように定義したと仮定します。

 result(Input, Result) :-
    Input #> 10 
    #? 
       Result = decline 
    #: 
       Input in 0..20,
       Result = offer.

実行例を次に示します。

?- result(15, X).
X = decline ;
false.

?- result(8, X).
X = offer.

免責事項

(#?)/2andの後者の構文は、Java の if-then-else 演算子and(#:)/2に触発されています。定義をオーバーライドまたは拡張できないため、より Prolog にインスパイアされた構文は使用できません。(?)/2(:)/2(;)/2

具体化の詳細については、たとえばここのセクション A.8.4 具体化を参照してください。私たちがしなかったことは、CLP(FD) if-then-else の定義で論理積と論理和を具体化することでした。なぜなら、then と else の部分には、CLP(FD) 制約以外の他の目標が含まれる可能性があるからです。

さよなら

于 2016-02-28T22:07:46.210 に答える
0

述語の順序は、Prolog プログラムの重要な部分です。これは、プルーフ サーチが厳密に定義された順序で進行し、SLD 解決が適用されるためです。

あなたの述語は妥当な結果をもたらします:

?- result(X,Y).
Y = decline,
X in 11..sup ;
Y = offer,
X in 0..20.

result/2 のカットの代わりに、呼び出し時に once/1 を使用して、一般的な使用に適切な定義を保持できます。

?- once(result(X,Y)).
Y = decline,
X in 11..sup.
于 2012-11-22T15:59:31.603 に答える