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 if (!m_callbacks.empty()) {
297 slp::println(
" ↳ user callback requested stop");
299 if (std::isfinite(options.max_iterations)) {
300 slp::println(
" ↳ executed {} iterations", options.max_iterations);
302 if (std::isfinite(options.timeout.count())) {
303 slp::println(
" ↳ {} elapsed", options.timeout);
306 if (m_decision_variables.size() == 1) {
307 slp::println(
"\n1 decision variable");
309 slp::println(
"\n{} decision variables", m_decision_variables.size());
312 auto print_constraint_types =
313 [](
const small_vector<Variable>& constraints) {
314 std::array<size_t, 5> type_counts{};
315 for (
const auto& constraint : constraints) {
316 ++type_counts[std::to_underlying(constraint.type())];
318 for (
const auto& [count, name] : std::views::zip(
319 type_counts, std::array{
"empty",
"constant",
"linear",
320 "quadratic",
"nonlinear"})) {
322 slp::println(
" ↳ {} {}", count, name);
328 if (m_equality_constraints.size() == 1) {
329 slp::println(
"1 equality constraint");
331 slp::println(
"{} equality constraints", m_equality_constraints.size());
333 print_constraint_types(m_equality_constraints);
334 if (m_inequality_constraints.size() == 1) {
335 slp::println(
"1 inequality constraint");
337 slp::println(
"{} inequality constraints",
338 m_inequality_constraints.size());
340 print_constraint_types(m_inequality_constraints);
343 auto print_chosen_solver = [](std::string_view solver_name,
344 const ExpressionType& f_type,
345 const ExpressionType& c_e_type,
346 const ExpressionType& c_i_type) {
347 constexpr std::array types{
"no",
"constant",
"linear",
"quadratic",
350 slp::println(
"\nUsing {} solver due to:", solver_name);
351 slp::println(
" ↳ {} cost function", types[std::to_underlying(f_type)]);
352 slp::println(
" ↳ {} equality constraints",
353 types[std::to_underlying(c_e_type)]);
354 slp::println(
" ↳ {} inequality constraints",
355 types[std::to_underlying(c_i_type)]);
361 auto f_type = cost_function_type();
362 auto c_e_type = equality_constraint_type();
363 auto c_i_type = inequality_constraint_type();
366 if (f_type <= ExpressionType::CONSTANT &&
367 c_e_type <= ExpressionType::CONSTANT &&
368 c_i_type <= ExpressionType::CONSTANT) {
369#ifndef SLEIPNIR_DISABLE_DIAGNOSTICS
370 if (options.diagnostics) {
371 print_chosen_solver(
"no-op", f_type, c_e_type, c_i_type);
374 return ExitStatus::SUCCESS;
379 if (m_equality_constraints.empty() && m_inequality_constraints.empty()) {
380#ifndef SLEIPNIR_DISABLE_DIAGNOSTICS
381 if (options.diagnostics) {
382 print_chosen_solver(
"Newton", f_type, c_e_type, c_i_type);
387 newton(m_decision_variables, m_f.value(), m_callbacks, options, x);
390 status = newton(m_decision_variables, zero, m_callbacks, options, x);
392 }
else if (m_inequality_constraints.empty()) {
393#ifndef SLEIPNIR_DISABLE_DIAGNOSTICS
394 if (options.diagnostics) {
395 print_chosen_solver(
"SQP", f_type, c_e_type, c_i_type);
399 status = sqp(m_decision_variables, m_equality_constraints, m_f.value(),
400 m_callbacks, options, x);
403 status = sqp(m_decision_variables, m_equality_constraints, zero,
404 m_callbacks, options, x);
407#ifndef SLEIPNIR_DISABLE_DIAGNOSTICS
408 if (options.diagnostics) {
409 print_chosen_solver(
"IPM", f_type, c_e_type, c_i_type);
413 status = interior_point(m_decision_variables, m_equality_constraints,
414 m_inequality_constraints, m_f.value(),
415 m_callbacks, options, x);
418 status = interior_point(m_decision_variables, m_equality_constraints,
419 m_inequality_constraints, zero, m_callbacks,
424#ifndef SLEIPNIR_DISABLE_DIAGNOSTICS
425 if (options.diagnostics) {
426 slp::println(
"\nExit: {}", to_message(status));
431 VariableMatrix{m_decision_variables}.set_value(x);