使用自定义约束条件和目标函数计算工作点

通常情况下,使用基于优化的搜索计算一个模型的Simulink稳态工作点时,可以指定已知的固定值或界限来约束你的模型状态,输入或万博1manbetx输出。然而,一些系统或应用程序需要在定义优化搜索参数额外的灵活性。

对于这样的系统,您可以指定自定义的限制,额外的优化目标函数,或两者兼而有之。当软件计算稳态工作点,它除了标准状态下,输入和输出规格适用于这些自定义约束和目标函数。

您可以指定自定义等式和不等式约束模型状态,输入和输出的代数组合。这些限制让你通过指定的输入,输出和状态之间的已知关系限制工作点的搜索空间。例如,你可以指定一个模型状态是其他两种状态的总和。

您还可以指定一个自定义的标量目标函数模型状态,输入和输出的代数组合。使用目标功能,您可以根据您的应用需求优化的稳态工作点。例如,假设你的模型有多个潜在的平衡点。您可以指定一个目标函数来找到最小输入能量稳态点。

对于复杂模型,您可以指定一个自定义映射函数,该函数选择模型输入、输出和状态的子集,并将其传递给自定义成本和约束函数。

您可以修剪你的模型时指定自定义优化功能:

  • 在命令行:使用以下命令创建操作点规范operspec,并指定使用自定义功能CustomConstrFcn,CustomCostFcnCustomMappingFcn本说明书中的特性。

  • 使用稳态经理:在规格选项卡上,单击修剪选项。在“修剪选项”对话框中自优化功能部分,指定函数名。

  • 使用线性化模型:在线性分析选项卡,在操作点下拉列表中,点击修剪模式。在修剪模式对话框,在选项选项卡,在自优化功能部分,指定函数名。

下面的示例展示了如何创建自定义优化函数,以及如何使用这些自定义函数在命令行中修剪模型。

万博1manbetx仿真软件模型

对于本例,使用一个由三个容器通过孔口彼此连接的模型。

MDL ='scdTanks';open_system(MDL)

罐1和TANK2之间的流动是理想的。TANK2和Tank3之间的流动是不期望的不可避免的泄漏。

在这个系统的预期稳定状态:

  • 罐1和TANK2具有相同的压力。

  • Tank2和Tank3的压差几乎是恒定的1补偿的负载。

由于Tank1和Tank2之间的连接性较弱,很难修剪模型,使Tank1和Tank2中的压力相等。

修剪模型没有自定义

为模型创建一个默认的工作点的规范。规格配置所有三个罐压力为免费指出,必须在稳定状态下的修整工作点。

opspec = operspec(MDL);

创建一个用于裁剪模型的选项集,抑制操作点搜索报告的命令窗口显示。具体的调整选项取决于您的应用程序。对于本例,使用非线性最小二乘优化。

选择= findopOptions ('OptimizerType','lsqnonlin');opt.DisplayReport =“关”;

修剪模型,并查看修剪后的油箱压力。

[OP0,rpt0] = findop(MDL,opspec,优化);op0.States
(1.)scdTanks /惯性X:0(2)scdTanks /罐1 X:9(3)scdTanks / TANK2 X:9.5(4)scdTanks / Tank3 X:10.5

Tank1和Tank2的调整压力不匹配。因此,默认的操作点规范无法找到满足预期稳定状态要求的操作点。如果你减少约束公差,opt.OptimizationOptions.TolCon时,不能达到一个可行的稳态解由于TANK2和Tank3之间的泄漏。

添加自定义约束

要指定自定义的约束,在当前的工作文件夹或输入参数的MATLAB的路径定义一个函数:

  • x-操作点指定状态,指定为矢量。

  • u-操作点指定输入,指定为矢量。

  • y-操作点指定输出,指定为矢量。

和输出参数:

  • c_ineq- 其必须满足不等式约束c_ineq <= 0修整期间,返回作为载体。

  • c_eq- 其必须满足等式约束c_eq = 0修整期间,返回作为载体。

的每个元素c_ineqc_eq指定一个约束。为应用程序定义为状态,输入和输出的代数组合的具体限制。如果没有定制的不等式约束,返回相应的输出参数作为[]

对于这个例子,以满足预期稳态的条件下,定义下面的定义约束功能。

