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