这是一个简单的CLPFD关系:
1 #= 81 mod X.
返回:
X in inf.. -1\/1..sup,
81 mod X#=1.
除非我的数学完全不正确,否则X
的域名不应该是-80.. -1\/1..80
?
答案 0 :(得分:4)
首先要做的事情:
约束求解器中是否存在错误?
否(必要),因为所有可接受的解决方案仍包含在推断的域中,并且未报告错误的解决方案。您推导出的域是解算器报告的正确子集。
在这种情况下,约束求解器是否会传播?
没有,显然不是,因为你的强势界限已经显示出来了。事实上,可接受的域甚至比你推断的要小:X in 2..80
也有效,因为X
肯定不是否定的,并且不能等于1。
练习:X in 2..80
最小(关于集合包含)域,在这种情况下可以推断出来吗?为什么不)?在什么,如果有的话,感觉是它是最小的?
那么,这里发生了什么?
解释相当简单:实施(mod)/2
,(rem)/2
,(div)/2
以及 - 在更小程度上 - 甚至(*)/2
以这样的方式传播在所有情况下尽可能残酷地才能做到正确,并且在这种情况下显然没有完成。
我们是否必须忍受这个缺点?
否,因为我们可以改进约束求解器来处理这种情况!也就是说,我们可以添加逻辑,以便它更强烈地传播 !优雅而正确地执行此操作通常是未解决的问题,以及活跃研究的主题。参见例如Finite Domain Constraint Solver Learning,其中包含的参考文献以及其他几篇论文。当然,梦想是以某种方式直接从这些操作的规范中获得传播,这至少需要几十年的时间。在此之前,发现并改进了这些问题,而不是 ad hoc 。
答案 1 :(得分:1)
免责声明:我不知道我在说什么,我只想亲眼看看会发生什么,并认为分享可能会有用。
使用SWI-Prolog和库(clpfd):
?- use_module(library(clpfd)).
true.
?- 1 #= 81 rem X.
X in inf.. -1\/1..sup,
81 rem X#=1.
?- 1 #= 81 mod X.
X in inf.. -1\/1..sup,
81 mod X#=1.
?- 1 #= 81 - X * (81 // X ).
X in -80.. -1\/1..80,
X*_G1053#=80,
81//X#=_G1053,
_G1053 in -80.. -1\/1..80.
奇怪的是,上一个例子中的表达式是不是应该如何定义模除法?
如果你服用Gnu-Prolog(mod
不直接支持):
| ?- 1 #= 81 rem X.
X = _#4(2..80)
yes
| ?- 1 #= 81 - X * (81 // X).
no
嗯。如果您只是重新排序表达式:
,该怎么办?| ?- 1 #= 81 - (81 // X) * X.
X = _#4(2..80)
yes
结论:是的,似乎写一个好的CLP(FD)库确实不容易。甚至可能会给人留下这样的印象,即这些图书馆表现出作者并不总是完全了解的紧急行为。