1

私は Prolog を初めて使用し、現在単純な制約プログラミングの問題に取り組んでいます。したがって、A + B + C + d = A B C * D = 7.11というプロパティを持つ 4 つの実数 A、B、C、D があります。整数で作業する方が簡単なので、次の実装を試しました。

   :- use_module(library(clpfd)).
   grocery(Vars):-
      Vars=[A,B,C,D],
      X #= 100 * A,
      Y #= 100 * B,
      Z #= 100 * C,
      W #= 100 * D,
      X+Y+Z+W #= 711,
      X*Y*Z*W #= 71100000000.

上記は部分的に解決された答えを与えるので、キーワードlabel(Vars)を最後に入れてみました。しかし、これにより、私の実行がgrocery(V)生成されます

ERROR: Arguments are not sufficiently instantiated.

grocery([V])与えてくれますfalse。ラベル付けの方法を教えてもらえますか? ありがとう

編集:以前にライブラリclpfdへの呼び出しを入れませんでした

4

1 に答える 1

3

あなたは私が別々に議論したい2つの問題に直面しています:

インスタンス化エラー

あなたが述べたように、私たちは得ます:

?- 食料品 (Vs)、ラベル (Vs)。
エラー: 引数が十分にインスタンス化されていません

ラベル付けでは、ラベル付けされるすべての変数が有限ドメインを持っている必要があります。あなたの場合、いくつかの変数のドメインがまだ無限であるため、label/1がスローされます。

?- 食料品([A,B,C,D])。
A in inf.. -1\/1..sup ,
100*A#=_9006,
_9006 in inf.. -100\/100..sup,
_9006+_9084+_9078+_9072#=711,
_9006*_9084#=_9102,
_9084 in inf.. -100\/100..sup,
100*B#=_9084、
_9102 in inf.. -1\/1..sup,
_9102*_9078#=_9222,
_9078 in inf.. -100\/100..sup,
100*C#=_9078,
C in inf.. -1\/1..sup、
_9222 in -71100000000.. -1\/1..71100000000,
_9222*_9072#=71100000000,
_9072 in -71100000000.. -100\/100..71100000000,
100*D#=_9072,
D in -711000000.. -1\/1..711000000,
B in inf.. -1\/1..sup .

これを修正する唯一の方法は、プログラムの適切な特殊化を作成することです。この場合、変数は最終的に有限領域になります。[Vs]の代わりに書くことVsは明らかに解決策ではありません:

?- 食料品(Vs)、ラベル([Vs])。
エラー: タイプ エラー: 'integer' が必要ですが、'[_8206,_9038,_8670,_8930]' (リスト) が見つかりました

これはlabel/1、引数がリストのリストではなく、有限ドメイン変数のリストである必要あるため です。

適切な専門化の例は次のとおりです。

?- 食料品 (Vs)、Vs ins 0..sup、ラベル (Vs)。

結果のプログラムにはがありませんが、インスタンス化エラーがなくなるため、少なくとも絶対に解がないことがわかります。

解決策なし

このようにして、2 番目のかなり独立した問題に到達しました。なぜ、この結果のプログラムには解がないのでしょうか?

Prolog のようなロジック プログラミング言語を使用する主な利点は、たとえばGUPUで示されているように、宣言型デバッグアプローチを 適用できることです。

GUPU と同様に、次の定義を使用してアウェイゴールを一般化します。

:- op(950,fy, *).

*_.

たとえば、プログラムの最後の目標を一般化できます。

食料品(Vars):-
        Vars = [A、B、C、D]、
        X #= 100 * A,
        Y #= 100 * B,
        Z #= 100 * C、
        W #= 100 * D、
        X+Y+Z+W #= 711,
        *  X*Y*Z*W #= 71100000000 .

純粋単調なProlog プログラムから制約を取り除いたので、結果のプログラムは明らかに元のプログラムよりも一般的です。

ここで、前のクエリを取得します。

?- 食料品(Vs)、Vs ins 0..sup、ラベル(Vs)。

そして今、私たちは知っています:より一般的なプログラムでさえ解決策がありません.

この場合の解決策を期待する場合は、残りのプログラムの一部を変更して、定式化の誤りを修正する必要があります。

このアプローチの詳細については、およびを参照してください。

于 2016-10-28T08:09:58.167 に答える