Prolog无限循环

时间:2017-01-02 19:35:06

标签: prolog clpfd

我的代码如下,这段代码是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,_,_,_,_,_]]).

2 个答案:

答案 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行,你有很多组合可以完成,其中大部分看起来非常相似。