1

我想要的形式來優化功能:在功能SciPy的優化linprog更復雜的功能

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

係數始終是1,但也有X 值條件下,例如

X - X < = 7X - X < = 4等。

我使用scipy.optimize.linprog,但是這隻能解決形式功能:

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

有沒有辦法使用scipy.optimize.linprog爲第一個功能?

回答

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