scipy 使用linprog进行线性规划优化

odopli94  于 12个月前  发布在  其他
关注(0)|答案(3)|浏览(156)

我正在尝试使用scipy.optimize中的linprog来解决这个问题。
沙拉是由以下材料组成的任何组合:(1)番茄,(2)生菜,(3)菠菜,(4)胡萝卜,(5)油。每种沙拉必须包含:(A)至少15克蛋白质,(B)至少2克且至多6克脂肪,(C)至少4克碳水化合物,(D)至多100毫克钠。(E)你不希望你的沙拉中含有超过50%的绿色蔬菜。这些成分的营养成分(每100克)是


的数据
解一个线性规划,使沙拉在营养限制下的热量最少。我想我可能在我的限制下做错了什么,欢迎任何建议。

linprog(c=21, 16, 371, 346, 884],
              A_ub=[[0.85, 0.162, 12.78, 8.39, 0],  
                    [0.33, 0.02, 1.58, 1.39, 0],  
                    [4.64, 2.37, 74.69, 80.70, 0],  
                    [9, 8, 7, 508, 0],  
                    [0, 0, 0, 0, 0]] ,
              b_ub=[15, 2, 4,100,50],
              bounds=[(0, None), (0, None), (0, None), (0, None), (0, None)])

字符串

bcs8qyzn

bcs8qyzn1#

因为你有很少的变量和约束,我们可以这样写你的约束:

# (A) protein, at least (*)
15 <= 0.85*x[tomato] + 1.62*x[lettuce] + 12.78*x[spinach] + 8.39*x[carrot] + 0.0*x[oil]

# (B1) fat, at least (*)
2 <= 0.33*x[tomato] + 0.2*x[lettuce] + 1.58*x[spinach] + 1.39*x[carrot] + 100.0*x[oil]

# (B2) fat, at most
0.33*x[tomato] + 0.2*x[lettuce] + 1.58*x[spinach] + 1.39*x[carrot] + 100.0*x[oil] <= 6

# (C) carbo, at least (*)
4 <= 4.64*x[tomato] + 2.37*x[lettuce] + 74.69*x[spinach] + 80.7*x[carrot] + 0.0*x[oil]

# (D) sodium, at most
9.0*x[tomato] + 8.0*x[lettuce] + 7.0*x[spinach] + 508.2*x[carrot] + 0.0*x[oil] <= 100

字符串
(*)然而,正如@AirSquid所写的,你不能用linprog传递约束的下限,你必须改变约束的意义来设置上限。

# (A) protein, at least -> change inequation sens
-0.85*x[tomato] + -1.62*x[lettuce] + -12.78*x[spinach] + -8.39*x[carrot] + -0.0*x[oil] <= -15

# (B1) fat, at least -> change inequation sense
-0.33*x[tomato] + -0.2*x[lettuce] + -1.58*x[spinach] + -1.39*x[carrot] + -100.0*x[oil] <= -2

# (B2) fat, at most
0.33*x[tomato] + 0.2*x[lettuce] + 1.58*x[spinach] + 1.39*x[carrot] + 100.0*x[oil] <= 6

# (C) carbo, at least -> change inequation sense
-4.64*x[tomato] + -2.37*x[lettuce] + -74.69*x[spinach] + -80.7*x[carrot] + -0.0*x[oil] <= -4

# (D) sodium, at most
9.0*x[tomato] + 8.0*x[lettuce] + 7.0*x[spinach] + 508.2*x[carrot] + 0.0*x[oil] <= 100


(E)你不希望你的沙拉中的绿色成分超过50%。
意思是:

# (E) green mass
x[lettuce] + x[spinach] <= 0.5*(x[tomato] + x[lettuce] + x[spinach] + x[carrot] + x[oil])


你必须简化这个表达式来提取系数:

# (E) green mass
-0.5*x[tomato] + 0.5*x[lettuce] + 0.5*x[spinach] + -0.5*x[carrot] + -0.5*x[oil] <= 0


现在你可以创建cA_ubb_ub参数了:

