Prolog中的迷你数独求解器在中途停止

时间:2011-04-11 05:31:21

标签: prolog sudoku clpfd

我正在研究“七周七种语言”,我只想从书中找到一个例子。它解决了一个迷你数独网格(4x4)。

作者正在使用gprolog,但我正在使用swi-prolog(无论出于何种原因,我都无法使用gprolog在我的VM上工作,但是swi-prolog首先尝试了)。

我在VirtualBox 4.0.4 r70112中运行Ubuntu 10.04(希望这不太相关!)

以下是我的prolog文件中的代码:

:- use_module(library(clpfd)).

valid([]).
valid([Head|Tail]) :-
    all_different(Head),    % in the book, this is 'fd_all_different'
    valid(Tail).

 % beginning of sudoku rule itself
sudoku(Puzzle, Solution) :- 
Solution = Puzzle,
Puzzle = [S11, S12, S13, S14,
          S21, S22, S23, S24,
          S31, S32, S33, S34,
          S41, S42, S43, S44],
Puzzle ins 1..4,    % in the book, this is 'fd_domain'

Row1 = [S11, S12, S13, S14],
Row2 = [S21, S22, S23, S24],
Row3 = [S31, S32, S33, S34],
Row4 = [S41, S42, S43, S44],

Col1 = [S11, S21, S31, S41],
Col2 = [S12, S22, S32, S42],
Col3 = [S13, S23, S33, S43],
Col4 = [S14, S24, S34, S44],

Square1 = [S11, S12, S21, S22],
Square2 = [S13, S14, S23, S24],
Square3 = [S31, S32, S41, S42],
Square4 = [S33, S34, S43, S44],

valid([Row1, Row2, Row3, Row4,
       Col1, Col2, Col3, Col4,
       Square1, Square2, Square3, Square4]).

我(有意)改变的唯一部分是:

  • 在顶部添加use_module(library(clpfd)).
  • fd_all_different(Head),更改为all_different(Head),
  • fd_domain(Puzzle, 1, 4),更改为Puzzle ins 1..4,

这是swipl的调用

?- sudoku([_, _, 2, 3,
           _, _, _, _,
           _, _, _, _,
           3, 4, _, _],
Solution).
Solution = [4, 1, 2, 3, 2, 3, 4, 1, 1|...] ;
false.

解决方案是正确的,直到它被切断,此时prolog似乎确定没有解决方案。但是有:

4 1 2 3
2 3 4 1
1 2 3 4
3 4 1 2

我已经搜索了代码,寻找拼写错误或错位的列,但一直无法找到它的来源。有什么想法吗?

2 个答案:

答案 0 :(得分:4)

在我看来,你依靠SWI-Prolog中的默认显示来编写代表解决方案的列表,并且它是SWI-Prolog的一个特性,它不打印这个长列表的所有条目使用“省略号”替换9个项目后的尾部...

当您向目标添加write(Puzzle)并因此看到整个列表时,您偶然发现了这一点。 SWI-Prolog的网站has a FAQ about this "abbreviation" of lists

答案 1 :(得分:2)

您自己输入;,不是吗? ;要求提供更多解决方案。由于您没有对变量使用labeling,因此Prolog仅限制它们而不实际生成完整的解决方案(它会执行一些constraint propagation来派生一些值)。只有一种方法来设置约束,所以没有第二种解决方案。如果您在labeling子句的末尾拨打sudoku,则可以循环使用这些解决方案。

(PS。:sudoku不需要两个参数,因为您将它们与Solution = Puzzle统一起来。)