这看起来是个难题(可能是 np-hard)。
您最好的选择(忽略与领域相关的高度调整的算法)是组合优化的经典方法:
- 元启发式(禁忌搜索、模拟退火等)
- SAT 求解器
- 约束编程
- 整数编程
- 易于制定,如下所示
- 提供非常好的商业求解器
-
完成
我将介绍后者的简单版本(这可能是其中最糟糕的方法;至少对于这个问题!)
它在 python 中实现并使用开源工具cvxpy(公式)和cbc(MIP-solver)。
代码
更新:先验修复一些元素值!
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.]]