功能[c_ineq, c_eq] = myConstraints (x, y) c_ineq = [];c_eq = [x (2) - x (3);%罐1压力 - 压力TANK2X(3)-x(4)1]。%TANK2压力 -  Tank3压力+ 1结束

的第一项c_eq约束罐1和TANK2的压力是相同的值。第二等式约束定义TANK2和Tank3之间的压降。

将自定义约束函数添加到操作点规范中。

opspec。CustomConstrFcn = @myConstraints;

使用包含自定义约束的修订的操作点规范修剪模型,并查看修剪后的状态值。

[OP1,RPT1] = findop(MDL,opspec,优化);op1.States
(1.) scdTanks/惯性x: 0 (2.) scdTanks/Tank1 x: 9.33 (3.) scdTanks/Tank2 x: 9.33 (4.) scdTanks/Tank3 x: 10.3

修剪与自定义约束功能的模型产生与所述第一和第二箱相等的压力,如所预期的工作点。此外,如预期的,有一个压力差1第三和第二罐之间。

要检查的规定约束的最终值,你可以检查CustomEqualityConstrCustomInequalityConstr工作点检索报告的性质。

rpt1.CustomEqualityConstr
ANS = 1.0E-06 * -0.0001 -0.1540

接近零值表明,平等约束得到满足。

添加自定义目标函数

若要指定自定义目标函数,请使用与自定义约束函数相同的输入参数定义函数(x,uy),以及输出参数FF为修整期间要最小化的目标函数值,以标量形式返回。

定义目标函数为应用程序作为状态,输入和输出的代数组合。

在这个例子中,假设你想保持在Tank3压力范围为[16,20]。然而,这种情况并不总是可行的。因此,与其强加硬约束,添加一个目标函数以招致罚如果压力不是在[16,20]范围内。要做到这一点,定义下列自定义的目标函数。

功能F = myObjective(X,U,Y)F = MAX(X(4)-20,0)+ MAX(16-X(4),0);结束

自定义目标函数添加到工作点规范对象。

opspec.CustomObjFcn = @myObjective;

修剪使用自定义的约束和自定义目标函数两者的操作点,并查看修剪状态值。

[OP2,RPT2]​​ = findop(MDL,opspec,优化);op2.States
(1) scd/惯性x: 0 (2) scd/ Tank1 x: 15 (3) scd/ Tank2 x: 15 (4) scd/ Tank3 x: 16

在修整操作点,在Tank3的压力在[16,20]在自定义目标函数范围内指定的。

要查看标量目标函数的终值,检查CustomObj操作点搜索报告的属性。

rpt2.CustomObj
ans = 0

添加自定义映射

对于复杂的模型,可以定义用于选择模型状态,输入和输出的一个子集传递给所述自定义约束和目标函数的自定义映射。这样做简化了通过消除不必要的状态,输入和输出的约束和目标函数。

要指定自定义映射,请使用操作点规范定义函数,opspec,作为输入参数和输出参数:

  • indx- 映射状态指数

  • indu-映射输入的索引

  • 印第- 映射输出指数

基于块的路径和状态名称使用获取状态,输入和输出索引getStateIndex,getInputIndexgetOutputIndex。使用这些命令是稳健的未来模型的变化,如增加模型状态。另外,您也可以手动指定索引。有关格式的更多信息indx,indu印第,请参阅getStateIndex,getInputIndexgetOutputIndex

如果没有状态,输入,或由自定义约束和目标函数使用的输出,返回对应的输出参数作为[]

对于这个例子,创建仅包括三个罐中压力状态的映射。为此,定义以下的自定义映射功能。

功能[INDX,INDU,印地] = myMapping(opspec)INDX = [getStateIndex(opspec,'scdTanks /罐1');getStateIndex(opspec,'scdTanks / TANK2');getStateIndex(opspec,'scdTanks / Tank3')];INDU = [];印= [];结束

将自定义映射添加到操作点规范。

opspec。CustomMappingFcn = @myMapping;

当您使用自定义映射功能,状态,输入,并在您的自定义约束和目标函数的输出指标必须是相对于映射函数指定的顺序。更新定义约束和目标函数与新的映射。

