1

我是 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

4

1 回答 1

3

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

实例化错误

正如你提到的,我们得到:

?- 杂货店(Vs),标签(Vs)。
错误:参数没有充分实例化

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

?- 杂货店([A,B,C,D])。
A inf.. -1\/1..sup ,
100*A#=_9006,
_9006 inf.. -100\/100..sup,
_9006+_9084+_9078+_9072#=711,
_9006*_9084#=_9102,
_9084 inf.. -100\/100..sup,
100*B#=_9084,
_9102 inf.. -1\/1..sup,
_9102*_9078#=_9222,
_9078 inf.. -100\/100..sup,
100*C#=_9078,
C inf.. -1\/1..sup ,
_9222 在 -71100000000.. -1\/1..71100000000,
_9222*_9072#=71100000000,
_9072 在 -71100000000.. -100\/100..71100000000,
100*D#=_9072,
D 在 -711000000.. -1\/1..711000000,
B inf.. -1\/1..sup

纠正这个问题的唯一机会是创建一个合适的程序专业化,其中变量以有限域结束。写[Vs]而不是Vs显然没有解决办法:

?- 杂货店(Vs),标签([Vs])。
错误:类型错误:预期为“整数”,找到“[_8206,_9038,_8670,_8930]”(列表)

这是因为label/1要求它的参数是有限域变量的列表,而不是列表的 列表

合适的专业化示例可能是:

?- 杂货店(Vs),Vs ins 0..sup,标签(Vs)。
的。

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

没有解决方案

因此,我们遇到了第二个相当独立的问题:为什么这个结果程序没有解决方案?

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

就像在 GUPU 中一样,使用以下定义来概括客场目标:

:- op(950,fy, *).

*_.

例如,我们可以概括掉程序的最后一个目标:

杂货店(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 回答