31 #ifndef DT_IPOPT_INTERFACE_HPP_ 
   32 #define DT_IPOPT_INTERFACE_HPP_ 
   35 #include <IpIpoptApplication.hpp> 
   38 using namespace Ipopt;
 
   40 namespace DirectTrajectoryOptimization {
 
   43 template<
typename DIMENSIONS>
 
   44 class DTOMethodInterface;
 
   49 template<
typename DIMENSIONS>
 
   54     EIGEN_MAKE_ALIGNED_OPERATOR_NEW
 
   56     typedef typename DIMENSIONS::state_vector_array_t state_vector_array_t;
 
   57     typedef typename DIMENSIONS::control_vector_array_t control_vector_array_t;
 
   67     this->_verbose = ipopt_verbose;
 
   68         _nlpSolver = 
new Ipopt::IpoptApplication();
 
   75             Ipopt::Referencer* t=NULL;
 
   80     virtual void InitializeSolver(
const std::string & problemName,
 
   81             const std::string & outputFile,
 
   82             const std::string & paramFile ,
 
   83             const bool &computeJacobian) 
override;
 
   85     virtual void Solve(
bool warminit = 
false) 
override;
 
   87     virtual void GetDTOSolution(state_vector_array_t &yTraj,
 
   88             control_vector_array_t &uTraj, Eigen::VectorXd &hTraj) 
override;
 
   90     virtual void GetDTOSolution(state_vector_array_t & y_trajectory,
 
   91             control_vector_array_t & u_trajectory,
 
   92             Eigen::VectorXd & h_trajectory,
 
   93             std::vector<int> & phaseId) 
override;
 
   95     virtual void GetFVector(Eigen::VectorXd &fVec) 
override;
 
  106     virtual void InitializeDecisionVariablesFromTrajectory( 
const state_vector_array_t & y_sol,
 
  107             const control_vector_array_t & u_sol, 
const Eigen::VectorXd &h_sol) 
override;
 
  109     void SetupSolverParameters() 
override;
 
  114     void SetupIpoptVariables();
 
  118     void SetSparsityVariables();
 
  120     void readParametersFromFile(
const std::string & p_file);
 
  123     virtual bool get_nlp_info(Index& n, Index& m, Index& nnz_jac_g,
 
  124             Index& nnz_h_lag, IndexStyleEnum& index_style) 
override;
 
  126     virtual bool get_bounds_info(Index n, Number* x_l, Number* x_u, Index m,
 
  127             Number *g_l, Number* g_u) 
override;
 
  129     virtual bool get_starting_point(Index n, 
bool init_x, Number* x,
 
  130             bool init_z, Number* z_L, Number* z_U, Index m, 
bool init_lambda,
 
  131             Number* lambda) 
override;
 
  133     virtual bool eval_f(Index n, 
const Number* x, 
bool new_x, Number& obj_value)
 
  136     virtual bool eval_grad_f(Index n, 
const Number* x, 
bool new_x,
 
  137             Number* grad_f) 
override;
 
  139     virtual bool eval_g(Index n, 
const Number* x, 
bool new_x, Index m,
 
  142     virtual bool eval_jac_g(Index n, 
const Number* x, 
bool new_x, Index m,
 
  143             Index nele_jac, Index* iRow, Index* jCol, Number* values) 
override;
 
  145     virtual void finalize_solution(SolverReturn status, Index n,
 
  146             const Number* x, 
const Number* z_L, 
const Number* z_U, Index m,
 
  147             const Number* g, 
const Number* lambda, Number obj_value,
 
  148             const IpoptData* ip_data, IpoptCalculatedQuantities* ip_cq)
 
  152     bool use_computeJacobian = 
false;
 
  154     Ipopt::SmartPtr<IpoptApplication> _nlpSolver;
 
  155     std::shared_ptr<DTOMethodInterface<DIMENSIONS> > _method;
 
  158     int _lenConstraint  = 0;            
 
  161     int _nnzConstraintJac = 0;          
 
  163     Eigen::VectorXd _valX;
 
  164     double _valCost = 0.0;              
 
  165     Eigen::VectorXd _valConstraint;     
 
  167     Eigen::VectorXd _valCostJac;        
 
  168     Eigen::VectorXd _valConstraintJac;  
 
  169     Eigen::VectorXd _lamdaConstraints;
 
  171     Eigen::VectorXi _jCostJac;          
 
  172     Eigen::VectorXi _iConstraintJac;    
 
  173     Eigen::VectorXi _jConstraintJac;    
 
  176     std::string ippt_name_of_problem    = 
"";
 
  177     std::string ippt_name_of_output_file= 
"";
 
  178     double ippt_print_level             = 5;
 
  179     double ippt_file_print_level        = 5;
 
  180     std::string ippt_print_user_options         = 
"no";
 
  181     std::string ippt_print_options_documentation= 
"no";
 
  182     std::string ippt_print_timing_statistics    = 
"yes";
 
  185     double ippt_tolerance           = 1e-4;
 
  186     double ippt_max_iter            = 10000;
 
  187     double ippt_max_cpu_time        = 1e6;
 
  188     std::string ippt_mu_strategy    = 
"adaptive";           
 
  189     double ippt_dual_inf_tol        = 1;
 
  190     double ippt_constr_viol_tol     = 1e-6;
 
  191     double ippt_compl_inf_tol       = 1e-6;
 
  192     double ippt_acceptable_tol      = 1e-6;
 
  193     double ippt_acceptable_iter     = 30;
 
  196     std::string ippt_nlp_scaling_method = 
"gradient-based";  
 
  197     double ippt_obj_scaling_factor      = 1;
 
  198     double ippt_nlp_scaling_max_gradient= 100;          
 
  199     double ippt_nlp_scaling_obj_target_gradient = 0;
 
  202     std::string ippt_linear_solver          = 
"ma57";       
 
  203     std::string ippt_fast_step_computation  = 
"no";         
 
  206     std::string ippt_derivative_test    = 
"none";  
 
  207     double ippt_derivative_test_tol     = 1e-4;
 
  208     double point_perturbation_radius    = 0.01;
 
  213     std::string ippt_hessian_approximation = 
"limited-memory"; 
 
  214     double ippt_limited_memory_max_history = 6;
 
  215     double ippt_limited_memory_max_skipping= 2;
 
  217     bool ippt_rethrowNonIpoptException = 
false;
 
  220 template<
typename DIMENSIONS>
 
  222         const std::string & problemName,
 
  223         const std::string & outputFile,
 
  224         const std::string & paramFile ,
 
  225         const bool &computeJacobian) {
 
  226     use_computeJacobian = computeJacobian;
 
  227     ippt_name_of_problem = problemName;
 
  228     ippt_name_of_output_file = outputFile;
 
  230     _method->Initialize();  
 
  232     SetupIpoptVariables();
 
  236         readParametersFromFile(paramFile);
 
  239     SetupSolverParameters();
 
  244 template<
typename DIMENSIONS>
 
  247     _lenX = _method->myNLP.GetNumVars();
 
  248     _lenConstraint = _method->myNLP.GetNumF();
 
  249     _valConstraint.resize(_lenConstraint);
 
  252 template<
typename DIMENSIONS>
 
  253 void DTOIpoptInterface<DIMENSIONS>::SetupNLP() {
 
  255     SetSparsityVariables();
 
  259 template <
class DIMENSIONS>
 
  261         const control_vector_array_t & u_sol, 
const Eigen::VectorXd &h_sol) {
 
  263     _method->SetDecisionVariablesFromStateControlIncrementsTrajectories(this->_valX,y_sol,u_sol,h_sol);
 
  268 template<
typename DIMENSIONS>
 
  272     _nlpSolver->Options()->SetStringValue(
"output_file", ippt_name_of_output_file);
 
  273     _nlpSolver->Options()->SetIntegerValue(
"print_level", ippt_print_level);
 
  274     _nlpSolver->Options()->SetIntegerValue(
"file_print_level", ippt_file_print_level);
 
  275     _nlpSolver->Options()->SetStringValue(
"print_user_options", ippt_print_user_options);
 
  276     _nlpSolver->Options()->SetStringValue(
"print_options_documentation", ippt_print_options_documentation);
 
  277     _nlpSolver->Options()->SetStringValue(
"print_timing_statistics", ippt_print_timing_statistics);
 
  280     _nlpSolver->Options()->SetNumericValue(
"tol",ippt_tolerance);
 
  281     _nlpSolver->Options()->SetIntegerValue(
"max_iter",ippt_max_iter);
 
  282     _nlpSolver->Options()->SetNumericValue(
"max_cpu_time",ippt_max_cpu_time);
 
  283     _nlpSolver->Options()->SetStringValue(
"mu_strategy",ippt_mu_strategy);
 
  284     _nlpSolver->Options()->SetNumericValue(
"dual_inf_tol",ippt_dual_inf_tol);
 
  285     _nlpSolver->Options()->SetNumericValue(
"constr_viol_tol", ippt_constr_viol_tol);
 
  286     _nlpSolver->Options()->SetNumericValue(
"compl_inf_tol", ippt_compl_inf_tol);
 
  287     _nlpSolver->Options()->SetNumericValue(
"acceptable_tol", ippt_acceptable_tol);
 
  288     _nlpSolver->Options()->SetIntegerValue(
"acceptable_iter", ippt_acceptable_iter);
 
  291     _nlpSolver->Options()->SetStringValue(
"nlp_scaling_method", ippt_nlp_scaling_method);
 
  292     _nlpSolver->Options()->SetNumericValue(
"obj_scaling_factor", ippt_obj_scaling_factor);
 
  293     _nlpSolver->Options()->SetNumericValue(
"nlp_scaling_max_gradient", ippt_nlp_scaling_max_gradient);
 
  294     _nlpSolver->Options()->SetNumericValue(
"nlp_scaling_obj_target_gradient", ippt_nlp_scaling_obj_target_gradient);
 
  297     _nlpSolver->Options()->SetStringValue(
"linear_solver", ippt_linear_solver);
 
  298     _nlpSolver->Options()->SetStringValue(
"fast_step_computation", ippt_fast_step_computation);
 
  301     _nlpSolver->Options()->SetStringValue(
"derivative_test", ippt_derivative_test);
 
  302     _nlpSolver->Options()->SetNumericValue(
"derivative_test_tol", ippt_derivative_test_tol);
 
  303     _nlpSolver->Options()->SetNumericValue(
"point_perturbation_radius", point_perturbation_radius);
 
  307     _nlpSolver->Options()->SetStringValue(
"hessian_approximation",ippt_hessian_approximation);
 
  308     _nlpSolver->Options()->SetIntegerValue(
"limited_memory_max_history",ippt_limited_memory_max_history);
 
  309     _nlpSolver->Options()->SetIntegerValue(
"limited_memory_max_skipping",ippt_limited_memory_max_skipping);
 
  311     _nlpSolver->RethrowNonIpoptException(ippt_rethrowNonIpoptException);
 
  313     if (use_computeJacobian) {
 
  314         _nlpSolver->Options()->SetStringValue(
"jacobian_approximation",
 
  315                 "finite-difference-values");
 
  319 template<
typename DIMENSIONS>
 
  326 template<
typename DIMENSIONS>
 
  327 void DTOIpoptInterface<DIMENSIONS>::SetSparsityVariables() {
 
  332      _jCostJac = _method->myNLP.GetjGvarCost();
 
  334     if (use_computeJacobian) {
 
  336         _nnzConstraintJac = _lenConstraint * _lenX;
 
  337         _iConstraintJac.resize(_nnzConstraintJac);
 
  338         _jConstraintJac.resize(_nnzConstraintJac);
 
  340         for (
int i = 0; i < _nnzConstraintJac; i++) {
 
  341             _iConstraintJac[i] = i % _lenConstraint;
 
  342             _jConstraintJac[i] = floor(i/_lenConstraint);
 
  345         _nnzConstraintJac   = _method->myNLP.GetDimG();
 
  346         _iConstraintJac     = _method->myNLP.GetiGfun();
 
  347         _jConstraintJac     = _method->myNLP.GetjGvar();
 
  351     _valCostJac.resize(_nnzCostJac);
 
  352     _valConstraintJac.resize(_nnzConstraintJac);
 
  355     assert(_iConstraintJac.size() == _nnzConstraintJac);
 
  356     assert(_jConstraintJac.size() == _nnzConstraintJac);
 
  359     if (this->_verbose) {
 
  360         std::cout << 
"[VERBOSE] _iConstraintJac : " << _iConstraintJac.transpose() << std::endl;
 
  361         std::cout << 
"[VERBOSE] _jConstraintJac : " << _jConstraintJac.transpose() << std::endl;
 
  368 template<
typename DIMENSIONS>
 
  371     ApplicationReturnStatus status;
 
  374     status = _nlpSolver->Initialize();
 
  376     if (status == Solve_Succeeded) {
 
  377         std::cout << std::endl << std::endl
 
  378                 << 
"*** Initialized successfully -- starting NLP." << std::endl;
 
  380         std::cout << std::endl << std::endl
 
  381                 << 
"*** Error during initialization!" << std::endl;
 
  386     status = _nlpSolver->OptimizeTNLP(
this);
 
  388     if (status == Solve_Succeeded) {
 
  389         std::cout << std::endl << std::endl << 
"*** The problem solved!" 
  392         std::cout << std::endl << std::endl << 
"*** The problem FAILED!" 
  397 template<
typename DIMENSIONS>
 
  399         control_vector_array_t &uTraj, Eigen::VectorXd &hTraj) {
 
  401     Eigen::Map<Eigen::VectorXd> x_local(_valX.data(), _lenX);
 
  402     _method->getStateControlIncrementsTrajectoriesFromDecisionVariables(x_local, yTraj, uTraj, hTraj);
 
  407 template <
class DIMENSIONS>
 
  409         control_vector_array_t & u_trajectory,Eigen::VectorXd & h_trajectory,
 
  410         std::vector<int> & phaseId) {
 
  412     Eigen::Map<Eigen::VectorXd> x_local(_valX.data(), _lenX);
 
  414     _method->getStateControlIncrementsTrajectoriesFromDecisionVariables(x_local,y_trajectory,u_trajectory,h_trajectory);
 
  416     phaseId = _method->node_to_phase_map;
 
  419 template<
typename DIMENSIONS>
 
  422     fVec.resize(1 + _valConstraint.size());
 
  425     fVec.segment(1, _valConstraint.size()) = _valConstraint;
 
  444 template<
typename DIMENSIONS>
 
  446         Index& nnz_jac_g, Index& nnz_h_lag, IndexStyleEnum& index_style) {
 
  450     nnz_jac_g = _nnzConstraintJac;
 
  453     index_style = TNLP::C_STYLE;
 
  458 template<
typename DIMENSIONS>
 
  459 bool DTOIpoptInterface<DIMENSIONS>::get_bounds_info(Index n, Number* x_l,
 
  460         Number* x_u, Index m, Number* g_l, Number* g_u) {
 
  464     pointer = _method->myNLP.GetXlb_p();
 
  465     memcpy(x_l, pointer, 
sizeof(Number) * n);
 
  467     pointer = _method->myNLP.GetXub_p();
 
  468     memcpy(x_u, pointer, 
sizeof(Number) * n);
 
  470     pointer = _method->myNLP.GetFlb_p();
 
  471     memcpy(g_l, pointer, 
sizeof(Number) * m);
 
  473     pointer = _method->myNLP.GetFub_p();
 
  474     memcpy(g_u, pointer, 
sizeof(Number) * m);
 
  479 template<
typename DIMENSIONS>
 
  480 bool DTOIpoptInterface<DIMENSIONS>::get_starting_point(Index n, 
bool init_x,
 
  481         Number* x, 
bool init_z, Number* z_L, Number* z_U, Index m,
 
  482         bool init_lambda, Number* lambda) {
 
  483     std::cout << 
"getting starting points" << std::endl;
 
  486     assert(init_z == 
false);
 
  487     if (init_z == 
true ){
 
  488         std::runtime_error(
"init_z should be false");
 
  491     Eigen::Map<Eigen::VectorXd> local_x(x, n);
 
  492     Eigen::Map<Eigen::VectorXd> local_lamndaF(lambda, m);
 
  494         std::cout << 
"x init is true" << std::endl;
 
  495         local_x = this->_valX;
 
  496         std::cout << 
"x initialized" << std::endl;
 
  499         std::runtime_error(
"init_lambda requested"); 
 
  500         local_lamndaF = this->_lamdaConstraints;
 
  503     this->_method->UpdateDecisionVariables(x);
 
  512 template<
typename DIMENSIONS>
 
  513 bool DTOIpoptInterface<DIMENSIONS>::eval_f(Index n, 
const Number* x, 
bool new_x,
 
  533     if (new_x) this->_method->UpdateDecisionVariables(x);
 
  535     this->_method->evalObjective(&obj_value);
 
  540 template<
typename DIMENSIONS>
 
  541 bool DTOIpoptInterface<DIMENSIONS>::eval_grad_f(Index n, 
const Number* x,
 
  542         bool new_x, Number* grad_f) {
 
  544     if (new_x) this->_method->UpdateDecisionVariables(x);
 
  546     if (use_computeJacobian)
 
  549     Eigen::VectorXd local_sparse_cost_gradient(_jCostJac.size());
 
  550     this->_method->evalSparseJacobianCost(local_sparse_cost_gradient.data());
 
  553     for (
int i = 0 ; i < n; i++)
 
  556     for (
int i = 0 ; i < _jCostJac.size() ; i++)
 
  557         grad_f[_jCostJac[i]] = local_sparse_cost_gradient(i);
 
  562 template<
typename DIMENSIONS>
 
  563 bool DTOIpoptInterface<DIMENSIONS>::eval_g(Index n, 
const Number* x, 
bool new_x,
 
  564         Index m, Number* g) {
 
  566     if (new_x) this->_method->UpdateDecisionVariables(x);
 
  568     this->_method->evalConstraintFct(g,m);
 
  573 template<
typename DIMENSIONS>
 
  574 bool DTOIpoptInterface<DIMENSIONS>::eval_jac_g(Index n, 
const Number* x,
 
  575         bool new_x, Index m, Index nele_jac, Index* iRow, Index* jCol,
 
  579     assert(nele_jac == _jConstraintJac.size());
 
  581     if (values == NULL) {
 
  582         std::cout << 
"Return sparsity" << std::endl;
 
  587         for (
int i = 0; i < nele_jac; i++) {
 
  588             iRow[i] = _iConstraintJac(i);
 
  589             jCol[i] = _jConstraintJac(i);
 
  593     } 
else if (!use_computeJacobian){
 
  594         if (new_x) this->_method->UpdateDecisionVariables(x);
 
  596         this->_method->evalSparseJacobianConstraint(values);
 
  608 template<
typename DIMENSIONS>
 
  609 void DTOIpoptInterface<DIMENSIONS>::finalize_solution(SolverReturn status,
 
  610         Index n, 
const Number* x, 
const Number* z_L, 
const Number* z_U, Index m,
 
  611         const Number* g, 
const Number* lambda, Number obj_value,
 
  612         const IpoptData* ip_data, IpoptCalculatedQuantities* ip_cq) {
 
  613     this->_method->UpdateDecisionVariables(x);
 
  615     assert(n == _valX.size());
 
  616     assert(m == _valConstraint.size());
 
  618     memcpy(_valX.data(), x, n * 
sizeof(Number));
 
  619     _valCost = obj_value;
 
  620     memcpy(_valConstraint.data(), g, m * 
sizeof(Number));
 
This class serves as a base interface for inheriting classes. 
Definition: base_method_interface.hpp:60
 
DTOIpoptInterface(std::shared_ptr< DTOMethodInterface< DIMENSIONS > > method, bool ipopt_verbose)
Create a new ipopt interface instance. 
Definition: ipopt.hpp:64
 
Base class for NLP Solvers interface. 
 
This class serves as a base interface for inheriting classes. 
Definition: base_solver_interface.hpp:47
 
Class interfacing Ipopt NLP with a DirectTrajectoryOptimization problem. 
Definition: ipopt.hpp:50