2015-01-08 4 views
0

Я пытаюсь scipy.optimize python, чтобы свести к минимуму некоторые функции, используя алгоритм SLSQP. Оптимизация работает отлично без ограничений и с одним ограничением матрицы, но затем я получаю сообщение об ошибке, когда добавляю второе ограничение матрицы.Матричные ограничения с Scipy.Optimize.Minimize

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

n = 3 
n_sim = 10000 
risk_aversion = 5 

Y = np.random.normal(loc=0, scale=1, size=(n_sim, n)) 

mu_Y = np.mean(Y, axis=0).reshape(1, n) 
sigma_Y = np.cov(Y, rowvar=0, bias=1) 

x0 = np.ones((n, 1))/n 

Aeq = np.ones((1, n)) 
beq = 1 
A = np.array([[1, 1, 0], [-1, -1, 0]]) 
b = np.array([[0.25], [-0.5]]) 

def func(x, mu, sigma, risk_aversion): 
    return -np.dot(mu, x) + 0.5 * risk_aversion * np.dot(np.dot(x.T, sigma), x) 
def func_deriv(x, sigma, risk_aversion): 
    return risk_aversion * np.dot(sigma, x) 

c_ = {'type': 'eq', 'fun' : lambda x: np.dot(Aeq, x) - beq, 'jac' : lambda x: Aeq} 
b_ = [(0,1) for i in range(n)] 

Эта версия с одним ограничением и границ работает отлично

res = minimize(lambda x: func(x, mu_Y, sigma_Y, risk_aversion), x0, 
       jac=lambda x: func_deriv(x, sigma_Y, risk_aversion), 
       constraints=c_, bounds=b_, method='SLSQP', options={'disp': True}) 

Однако два ограничения версия дает мне ошибку

d_ = (c_, 
     {'type': 'ineq', 'fun' : lambda x: np.dot(A, x) - b, 'jac' : lambda x: A}) 

res2 = minimize(lambda x: func(x, mu_Y, sigma_Y, risk_aversion), x0, 
       jac=lambda x: func_deriv(x, sigma_Y, risk_aversion), 
       constraints=d_, bounds=b_, method='SLSQP', options={'disp': True}) 

ответ

0

Если я использую

A = np.array([-1, -1, 0]) 
b = -0.5 

вместо того, что у меня было строго, тогда оптимизация работает. Это говорит о том, что я не могу сделать матрицу ограничений (например, я бы использовал fmincon в Matlab), если кто-то не может подтвердить это в противном случае. Однако я могу просто добавлять ограничения, чтобы они работали. Ограничения должны быть в виде кортежей словарей, так что я положил вместе

d = [] 
for i in range(0, b.size): 
    d.append({'type': 'ineq', 'fun' : lambda x: np.dot(A[i, ], x) - b[i], 'jac' : lambda x: A[i, ]}) 
d_ = tuple(d) 
c_tuple = c_, 
d_ = d_ + c_tuple 

, который, кажется, работает правильно.

+0

При добавлении материала к типу ограничений в цикле for, будьте осторожны: https://stackoverflow.com/questions/233673/lexical-closures-in-python –

+0

@pv. Моя цель состояла в том, чтобы работайте достаточно хорошо, чтобы сравнить базовую производительность с nlopt. nlopt был примерно в 3 раза быстрее, поэтому я собираюсь больше сосредоточиться на использовании этого (что не требует этого синтаксиса). – John

Смежные вопросы