我的代码如下,这段代码是Sudoku求解的代码,但是对于行和列,第一次运行div2检查raw是否全部不同然后在转置第二次运行div2之后应该检查列是否是各种各样。
:- use_module(library(clpfd)).
len(P):-
div2(P),
write("\n 1P2: "),
write(P),
transpose(P,X),
div2(X),
write("\n 1X: "),
write(X).
div2([H|T]) :-
H ins 1..9,
all_distinct(H),
label(H),
div2(T).
div2([]).
为什么它会陷入无限循环?在使用此示例进行测试时,它会将其自身重复到无限循环中,在第一次运行X后它应该停止。
len([
[_,_,_,_,_,4,3,_,7],
[7,6,_,1,5,_,_,_,9],
[_,5,_,_,_,_,_,_,_],
[6,_,5,_,_,8,7,_,_],
[9,_,_,_,_,_,_,_,4],
[_,_,3,2,_,_,1,_,5],
[_,_,_,_,_,_,_,6,_],
[5,_,_,_,3,1,_,2,8],
[1,_,9,4,_,_,_,_,_]]).
答案 0 :(得分:2)
@Scott的答案是对的,你的程序确实找到了所有的解决方案。但是我们似乎等待的时间太长了。
相反,请删除label/1
目标,这是枚举这些解决方案的来源并在最后添加!
latin_(P,Vs) :-
div2(P),
transpose(P,X),
div2(X),
append(P,Vs).
latin(P) :-
latin_(P, Vs),
labeling([], Vs).
使用有限域进行约束编程的想法是将实际枚举(标记)延迟到稍后的点。以这种方式,标记可以考虑所有现有约束。确保遵循此方法的最简单方法是将谓词拆分为两部分。实际的核心关系(latin_/2
)和完整的关系(latin/1
)。通常,可以观察到核心关系的终止,而这对于完整的关系来说是非常昂贵的。
答案 1 :(得分:1)
它不是一个"无限循环",只是一个非常长的。
假设div2(P)
找到了一个建议的解决方案,div2(X)
确定该解决方案不是解决方案。 div2(P)
将回滚&通过为最后一行提供一个新标签来生成另一个解决方案,至少在它已经用尽所有标记最后一行的方式之前,然后为倒数第二行获得一个新的标签 - 行,然后再次运行最后一行的所有可能性。将它滚动到所有9行,你有很多组合可以完成,其中大部分看起来非常相似。