看看以下目标(我使用来自Markus Triska的clpfd的swi-prolog):
result(Input,Result) :-
Input #> 10,
Result=decline.
result(Input,Result) :-
Input in 0..20,
Result=offer.
Run Code Online (Sandbox Code Playgroud)
可能的查询如下所示:
?- result(15,B).
B = decline ;
B = offer.
Run Code Online (Sandbox Code Playgroud)
我想添加订单或某种解决方案优先级.如果"拒绝"是有效的响应Input=15
,则不应再考虑第二个目标,因此只有B=decline
解决方案而不是B=offer
.
我知道我可以添加一个!/0
然后反过来也行不通.给我这个谓词的所有可能答案.
考虑到这个例子,a Result=offer
应该只适用于Input 0..10
,否则应该触发较高的先前下降目标.
当我尝试在谓词中考虑订单时,我是否认为太迫切了?
这里有几个问题,让我们先从最明显的开始:
你有关系(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.
然后还有另一个更基本的问题.这实际上要严重得多,因为到目前为止给出的所有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 (假的解决方案,但具有较少的负面含义)传达了这个想法更好.
所以答案可能包含解决方案,但有些答案根本不包含解决方案.因此,目标的成功不能视为解决方案的存在!也就是说,所有SO-answers建议某种提交为(;)/ 2 - if-then-else,一次/ 1或!/ 0都是不正确的,如果他们将成功作为解决方案.要看到这一点,请尝试使用:
?- 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才能正确显示它们.