如何修改SWI-Prolog数独示例代码以返回所有可行解?
解决SWI-Prolog数独求解返回变量标识符的问题
问题出在你原有的sudoku/1谓词只定义了约束条件,没有触发变量的实例化。CLP(FD)的约束是延迟执行的,仅建立变量间的关系,不会自动把变量绑定到具体数字。findall/3收集到的是未实例化的变量结构,所以打印出来是_xxxx这类标识符。
解决步骤
修改数独求解谓词,添加实例化步骤
在原sudoku/1的末尾添加label(Vs),触发变量绑定,把所有约束的变量实例化为具体数字。Vs是之前append(Rows, Vs)得到的所有单元格变量列表。调整求解与收集逻辑
确保findall/3收集的是已经实例化后的完整数独棋盘。
修改后的完整代码
% 原数独约束+实例化 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), % 新增:实例化所有变量为具体数字 label(Vs). 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). % 打印相关谓词(变量实例化后会输出具体数字) print_lists([]). print_lists([H|T]) :- print_list(H), nl, print_lists(T). print_list([]). print_list([H|[]]) :- writef('%w', [H]). print_list([H|T]) :- writef('%w ', [H]), print_list(T). print_all_solutions([]). print_all_solutions([H|T]) :- write('Solution:'), nl, print_lists(H), nl, print_all_solutions(T). example :- Board = [[_,_,_,_,_,_,_,_,_], [_,_,_,_,_,_,_,_,_], [_,_,_,_,_,_,_,_,_], [_,_,_,_,_,_,_,_,_], [_,_,_,_,_,_,_,_,_], [_,_,_,_,_,_,_,_,_], [_,_,_,_,_,_,_,_,_], [_,_,_,_,_,_,_,_,_], [_,_,_,_,_,_,_,_,_]], findall(Board, sudoku(Board), Solutions), print_all_solutions(Solutions).
测试说明
- 运行
example.后,findall/3会收集所有实例化后的数独解,打印时会输出具体的1-9数字,不再是变量标识符。 - 注意:空数独的解数量极大(约6.6e21),实际测试建议用部分填充的数独(比如填几个数字),避免程序长时间运行。
内容的提问来源于stack exchange,提问作者winnie
相关产品推荐
相关产品推荐

