Matrix 如何解决这个ILP/CP矩阵难题

Matrix 如何解决这个ILP/CP矩阵难题,matrix,puzzle,constraint-programming,integer-programming,Matrix,Puzzle,Constraint Programming,Integer Programming,我正在研究算法,最近发现了一个有趣的挑战 它将给我们一些行/列,我们的任务是用整数1~N填充表格,该整数只显示一次,并且它们的行和列总和等于给定的行/列 挑战是一个简单的例子: [ ] [ ] [ ] 13 [ ] [ ] [ ] 8 [ ] [ ] [ ] 24 14 14 17 answer: [2] [6] [5] 13 [3] [1] [4] 8 [9] [7] [8]

我正在研究算法,最近发现了一个有趣的挑战

它将给我们一些行/列,我们的任务是用整数1~N填充表格,该整数只显示一次,并且它们的行和列总和等于给定的行/列

挑战是一个简单的例子:

    [ ]  [ ]  [ ]   13
    [ ]  [ ]  [ ]    8
    [ ]  [ ]  [ ]   24
     14   14   17

answer:

    [2]  [6]  [5]   13
    [3]  [1]  [4]    8
    [9]  [7]  [8]   24
     14   14   17

谢谢

我认为回溯算法在这里会非常有效

虽然回溯仍然是一种“蛮力”,但在一般情况下,回溯的速度确实很快。例如,用回溯法求解数独通常只需要1000-10000次迭代(考虑到O复杂度为O(9^n),其中n为空空间,这是非常快的,因此平均数独大约有9^60种可能性,这将需要几年时间在计算机上完成)

这个任务有很多规则(数字的唯一性和行/列的和),这对跟踪非常有用。更多规则=在每个步骤后进行更多检查,并丢弃无法带来解决方案的分支


这可能会有所帮助:

据我所知,没有比使用回溯方法更有效地解决这个特定问题的直接算法

但是,与简单地枚举所有可能的解决方案相比,您可以更智能地执行此操作。一种有效的方法是约束编程(CP)(或约束逻辑编程(CLP)等派生范式)。基本上,它归结于对问题施加的约束进行推理,试图缩小变量的范围

在减少域之后,您可以选择以后可以回溯的域。在做出这样的选择后,您再次减少域,并且可能必须做出额外的选择

例如,您可以为此使用ECLiPSe(不是IDE,而是约束逻辑编程工具):

:- lib(ic).
:- import alldifferent/1 from ic_global.
:- import sumlist/2 from ic_global.

solve(Problem) :-
    problem(Problem,N,LA,LB),
    puzzle(N,LA,LB,Grid),
    print_Grid(Grid).

puzzle(N,LA,LB,Grid) :-
    N2 is N*N,
    dim(Grid,[N,N]),
    Grid[1..N,1..N] :: 1..N2,
    (for(I,1,N), param(N,Grid,LA,LB) do
        Sc is nth1(I,LA),
        Lc is Grid[1..N,I],
        sumlist(Lc,Sc),
        Sr is nth1(I,LB),
        Lr is Grid[I,1..N],
        sumlist(Lr,Sr)
    ),
    term_variables(Grid,Vars),
    alldifferent(Vars),
    labeling(Vars).

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

nth1(1,[H|_],H) :- !.
nth1(I,[_|T],H) :-
    I1 is I-1,
    nth1(I1,T,H).

problem(1,3,[14,14,17],[13,8,24]).
该计划是基于模糊的。现在,您可以使用ECLiPSe解决此问题:

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.00 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.05 seconds
  2  5  6
  3  1  4
  9  8  7


Yes (0.05s cpu, solution 1, maybe more) ? ;
  5  2  6
  1  3  4
  8  9  7


Yes (0.05s cpu, solution 2, maybe more) ? ;
  2  6  5
  3  1  4
  9  7  8


Yes (0.05s cpu, solution 3, maybe more) ? ;
  3  6  4
  2  1  5
  9  7  8


Yes (0.05s cpu, solution 4, maybe more) ? ;
  6  2  5
  1  3  4
  7  9  8


Yes (0.05s cpu, solution 5, maybe more) ? ;
  6  3  4
  1  2  5
  7  9  8


Yes (0.05s cpu, solution 6, maybe more) ? ;
  2  6  5
  4  1  3
  8  7  9


Yes (0.05s cpu, solution 7, maybe more) ? ;
  4  6  3
  2  1  5
  8  7  9


Yes (0.05s cpu, solution 8, maybe more) ? 
  6  2  5
  1  4  3
  7  8  9


Yes (0.05s cpu, solution 9, maybe more) ? ;
  6  4  3
  1  2  5
  7  8  9


Yes (0.05s cpu, solution 10, maybe more) ? ;

No (0.06s cpu)
只需查询
solve(1)
,约束逻辑编程工具完成其余工作。因此,总共有
10个
解决方案


