286 Eigen::VectorXd x{m_decision_variables.size()};
287 for (
size_t i = 0; i < m_decision_variables.size(); ++i) {
288 x[i] = m_decision_variables[i].value();
291#ifndef SLEIPNIR_DISABLE_DIAGNOSTICS
292 if (options.diagnostics) {
294 slp::println(
"User-configured exit conditions:");
295 slp::println(
" ↳ error below {}", options.tolerance);
296 slp::println(
" ↳ error below {} for {} iterations",
297 options.acceptable_tolerance,
298 options.max_acceptable_iterations);
299 if (!m_callbacks.empty()) {
300 slp::println(
" ↳ user callback requested stop");
302 if (std::isfinite(options.max_iterations)) {
303 slp::println(
" ↳ executed {} iterations", options.max_iterations);
305 if (std::isfinite(options.timeout.count())) {
306 slp::println(
" ↳ {} elapsed", options.timeout);
309 if (m_decision_variables.size() == 1) {
310 slp::println(
"\n1 decision variable");
312 slp::println(
"\n{} decision variables", m_decision_variables.size());
315 auto print_constraint_types =
316 [](
const small_vector<Variable>& constraints) {
317 std::array<size_t, 5> type_counts{};
318 for (
const auto& constraint : constraints) {
319 ++type_counts[std::to_underlying(constraint.type())];
321 for (
const auto& [count, name] : std::views::zip(
322 type_counts, std::array{
"empty",
"constant",
"linear",
323 "quadratic",
"nonlinear"})) {
325 slp::println(
" ↳ {} {}", count, name);
331 if (m_equality_constraints.size() == 1) {
332 slp::println(
"1 equality constraint");
334 slp::println(
"{} equality constraints", m_equality_constraints.size());
336 print_constraint_types(m_equality_constraints);
337 if (m_inequality_constraints.size() == 1) {
338 slp::println(
"1 inequality constraint");
340 slp::println(
"{} inequality constraints",
341 m_inequality_constraints.size());
343 print_constraint_types(m_inequality_constraints);
346 auto print_chosen_solver =
347 [](std::string_view solver_name,
const ExpressionType& f_type,
348 const ExpressionType& c_e_type,
const ExpressionType& c_i_type) {
349 slp::println(
"\nUsing {} solver due to:", solver_name);
350 slp::println(
" ↳ {} cost function", ToMessage(f_type));
351 slp::println(
" ↳ {} equality constraints", ToMessage(c_e_type));
352 slp::println(
" ↳ {} inequality constraints", ToMessage(c_i_type));
358 auto f_type = cost_function_type();
359 auto c_e_type = equality_constraint_type();
360 auto c_i_type = inequality_constraint_type();
363 if (f_type <= ExpressionType::CONSTANT &&
364 c_e_type <= ExpressionType::CONSTANT &&
365 c_i_type <= ExpressionType::CONSTANT) {
366#ifndef SLEIPNIR_DISABLE_DIAGNOSTICS
367 if (options.diagnostics) {
368 print_chosen_solver(
"no-op", f_type, c_e_type, c_i_type);
371 return ExitStatus::SUCCESS;
376 if (m_equality_constraints.empty() && m_inequality_constraints.empty()) {
377#ifndef SLEIPNIR_DISABLE_DIAGNOSTICS
378 if (options.diagnostics) {
379 print_chosen_solver(
"Newton", f_type, c_e_type, c_i_type);
384 newton(m_decision_variables, m_f.value(), m_callbacks, options, x);
387 status = newton(m_decision_variables, zero, m_callbacks, options, x);
389 }
else if (m_inequality_constraints.empty()) {
390#ifndef SLEIPNIR_DISABLE_DIAGNOSTICS
391 if (options.diagnostics) {
392 print_chosen_solver(
"SQP", f_type, c_e_type, c_i_type);
396 status = sqp(m_decision_variables, m_equality_constraints, m_f.value(),
397 m_callbacks, options, x);
400 status = sqp(m_decision_variables, m_equality_constraints, zero,
401 m_callbacks, options, x);
404#ifndef SLEIPNIR_DISABLE_DIAGNOSTICS
405 if (options.diagnostics) {
406 print_chosen_solver(
"IPM", f_type, c_e_type, c_i_type);
410 status = interior_point(m_decision_variables, m_equality_constraints,
411 m_inequality_constraints, m_f.value(),
412 m_callbacks, options, x);
415 status = interior_point(m_decision_variables, m_equality_constraints,
416 m_inequality_constraints, zero, m_callbacks,
421#ifndef SLEIPNIR_DISABLE_DIAGNOSTICS
422 if (options.diagnostics) {
423 slp::println(
"\nExit: {}", ToMessage(status));
428 VariableMatrix{m_decision_variables}.set_value(x);