查看以下目标(我使用 swi-prolog 和 Markus Triska 的 clpfd):
result(Input,Result) :-
Input #> 10,
Result=decline.
result(Input,Result) :-
Input in 0..20,
Result=offer.
可能的查询如下所示:
?- result(15,B).
B = decline ;
B = offer.
我想添加订单或某种解决方案优先级。
如果“decline”是 Input=15
的有效响应,则不应再考虑第二个目标,因此只有 B=decline
是解决方案,而 >B=报价
。
我知道我可以添加 !/0
但反过来就行不通了。给我这个谓词的所有可能的答案。
考虑到此示例,Result=offer
应该仅对于 Input 0..10
为 true,否则应触发更高的优先拒绝目标。
当我尝试考虑谓词内的顺序时,我是否认为太势在必行?
最佳答案
这里有几个问题,让我们首先从最明显的问题开始:
建模问题
您有一个关系( result/2
可能不是最好的名字),并且该关系应该在 decline
时建模当 offer
应该是真的。在阅读你的程序之前,我更喜欢问Prolog:
?- result(X, decline), result(X, offer). X in 11..20 ; false.
因此,对于从 11 到 20 的值,您的关系是不明确的。如果你想做出决定,那就先修复这个关系。实际上,我会从
- 关系的更好名称,表明它是一个关系
- 没有祈使句(例如
Input
或祈使句) - 更紧凑的配方,不需要那么多
(=)/2
你的计划中的目标。相反,你可以这样写:
heigth_decision(I, decline) :- I #< 10.
CLP 中的答案和成功与解决方案
还有另一个更根本的问题。这实际上要严重得多,因为到目前为止给出的所有 SO 答案都完全忽略了这一方面。它涉及答案和成功的概念,另一方面涉及解决方案的概念。
当您在 Prolog 中提出查询时,您得到的就是答案。这样的答案可能包含解决方案,例如答案 L = [_,_]
其中包含无限多个解。或者答案可能只包含一个解决方案,如 Decision = decline
。但是,如果您使用像 library(clpfd)
这样的约束,那么两者之间还有更多的内容。 .
您现在可以获得有限多个解决方案:
?- abs(X) #< 3. X in -2..2.
或者无穷多个:
?- X #> Y. Y#=<X+ -1.
但是您也可以获得完全相同的一种解决方案,但它看起来并不像一个:
?- 2^X #= 1. 2^X#=1.
所以,重申一下:我们这里只有一个整数解,但对于 Prolog 来说这太复杂了。我们得到的答案是:是的,这都是真的,只要所有这些细则都是真的。
更糟糕的是,有时我们得到的答案不包含任何解决方案。
?- X^X#=0. X^X#=0.
如果 Prolog 足够聪明,它会回答 false
。但它不可能总是那么聪明,仅仅因为你可以轻松地提出无法判定的问题。这样的答案有时被称为不一致。德国的概念 Scheinlösung(~假解决方案,但负面含义较少)更好地传达了这个想法。
所以答案可能包含解决方案,但有些答案根本不包含解决方案。因此,目标的成功并不能视为解决方案的存在!也就是说,如果将成功视为解决方案,则所有建议某种提交(如 (;)/2 – if-then-else、once/1 或 !/0)的 SO 答案都是不正确的。要看到这一点,请尝试使用:
?- X^X#=0, result(X,decline). X in 11..sup, X^X#=0 ; false. ?- X^X#=0, result(X,offer). X in 0..20, X^X#=0.
那么你现在怎么能确定任何事情呢?
目标的失败是值得信赖的。
您可以尝试
labeling/2
,但这仅适用于有限域。您可以使用
call_residue_vars/2
和copy_term/3
确定是否存在“徘徊”的约束不幸的是,您不能完全依赖 SWI 的顶层,它隐藏了与答案中的变量无关的约束。只有 SICStus 能够正确显示它们。
关于prolog - 将命令纳入谓词解析,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13515161/