在Prolog约束编程中标记

时间:2016-10-27 17:52:32

标签: prolog clpfd instantiation-error

我是Prolog的新手,目前正致力于一个简单的约束编程问题。所以我有四个实数A,B,C,D具有这样的属性 A + B + C + d = A B C * D = 7.11 由于使用整数更容易,我尝试了以下实现:

   :- 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

1 个答案:

答案 0 :(得分:3)

您正面临两个问题,我想分别讨论

实例化错误

如你所说,我们得到:

?- grocery(Vs), label(Vs).
ERROR: Arguments are not sufficiently instantiated

标记要求所有要标记的变量都具有有限域。在您的情况下,label/1会引发,因为某些变量的域仍为无限

?- grocery([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显然不是解决方案:

?- grocery(Vs), label([Vs]).
ERROR: Type error: `integer' expected, found `[_8206,_9038,_8670,_8930]' (a list)

这是因为label/1要求其参数为有限域变量列表, 列表列表。

合适的专业化的一个例子可能是:

?- grocery(Vs), Vs ins 0..sup, label(Vs).
false.

生成的程序无解决方案,但至少我们知道肯定没有解决方案,因为没有更多的实例化错误。

没有解决方案

我们因此得出了第二个,而不是独立的问题:为什么这个结果程序没有解决方案?

使用像Prolog这样的逻辑编程语言的一个主要优点是它可以应用声明性调试方法,例如 GUPU 中所示。

与GUPU一样,使用以下定义概括目标:

:- op(920,fy, *).

*_.

例如,我们可以概括您计划的最后一个目标:

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.

结果程序显然比原始程序更通用,因为我们单调中删除了约束 Prolog程序。

现在,我们仍然可以获得前面的查询:

?- grocery(Vs), Vs ins 0..sup, label(Vs).
false.

现在我们知道了:即使是更通用的程序也没有解决方案。

如果您希望在这种情况下解决方案,则必须更改剩余程序的部分以更正公式中的错误。

有关此方法的详细信息,请参阅