功能[c_ineq,c_eq] = myConstraintsMap(X,U,Y)c_ineq = [];c_eq = [x - x (1) (2);%罐1压力 - 压力TANK2X(2)-X(3)1];%TANK2压力 -  Tank3压力+ 1结束
功能F = myObjectiveMap(X,U,Y)F = MAX(X(3)-20,0)+ MAX(16-X(3),0);结束

在这里,x,uy分别是映射状态、输入和输出的向量。这些向量包含指定的映射值indx,indu印第,分别。

添加更新的自定义功能,操作点规范。

opspec.CustomConstrFcn = @myConstraintsMap;opspec.CustomObjFcn = @myObjectiveMap;

使用自定义映射修剪模式,并查看修剪状态,匹配在以前的结果,其《凤凰社》第2章

[op3, rpt3] = findop (mdl opspec,选择);op3.States
(1) scd/惯性x: 0 (2) scd/ Tank1 x: 15 (3) scd/ Tank2 x: 15 (4) scd/ Tank3 x: 16

添加解析梯度,以自定义功能

为了更快或更可靠的计算,你可以添加解析梯度到您的自定义约束和目标函数。添加梯度可以减少优化过程中的函数调用的数量和潜在的改善优化结果的准确性。如果指定渐变,则必须自定义约束和目标函数都指定它们。(自定义渐变修剪不支持的Simscape™机型。)万博1manbetx

要定义一个给定的约束或目标函数的梯度,取导数函数的相对于给定的状态,输入,或输出。例如,如果目标函数是

F =(U(1)3)^ 2 + Y(1)^ 2

然后的梯度F关于U(1)

G = 2 *(U(1)3)

要渐变添加到您的自定义的约束功能,指定以下额外的输出参数:

  • G_ineq-不等式约束的梯度数组

  • G_eq- 梯度阵列用于等式约束

的每一列G_ineqG_eq包含一个约束的梯度,并且列的顺序与相应约束向量中的行顺序匹配。两者中的行数G_ineqG_eq等于状态、输入和输出的总数x,uy。每一列包含相对于状态in的梯度x,然后在输入u,则输出iny

在这个例子中,添加渐变到使用自定义映射的约束功能。你不必使用渐变时指定自定义映射。然而,限定梯度使用状态,输入和输出的映射的子集时更简单。

功能[c_ineq,c_eq,G_ineq,G_eq] = myConstraintsGrad(x,u,y) c_ineq = [];c_eq = [x - x (1) (2);%罐1压力 - 压力TANK2X(2)-X(3)1];%TANK2压力 -  Tank3压力+ 1G_ineq = [];G_eq = [1 0;-1 1;0 -1];结束

在此功能中,排G_eq包含梯度相对于状态X(ⅰ)

同样,要渐变添加到您的自定义的目标函数,指定一个额外的输出参数G,其中包含的梯度FG返回为一个列向量具有相同的格式的列G_ineqG_eq

功能[F,G] = myObjectiveGrad(X,U,Y)F = MAX(X(3)-20,0)+ MAX(16-X(3),0);如果X(3)> = 20 G = [0 0 1]';elseifx(3) <= 16g = [0 0 -1]';其他G = [0 0 0]';结束结束

因为这个例子中的目标函数是分段可微的,的值G取决于Tank3的压力的值。

添加更新的自定义功能,操作点规范。

opspec.CustomConstrFcn = @myConstraintsGrad;opspec.CustomObjFcn = @myObjectiveGrad;

为了能够在优化算法梯度,使雅可比优化选择。

opt.OptimizationOptions.Jacobian ='上';

要使用微调模型时,使用分析雅克比稳态经理或者线性化模型,选择启用雅可比分析调整选项。

使用自定义功能与梯度修剪模型,并查看修整状态。

[op4, rpt4] = findop (mdl opspec,选择);op4.States
(1) scd/惯性x: 0 (2) scd/ Tank1 x: 15 (3) scd/ Tank2 x: 15 (4) scd/ Tank3 x: 16

优化结果与非梯度解的结果一致。

要查看梯度是否提高了优化效率,请查看操作点搜索报告。例如,比较数值函数对解决方案的评估:

  • 没有梯度:

rpt3.OptimizationOutput.funcCount
ans = 25
  • 与梯度:

rpt4.OptimizationOutput.funcCount
ans = 5

对于此示例,将所述分析梯度降低的优化过程中的函数调用的数目。

另请参阅

||||

相关话题