Artificial intelligence 多数独人工智能方法

Artificial intelligence 多数独人工智能方法,artificial-intelligence,theory,sudoku,solver,constraint-programming,Artificial Intelligence,Theory,Sudoku,Solver,Constraint Programming,我正在构思一个数独变体的解算器,称为多重数独,其中多个板重叠如下: 如果我对游戏理解正确,您必须以这样的方式解决每个网格,即任意两个或多个网格之间的重叠是每个网格解决方案的一部分 我不确定我该怎么想。有人得到任何提示/概念线索吗?此外,如果我想到人工智能的任何话题,我也想听听。约束编程(CP) 数独是一个典型的约束编程问题。您有一组变量(网格中的字段),每个变量都有一个域(这里是数字0到9)和一组对这些变量的约束(一个数字在一行、一列、一个块中只出现一次) 解决约束编程问题的一种通用方法是弧一

我正在构思一个数独变体的解算器,称为多重数独,其中多个板重叠如下:

如果我对游戏理解正确,您必须以这样的方式解决每个网格,即任意两个或多个网格之间的重叠是每个网格解决方案的一部分

我不确定我该怎么想。有人得到任何提示/概念线索吗?此外,如果我想到人工智能的任何话题,我也想听听。

约束编程(CP) 数独是一个典型的约束编程问题。您有一组变量(网格中的字段),每个变量都有一个域(这里是数字
0
9
)和一组对这些变量的约束(一个数字在一行、一列、一个块中只出现一次)

解决约束编程问题的一种通用方法是弧一致性(AC):传播约束。通过(部分)填充变量,您可以减少剩余变量的域,等等。最后,如果传播不再能够使域变小,您必须做出选择

通过选择,您可以为某个变量选择一个值。一个好的策略是选择一个可能剩下少量值的变量。接下来,您将再次传播,并可能做出另一个选择,以此类推

您的程序可能会发现一个选择是错误的:它使一个或多个变量的域为空。在这种情况下,您可以回溯:撤消先前所做的选择(以及在该选择之后进行的传播),然后选择另一个值

这个答案显然不是为了对主题进行深入的概述,但是可以提供更好的概述和指向更多信息的指针

有一些约束编程解算器,比如ECLiPSe(而不是IDE)、Minizing等,可以简单地定义变量、域和约束

用ECLiPSe解决问题 在ECLiPSe网站上,您可以找到。如果您阅读了一些关于ECLiPSe的文档,您可以将此文件转换为多数独的模型。我做了一些小的修改,得到了以下快速而肮脏的解决方案:

% credits to Joachim Schimpf for his model of sudoku
% http://eclipseclp.org/examples/sudoku.ecl.txt
:- lib(ic).
:- import alldifferent/1 from ic_global.

solve(ProblemName) :-
    problem(ProblemName,BA,BB),
    multi_sudoku(3,BA,BB),
    print_board(BA),
    print_board(BB).

multi_sudoku(N,BA,BB) :-
    sudoku(N,BA,VA),
    sudoku(N,BB,VB),
    N2 is N*N,
    Inc is N2-N,
    (multifor([I,J],1,N,1),param(BA,BB,Inc) do
        BA[I+Inc,J+Inc] #= BB[I,J]
    ),
    append(VA,VB,Vars),
    labeling(Vars).

sudoku(N,Board,Vars) :-
    N2 is N*N,
    dim(Board,[N2,N2]),
    Board[1..N2,1..N2] :: 1..N2,
    ( for(I,1,N2), param(Board,N2) do
        Row is Board[I,1..N2],
        alldifferent(Row),
        Col is Board[1..N2,I],
        alldifferent(Col)
    ),
    ( multifor([I,J],1,N2,N), param(Board,N) do
        ( multifor([K,L],0,N-1), param(Board,I,J), foreach(X,SubSquare) do
        X is Board[I+K,J+L]
        ),
        alldifferent(SubSquare)
    ),
    term_variables(Board, Vars).


print_board(Board) :-
    dim(Board, [N,N]),
    ( for(I,1,N), param(Board,N) do
        ( for(J,1,N), param(Board,I) do
            X is Board[I,J],
        ( var(X) -> write("  _") ; printf(" %2d", [X]) )
        ), nl
    ), nl.


%----------------------------------------------------------------------
% Sample data
%----------------------------------------------------------------------

problem(1, [](
    [](_, _, _, _, 6, _, _, _, _),
    [](_, _, _, 4, _, 9, _, _, _),
    [](_, _, 9, 7, _, 5, 1, _, _),
    [](_, 5, 2, _, 7, _, 8, 9, _),
    [](9, _, _, 5, _, 2, _, _, 4),
    [](_, 8, 3, _, 4, _, 7, 2, _),
    [](_, _, _, 2, _, 8, _, _, _),
    [](_, _, _, 6, _, 4, _, _, _),
    [](_, _, _, _, 5, _, _, _, _)
           ),
           [](
    [](_, _, _, _, 3, _, _, _, _),
    [](_, _, _, 8, _, 7, _, _, _),
    [](_, _, _, 1, _, 6, 3, _, _),
    [](_, 9, 8, _, _, _, 1, 2, _),
    [](2, _, _, _, _, _, _, _, 3),
    [](_, 4, 3, _, _, _, 6, 5, _),
    [](_, _, 7, 3, _, 5, 9, _, _),
    [](_, _, _, 4, _, 2, _, _, _),
    [](_, _, _, _, 6, _, _, _, _)
           )
    ).
