如何使用Scipy最小化约束和动态函数

时间:2014-09-23 21:03:14

标签: python optimization numpy matrix scipy

我是scipy.optimize模块的新手,需要帮助尝试在公式V上使用最小化函数,该公式适用于矩阵并且有2个约束但是我不确定我是否正确处理函数的形成或者其中一个约束。

M是NxN矩阵,但例如我将给出4x4矩阵

 [[ 0.00123727  0.00011974  0.00067403  0.00060845]
 [ 0.00011974  0.00736665  0.00165674  0.00053581]
 [ 0.00067403  0.00165674  0.00281547  0.00129646]
 [ 0.00060845  0.00053581  0.00129646  0.00153195]]

X是一个1xN矩阵,其中所有数字都是正数,必须加起来为1,这是我正在解决的问题

约束:

X[0] + X[1] + X[2] + … X[n] = 1

E = X[0]*R[0] + X[1]*R[1] + X[2]*R[2] + … X[n]*R[n] (E is user input)

我想要最小化的功能是:

V = X[0]**2 * M[0][0]  + 2*X[0]*X[1]*M[0][1] + 2*X[0]*X[2]*M[0][2] + 2 * X[0] * X[3] * M[0][3] * X[1]**2 * M[1][1] + ….etc

到目前为止我的代码是

    cons = ({'type': 'eq', 'fun': lambda x: sum(w) - 1})

    args = n, m, w

    answer = scipy.optimize.minimize(func(*args), w, args=(), method='SLSQP',
                                     bounds=((0, None), (0, None)),
                                     constraints=cons)
def func(n, m, x):
    row = 0
    col = 0
    formula = []
    while row < n:
        while col < n:
            if col == row:
                item = (x[row]**2) * m[row][col]
                formula.append(item)
                col += 1
            else:
                item2 = 2 * x[row] * x[col] * m[row][col]
                formula.append(item2)
                col += 1

        row += 1
        col = 0

    return sum(formula)

我理解的是如何发出第二个约束。我也不确定我是否正确处理了公式的创建。非常感谢任何帮助

1 个答案:

答案 0 :(得分:3)

如评论中所述,这可以通过专门的凸解算器来解决。


from __future__ import print_function

import numpy as np
import cvxpy
from scipy.optimize import minimize

# Problem data.
n = 4
M = [
        [0.00123727, 0.00011974, 0.00067403, 0.00060845],
        [0.00011974, 0.00736665, 0.00165674, 0.00053581],
        [0.00067403, 0.00165674, 0.00281547, 0.00129646],
        [0.00060845, 0.00053581, 0.00129646, 0.00153195]]
np.random.seed(1)
R = np.random.randn(n)
E = np.random.randn()

print('R:', R)
print('E:', E)
print()

A = np.matrix([np.ones(n), R])
b = np.matrix([[1], [E]])


def solve_cvxpy():

    # Construct the problem.
    x = cvxpy.Variable(n)
    objective = cvxpy.Minimize(cvxpy.quad_form(x, M))
    constraints = [0 <= x, A*x == b]
    problem = cvxpy.Problem(objective, constraints)

    # Solve the problem.
    result = problem.solve()
    print('cvxpy solution:')
    print(x.value)
    print()


def solve_scipy():
    def simplex_constraint(x):
        return x.sum() - 1
    def dot_constraint(x):
        return x.dot(R) - E
    def objective(x):
        return x.dot(M).dot(x)
    x0 = np.ones(n) / n
    bounds = [(0, np.inf)]*n
    constraints = (
            dict(type='eq', fun=simplex_constraint),
            dict(type='eq', fun=dot_constraint))
    result = minimize(
            objective, x0, method='SLSQP', tol=1e-8,
            bounds=bounds, constraints=constraints)
    print('scipy solution:')
    print(result.x)
    print()

solve_cvxpy()
solve_scipy()

R: [ 1.62434536 -0.61175641 -0.52817175 -1.07296862]
E: 0.865407629325

cvxpy solution:
[[  7.03877116e-01]
 [  8.62848827e-02]
 [  5.54383296e-06]
 [  2.09832457e-01]]

scipy solution:
[  7.03877583e-01   8.62886986e-02  -1.24818775e-17   2.09833718e-01]