繁体   English   中英

scipy优化最小化函数不强制约束

[英]scipy optimization minimize function not enforcing constraints

所以我的约束函数没有被正确强加它会出现。

import numpy as np 
import scipy.integrate as integrate
import scipy.interpolate as interpolate
import pylab as plt
import scipy.optimize as op
import math

def make_cons(parameter_guess):
    cons=()
    for i in range(0,len(parameter_guess)):
        constraint = {'type': 'ineq', 'fun': lambda parameter_guess:  -math.fabs(parameter_guess[i]) + 1 }
        cons +=(constraint,)
    # print cons
    #cons=({'type': 'ineq', 'fun': lambda parameter_guess:  -parameter_guess+ 1 })
    return cons


def problem(N,IC):
    t=np.linspace(0,5,1000)
    tt=np.linspace(0,5+.5,N+1)
    parameter_guess = .5*np.ones(len(tt))
    res=op.minimize(cost_function, parameter_guess, args=(t,tt,IC), method='SLSQP',constraints=make_cons(parameter_guess))
    true_param= res.x
    print res.message
    print true_param
    generate_state_and_control(true_param,t,tt,IC)


def cost_function(parameter_guess,t,tt,IC):
    #print parameter_guess
    f_p = interpolate.interp1d(tt, parameter_guess)
    sol = integrate.odeint(f, [IC[0],IC[1],0], t, args=(f_p,))
    cost_sol = sol[:,2]
    cost=cost_sol[-1]
    print 'cost ' + str(cost) 
    return cost


def f(y,t,f_p):
    dydt=[-y[0] +2*y[1] , y[0] -.2*y[1] + f_p(t), .5*(y[0]**2 + 2*y[1]**2 + 3*f_p(t)**2)]
    return dydt


def generate_state_and_control(parameters,t,tt,IC):
    f_p = interpolate.interp1d(tt, parameters)
    sol = integrate.odeint(f, [IC[0],IC[1],0], t, args=(f_p,))
    control=f_p(t)
    position=sol[:,0]
    velocity=sol[:,1]
    cost_sol = sol[:,2]
    cost=cost_sol[-1]
    print 'cost ' + str(cost) 
    print parameters
    plt.plot(tt,parameters,label='Control')
    plt.xlabel('time')
    plt.ylabel('u')
    plt.title('Control')
    plt.show()
    plt.clf()
    plt.plot(position,velocity,label='Velocity vs Position')
    plt.xlabel('Position')
    plt.ylabel('Velocity')
    plt.title('Velocity vs Position')
    plt.show()



problem(15,[3,6])

我在make_cons函数中创建了约束。 我只是说每个变量的绝对值都必须小于1(即| p_i | <= 1 - 函数期望格式为g(p_i)> = 1)

但是,如果我跑。

problem(15,[3,6])





[ -6.91310983 -11.84886554  -8.39257891  -5.89026938  -3.94611243
  -2.83438566  -1.84550722  -1.18591646  -0.72311117  -0.5668469
   0.10564927  -0.02283327  -0.0312163   -0.08288569   0.34830762   0.5       ]

我们显然可以看到并非所有这些变量都在-1和1之间。

有人看到我在这里制作的琐碎小虫?

不要在约束函数中使用绝对值函数。 SLSQP算法假定约束函数是连续可微的。

要获得与当前约束之一相同的效果,可以创建两个约束函数,一个用于确保x> -1,另一个用于确保x <1。

例如:

def make_cons(parameter_guess):
    cons=()
    for i in range(0,len(parameter_guess)):
        constraint = {'type': 'ineq', 'fun': lambda x: 1 - x}
        cons +=(constraint,)
        constraint = {'type': 'ineq', 'fun': lambda x: 1 + x}
        cons +=(constraint,)
    return cons

或者您可以将约束表达为1 - x**2 > 0

def make_cons(parameter_guess):
    cons=()
    for i in range(0,len(parameter_guess)):
        constraint = {'type': 'ineq', 'fun': lambda x: 1 - x**2}
        cons +=(constraint,)
    return cons

这仍然不会给出好结果。 如果将成本函数扩展为返回相对较小的值,则效果会更好。 在从cost_function()返回之前简单地设置cost /= 100000会产生很大的不同。

通过这两个更改,我在运行结束时得到以下内容:

Optimization terminated successfully.
[ 0.31417892  0.21871057  0.28818131  0.40615797  0.26569214  0.74145029
 -1.00000002 -0.9983564  -0.77176625 -0.10348714 -0.14786611  0.04025887
  0.24103308  0.39788151  0.49343655  0.5       ]
cost 132978.180126
[ 0.31417892  0.21871057  0.28818131  0.40615797  0.26569214  0.74145029
 -1.00000002 -0.9983564  -0.77176625 -0.10348714 -0.14786611  0.04025887
  0.24103308  0.39788151  0.49343655  0.5       ]

由于约束是变量的简单常量边界,因此可以使用bounds参数而不是约束函数。 例如,具有以下内容

res=op.minimize(cost_function, parameter_guess, args=(t,tt,IC),
                method='SLSQP',
                #constraints=make_cons(parameter_guess),
                bounds=[(-1, 1)]*(N+1),
                options={'ftol': 1e-10})

我得到了更好的结果:

Optimization terminated successfully.
[ 0.34405263  0.20874193  0.01236256 -0.88512666  0.90658335  0.65950279
 -0.9576039  -0.99462141 -0.97049943 -0.99994613 -0.99998563 -0.99999957
 -1.          0.09842358  0.47056459  0.5       ]
cost 125446.690335
[ 0.34405263  0.20874193  0.01236256 -0.88512666  0.90658335  0.65950279
 -0.9576039  -0.99462141 -0.97049943 -0.99994613 -0.99998563 -0.99999957
 -1.          0.09842358  0.47056459  0.5       ]

另一方面,与

res=op.minimize(cost_function, parameter_guess, args=(t,tt,IC),
                method='SLSQP',
                constraints=make_cons(parameter_guess),
                #bounds=[(-1, 1)]*(N+1),
                options={'ftol': 1e-10, 'maxiter': 1000})

结果更好:

Optimization terminated successfully.
[ 0.26307724  0.05991932  0.24965239 -0.99940001 -0.22487722 -0.99946811
 -0.9997716  -0.99045829 -0.98981196 -0.9946721  -1.         -0.99999917
 -1.         -0.99975764  0.27805723  0.5       ]
cost 116703.409203
[ 0.26307724  0.05991932  0.24965239 -0.99940001 -0.22487722 -0.99946811
 -0.9997716  -0.99045829 -0.98981196 -0.9946721  -1.         -0.99999917
 -1.         -0.99975764  0.27805723  0.5       ]

去搞清楚。

我建议再尝试一下这些选项。

暂无
暂无

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

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