web-dev-qa-db-ja.com

cvxpyの最小化問題を解決する問題

私は線形最適化問題を抱えています。これは次のようなコスト関数コードで表すことができます。

value_to_minimize = 0.0;
for i in range(0, len(v_1)):
    value_to_minimize += np.abs(v_1[i] - (v_2[i] * c1 + v_3[i] * c2 + v_4[i] * c3));

ソルバーのタスクは、値を最小化する変数c1c2c3の値を見つけることです。境界条件として、c1c2c3を一緒にすると、1.0になり、負にならないようにする必要があります。 v_1v_2v_3およびv_4は、10000の浮動小数点値を持つベクトルです。

これはcvxpyでこの最小化問題を解決するための概要ですが、cp.Minimize(...)でパラメーターを渡さないでください。

V1 = np.array(v_1).reshape(10000, 1)
V2 = np.array(v_2 + v_3 + v_4).reshape(10000, 3)
c = cp.Variable((3,1),nonneg=True)

prob = cp.Problem(cp.Minimize(..., # ???
                [sum(c) == 1])) 
prob.solve(verbose=True)

その場合、cvxpyの最小化関数はどのように見えますか?

2
MerklT

別のライブラリを使用してもかまわない場合は、scipyをお勧めします。

from scipy.optimize import minimize
import numpy as np

def OF(x0, v_1, v_2, v_3, v_4):
  value_to_minimize = 0.0
  for i in range(0, len(v_1)):
    value_to_minimize += np.abs(v_1[i] - (v_2[i] * x0[0] + v_3[i] * x0[1] + v_4[i] * x0[2]))
  return value_to_minimize


if __name__ == '__main__':

  x0 = np.array([0, 0, 0])
  v_1 = np.random.randint(10, size = 10000)
  v_2 = np.random.randint(10, size = 10000)
  v_3 = np.random.randint(10, size = 10000)
  v_4 = np.random.randint(10, size = 10000)


  minx0 = np.repeat(0, [len(x0)] , axis = 0)
  maxx0 = np.repeat(np.inf, [len(x0)] , axis = 0)
  bounds = Tuple(Zip(minx0, maxx0))

  cons = {'type':'eq', 
  'fun':lambda x0: 1 - sum(x0)}
  res_cons = minimize(OF, x0, (v_1, v_2, v_3, v_4), bounds = bounds, constraints=cons, method='SLSQP')



  print(res_cons)
  print('Current value of objective function: ' + str(res_cons['fun']))
  print('Current value of controls:')
  print(res_cons['x'])

出力は次のとおりです。

     fun: 27919.666908810435
     jac: array([5092.        , 5672.        , 5108.39868164])
 message: 'Optimization terminated successfully.'
    nfev: 126
     nit: 21
    njev: 21
  status: 0
 success: True
       x: array([0.33333287, 0.33333368, 0.33333345])
Current value of objective function: 27919.666908810435
Current value of controls:
[0.33333287 0.33333368 0.33333345]

しかし、v_の値にランダムな整数を使用しただけなので、ここでの実際の値はそれほど意味がありません...このモデルがcの値の制約と1との境界に加えられるという単なるデモですゼロ以上(負)。

編集の更新:これは線形問題であることを理解するのに十分にOF /制約を調べませんでした...線形ソルバーアルゴリズムを使用する必要があります(ただし、非線形を使用できますが、やりすぎです) 。

scipyの線形ソルバーは、このような複雑な最適化問題には適しておらず、cvxpyに戻ります。

import numpy as np
import cvxpy as cp

# Create two scalar optimization variables.
x = cp.Variable()
y = cp.Variable()
z = cp.Variable()

v_1 = np.random.randint(10, size = 10000)
v_2 = np.random.randint(10, size = 10000)
v_3 = np.random.randint(10, size = 10000)
v_4 = np.random.randint(10, size = 10000)

constraints = [x + y + z == 1, x >= 0, y >= 0, z >= 0]

objective = cp.Minimize(cp.sum(cp.abs(v_1 - (v_2 * x + v_3 * y + v_4 * z))))

prob = cp.Problem(objective, constraints)
print("Value of OF:", prob.solve())
print('Current value of controls:')
print(x.value, y.value, z.value)

出力:

Value of OF: 27621.999978414093
Current value of controls:
0.3333333333016109 0.33333333406414983 0.3333333326298208
3
Anna Nevison

パラメータの1つと制約を削除することを強くお勧めします。あなたがそれを知っているならc1 + c2 + c3 = 1.、次にc3 = 1. - c1 - c2!これにより、最小化のタスクがはるかに簡単になります。また、v_1などは数の多い配列であり、配列として使用します。たとえば、

c3 = 1. - c1 - c2
value_to_minimize = np.sum(np.abs(v_1 - (v_2 * c1 + v_3 * c2 + v_4 * c3)))
0
rpoleski