c = [21, 16, 371, 346, 884]
A_ub = [[-0.85, -1.62, -12.78, -8.39, -0.0],
        [-0.33, -0.2, -1.58, -1.39, -100.0],
        [0.33, 0.2, 1.58, 1.39, 100.0],
        [-4.64, -2.37, -74.69, -80.7, -0.0],
        [9.0, 8.0, 7.0, 508.2, 0.0],
        [-0.5, 0.5, 0.5, -0.5, -0.5]]
b_ub = [-15, -2, 6, -4, 100, 0]
bounds = [(0, None), (0, None), (0, None), (0, None), (0, None)])
linprog(c=c, A_ub=A_ub, b_ub=b_ub, bounds=bounds)


输出量:

message: Optimization terminated successfully. (HiGHS Status 7: Optimal)
        success: True
         status: 0
            fun: 232.5146989957854
              x: [ 5.885e+00  5.843e+00  4.163e-02  0.000e+00  0.000e+00]
            nit: 3
          lower:  residual: [ 5.885e+00  5.843e+00  4.163e-02  0.000e+00
                              0.000e+00]
                 marginals: [ 0.000e+00  0.000e+00  0.000e+00  1.292e+03
                              8.681e+02]
          upper:  residual: [       inf        inf        inf        inf
                                    inf]
                 marginals: [ 0.000e+00  0.000e+00  0.000e+00  0.000e+00
                              0.000e+00]
          eqlin:  residual: []
                 marginals: []
        ineqlin:  residual: [ 0.000e+00  1.176e+00  2.824e+00  4.026e+01
                              0.000e+00  0.000e+00]
                 marginals: [-3.159e+01 -0.000e+00 -0.000e+00 -0.000e+00
                             -2.414e+00 -3.174e+01]
 mip_node_count: 0
 mip_dual_bound: 0.0
        mip_gap: 0.0

wfypjpf4

wfypjpf42#

三件事:
1.你至少有3个错别字在你的A矩阵,我看到与给定的信息比较。修复它们。
1.在问题中,你被告知约束是“大于或等于”,但是linprog只给你一个A_ubb_ub来表示小于或等于的约束。怎么办?使用一些代数来将约束转换为linprog接受的约束。

Ax >= b     <==>    -Ax <= -b

字符串
1.让上面的东西工作,然后尝试50%的绿色约束。写出来 * 代数 *,然后转换成另一行A和标量元素b

tez616oj

tez616oj3#

其他答案都是正确的,但.

import numpy as np
from scipy.optimize import milp, Bounds, LinearConstraint

names = ('tomato', 'lettuce', 'spinach', 'carrot', 'oil')
energy_kcal = (21,        16,       371,      346,   884)
protein_g = (0.85,      1.62,     12.78,     8.39,     0)
fat_g =     (0.33,      0.20,      1.58,     1.39,   100)
carbs_g =   (4.64,      2.37,     74.69,    80.70,     0)
sodium_mg = (   9,         8,         7,    508.2,     0)

nutrient_constraint = LinearConstraint(
    A=(protein_g, fat_g, carbs_g, sodium_mg),
    lb=(      15,     2,       4,   -np.inf),
    ub=(  np.inf,     6,  np.inf,       100),
)

# (lettuce + spinach) / all <= 0.5
# lettuce + spinach <= 0.5all
# 0 <= 0.5all - lettuce - spinach
# 0 <= all - 2lettuce - 2spinach
green_constraint = LinearConstraint(
    A=(1, -1, -1, 1, 1),
    lb=0,
)

result = milp(
    c=energy_kcal,
    integrality=False,
    bounds=Bounds(lb=0),
    constraints=(nutrient_constraint, green_constraint),
)
assert result.success, result.message

for name, hundred_g in zip(names, result.x):
    print(f'{name:>7}: {hundred_g * 100:5.1f} g')

protein, fat, carbs, sodium = nutrient_constraint.A @ result.x
greens = (result.x[1] + result.x[2]) / result.x.sum()
print(f'''
 energy: {result.fun:5.1f} kcal
protein: {protein:5.1f} g
    fat: {fat:5.1f} g
  carbs: {carbs:5.1f} g
 sodium: {sodium:5.1f} mg
 greens: {greens:6.1%}
''')

个字符

相关问题