解决cvxpy中的最小化问题的问题
Problem solving a minimization problem in 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));
求解器的任务应该是为变量 c1
、c2
、c3
找到最小值的值。作为边界条件,c1
、c2
、c3
一起应导致 1.0 而不是负数。
v_1
、v_2
、v_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 的最小化函数看起来如何?
我强烈建议删除其中一个参数和一个约束。如果你知道c1 + c2 + c3 = 1.
,那就用c3 = 1. - c1 - c2
!这使得最小化器的任务变得更加容易。此外,如果 v_1
等是 numpy 数组,则将它们用作数组,例如
c3 = 1. - c1 - c2
value_to_minimize = np.sum(np.abs(v_1 - (v_2 * c1 + v_3 * c2 + v_4 * c3)))
如果您不介意使用其他库,我会推荐 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/constraints 以意识到这是一个线性问题...应该使用线性求解器算法(尽管,你可以使用非线性,但它有点矫枉过正)。
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
我有一个线性优化问题,可以用这样的成本函数代码表示:
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));
求解器的任务应该是为变量 c1
、c2
、c3
找到最小值的值。作为边界条件,c1
、c2
、c3
一起应导致 1.0 而不是负数。
v_1
、v_2
、v_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 的最小化函数看起来如何?
我强烈建议删除其中一个参数和一个约束。如果你知道c1 + c2 + c3 = 1.
,那就用c3 = 1. - c1 - c2
!这使得最小化器的任务变得更加容易。此外,如果 v_1
等是 numpy 数组,则将它们用作数组,例如
c3 = 1. - c1 - c2
value_to_minimize = np.sum(np.abs(v_1 - (v_2 * c1 + v_3 * c2 + v_4 * c3)))
如果您不介意使用其他库,我会推荐 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/constraints 以意识到这是一个线性问题...应该使用线性求解器算法(尽管,你可以使用非线性,但它有点矫枉过正)。
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