【问题标题】:Scipy optimize linprog with more complex functionScipy 用更复杂的功能优化 linprog
【发布时间】:2017-04-10 05:07:30
【问题描述】:

我正在尝试以以下形式优化函数:

1*abs(x_0) + 1*abs(x_1) + .. + 1*abs(x_n)

函数中的系数总是1,但是xi的取值是有条件的,例如

x2 - x3x3 - x 4 等等。

我用的是scipy.optimize.linprog,但是这个只能解决以下形式的函数:

a_0*x_0 + a_1*x_1 + .. + a_n*x_n

有没有办法将scipy.optimize.linprog 用于第一个函数?

【问题讨论】:

    标签: python scipy mathematical-optimization linear-programming


    【解决方案1】:

    问题:

    Minimize 1*abs(x_0) + 1*abs(x_1) + ... + 1*abs(x_n))
    s.t.     x_2 - x3 <= 7
    

    可以转换成问题:

    Minimize 1*y_0 + 1*y_1 + ... + 1*y_n
    s.t.     x_2 - x3 <= 7
             -y_i <= x_i <= y_i  // for i in n
    

    这里我们引入了新变量y_0, ..., y_n

    所以你的一个稍微修改的问题(假设:最小化)看起来像这样:

    from scipy.optimize import linprog
    import numpy as np
    
    N = 5
    N_AUX = N
    
    c = np.hstack((np.zeros(N), np.ones(N_AUX))) # objective -> sum of aux-vars
    
    A_orig = [[0, 1, -1, 0, 0, 0, 0, 0, 0, 0],   # orig constraint 1
              [0, 0, 1, -1, 0, 0, 0, 0, 0, 0],   # orig constraint 2
              [-1, -1, 0, 0, 0, 0, 0, 0, 0, 0],  # more interesting problem
              [0, -1, -1, 0, 0, 0, 0, 0, 0, 0]]  # ""   ""          ""
    
    A_aux = [[-1, 0, 0, 0, 0, -1, 0, 0, 0, 0],
             [0, -1, 0, 0, 0, 0, -1, 0, 0, 0],
             [0, 0, -1, 0, 0, 0, 0, -1, 0, 0],
             [0, 0, 0, -1, 0, 0, 0, 0, -1, 0],
             [0, 0, 0, 0, -1, 0, 0, 0, 0, -1],
             [1, 0, 0, 0, 0, -1, 0, 0, 0, 0],
             [0, 1, 0, 0, 0, 0, -1, 0, 0, 0],
             [0, 0, 1, 0, 0, 0, 0, -1, 0, 0],
             [0, 0, 0, 1, 0, 0, 0, 0, -1, 0],
             [0, 0, 0, 0, 1, 0, 0, 0, 0, -1]]
    
    A = np.vstack((A_orig, A_aux))
    
    b = [7, 4, -5, -8] + [0 for i in range(N_AUX*2)]
    bnds = [(0, 50) for i in range(N)] + [(None, None) for i in range(N_AUX)] # some custom bounds
    
    res = linprog(c, A_ub=A, b_ub=b, bounds=bnds)
    
    print(res)
    
    #     fun: 8.0
    # message: 'Optimization terminated successfully.'
    #     nit: 10
    #   slack: array([  5.,   1.,   0.,  10.,   6.,   0.,   0.,   0.,   0.,          0.,   0.,
    #     0.,  50.,  45.,  47.,  50.,  50.,   0.,   0.])
    #  status: 0
    # success: True
    #       x: array([ 0.,  5.,  3.,  0.,  0.,  0.,  5.,  3.,  0.,  0.])
    

    如果您对安装库有一点了解,我建议您使用cvxpy

    • 自动进行这种转换(等等)
    • 支持更好的求解器(开源和商业;基于单纯形和非单纯形)

    同样的例子:

    from cvxpy import *
    
    x = Variable(5)
    constraints = [x[1] - x[2] <= 7,
                   x[2] - x[3] <= 4,
                   x[0] + x[1] >= 5,
                   x[1] + x[2] >= 8,
                   x >= 0,
                   x <= 50]
    objective = Minimize(sum_entries(abs(x)))
    problem = Problem(objective, constraints)
    problem.solve()
    print(x.value)
    print(problem.value)
    
    # [[ -1.56436431e-11]
    #  [  5.83767132e+00]
    #  [  2.16232868e+00]
    #  [  6.53497343e-10]
    #  [  7.79511984e-10]]
    # 8.00000000102
    

    【讨论】:

      猜你喜欢
      • 2020-08-25
      • 2020-03-20
      • 2017-03-24
      • 2011-03-06
      • 2017-08-01
      • 2012-10-19
      • 2021-10-01
      • 2013-11-20
      • 2014-04-08
      相关资源
      最近更新 更多