@@ -83,6 +83,46 @@ namespace roboptim
8383 {}
8484#endif // !ROBOPTIM_CORE_IPOPT_PLUGIN_CHECK_GRADIENT
8585
86+ template <typename T>
87+ void fillMultipliers (Function::vector_t & multipliers,
88+ const Function::value_type* z_L,
89+ const Function::value_type* z_U,
90+ const Function::value_type* lambda,
91+ Function::size_type n,
92+ Function::size_type m,
93+ const Solver<T>& solver)
94+ {
95+ const Eigen::Map<const Function::argument_t > map_zL (z_L, n);
96+ const Eigen::Map<const Function::argument_t > map_zU (z_U, n);
97+ const Eigen::Map<const Function::argument_t > map_lambda (lambda, m);
98+
99+ multipliers.resize (n + m + 1 );
100+ multipliers.setZero ();
101+
102+ // First, argument bounds multipliers
103+ Function::size_type i = 0 ;
104+ typedef IpoptSolver::problem_t ::intervals_t ::const_iterator citer_t ;
105+ for (citer_t it = solver.problem ().argumentBounds ().begin ();
106+ it != solver.problem ().argumentBounds ().end (); ++it)
107+ {
108+ // Active lower bound
109+ // Note: we expect λ < 0 if active lower bound constraint, and λ > 0 if
110+ // active upper bound constraint
111+ if ((*it).first != -Function::infinity () && map_zL[i] > map_zU[i])
112+ multipliers[i] = -map_zL[i];
113+ // Active upper bound
114+ else if ((*it).second != Function::infinity () && map_zU[i] >= map_zL[i])
115+ multipliers[i] = map_zU[i];
116+
117+ i++;
118+ }
119+
120+ // Then constraint multipliers
121+ multipliers.segment (n, m) = map_lambda;
122+
123+ // Finally, for 1D objective function: 1
124+ multipliers[n+m] = 1 .;
125+ }
86126
87127 void
88128 jacobianFromGradients
@@ -541,12 +581,11 @@ namespace roboptim
541581 return false ;
542582 }
543583
544- #define FILL_RESULT () \
545- array_to_vector (res.x, x); \
546- res.constraints.resize (m); \
547- array_to_vector (res.constraints, g); \
548- res.lambda.resize (m); \
549- array_to_vector (res.lambda, lambda); \
584+ #define FILL_RESULT () \
585+ res.x = Eigen::Map<const Function::argument_t > (x, n); \
586+ res.constraints = Eigen::Map<const Function::vector_t > (g, m); \
587+ res.lambda = Eigen::Map<const Function::vector_t > (lambda, m); \
588+ fillMultipliers (res.lambda, z_L, z_U, lambda, n, m, solver_); \
550589 res.value (0 ) = obj_value
551590
552591#define SWITCH_ERROR (NAME, ERROR ) \
@@ -599,8 +638,8 @@ namespace roboptim
599638 void
600639 Tnlp<T>::finalize_solution
601640 (SolverReturn status,
602- Index n, const Number* x, const Number*,
603- const Number*, Index m, const Number* g,
641+ Index n, const Number* x, const Number* z_L ,
642+ const Number* z_U , Index m, const Number* g,
604643 const Number* lambda, Number obj_value,
605644 const IpoptData*,
606645 IpoptCalculatedQuantities*)
0 commit comments