简体   繁体   English

scipy.optimize.minimize约束问题

[英]scipy.optimize.minimize constraints problem

I have a minimize task: That function work fine:我有一个最小化任务: function 工作正常:

def list_year_payments(clear_payments, number_periods):
    payments = clear_payments[:number_periods+1]
    eq_const = {'type':'eq', 'fun': lambda x:   np.sum(x*discoun_coeff(number_periods,d_r))-future_value_of_aim}
    eq_const_1 = {'type':'eq', 'fun': lambda x: (payments[0]/x[0] - payments[1]/x[1])}
    eq_const_2 = {'type':'eq', 'fun': lambda x: (payments[1]/x[1] - payments[2]/x[2])}
    eq_const_3 = {'type':'eq', 'fun': lambda x: (payments[2]/x[2] - payments[3]/x[3])}
    eq_const_4 = {'type':'eq', 'fun': lambda x: (payments[3]/x[3] - payments[4]/x[4])}
    eq_const_5 = {'type':'eq', 'fun': lambda x: (payments[4]/x[4] - payments[5]/x[5])}
    eq_const_6 = {'type':'eq', 'fun': lambda x: (payments[5]/x[5] - payments[6]/x[6])}
    bounds = ((0,70),)*(number_periods+1)
    res = minimize(aim, X, method='SLSQP', constraints=[eq_const,eq_const_1, eq_const_2,eq_const_3,eq_const_4,eq_const_5, eq_const_6] , bounds=bounds)
    return res.x

But in real all constraints depend on '''number_periods''': so I need one instruction for all constraints for to six.但实际上所有约束都取决于“number_periods”:所以我需要一条指令来处理最多 6 条约束。

def minimizze(clear_payments, number_periods):
    payments = clear_payments[:number_periods+1]
    eq_const = {'type':'eq', 'fun': lambda x: np.sum(x*discoun_coeff(number_periods,d_r))-future_value_of_aim}
    eq_const_1 = {'type':'eq', 'fun': lambda x : np.sum([payments[i]/x[i] ==    payments[i+1]/x[i+1] for i in range(number_periods)])-number_periods}

    bounds = ((1,70),)*(number_periods+1)
    res = minimize(aim, X, method='SLSQP', constraints=[eq_const,eq_const_1] , bounds=bounds)
    return res.x

but this didn't work return array of start x iterations(like [1,1,1,1,1,1,1]), looks like eq_const about sum that should be 470 didn't work.但这不起作用返回开始 x 迭代的数组(如 [1,1,1,1,1,1,1]),看起来应该是 470 的总和的 eq_const 不起作用。

all code:所有代码:

import numpy as np
from scipy.optimize import minimize

clear_payments = np.array([90,100,110,120,130,120,110,100,90])
future_value_of_aim = 470
number_periods = 6
d_r = 0.12


def discoun_coeff(per,d_r):
    x = np.ones(per+1)
    k = np.empty(per+1)
    for i in range(per+1):
        k[i]=x[i]*(1+d_r)**i

    return k[::-1]


def aim(X):
    return np.sum(X)

X = np.ones(number_periods+1)
x = np.linspace(0,70,7000)
def paymets_year(clear_payments, number_periods):
    payments = clear_payments[:number_periods+1]

    eq_const = {'type':'eq', 'fun': lambda x: np.sum(x*discoun_coeff(number_periods,d_r))-future_value_of_aim}

    eq_const_1 = {'type':'eq', 'fun': lambda x: (payments[0]/x[0] - payments[1]/x[1])}
    eq_const_2 = {'type':'eq', 'fun': lambda x: (payments[1]/x[1] - payments[2]/x[2])}
    eq_const_3 = {'type':'eq', 'fun': lambda x: (payments[2]/x[2] - payments[3]/x[3])}
    eq_const_4 = {'type':'eq', 'fun': lambda x: (payments[3]/x[3] - payments[4]/x[4])}
    eq_const_5 = {'type':'eq', 'fun': lambda x: (payments[4]/x[4] - payments[5]/x[5])}
    eq_const_6 = {'type':'eq', 'fun': lambda x: (payments[5]/x[5] - payments[6]/x[6])}
    bounds = ((0,70),)*(number_periods+1)
    res = minimize(aim, X, method='SLSQP', constraints=[eq_const,eq_const_1,       eq_const_2,eq_const_3,eq_const_4,eq_const_5, eq_const_6] , bounds=bounds)
    return res.x

p=paymets_year(clear_payments, number_periods)
p
array([38.34895684, 42.60995205, 46.87094726, 51.13194246, 55.39293767,
   51.13194246, 46.87094726])

If I understand right, you want to generalize如果我理解正确,你想概括

 {'type':'eq', 'fun': lambda x: (payments[0]/x[0] - payments[1]/x[1])}
 {'type':'eq', 'fun': lambda x: (payments[1]/x[1] - payments[2]/x[2])}
 {'type':'eq', 'fun': lambda x: (payments[2]/x[2] - payments[3]/x[3])}
 {'type':'eq', 'fun': lambda x: (payments[3]/x[3] - payments[4]/x[4])}
 {'type':'eq', 'fun': lambda x: (payments[4]/x[4] - payments[5]/x[5])}
 {'type':'eq', 'fun': lambda x: (payments[5]/x[5] - payments[6]/x[6])}

for other values than number_periods = 6 , and you tried to do this with对于number_periods = 6以外的其他值,您尝试使用

 {'type':'eq', 'fun': lambda x : np.sum([payments[i]/x[i] ==    payments[i+1]/x[i+1] for i in range(number_periods)])-number_periods}

but failed, despite ideationally the computations are equivalent.但失败了,尽管从理论上讲计算是等效的。 In reality though, the optimization likely fails due to the discontinuity of the == relation together with the imprecision of floating-point arithmetic.但实际上,由于==关系的不连续性和浮点运算的不精确性,优化可能会失败。
A better approach would be more similar to the original:更好的方法将与原始方法更相似:

 {'type': 'eq',
  'fun': lambda x: np.sum([(payments[i]/x[i]-payments[i+1]/x[i+1])**2 for i in range(number_periods)])
 }

Here subtraction is used as before, and to let the overall sum for equal quotients approximate zero the individual differences are squared.这里像以前一样使用减法,为了让相等商的总和接近于零,对个体差异进行平方。
But beware: With this single constraint summarizing the original constraints, the optimization converges rather poorly.但要注意:由于这个单一约束总结了原始约束,优化收敛得相当差。 Better keep using individual constraints;最好继续使用个人约束; you can generate them for any number_periods :您可以为任何number_periods生成它们:

    constr = [eq_const]
    for i in range(number_periods):
        constr.append({'type': 'eq', 'fun': lambda x, i=i: payments[i]/x[i]-payments[i+1]/x[i+1]})
    res = minimize(aim, X, method='SLSQP', constraints=constr, bounds=bounds)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM