【问题标题】:Scipy.optimize - constraints not giving expected outputScipy.optimize - 约束没有给出预期的输出
【发布时间】:2018-01-31 09:12:10
【问题描述】:

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

  • x0 -> 常规
  • x1 -> 拿铁
  • x2 -> 摩卡

约束:

  • x0+x1+x2
  • x1+x2
  • x2

目标函数

  • 最大化 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

     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.])

有什么建议吗?谢谢...

【问题讨论】:

    标签: python optimization scipy


    【解决方案1】:

    问题在于您的目标函数和约束。由于您使用的是 scipy 的 minimize 函数,因此您必须 将目标函数的负数最小化以找到函数的最大值(这有点棘手)。

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

    您还错误地键入了不等式函数。如果您查看 scipy 文档,所有不等式都采用 g(x)>=0 的形式。所以,例如,如果你想要 x2 = 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. ])
    

    线性编程太酷了!

    希望对你有帮助:)

    【讨论】:

    • 好收获!公平地说:这是一个通过将其视为 NLP(包括数值差异)来解决的 LP。
    • 您的权利。使用 scipy.optimize.linprog 可能更有效。
    猜你喜欢
    • 2018-09-18
    • 2019-09-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-22
    • 2019-07-16
    相关资源
    最近更新 更多