请注意,该程序适用于任意的
N
,尽管-因为最坏的情况下,该程序执行回溯-显然,该程序只能解决合理的
N

问题。哦,当这些小优化问题出现时,我非常喜欢。他们总是让我想起我第一年的一次,当时我做了一个可以解决数独问题的东西,玩得很开心!你可能猜到从那以后我解决了多少数独游戏:)


现在,你的问题是一个问题。甚至在你阅读那篇文章之前,你应该注意到ILP是很难的。将解决方案空间限制为NZ是严重的限制,通常情况下,这样的解决方案不存在

对于你的问题,手头的任务基本上归结为解决这个问题

Minimise 0 (arbitrary objective function)
根据,

x1 + x2 + x3 = 13
x4 + x5 + x6 = 8
x7 + x8 + x9 = 24

x1 + x4 + x7 = 14
x2 + x5 + x8 = 14
x3 + x6 + x9 = 17
A * x = B
以及

x_i in N, x_i distinct.
以矩阵形式,这些方程变成

    |1   1   1   0   0   0   0   0   0|
    |0   0   0   1   1   1   0   0   0|
A = |0   0   0   0   0   0   1   1   1|
    |1   0   0   1   0   0   1   0   0|
    |0   1   0   0   1   0   0   1   0|
    |0   0   1   0   0   1   0   0   1|
以及

使约束减少到
A*x=B
。所以我们要解决的问题现在可以等价地写成

Minimise 0
根据,

x1 + x2 + x3 = 13
x4 + x5 + x6 = 8
x7 + x8 + x9 = 24

x1 + x4 + x7 = 14
x2 + x5 + x8 = 14
x3 + x6 + x9 = 17
A * x = B
以及

你觉得这很难吗?如果不是,想想看:真正的线是巨大的,在这条线上,每隔一段时间,就会有一个小点。这是一个整数。我们需要一些。我们不知道是哪一个。所以本质上,一个完美的类比就是大海捞针

现在,不要绝望,我们非常擅长发现这些ILP针!我只是想让你们了解这个问题所产生的领域的非平凡的困难


我想为您提供工作代码,但我不知道您首选的语言/工具包。如果这只是一个业余爱好者的方法,那么即使是Excel的解算器也会工作得很好。如果不是的话,我认为我的措辞不可能比Willem Van Onsem已经有的更好,我想让你看看他的实现答案。

下面是另一个约束编程模型,使用与Willem Van Onsem解决方案类似的方法,即使用全局约束“所有不同”,这是确保矩阵中的数字只分配一次的有效方法。(在CP中,“全局约束”的概念非常重要,有很多研究发现可以快速实现各种常见约束。)

这是一个迷你锌模型:

以下是前两个(共10个)解决方案:

 2  5  6
 3  1  4
 9  8  7
 ----------

 5  2  6
 1  3  4
 8  9  7
 ----------
 ...
另一条评论:CP的一个有趣之处以及一个重要概念是,可以使用几乎相同的模型生成新的问题实例:

唯一的区别是以下几行,即将“行和”和“列和”更改为决策变量,并对提示进行注释

  array[1..rows] of var int: row_sums; % add "var"
  array[1..cols] of var int: col_sums; % add "var"

  % ...

  % row_sums = [13,8,24];
  % col_sums = [14,14,17];
以下是三个生成的问题实例(可能为9!=362880):


这个问题转化为9个未知数,但只有6个方程式。因此,我认为没有唯一的解决方案。@TimBiegeleisen有很多隐式约束,变量必须是超出[1..N]范围的唯一整数。“蛮力”是一种算法。你也可以用遗传算法来解决:)试着建立方程组,然后为3个正方形选择种子值。你应该能够解决其他6个问题。你可以迭代,直到在你的范围内找到一个解决方案。说真的,答案不错!我试图在我的文章中添加更多的背景信息,但这是一个很好的答案,因为您还为OP提供了工作代码和开始的基础。穆伊·沃克:)。我没有考虑过ILP,但这确实会奏效。戈德·格达安!;)+1.我担心你的“任意”目标函数。这是行不通的,因为目标不是约束变量的函数。如果添加约束
x_i>=0
,则返回值将为0,而不处理任何约束!检查:或任何教科书或维基。@Erobre
  array[1..rows] of var int: row_sums; % add "var"
  array[1..cols] of var int: col_sums; % add "var"

  % ...

  % row_sums = [13,8,24];
  % col_sums = [14,14,17];
  row_sums: [21, 15, 9]
  col_sums: [19, 15, 11]

  5  9  7
  8  4  3
  6  2  1
  ----------
  row_sums: [20, 16, 9]
  col_sums: [20, 14, 11]

  5  8  7
  9  4  3
  6  2  1
  ----------
  row_sums: [22, 14, 9]
  col_sums: [18, 15, 12]

  5  9  8
  7  4  3
  6  2  1
  ----------