理解Prolog中的约束

理解Prolog中的约束,prolog,clpfd,Prolog,Clpfd,我试图熟悉Prolog中的约束条件,但在理解以下程序时遇到困难: sudoku(Rows) :- length(Rows, 9), maplist(same_length(Rows), Rows), append(Rows, Vs), Vs ins 1..9, maplist(all_distinct, Rows), transpose(Rows, Columns), maplist(all_distinct, Co

我试图熟悉Prolog中的约束条件,但在理解以下程序时遇到困难:

sudoku(Rows) :-
        length(Rows, 9), maplist(same_length(Rows), Rows),
        append(Rows, Vs), Vs ins 1..9,
        maplist(all_distinct, Rows),
        transpose(Rows, Columns),
        maplist(all_distinct, Columns),
        Rows = [As,Bs,Cs,Ds,Es,Fs,Gs,Hs,Is],
        blocks(As, Bs, Cs),
        blocks(Ds, Es, Fs),
        blocks(Gs, Hs, Is).

blocks([], [], []).
blocks([N1,N2,N3|Ns1], [N4,N5,N6|Ns2], [N7,N8,N9|Ns3]) :-
        all_distinct([N1,N2,N3,N4,N5,N6,N7,N8,N9]),
        blocks(Ns1, Ns2, Ns3).

problem(1, [[_,_,_,_,_,_,_,_,_],
            [_,_,_,_,_,3,_,8,5],
            [_,_,1,_,2,_,_,_,_],
            [_,_,_,5,_,7,_,_,_],
            [_,_,4,_,_,_,1,_,_],
            [_,9,_,_,_,_,_,_,_],
            [5,_,_,_,_,_,_,7,3],
            [_,_,2,_,1,_,_,_,_],
            [_,_,_,_,4,_,_,_,9]]).
如果有人能帮助我分解此代码,以便更好地理解如何使用约束解决此问题,我将不胜感激。

发生的事情是:

  • 数独/1
    对9x9元素矩阵施加约束
    • 借助
      blocks/2
  • 问题/2
    列出了一个特定的问题
然后我们可以把两者结合起来:

?-问题(1,矩阵),
%矩阵现在是部分绑定元素的9x9矩阵。
%施加约束;这些足以找到一个独特的解决方案
数独(矩阵)。
矩阵=[[9,8,7,6,5,4,3,2,1],
[2,4,6,1,7,3,9,8,5],
[3,5,1,9,2,8,7,4,6],
[1,2,8,5,3,7,6,9,4],
[6,3,4,8,9,2,1,5,7],
[7,9,5,4,6,1,8,3,2],
[5,1,9,2,8,6,4,7,3],
[4,7,2,3,1,9,5,6,8],
[8,6,3,7,4,5,2,1,9]].
约束解算器立即开始工作(显然,它检测到有足够的信息继续;是否总是这样?)。没有必要打电话

让我们看看矩阵元素之间的约束是如何设置的:

sudoku(行):-
%如果“行”未绑定,则将其绑定到包含9个未绑定变量的列表。
%如果“Rows”是绑定的(如上面的调用中所示),那么这只是验证是否存在
%实际上,行中有9个元素。等同于:
%
%行=[R1,
%R2,
%R3,
%R4,
%R5,
%R6,
%R7,
%R8,
%R9]。
长度(行,9),
%对于“行”中的每个元素,将元素绑定到相同元素的列表
%长度为“行”(即9);我们现在有一个9 x 9的矩阵
%未绑定变量。可能有点太聪明了。
%
%同:
%
%行=[[E11、E12、E13、E14、E15、E16、E17、E18、E19],
%[E21、E22、E23、E24、E25、E26、E27、E28、E29],
%[E31、E32、E33、E34、E35、E36、E37、E38、E39],
%[E41、E42、E43、E44、E45、E46、E47、E48、E49],
%[E51、E52、E53、E54、E55、E56、E57、E58、E59],
%[E61、E62、E63、E64、E65、E66、E67、E68、E69],
%[E71,E72,E73,E74,E75,E76,E77,E78,E79],
%[E81、E82、E83、E84、E85、E86、E87、E88、E89],
%[E91、E92、E93、E94、E95、E96、E97、E98、E99]]。
地图列表(相同长度(行),行),
%将所有行中的所有变量连接到一个新列表中
%谓词的名称不正确,它将列表从一个列表连接到一个列表)
追加(行,Vs),
%第一个约束:Vs中的每个元素Exx必须位于域[1..9]中
%如果我们传入一个矩阵行,其中包含Exx的具体值
%在域[1..9]中,此操作将失败。
Vs ins 1..9,
%另一个约束:对于行中的每一行(9个元素的列表):
%行的所有元素必须是不同的
地图列表(所有不同的行),
%我们现在要对每一列施加约束,
%列的所有元素必须是不同的
%将9x9矩阵行转换为9x9矩阵列。
%(新行的列是行的列)。
%
%列=[[E11、E21、E31、E41、E51、E61、E71、E81、E91],
%[E12、E22、E32、E42、E52、E62、E72、E82、E92]
%[E13、E23、E33、E43、E53、E63、E73、E83、E93]
%[E14、E24、E34、E44、E54、E64、E74、E84、E94]
%[E15、E25、E35、E45、E55、E65、E75、E85、E95]
%[E16、E26、E36、E46、E56、E66、E76、E86、E96]
%[E17、E27、E37、E47、E57、E67、E77、E87、E97]
%[E18、E28、E38、E48、E58、E68、E78、E88、E98]
%[E19、E29、E39、E49、E59、E69、E79、E89、E99]]。
转置(行、列),
%另一个约束:对于每个“行列”
%列的所有元素必须是不同的
地图列表(所有不同的列),
%现在我们需要施加“所有不同的”约束
%关于3x3子矩阵
%为行指定不同的名称
行=[As、Bs、Cs、Ds、Es、Fs、Gs、Hs、Is],
%对“三元素范围”的
%As、Bs、Cs的“三排高”组:即“全部不同”
模块(As、Bs、Cs),
%与下一个“3高”组相同
区块(Ds、Es、Fs),
%与下一个“3高”组相同
块(Gs、Hs、Is)。

如果我可以问的话,这些代码是从哪里来的?@DavidTonhofer示例9.7 from:是的,也发现它在下面,该程序中有很多好的诡计。