Prolog 约束规划中的标记
Labeling in Prolog constraint programming
我是 Prolog 的新手,目前正在研究一个简单的约束规划问题。所以我有四个实数 A、B、C、D 和 属性 这样
A+B+C+d = ABC*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
你面临两个问题,我想单独讨论:
实例化错误
如您所述,我们得到:
?- grocery(Vs), label(Vs).
ERROR: Arguments are not sufficiently instantiated
标注要求被标注的变量都具有有限域。在你的例子中,label/1
抛出一个 instantiation-error 因为一些变量的域仍然是 infinite:
?- 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[=84] =].
就像在 GUPU 中一样,使用以下定义来 概括掉 个目标:
:- op(950,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.
而现在我们知道:即使是更一般的程序也没有解决方案。
如果您希望在这种情况下得到解决方案,您将不得不更改剩余程序的部分以更正公式中的错误.
有关此方法的详细信息,请参阅 program-slicing and logical-purity。
我是 Prolog 的新手,目前正在研究一个简单的约束规划问题。所以我有四个实数 A、B、C、D 和 属性 这样 A+B+C+d = ABC*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
你面临两个问题,我想单独讨论:
实例化错误
如您所述,我们得到:
?- grocery(Vs), label(Vs). ERROR: Arguments are not sufficiently instantiated
标注要求被标注的变量都具有有限域。在你的例子中,label/1
抛出一个 instantiation-error 因为一些变量的域仍然是 infinite:
?- 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[=84] =].
就像在 GUPU 中一样,使用以下定义来 概括掉 个目标:
:- op(950,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.
而现在我们知道:即使是更一般的程序也没有解决方案。
如果您希望在这种情况下得到解决方案,您将不得不更改剩余程序的部分以更正公式中的错误.
有关此方法的详细信息,请参阅 program-slicing and logical-purity。