我“借用”了Joachim Schimpf的数独模型,所以我把它归功于他。此外,请注意,这个答案并不建议在另一个工具上使用ECLiPSe。在约束编程方面,我更熟悉Prolog工具链。但是如果你更喜欢C++,Gecode会用大致相同(甚至更好)的性能来做这个把戏。 这将生成输出:

ECLiPSe Constraint Logic Programming System [kernel]
Kernel and basic libraries copyright Cisco Systems, Inc.
and subject to the Cisco-style Mozilla Public Licence 1.1
(see legal/cmpl.txt or http://eclipseclp.org/licence)
Source available at www.sourceforge.org/projects/eclipse-clp
GMP library copyright Free Software Foundation, see legal/lgpl.txt
For other libraries see their individual copyright notices
Version 6.1 #199 (x86_64_linux), Sun Mar 22 09:34 2015
[eclipse 1]: solve(1).
lists.eco  loaded in 0.00 seconds
WARNING: module 'ic_global' does not exist, loading library...
queues.eco loaded in 0.00 seconds
ordset.eco loaded in 0.01 seconds
heap_array.eco loaded in 0.00 seconds
graph_algorithms.eco loaded in 0.03 seconds
max_flow.eco loaded in 0.00 seconds
flow_constraints_support.eco loaded in 0.00 seconds
ic_sequence.eco loaded in 0.01 seconds
ic_global.eco loaded in 0.07 seconds
  2  1  4  8  6  3  9  5  7
  8  7  5  4  1  9  2  6  3
  6  3  9  7  2  5  1  4  8
  4  5  2  3  7  1  8  9  6
  9  6  7  5  8  2  3  1  4
  1  8  3  9  4  6  7  2  5
  5  4  1  2  3  8  6  7  9
  7  2  8  6  9  4  5  3  1
  3  9  6  1  5  7  4  8  2

  6  7  9  5  3  4  2  8  1
  5  3  1  8  2  7  4  6  9
  4  8  2  1  9  6  3  7  5
  7  9  8  6  5  3  1  2  4
  2  6  5  7  4  1  8  9  3
  1  4  3  2  8  9  6  5  7
  8  2  7  3  1  5  9  4  6
  9  1  6  4  7  2  5  3  8
  3  5  4  9  6  8  7  1  2
我的机器大约用了0.11秒。此外,总共有60个有效的解决方案

最后两个“矩阵”显示了两个数独的解。正如您所看到的(我还没有完全检查),它们共享一个块(相同的输出),并且所有数独约束都是有效的。解决方案的更方便的表示方式如下所示:

+-----+-----+-----+
|2 1 4|8 6 3|9 5 7|
|8 7 5|4 1 9|2 6 3|
|6 3 9|7 2 5|1 4 8|
+-----+-----+-----+
|4 5 2|3 7 1|8 9 6|
|9 6 7|5 8 2|3 1 4|
|1 8 3|9 4 6|7 2 5|
+-----+-----+-----+-----+-----+
|5 4 1|2 3 8|6 7 9|5 3 4|2 8 1|
|7 2 8|6 9 4|5 3 1|8 2 7|4 6 9|
|3 9 6|1 5 7|4 8 2|1 9 6|3 7 5|
+-----+-----+-----+-----+-----+
            |7 9 8|6 5 3|1 2 4|
            |2 6 5|7 4 1|8 9 3|
            |1 4 3|2 8 9|6 5 7|
            +-----+-----+-----+
            |8 2 7|3 1 5|9 4 6|
            |9 1 6|4 7 2|5 3 8|
            |3 5 4|9 6 8|7 1 2|
            +-----+-----+-----+
我不知道Python中的约束编程库,也不知道ECLiPSe到Python的端口。但我的经验是,所有现代编程语言都有这样的工具

使用ECLiPSe、Gecode等约束编程工具的优势,。。。首先,你只需要指定你的问题,如何解决它是你不必担心的事情。此外,这些库对约束编程进行了30年的研究:它们经过了极大的优化,以大多数人无法想象的方式利用约束和结构,并且不太可能包含bug(比定制算法)。此外,如果新的策略、算法,。。。如果发现,ECLiPSe的更新将加快模型的处理速度

的一个缺点是一些难题仍然无法使用约束编程来解决:搜索空间太大,约束太复杂,无法将域缩减为小集合,并且没有足够的处理能力来做出足够的选择以找到有效的解决方案。另一个缺点是,指定一个问题并不总是容易的:尽管程序员的目标是设计好的约束,但在没有为其定义易于使用的约束的情况下,总是存在复杂的问题

其他技术
显然还有其他人工智能技术来解决问题。一种常用于解决困难搜索和优化问题的技术是进化计算:一种是先填写数独,允许某些值出错,然后在每一个时间步,他们都要修复一个或多个字段。有时,为了最终找到有效的解决方案,他们会引入新的错误。

另一种方法是使用遗传算法。这是基于生物进化的。遗传算法是进化算法的一部分,因此具有相似的“适应度函数”。通过重组、选择和突变找到了有效的解决方案

基本概念是通过随机方式初始化由“染色体”组成的多个解决方案“个体”(解决方案当然可能是错误的)。定义一个“适应度函数”,用于评估当前“一代人”中每个人的素质。以较高的概率将适应性较好的个体重组为“子”解决方案,并以较低的概率对新一代中的某些个体进行变异。重复此操作,直到某些条件(最大迭代次数、找到的有效解决方案)为真

使遗传算法适合您的问题。您可以执行以下操作。为每个3x3或9x9数独创建一个本地正确的解决方案。这些是染色体。将它们放在一个数据结构中。那是一个人。创造一堆,形成一代人。根据每个人违反的约束来评估每个人。计算相应的概率。重组个体,变异一些染色体