所以我的约束函数没有被正确强加它会出现。
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之间。
有人看到我在这里制造的琐碎错误吗?
答案 0 :(得分:5)
不要在约束函数中使用绝对值函数。 SLSQP算法假设约束函数是连续可微的。
要获得与当前约束之一相同的效果,可以创建两个约束函数,一个用于确保x> -1和另一个以确保x <1。 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 /= 100000
返回之前简单地添加cost_function()
会产生很大的不同。
通过这两项更改,我在运行结束时得到以下内容:
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 ]
去图。
我建议您尝试使用这些选项。