对于家庭作业,所以没有明确的,请:
有没有办法让Prolog只返回程序找到的第一个目标而忽略找到的其他目标?
为了说明的目的,给出了程序:
permutation([X|Xs],Zs):-permutation(Xs,Ys), insert(X,Ys,Zs).
permutation([],[]).
有没有办法让程序只返回第一个排列作为唯一的解决方案?在以下情况中:
| ?- permutation([1,2,3],X).
X = [1,2,3] ? ;
X = [1,3,2] ? ;
X = [2,1,3] ? ;
X = [2,3,1] ? ;
X = [3,1,2] ? ;
X = [3,2,1] ? ;
no
我们可以
吗?X = [1,2,3] ?;
no
作为解决方案?
答案 0 :(得分:6)
剪切它是您正在寻找的控件。把它放在需要提交解决方案的地方(我猜这里是顶级的)。还有内置的一次/ 1 ,它允许在本地限制提交的范围(例如在findall / 3中内联的连接中很有用)。
答案 1 :(得分:4)
每当搜索树中的替代分支成为可能时,Prolog就会设置选择点。为了避免回溯到选择点并探索这些替代方案,您必须添加一个剪切(!/0
)。
您必须检查程序中选择点的位置,并在该调用后添加剪切。
答案 2 :(得分:2)
坚持第一个解决方案的最佳方法是once/1
,因为这会使效果尽可能保持在本地。使用!/0
通常会产生意想不到的影响,因为!/0
的范围更大。我们来看一个非常简单的例子:
( X = 1 ; X = 2 ; X = 3 )
p(X) :- ( X = 1 ; X = 2 ; X = 3 ).
p(4).
使用once/1
我们得到:
p1(X) :- once( ( X = 1 ; X = 2 ; X = 3 ) ).
p1(4).
?- p1(X).
X = 1 ;
X = 4.
使用!
,我们只得到一个答案:
p2(X) :- ( X = 1 ; X = 2 ; X = 3 ), !.
p2(4).
?- p2(X).
X = 1.
这通常不是故意的。
但是提交第一个解决方案存在一个更普遍的问题。
?- p1(2).
true.
?- dif(X,1),p1(X).
X = 2 ;
X = 4.
那么,2现在也是第一个解决方案吗?出于这样的原因,必须非常小心地使用承诺。显示与p1/1
类似行为的谓词缺乏坚定性。这样的谓词不能被理解为关系,因为它根据实际查询改变其含义。