Python中的二进制和整数程序

0 投票
1 回答
61 浏览
提问于 2025-04-14 15:41

我有一个二进制/整数程序,想用Python中的milp来解决。下面是我目前的代码和一张图片。当我运行它时,出现了以下问题:

`bounds.lb` and `bounds.ub` must contain reals and be broadcastable to `c.shape`.

我以为在“bounds”这个变量里已经考虑了上下限,但显然没有。那么我缺少了什么呢?

这里输入图片描述

from scipy.optimize import linprog
import numpy as np
from scipy.optimize import milp, LinearConstraint, Bounds 
c = [3, 5, 7, 9, 2, 8, 6, 4, 1]  # x1 to x9 (office setup cost multipliers)
c = c + [0]*36     


A = [
    [1700, 3600, 2100, 2500, 3100, 2700, 4100, 3400, 4100] + [24.3]*9 + [32.4]*9 + [28.9]*9+[26]*9,  # Setup and transfer costs
    [0, 0, 0, -1, 0, -1, 1, 0, 0] + [0]*36,  # x7 <= x4 + x6
    [1, 0, 0, 0, 0, 1, 0, 0, 0] + [0]*36,  # x1 + x6 <= 1
    [0]*9 + [1]*9 + [0]*27,  # Chicago
    [0]*18 + [1]*9 + [0]*18,  # Charlotte
    [0]*27 + [1]*9 + [0]*9,  # Pittsburgh
    [0]*36 + [1]*9   # Houston
]

b = [
    14000,  
    0,  
    1,  
    29, 
    22, 
    19,  
    27,  
]

# Define bounds for each variable (0 <= xi <= 1 for binary variables, 0 <= yij)
x_bounds = [(0, 1)] * 9  # Bounds for the x variables
y_bounds = [(0, None)] * 36  # Bounds for the y variables (unbounded upper limit)

# Combine bounds
bounds = x_bounds + y_bounds

integrality = ([1]) * 45

milp(c, integrality = integrality,
    bounds = Bounds(bounds),
     constraints = LinearConstraint(A, b))

1 个回答

1

你的代码有两个问题。首先,如果想要禁用边界或者定义“无限边界”,应该使用 np.inf 或者 -np.inf,而不是 None

其次,你现在给 scipy.optimize.Bounds 提供的是一个元组的列表,这样是不行的。你应该分别提供一个下边界的列表和一个上边界的列表。

为了解决这些问题,你可以把代码的最后部分改成:

# Define bounds for each variable (0 <= xi <= 1 for binary variables, 0 <= yij)
x_bounds = [(0, 1)] * 9  # Bounds for the x variables
y_bounds = [(0, np.inf)] * 36  # Bounds for the y variables (unbounded upper limit)

# Combine bounds
bounds = x_bounds + y_bounds

integrality = ([1]) * 45

l_bounds = [x for (x,y) in bounds]
u_bounds = [y for (x,y) in bounds]

milp(c, integrality = integrality,
    bounds = Bounds(l_bounds, u_bounds),
     constraints = LinearConstraint(A, b))

除了用列表推导式,你也可以使用 zip 函数,这样会更简洁:

l_bounds, u_bounds = zip(*bounds)

或者直接这样写:

bounds = Bounds(*zip(*bounds))

我个人更喜欢使用列表推导式的解决方案,因为这样能让读者更清楚地理解发生了什么,而且对于这种长度的列表来说,性能其实不是问题。

撰写回答