请参阅上图以了解我对问题的解释。
from scipy.optimize import linprog
a = [-800,-1200,-800]
b = [[200,100,400],[200,200,400],[200,300,200]]
c = [600,600,600]
result = linprog(a,b,c)
print(result)
我写的代码就在上面。我感兴趣的输出中的数字是fun : -2400.0
< - 这是当前的结果。这不是我想要的。
这是问题,也是我要找的。 p>
图中有两张桌子。 RHS上的表是整数部分,LHS表是二进制部分。我想要的答案是fun : -2800.0
,它是LHS表中第4列的一部分。
让我告诉你我是如何确定答案的。 首先,正如您所看到的,对于LHS表中的所有三个分配,都会编写0和1和1的所有可能组合。我必须从第4列LHS中找到满足RHS表中所有条件的最佳数字。例如:从顶部开始;从LHS和RHS表中取得的数字。 1表示选择分配,0表示不选择。因此第一行有1 1 1意味着选择所有分配。现在,我们添加第0,1和第2天的所有数字,我们可以看到它们都超过600.添加200 * 1 + 100 * 1 + 400 * 1 = 700,大于600.同样的事情一天因此,2801不是我们想要的数字。接下来,我们选择2800,它确实满足每个添加数字< = 600的总条件,因为assignment1为0,所以200 * 0 + 100 * 1 + 400 * 1 = 500,小于600,同样的事情其余两天。
我只是不明白如何将每一件事放在python中并获得-2800而不是-2400的结果。
linprog必须有一个简单的方法。
我在LHS表的第4个中获得数字的方式是使用RHS表中的绿色突出显示的数字,这些数字也在LHS表的最后一行。 我做了=((B5 + $ B $ 13)+(C5 * $ C $ 13)+(D5 * $ D $ 13))获得2801,依此类推其余的。
如果不使用linprog,我无法想到比以下代码更好的内容:
B = [800,1200,800]
A = [[200,100,400],[200,200,400],[200,300,200]]
for num in A[0],A[1],A[2]:
t0 = num[0]*1 + num[1]*1 + num[2]*1
t1 = num[0]*0 + num[1]*1 + num[2]*1
print(t0)
答案 0 :(得分:1)
首先:你的问题非常严厉(你对linprog的使用并不常见; Variable A
通常是2d-one。)
通常我对这些问题犹豫不决(=非常不完整),但我认为我现在遇到了问题。
z = 1*x0 + 1200*x1 + 800*x2 + 800
以下代码(我以常用方式使用变量名称)忽略偏移量(常量偏移量不会改变有关决策变量的结果)。因此,您希望稍后将偏移量添加到您获得的解决方案/或忽略返回的目标,并通过上面的公式自行计算!
from scipy.optimize import linprog
import numpy as np
a_ub = [[200, 100, 400], [200, 200, 300], [400, 400, 200]]
b_ub = [600, 600, 600]
c = [-1, -1200, -800]
result = linprog(c,a_ub,b_ub, bounds=(0,1))
print('*** result: (negated, offset of 800 missing) ***\n')
print(result)
结果:
*** result: (negated, offset of 800 missing) ***
fun: -2000.0
message: 'Optimization terminated successfully.'
nit: 3
slack: array([ 100., 100., 0., 1., 0., 0.])
status: 0
success: True
x: array([ 0., 1., 1.])
在否定目标后,只需添加偏移量即可获得所需的2800结果!
""" Alternative formulation
We introduce a 4th variable W, which is set to 1 and introduce the offset
into the objective
"""
from scipy.optimize import linprog
import numpy as np
a_ub = [[200, 100, 400, 0], [200, 200, 300, 0], [400, 400, 200, 0]] # no upper bound for W
b_ub = [600, 600, 600]
c = [-1, -1200, -800, -800] # W*800 added to objective
a_eq = [[0, 0, 0, 1]] # W=1 fixed
b_eq = [1] # "" ""
result = linprog(c,a_ub,b_ub, a_eq, b_eq, bounds=(0,1))
print('*** alternative result (negated, including offset): ***\n')
print(result)
结果:
*** alternative result (negated, including offset): ***
fun: -2800.0
message: 'Optimization terminated successfully.'
nit: 4
slack: array([ 100., 100., 0., 1., 0., 0., 0.])
status: 0
success: True
x: array([ 0., 1., 1., 1.])
线性编程方法通常不起作用。正如评论中提到的那样,单模矩阵意味着LP求解器保证了最优的整数解。但是如果没有关于你的数据的一些规则,一般不会给出这种单模块性的特征!
查看以下示例代码,该代码生成随机实例并比较LP求解器的结果。和一个MIP求解器。第一个随机实例失败了,因为LP解是连续的!
当然你可以坚持使用MIP解算器,但是:
代码:
from scipy.optimize import linprog
import numpy as np
from cylp.cy import CyCbcModel, CyClpSimplex
from cylp.py.modeling.CyLPModel import CyLPModel, CyLPArray
np.random.seed(1)
def solve_lp(a_ub, b_ub, c):
result = linprog(c,a_ub,b_ub, bounds=(0,1))
print(result)
return result.fun
def solve_mip(a_ub, b_ub, c):
a_ub, b_ub, c = np.matrix(a_ub), np.array(b_ub), np.array(c)
n = b_ub.shape[0]
model = CyLPModel()
x = model.addVariable('x', n, isInt=True)
model += a_ub*x <= b_ub
for i in range(n):
model += 0 <= x[i] <= 1
c = CyLPArray(c)
model.objective = c*x
s = CyClpSimplex(model)
cbcModel = s.getCbcModel()
cbcModel.branchAndBound()
print('sol: ', cbcModel.primalVariableSolution['x'])
print('obj: ', cbcModel.objectiveValue)
return cbcModel.objectiveValue
def solve_random_until_unequal():
while True:
a_ub = np.random.randint(0, 1000, size=(3,3))
b_ub = np.random.randint(0, 1000, size=3)
c = [-1, -1200, -800]
lp_obj = solve_lp(a_ub, b_ub, c)
mip_obj = solve_mip(a_ub, b_ub, c)
print('A_ub: ', a_ub)
print('b_ub: ', b_ub)
assert np.isclose(lp_obj, mip_obj)
solve_random_until_unequal()
输出:
fun: -225.29335071707953
message: 'Optimization terminated successfully.'
nit: 1
slack: array([ 9.15880052e+02, 0.00000000e+00, 7.90482399e+00,
1.00000000e+00, 8.12255541e-01, 1.00000000e+00])
status: 0
success: True
x: array([ 0. , 0.18774446, 0. ])
Clp0000I Optimal - objective value 0
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
('sol: ', array([ 0., 0., 0.]))
('obj: ', -0.0)
('A_ub: ', array([[ 37, 235, 908],
[ 72, 767, 905],
[715, 645, 847]]))
('b_ub: ', array([960, 144, 129]))
Traceback (most recent call last):
File "so_linprog_v3.py", line 45, in <module>
solve_random_until_unequal()
File "so_linprog_v3.py", line 43, in solve_random_until_unequal
assert np.isclose(lp_obj, mip_obj)
AssertionError