123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227 |
- #ifndef INCLUDE_PROGRAM
- #define INCLUDE_PROGRAM
- #include "IpTNLP.hpp"
- #include <armadillo>
- #include "GPM.h"
- using namespace arma;
- using namespace Ipopt;
- /*
- MyNLP实现了一个C ++示例,该示例显示了如何通过TNLP接口与IPOPT接口。
- 本示例旨在与教程文档一起使用(请参阅示例/ CppTutorial /)。
- 此类实现以下NLP。
-
- min_x f(x) = -(x2-2)^2
- s.t.
- 0 = x1^2 + x2 - 1
- -1 <= x1 <= 1
-
- */
- class Program : public TNLP
- {
- public:
- /* 默认构造函数 */
- Program();
-
- /* 默认析构函数 */
- virtual ~Program();
- /* 从TNLP重载 */
- /*
- 返回有关nlp的一些信息的方法
- n :(输出),问题中变量的数量(x的维)。
- m :(输出),问题中约束的数量(g(x)的维)。
- nnz_jac_g : (输出),雅可比行列中非零条目的数量。
- nnz_h_lag : (输出),Hessian中非零条目的数量。
- IndexStyleEnum:(输出),用于稀疏矩阵格式的行/列条目的编号样式(C样式:基于0; FORTRAN样式:基于1;另请参见附录A)。
- Ipopt在分配数组时会使用此信息,稍后它将要求您填充值。 请谨慎使用此方法,因为不正确的值将导致可能很难找到的内存错误。
- */
- virtual bool get_nlp_info(Index& n, Index& m, Index& nnz_jac_g,
- Index& nnz_h_lag, IndexStyleEnum& index_style);
- /*
- 返回问题界限的方法
- n : (输入),问题中的变量数(x的维数)。
- x_l :(输出),x的下限xL。
- x_u :(输出),x的上限xU。
- m : (输入),问题中的约束个数(g(x)的维)。
- g_l :(输出),g(x)的下限gL。
- g_u :(输出),g(x)的上限gU。
- 您在get nlp info中指定的n和m值将传递给您进行调试检查。
- 将下界设置为小于或等于选项nlp_lower_bound_inf将导致Ipopt假定没有下界。
- 同样,指定大于或等于选项nlp_upper_bound_inf将使Ipopt假定没有上限。
- 默认情况下,这些选项(nlp_lower_bound_inf 和 nlp_upper_bound_inf)分别设置为-10^19和10*19,但可以通过更改选项进行修改。
- */
- virtual bool get_bounds_info(Index n, Number* x_l, Number* x_u,
- Index m, Number* g_l, Number* g_u);
- /*
- 返回算法起点的方法
- n : (输入),问题中的变量数(x的维数)。
- init_x : (输入),如果为true,则此方法必须为x提供初始值。
- x : (输出),原始变量x的初始值。
- init_z : (输入),如果为true,则此方法必须为边界乘数zL和zU提供一个初始值。
- z_L : (输出),边界乘数zL的初始值。
- z_U : (输出),边界乘数zU的初始值。
- m : (输入),问题中的约束个数(g(x)的维)。
- init_lambda:(输入),如果为true,则此方法必须为约束乘数λ提供初始值。
- lambda : (输出),约束乘数的初始值λ
- 为方便起见,传递了变量n和m。
- 这些变量将具有您在get nlp info中指定的相同值。
- 根据已设置的选项,Ipopt可能会或可能不需要原始变量x,边界乘数zL和zU以及约束乘数λ的边界。
- 布尔标志init_x,init_z和init_lambda告诉您是否应分别为x,zL,zU或λ提供初始值。
- 默认选项只需要初始变量x的初始值。
- 请注意,“无穷大”边界(x(Li)=-∞或x(Ui)=∞)的边界乘数分量的初始值将被忽略
- */
- virtual bool get_starting_point(Index n, bool init_x, Number* x,
- bool init_z, Number* z_L, Number* z_U,
- Index m, bool init_lambda,
- Number* lambda);
- /*
- 返回目标值的方法
- n : (输入),问题中的变量数(x的维数)。
- x : (输入),原始变量x的值,将在此求f(x)。
- new_x : (输入),如果先前使用x中相同的值调用了任何评估方法,则为false,否则为true。
- obj_value: (输出), 目标函数的值(f(x))。
- 如果最后一次对任何评估方法(eval *)的调用使用相同的x值,则布尔变量new_x将为false。
- 当用户具有可以一次计算多个输出的高效实现时,这将很有帮助。
- Ipopt在内部缓存TNLP的结果,通常可以忽略此标志。
- 为方便起见,传入了变量n。 此变量将具有您在get_nlp_info中指定的相同值。
- */
- virtual bool eval_f(Index n, const Number* x, bool new_x, Number& obj_value);
- /*
- 返回指标梯度的方法
- n : (输入),问题中的变量数(x的维数)。
- x : (输入),原始变量x的值,应在其中求出梯度。
- new_x :(输入),如果先前使用x中相同的值调用了任何评估方法,则为false,否则为true。
- grad_f: (输出),目标函数梯度的值。
- 梯度数组与x变量的顺序相同(即,性能指标相对于x[2]的梯度应放在grad_f[2]中)。
- 如果最后一次对任何评估方法(eval *)的调用使用相同的x值,则布尔变量new x将为false。
- 当用户具有可以一次计算多个输出的高效实现时,这将很有帮助。
- Ipopt在内部缓存TNLP的结果,通常可以忽略此标志。
- 为方便起见,传入了变量n。 此变量将具有您在get_nlp_info中指定的相同值。
- */
- virtual bool eval_grad_f(Index n, const Number* x, bool new_x, Number* grad_f);
- /*
- 返回约束残差的方法
- n : (输入),问题中的变量数(x的维数)。
- x : (输入),原始变量x的值,将以此计算约束函数g(x)。
- new_x :(输入),如果先前使用x中相同的值调用了任何评估方法,则为false,否则为true。
- m : (输入),问题中的约束个数(g(x)的维)。
- g : (输出),约束函数值的数组,g(x)
- g中返回的值应仅为g(x)值,请勿加或减边界值gL或gU。
- 如果最后一次对任何评估方法(eval *)的调用使用相同的x值,则布尔变量new x将为false。
- 当用户具有可以一次计算多个输出的高效实现时,这将很有帮助。
- Ipopt在内部缓存TNLP的结果,通常,此标志可以忽略
- 为方便起见,传递了变量n和m。 这些变量将具有您在get nlp info中指定的相同值。
- */
- virtual bool eval_g(Index n, const Number* x, bool new_x, Index m, Number* g);
- /* 该方法返回如下值:
- 1) 雅可比矩阵的结构 ( 如果 "values" 为 NULL)
- 2) 雅可比的值 ( 如果 "values" 不为 NULL)
- n : (输入),问题中的变量数(x的维数)。
- x: (输入),原始变量x的值,在该变量上求约束Jacobian。
- new_x : (输入),如果先前使用x中相同的值调用了任何评估方法,则为false,否则为true。
- m : (输入),问题中的约束个数(g(x)的维)。
- n_ele_jac :(输入),雅可比行列中非零元素的数量(iRow,jCol和值的维)。
- iRow : (输出),约束的雅可比行中条目的行索引。
- jCol : (输出),约束的雅可比行中条目的列索引。
- values : (输出),约束的雅可比行列中的条目的值。
- 雅可比行列式是导数矩阵,其中约束g(i)相对于变量x(j)的导数位于第i行和第j列。
- 有关此方法中使用的稀疏矩阵格式的讨论,请参见附录A。
- 如果iRow和jCol参数不为NULL,则Ipopt希望您填写Jacobian的稀疏结构(仅行和列索引)。此时,x参数和values参数将为NULL。
- 如果x参数和values参数不为NULL,则Ipopt希望您填写从数组x计算得出的Jacobian值(使用与指定稀疏结构时相同的顺序)。
- 此时,iRow和jCol参数将为NULL;如果最后一次对任何评估方法(eval *)的调用使用相同的x值,则布尔变量new x将为false。
- 当用户具有可以一次计算多个输出的高效实现时,这将很有帮助。
- Ipopt在内部缓存TNLP的结果,通常可以忽略此标志。
- 为方便起见,传递了变量n,m和nele jac。这些参数将具有您在获取nlp信息中指定的值。
- */
- virtual bool eval_jac_g(Index n, const Number* x, bool new_x,
- Index m, Index nele_jac, Index* iRow, Index *jCol,
- Number* values);
- /* 该方法返回如下值:
- 1) 拉格朗日海森矩阵的结果 (如果 "values" 为 NULL)
- 2) 拉格朗日海森矩阵的值 (如果 "values" 不为 NULL)
- n : (输入),问题中的变量数(x的维数)。
- x : (输入),原始变量x的值,将在该变量上评估Hessian。
- new x : (输入),如果先前使用x中相同的值调用了任何评估方法,则为false,否则为true。
- obj factor: (输入),在黑森州,sigmaf中,位于客观术语前面的因子。
- m : (输入),问题中的约束个数(g(x)的维)。
- lambda : (输入),用于在其上评估Hessian的约束乘数λ的值。
- new lambda: (输入),如果先前使用lambda中的相同值调用了任何评估方法,则为false,否则为true。
- nele hess :(输入),黑森矩阵非零元素的数量(iRow,jCol和值的维)
- iRow : (输出),黑森矩阵条目的行索引。
- jCol : (输出),黑森矩阵条目的列索引。
- values : (输出),黑森矩阵中条目的值。
- Ipopt使用的Hessian矩阵在等式中 9.有关此方法中使用的稀疏对称矩阵格式的讨论,请参见附录A。
- 如果iRow和jCol参数不为NULL,则Ipopt希望您填写Hessian的稀疏结构(仅下部三角形或上部三角形的行和列索引)。
- 在这种情况下,x,lambda和values数组将为NULL。
- 如果x,lambda和values数组不为NULL,则Ipopt希望您填写使用x和lambda计算的Hessian值(使用与指定稀疏结构时相同的顺序)。
- 在这种情况下,iRow和jCol参数将为NULL。
- 如果对任何评估方法(eval *)的最后一次调用使用相同的值,则布尔变量new x和new lambda都将为false。
- 当用户有足够的执行能力可以一次计算多个输出时,这将很有帮助。
- Ipopt在内部缓存TNLP的结果,通常可以忽略此标志。
- 为方便起见,传递了变量n,m和nele hess。这些参数将具有您在get nlp info中指定的相同值。
- */
- virtual bool eval_h(Index n, const Number* x, bool new_x,
- Number obj_factor, Index m, const Number* lambda,
- bool new_lambda, Index nele_hess, Index* iRow,
- Index* jCol, Number* values);
- /*
- 解决方法
- 算法完成后将调用此方法,以便TNLP可以存储/写入解决方案
- status :(输入),给出IpAlgTypes.hpp中指定的算法状态,
- –SUCCESS: 算法在局部最优点成功终止,满足收敛容限(可以通过选项指定)。
- –MAXITER EXCEEDED: 超过最大迭代次数(可以通过选项指定)。
- –STOP AT TINY STEP: 算法进展甚微。
- –STOP AT ACCEPTABLE POINT:算法在收敛点停止,而不是收敛到“期望的”公差,而是达到“可接受的”公差(请参阅accept -...选项)。
- –LOCAL INFEASIBILITY: 算法收敛到局部不可行点。问题可能不可行。
- –USER REQUESTED STOP: 用户回调函数中间回调(请参阅第3.3.4节)返回false,即用户代码请求过早终止优化。
- –DIVERGING ITERATES: 迭代似乎是发散的。
- –RESTORATION FAILURE: 恢复阶段失败,算法不知道如何继续。
- –ERROR IN STEP COMPUTATION:Ipopt尝试计算搜索方向时发生不可恢复的错误。
- –INVALID NUMBER DETECTED: 算法从NLP接收到无效数字(例如NaN或Inf);另请参阅naninf的选项检查派生工具。
- –INTERNAL ERROR: 发生未知的内部错误。 请通过邮件列表联系Ipopt作者。
- n : (输入),问题中的变量数(x的维数)。
- x : (输入),原始变量x ∗的最终值。
- z L : (输入),下界乘数的最终值zL。
- z U : (输入),上限乘数zU的最终值。
- m : (输入),问题中的约束个数(g(x)的维)。
- g : (输入),约束函数值的最终值g(x ∗)。
- lambda : (输入),约束乘数的最终值λ。
- obj_value: (输入),目标的最终值f(x)。
- 为专业用户提供了ip_data和ip_cq。
- */
- virtual void finalize_solution(SolverReturn status,
- Index n, const Number* x, const Number* z_L, const Number* z_U,
- Index m, const Number* g, const Number* lambda,
- Number obj_value,
- const IpoptData* ip_data,
- IpoptCalculatedQuantities* ip_cq);
- public:
- static vec x; // 当前点的值
- static vec z_L; // 变量乘子下限
- static vec z_U; // 变量乘子上限
- static vec lambda; // 约束乘子
- private:
- /* 阻止默认编译器方法的方法。
- 编译器自动生成以下三种方法。
- 由于默认编译器实现通常不是您想要的(对于所有类,而是最简单的类),因此我们通常将这些方法的声明放在private节中,而不用实现它们。
- 这可以防止编译器在我们不知道的情况下实现错误的“默认”行为。 (请参阅Scott Meyers的书“有效的C ++”) */
- Program(const Program&);
- Program& operator=(const Program&);
- };
- #endif
|