并行优化ode
这个例子展示了如何优化ODE的参数。
当ODE解同时返回目标函数和非线性约束函数时,如何避免计算两次。这个例子比较patternsearch
而且遗传算法
在运行求解器的时间和解决方案的质量方面。
您需要一个并行计算工具箱™许可证才能使用并行计算。
步骤1。定义问题。
问题是要改变大炮的位置和角度,使炮弹尽可能飞出墙外。炮口初速300米/秒。这面墙有20米高。如果大炮离墙太近,它就必须以太陡的角度发射,炮弹就不能飞得足够远。如果大炮离墙太远,炮弹也飞不远。
空气阻力使弹丸减速。阻力与速度的平方成正比,比例常数为0.02。重力作用于弹丸,使其以恒定的9.81米/秒向下加速2.因此,轨迹的运动方程x(t)
在哪里
初始位置x0
和初始速度xp0
是二维向量。然而,初始高度x0 (2)
等于0,那么初始位置只取决于标量x0 (1)
.初速度xp0
有300量级(初速),所以只取决于初始角度,一个标量。对于初始角th
,xp0
=300 * (cos (th), sin (th))
.因此,优化问题只依赖于两个标量,因此它是一个二维问题。用水平距离和角度作为决策变量。
步骤2。建立ODE模型。
ODE求解器要求您将模型表述为一阶系统。增加轨迹向量(x1(t),x2(t))及其时间导数(x'1(t),x'2(t),形成4-D轨迹矢量。根据增广向量,微分方程变成
把微分方程写成函数文件,保存到你的MATLAB中®路径。
函数F =炮灰(t,x) F = [x(3);x(4);x(3);x(4)];%初始化,使f(1)和f(2)正确NRM = norm(x(3:4)) * .02;%速度的范数乘以常数f (3) = - x(3) *全国抵抗运动;%的水平加速度F (4) = -x(4)*nrm - 9.81;%的垂直加速度
想象ODE的解从距离墙30米的角度开始π/ 3
.
步骤3。使用patternsearch解决。
问题是要找到初始位置x0 (1)
和初始角x0 (2)
为了使弹丸落地的距离最大化。因为这是一个最大化的问题,最小化距离的负数(见最大化和最小化).
使用patternsearch
要解决这个问题,您必须提供目标、约束、初始猜测和选项。
这两个文件是目标函数和约束函数。将它们复制到MATLAB路径上的文件夹中。
函数f = cannonobjective x0 (x) = (x (1); 0; 300 * cos (x (2)); 300 * sin (x (2)));索尔=数值(@cannonfodder [0, 15], x0);找出当y_2(t) = 0时的时刻tzerofnd = fzero (@ (r)德瓦尔(sol r 2), [sol.x (2), sol.x(结束)]);然后找到此时的x位置。f =德瓦尔(sol zerofnd 1);f = - f;取距离的负数为最大值。函数[c,ceq] = cannonconstraint(x) ceq = [];x0 = [x (1), 0; 300 * cos (x (2)); 300 * sin (x (2)));索尔=数值(@cannonfodder [0, 15], x0);如果sol.y (1) < = 0投掷物永远打不到墙C = 20 - sol.y(2,end);其他的找出当弹丸穿过x = 0时zerofnd = fzero (@ (r)德瓦尔(溶胶,r, 1), [sol.x (2), sol.x(结束)]);然后找到这个高度,然后减去20C = 20 - deval(sol,zerofnd,2);结束
注意,目标函数和约束函数设置了它们的输入变量x0
到ODE求解器的4-D初始点。ODE求解器不停止,如果弹丸击中墙壁。相反,约束函数只是变成正的,表明一个不可行的初始值。
初始位置x0 (1)
不能高于0,如果低于-200也是徒劳的。(它应该在-20附近,因为在没有空气阻力的情况下,最长的轨迹会在-20处以一个角度开始π/ 4
)。同样,初始角x0 (2)
不能小于0,也不能大于0π/ 2
.设置边界稍微远离这些初始值:
磅= (-200;0.05);乌兰巴托=(1;π/ 2 . 05);x0 =(-30,π/ 3);%初始猜测
设置UseCompletePoll
选项真正的
.这提供了更高质量的解决方案,并支持与并行处理的直接比较,因为并行计算需要此设置。
选择= optimoptions (“patternsearch”,“UseCompletePoll”,真正的);
调用patternsearch
解决问题。
抽搐%时间解决[xsolution、距离、eflag, outpt] = patternsearch (x0, @cannonobjective...[],[],[],[], 磅,乌兰巴托,@cannonconstraint toc选择)
优化终止:网格尺寸小于选项。MeshTolerance和约束违例小于options. constraintolerance。xsolution = -28.8123 0.6095 distance = -125.9880 eflag = 1 outpt = struct with fields: function: @cannonobjective problemtype: 'nonlinearconstr' pollmethod: 'gpspositivebasis2n' maxconstraint: 0 searchmethod: [] iterations: 5 funccount: 269 meshsize: 8.9125e-07 rngstate: [1×1 struct] message: '优化终止:网格尺寸小于选项。MeshTolerance '和约束违规小于options. constraintolerance .'运行时间为0.792152秒。
以0.6095弧度的角度从距离墙体29米的地方发射,最远距离约126米。报告的距离是负的,因为目标函数是到墙的距离的负数。
可视化的解决方案。
x0 = [xsolution (1), 0; 300 * cos (xsolution(2)); 300 *罪(xsolution (2)));索尔=数值(@cannonfodder [0, 15], x0);找出投掷物落地的时间zerofnd = fzero (@ (r)德瓦尔(sol r 2), [sol.x (2), sol.x(结束)]);t = linspace (0, zerofnd);%相等的时间为情节x =德瓦尔(sol t 1);插值的x值y =德瓦尔(sol t 2);插值的y值情节(x, y)在情节([0,0],[0,20],“k”)%画墙包含(的水平距离) ylabel (的轨道高度)传说(“轨迹”,“墙”,“位置”,“西北”ylim([0 70]) hold住从
步骤4。避免两次调用昂贵的子例程。
目标函数和非线性约束函数都调用ODE求解器来计算它们的值。在以下方面使用该技术同一函数中的目标约束与非线性约束避免调用两次求解器。的runcannon
File实现了这种技术。将此文件复制到MATLAB路径上的文件夹中。
函数[x, f, eflag, outpt] = runcannon (x0,选择)如果输入参数个数= = 1%没有提供选项选择= [];结束xLast = [];最后一个叫ode solver的地方索尔= [];% ODE解决方案结构有趣= @objfun;%目标函数,嵌套在下面cfun = @constr;约束函数,嵌套在下面磅= (-200;0.05);乌兰巴托=(1;π/ 2 . 05);%叫patternsearch[x, f, eflag, outpt] = patternsearch (x0有趣, ,[],[],[],[], 磅,乌兰巴托,cfun选择);函数y = objfun (x)如果~ isequal (x, xLast)检查是否需要计算x0 = [x (1), 0; 300 * cos (x (2)); 300 * sin (x (2)));索尔=数值(@cannonfodder [0, 15], x0);xLast = x;结束现在计算目标函数首先找到当弹丸击中地面。zerofnd = fzero (@ (r)德瓦尔(sol r 2), [sol.x (2), sol.x(结束)]);然后计算该时刻的x位置。y =德瓦尔(sol zerofnd 1);y = - y;取距离的负数结束函数[c,ceq] = constr(x) ceq = [];如果~ isequal (x, xLast)检查是否需要计算x0 = [x (1), 0; 300 * cos (x (2)); 300 * sin (x (2)));索尔=数值(@cannonfodder [0, 15], x0);xLast = x;结束%现在计算约束函数首先找到当弹丸穿过x = 0zerofnd = fzero (@ (r)德瓦尔(溶胶,r, 1), [sol.x (1) sol.x(结束)]);然后找到这个高度,然后减去20C = 20 - deval(sol,zerofnd,2);结束结束
重新初始化问题并计时调用runcannon
.
x0 =(-30;π/ 3);Tic [xsolution,distance,eflag,outpt] = runcannon(x0,opts);toc
优化终止:网格尺寸小于选项。MeshTolerance和约束违例小于options. constraintolerance。运行时间为0.670715秒。
解算器比以前运行得快。如果您检查解,您会看到输出是相同的。
第5步。并行计算。
尝试通过并行计算来节省更多的时间。首先打开一个平行的工作池。
parpool
使用“本地”配置文件启动parpool…连接到并行池(number of workers: 6). ans = ProcessPool with properties: Connected: true NumWorkers: 6 Cluster: local AttachedFiles: {} AutoAddClientPath: true IdleTimeout: 30 minutes (30 minutes remaining) SpmdEnabled: true
设置选项以使用并行计算,并重新运行求解器。
选择= optimoptions (“patternsearch”选择,“UseParallel”,真正的);x0 =(-30;π/ 3);Tic [xsolution,distance,eflag,outpt] = runcannon(x0,opts);toc
优化终止:网格尺寸小于选项。MeshTolerance和约束违例小于options. constraintolerance。运行时间为1.894515秒。
在这种情况下,并行计算速度较慢。如果您检查解,您会看到输出是相同的。
步骤6。与遗传算法进行比较。
你也可以尝试用遗传算法来解决这个问题。然而,遗传算法通常速度较慢,可靠性较差。
在解释同一函数中的目标约束与非线性约束,使用时无法节省时间遗传算法
采用嵌套函数技术patternsearch
在步骤4。相反,叫遗传算法
同时设置适当的选项。
选择= optimoptions (“遗传算法”,“UseParallel”,真正的);rng默认的%的再现性抽搐%时间解决[xsolution、距离、eflag, outpt] = ga (@cannonobjective 2...[],[],[],[], 磅,乌兰巴托,toc @cannonconstraint、期权)
优化终止:适应度值的平均变化小于选项。FunctionTolerance和约束违规小于options. constraintolerance。xsolution = -37.6217 0.4926 distance = -122.2181 eflag = 1 outpt = struct with fields: problemtype: '非线性constr' rngstate: [1×1 struct] generations: 4 funccount: 9874 message: '优化终止:适合度值的平均变化小于选项。FunctionTolerance ` `和约束违规小于options. constraintolerance。' maxconstraint: 0 hybridflag:[]运行时间为12.529131秒。
的遗传算法
解决方案不如patternsearch
解决方案:122米vs 126米。遗传算法
需要更多的时间:大约12秒对不到2秒;patternsearch
串行和嵌套的时间更短,不到1秒。运行遗传算法
连续测试甚至需要更长的时间,一次测试运行大约需要30秒。