矩阵中数字分布的算法

时间:2016-10-11 20:04:02

标签: algorithm optimization

这是我关于堆栈交换的第一个问题。我正在研究一个问题,我需要在矩阵中找到非负整数的分布,其中每行和每列总计达到目标总和。我确信有一种算法可以做到这一点(或者一种理论说明何时可行,何时不行)但我没有太多运气在网上找到它。

在附图中(Image)我有一个解决方案的例子,我找到了一个特定的问题实例,但没有涉及可定义的算法。灰色总计是每列和每行的目标总计,而浅蓝色总计是显示的当前分布的总计。在算法的开头只提供了总数,所以我从一个空矩阵开始。

有人可以指点我这个问题的资源/解决方案吗?

谢谢

2 个答案:

答案 0 :(得分:0)

这看起来像一个难题(可能 np-hard )。

最好的选择(忽略依赖于域的高度调优算法)是组合优化的经典方法:

  • Metaheuristics(禁忌搜索,模拟退火& co。)
    • 需要一些调整/邻居定义......
  • SAT-求解器
    • 需要恼人的加法器模拟
    • 完成(可以证明,没有解决方案)
  • 约束编程
    • 易于制定
    • 可以调整
    • 完整
  • 整数编程
    • 易于配制,如下所示
    • 非常好的商业解决方案
    • 完整 我将介绍后者的一个简单版本(这可能是这些中最糟糕的方法;至少对于这个问题!)

它在python中实现并使用开源工具cvxpy(配方)& cbc(MIP解算器)。

代码

更新:修复一些元素值a-priori!

from cvxpy import *

targets_X = [17, 45, 7, 6]
targets_Y = [3 for i in range(11)] + [2 for i in range(21)]
fixed_elements_indices_x, fixed_elements_indices_y = [0, 1, 2], [0, 1, 2]
fixed_elements_values = [3, 3, 3]
dim_x, dim_y = len(targets_X), len(targets_Y)

# Vars
T = Int(dim_x, dim_y)

# Constraints
constraints = []
constraints.append(T >= 0)
constraints.append(sum_entries(T, axis=1) == targets_X)
constraints.append(sum_entries(T, axis=0).T == targets_Y)
constraints.append(T[fixed_elements_indices_x, fixed_elements_indices_y] == fixed_elements_values)
problem = Problem(Minimize(0), constraints)
problem.solve(CBC, verbose=True)

print(T.value.T)

输出

Clp0006I 0  Obj 0 Primal inf 159 (39)
Clp0006I 36  Obj 0 Primal inf 98.999998 (19)
Clp0006I 69  Obj 0
Clp0006I 69  Obj 0
Clp0000I Optimal - objective value 0
Cbc0045I No integer variables out of 128 objects (128 integer) have costs
Cbc0045I branch on satisfied N create fake objective Y random cost Y
Clp0000I Optimal - objective value 0
Node 0 depth 0 unsatisfied 0 sum 0 obj 0 guess 0 branching on -1
Clp0000I Optimal - objective value 0
Cbc0004I Integer solution of 0 found after 0 iterations and 0 nodes (0.00 seconds)
Cbc0001I Search completed - best objective 0, took 0 iterations and 0 nodes (0.00 seconds)
Cbc0035I Maximum depth 0, 0 variables fixed on reduced cost
Clp0000I Optimal - objective value 0
Clp0000I Optimal - objective value 0
[[ 3.  0.  0.  0.]
 [ 0.  3.  0.  0.]
 [ 0.  0.  3.  0.]
 [ 0.  3.  0.  0.]
 [ 0.  0.  3.  0.]
 [ 0.  0.  0.  3.]
 [ 0.  0.  0.  3.]
 [ 0.  2.  1.  0.]
 [ 0.  3.  0.  0.]
 [ 0.  3.  0.  0.]
 [ 0.  3.  0.  0.]
 [ 0.  2.  0.  0.]
 [ 0.  2.  0.  0.]
 [ 0.  2.  0.  0.]
 [ 0.  2.  0.  0.]
 [ 0.  2.  0.  0.]
 [ 0.  2.  0.  0.]
 [ 0.  2.  0.  0.]
 [ 0.  2.  0.  0.]
 [ 0.  2.  0.  0.]
 [ 0.  2.  0.  0.]
 [ 0.  2.  0.  0.]
 [ 0.  2.  0.  0.]
 [ 0.  2.  0.  0.]
 [ 0.  2.  0.  0.]
 [ 2.  0.  0.  0.]
 [ 2.  0.  0.  0.]
 [ 2.  0.  0.  0.]
 [ 2.  0.  0.  0.]
 [ 2.  0.  0.  0.]
 [ 2.  0.  0.  0.]
 [ 2.  0.  0.  0.]]

答案 1 :(得分:0)

您可以使用maximum flow algorithm在多项式时间内解决此问题。

设置源节点,每行的节点,每列的节点和目标节点。

从源节点到行节点的边缘应具有等于给定行总和的容量。

从col节点到dest的边缘应具有与给定列总和相等的容量。

从行节点到col节点的边缘应具有根据矩阵中允许值的容量。 (例如,如果矩阵的第x行,第0列的条目必须为零,则将行的容量设置为0,从行节点x到col节点y。)

然后计算从源到目标的最大流量,行节点和列节点之间的流量给出矩阵中的条目。

对于nxn矩阵的解,复杂度为O(n ^ 3)。