fmincon跑了一晚上回来一看,exitflag是-2,输出结构里写着“No feasible solution found”,约束条件写死了。回去查非线性约束函数,c(x)小于等于0那部分符号写反了,本来想表达“应力不超过许用值”,结果写成了“许用值不超过应力”,整个可行域变成了空集。把c函数里的两项位置调过来,重新跑,二十分钟收敛到最优解。D:\Matlab_work\optimization\constraint_check.m 里存着这个出错的约束函数和改对的版本。
目标函数里带仿真的时候最怕梯度不连续。调用Abaqus或者Fluent算一次目标值,返回的是一个离散的数值,fmincon用有限差分算梯度,步长给默认的sqrt(eps)≈1.5e-8,仿真结果的变化量比这个还小,梯度全是零,求解器原地踏步。把FiniteDifferenceStepSize手动设大一点,1e-4或者1e-3,或者直接用ga这种不需要梯度的算法。有个电机优化的例子,目标函数是效率,仿真精度只到小数点后三位,fmincon跑不动,换patternsearch跑了两百多步找到最优,虽然慢但稳。D:\Matlab_work\optimization\gradient_issue_notes.txt 里记着这个切换的过程。
遗传算法的种群和代数设置直接决定能不能找到全局最优。PopulationSize默认50,变量多的时候不够,20个变量以上给200到500。MaxGenerations默认100,目标函数是仿真的话一代跑几分钟,100代要几个小时,先给30代看收敛趋势,曲线平了再停。CrossoverFraction默认0.8,变异率默认0.01,这两个一般不用动。ga的并行计算设置对仿真类目标函数是刚需,UseParallel设为true,Matlab自动开并行池,几个核同时算几代,加速比接近核数。D:\Matlab_work\optimization\ga_setup.m 里存着参数模板,变量数、上下界、非线性约束都填好了,换目标函数就能跑。

patternsearch跟fmincon的区别在不需要梯度,目标函数有噪声或者不连续的时候比fmincon靠谱。Poll方法选GPS或者MADS,MADS收敛性更好但每步算得慢。Mesh Tolerance控制搜索精度,给1e-6的话要跑很多步,实际优化工程问题给1e-3到1e-4就够,那个级别的精度对设计参数来说已经没什么意义了。Cache设成on,重复的网格点不重算,能省不少时间。UseCompletePoll设成on,每次poll所有的方向都算一遍,收敛更稳,代价是每步的计算量翻倍。D:\Matlab_work\optimization\patternsearch_template.m 里那个Cache还没开,下次加上。
多目标优化用gamultiobj,Pareto前沿画出来之后选点的时候别只看两端的极端解,中间那个拐点通常是工程上最实用的。ParetoSet和ParetoFront两个输出,前者是设计变量,后者是对应的目标函数值。加第三个目标的时候用paretosearch,gamultiobj只支持两个目标。约束边界画在图上,可行域和不可行域分清楚,选出来的点必须落在可行域里。D:\Matlab_work\optimization\multiobj\ 下面那个支架的轻量化案例,Pareto前沿上选了质量和频率的拐点,质量比初始设计降了22%,一阶频率还升了8%。
代理模型优化在仿真太慢的时候用。先跑几十个样本点建Kriging或者响应面,surrogateopt在代理模型上优化,找到最有希望的点再回仿真验证,验证的结果加进样本集重新建代理模型。循环几轮下来,总仿真次数比遗传算法少一个数量级。fitrgp建高斯过程模型,predict输出均值和标准差,surrogateopt的AcquisitionFunctionName选'expected-improvement-plus',兼顾探索和开发。D:\Matlab_work\optimization\surrogate\ 下面那个翼型优化的案例,原始仿真一次要二十分钟,代理模型跑了八十次仿真找到最优,比直接遗传算法省了二十倍的时间。
优化结果出来之后别急着用,先验证。最优点的约束违反量查一遍,c(x)是不是真的小于等于0,ceq(x)是不是真的等于0,数值优化出来的结果会有微小的违反,超过容差的话说明约束函数写错了。灵敏度分析也跑一下,最优解附近扰动各个变量,看目标函数和约束的变化,变量对目标的影响越大,实际加工的时候那个变量的公差就要卡得越紧。D:\Matlab_work\optimization\post_check.m 里写了一个自动验证的脚本,输入最优点和约束函数,输出约束违反量和灵敏度。
下次把那个电机的效率优化换成代理模型跑一遍,现在用的patternsearch跑一次要六个小时,代理模型估计一个小时能出结果,目标函数里的仿真调用是……
免责声明:本文系网络转载或改编,未找到原创作者,版权归原作者所有。如涉及版权,请联系删