Scipy.optimize - 没有给出预期输出的约束

时间:2018-01-31 00:28:52

标签: python optimization scipy

我尝试复制this简单优化问题,以便开始使用Scipy.optimize。 问题是一个典型的产品组合问题,其目标是在一些生产和配料限制的情况下实现利润最大化,在这种情况下,它是一家拥有三种咖啡类型的咖啡店。

  • x0 - >定期
  • x1 - >拿铁
  • x2 - >摩卡

约束:

  • x0 + x1 + x2 <= 500
  • x1 + x2 <= 350
  • x2 <= 125

目标函数

  • 最大化x0 * 1.5 + x1 * 2.00 + x2 * 2.25

这是我的代码(请注意我在笔记本中运行):

from scipy.optimize import minimize

#profit / cup
Reg = 1.25
Lat = 2.00
Moc = 2.25

#objective function to maximize
def objective(x):
    return (x[0]*Reg + x[1]*Lat + x[2]*Moc)

#constraints
def cons_total_production(x):
    return (sum(x))-500

def cons_choc(x):
    return (x[2])-125

def cons_milk(x):
    return (sum(x[1:]))-350

cons1 = {'type':'ineq', 'fun':cons_total_production}
cons2 = {'type':'ineq', 'fun':cons_choc}
cons3 = {'type':'ineq', 'fun':cons_milk}
cons = [cons1,cons2,cons3]

#boundries
bnds = ((0,None),(0,None),(0,None))

#initial guess
x0 = [250,150,100]

#let scipy do its magic
sol = minimize(objective, x0, constraints=cons, bounds=bnds)

这会产生正确的输出。 当我使用scipy最小化时,这怎么可能?

     fun: 918.7499999999358
     jac: array([ 1.25,  2.  ,  2.25])
 message: 'Optimization terminated successfully.'
    nfev: 50
     nit: 10
    njev: 10
  status: 0
 success: True
       x: array([ 150.,  225.,  125.])

但是当我尝试添加一个约束时,输出是错误的。例如,如果我做一个约束声明x0必须等于x1,我会更改以下内容并再次运行模型:

def cons_eq(x):
    return x[0]-x[1]

cons4 = {'type':'eq', 'fun':cons_eq}

cons = [cons1, cons2, cons3, cons4]

但是现在我的约束x2&lt; = 125被忽略了:

     fun: 937.4999999999934
     jac: array([ 1.25,  2.  ,  2.25])
 message: 'Optimization terminated successfully.'
    nfev: 35
     nit: 7
    njev: 7
  status: 0
 success: True
       x: array([ 150.,  150.,  200.])

有什么建议吗? thx ...

1 个答案:

答案 0 :(得分:2)

问题在于你的目标函数和约束。由于您使用scipy的最小化功能,您必须最小化目标函数的负数以找到函数的最大值(这有点棘手)。< / p>

#objective function to maximize
def objective(x):
    return -1.0*(x[0]*Reg + x[1]*Lat + x[2]*Moc)

您还错误地输入了不等式函数。如果你查看scipy文档,所有不等式都是g(x)&gt; = 0的形式。因此,例如,如果你想要x2&lt; = 125,你必须乘以负1(以切换不等式),然后加125得到:g(x)= 125-x2&gt; = 0.所以其余的你的约束:

#constraints
def cons_total_production(x):
    return (-1.0*sum(x))+500

def cons_choc(x):
    return (-1.0*x[2])+125

def cons_milk(x):
    return (-1.0*sum(x[1:]))+350

这将为您提供输出:

 fun: -918.7499999999989
 jac: array([-1.25, -2.  , -2.25])
 message: 'Optimization terminated successfully.'
 nfev: 35
 nit: 7
 njev: 7
 status: 0
 success: True
 x: array([ 150.,  225.,  125.])

 fun: -890.62499998809
 jac: array([-1.25, -2.  , -2.25])
 message: 'Optimization terminated successfully.'
 nfev: 10
 nit: 2
 njev: 2
 status: 0
 success: True
 x: array([ 187.5,  187.5,  125. ])

线性编程非常酷!

希望有所帮助:)