我只是想知道你们中是否有人知道什么更快,
L=[1,2,3,4,5], all_different(L). % needs use_module(library(clpfd)).
或者
L=[1,2,3,4,5], is_set(L).
有谁知道?我的数独求解器需要更快的解决方案。谢谢!
all_diff/1和is_set/1之间的区别在于前者使用“约束逻辑”并且可以在列表的条目完全实例化之前施加预期限制,这样当 Prolog 引擎被迫统一或分配相等时会发生故障列表参数的两个条目的值。
我们可以用以下一对查询来说明all_diff的“约束逻辑” :
?- length(L,5), all_different(L), L=[1,2,3,4,5].
L = [1, 2, 3, 4, 5].
?- length(L,5), all_different(L), L=[1,2,3,4,1].
false.
有必要为all_different提供一个适当的列表,但不要拥有完全绑定或“基本”条目之一。上面表明all_diff可以预期地对列表的条目施加约束。
将结果与is_set进行比较:
?- length(L,5), is_set(L), L=[1,2,3,4,5].
L = [1, 2, 3, 4, 5].
?- length(L,5), is_set(L), L=[1,2,3,4,1].
L = [1, 2, 3, 4, 1].
一旦is_set成功,它就不能阻止将来创建相同条目的绑定。
所以谓词all_different依赖于约束逻辑库中的额外机制来完成is_set不能做的事情,并且在大多数情况下,这种额外的机制会增加开销。然而,在 viktor 的问题中使用了简单的方法,额外的机器并没有使用太多。检查是在完全绑定的条件下进行的,而不是以预期的方式进行的,并且效率是可比的。
使用谓词 time/1 来衡量推理次数和进行计算所花费的实际时间。在你的例子中,你会做类似的事情
time((L=[1,2,3,4,5], all_different(L))) vs. time((L=[1,2,3,4,5], is_set(L)))
请注意,测量的时间取决于第一次成功。