268 using DenseVector = Eigen::Vector<Scalar, Eigen::Dynamic>;
269 using SparseMatrix = Eigen::SparseMatrix<Scalar>;
270 using SparseVector = Eigen::SparseVector<Scalar>;
273 DenseVector x{m_decision_variables.size()};
274 for (
size_t i = 0; i < m_decision_variables.size(); ++i) {
275 x[i] = m_decision_variables[i].value();
278 if (options.diagnostics) {
279 print_exit_conditions(options);
280 print_problem_analysis();
289 if (f_type <= ExpressionType::CONSTANT &&
290 c_e_type <= ExpressionType::CONSTANT &&
291 c_i_type <= ExpressionType::CONSTANT) {
292#ifndef SLEIPNIR_DISABLE_DIAGNOSTICS
293 if (options.diagnostics) {
294 slp::println(
"\nInvoking no-op solver...\n");
297 return ExitStatus::SUCCESS;
300 gch::small_vector<SetupProfiler> ad_setup_profilers;
301 ad_setup_profilers.emplace_back(
"setup").start();
303 VariableMatrix<Scalar> x_ad{m_decision_variables};
306 Variable f = m_f.value_or(Scalar(0));
309 ad_setup_profilers.emplace_back(
" ↳ ∇f(x)").start();
311 ad_setup_profilers.back().stop();
314 int num_decision_variables = m_decision_variables.size();
316 int num_equality_constraints = m_equality_constraints.size();
318 int num_inequality_constraints = m_inequality_constraints.size();
320 gch::small_vector<std::function<bool(
const IterationInfo<Scalar>& info)>>
322 for (
const auto& callback : m_iteration_callbacks) {
323 callbacks.emplace_back(callback);
325 for (
const auto& callback : m_persistent_iteration_callbacks) {
326 callbacks.emplace_back(callback);
331 if (m_equality_constraints.empty() && m_inequality_constraints.empty()) {
332 if (options.diagnostics) {
333 slp::println(
"\nInvoking Newton solver...\n");
337 ad_setup_profilers.emplace_back(
" ↳ ∇²ₓₓL").start();
338 Hessian<Scalar, Eigen::Lower> H{f, x_ad};
339 ad_setup_profilers.back().stop();
341 ad_setup_profilers[0].stop();
343#ifndef SLEIPNIR_DISABLE_DIAGNOSTICS
345 std::unique_ptr<Spy<Scalar>> H_spy;
348 H_spy = std::make_unique<Spy<Scalar>>(
349 "H.spy",
"Hessian",
"Decision variables",
"Decision variables",
350 num_decision_variables, num_decision_variables);
351 callbacks.push_back([&](
const IterationInfo<Scalar>& info) ->
bool {
359 status = newton<Scalar>(NewtonMatrixCallbacks<Scalar>{
360 [&](
const DenseVector& x) -> Scalar {
364 [&](
const DenseVector& x) -> SparseVector {
368 [&](
const DenseVector& x) -> SparseMatrix {
372 callbacks, options, x);
373 }
else if (m_inequality_constraints.empty()) {
374 if (options.diagnostics) {
375 slp::println(
"\nInvoking SQP solver\n");
378 VariableMatrix<Scalar> c_e_ad{m_equality_constraints};
381 ad_setup_profilers.emplace_back(
" ↳ ∂cₑ/∂x").start();
382 Jacobian A_e{c_e_ad, x_ad};
383 ad_setup_profilers.back().stop();
386 VariableMatrix<Scalar> y_ad(num_equality_constraints);
387 Variable L = f - y_ad.T() * c_e_ad;
390 ad_setup_profilers.emplace_back(
" ↳ ∇²ₓₓL").start();
391 Hessian<Scalar, Eigen::Lower> H{L, x_ad};
392 ad_setup_profilers.back().stop();
394 ad_setup_profilers[0].stop();
396#ifndef SLEIPNIR_DISABLE_DIAGNOSTICS
398 std::unique_ptr<Spy<Scalar>> H_spy;
399 std::unique_ptr<Spy<Scalar>> A_e_spy;
402 H_spy = std::make_unique<Spy<Scalar>>(
403 "H.spy",
"Hessian",
"Decision variables",
"Decision variables",
404 num_decision_variables, num_decision_variables);
405 A_e_spy = std::make_unique<Spy<Scalar>>(
406 "A_e.spy",
"Equality constraint Jacobian",
"Constraints",
407 "Decision variables", num_equality_constraints,
408 num_decision_variables);
409 callbacks.push_back([&](
const IterationInfo<Scalar>& info) ->
bool {
411 A_e_spy->add(info.A_e);
418 status = sqp<Scalar>(
419 SQPMatrixCallbacks<Scalar>{
420 [&](
const DenseVector& x) -> Scalar {
424 [&](
const DenseVector& x) -> SparseVector {
428 [&](
const DenseVector& x,
const DenseVector& y) -> SparseMatrix {
433 [&](
const DenseVector& x) -> DenseVector {
435 return c_e_ad.value();
437 [&](
const DenseVector& x) -> SparseMatrix {
441 callbacks, options, x);
443 if (options.diagnostics) {
444 slp::println(
"\nInvoking IPM solver...\n");
447 VariableMatrix<Scalar> c_e_ad{m_equality_constraints};
448 VariableMatrix<Scalar> c_i_ad{m_inequality_constraints};
451 ad_setup_profilers.emplace_back(
" ↳ ∂cₑ/∂x").start();
452 Jacobian A_e{c_e_ad, x_ad};
453 ad_setup_profilers.back().stop();
456 ad_setup_profilers.emplace_back(
" ↳ ∂cᵢ/∂x").start();
457 Jacobian A_i{c_i_ad, x_ad};
458 ad_setup_profilers.back().stop();
461 VariableMatrix<Scalar> y_ad(num_equality_constraints);
462 VariableMatrix<Scalar> z_ad(num_inequality_constraints);
463 Variable L = f - y_ad.T() * c_e_ad - z_ad.T() * c_i_ad;
466 ad_setup_profilers.emplace_back(
" ↳ ∇²ₓₓL").start();
467 Hessian<Scalar, Eigen::Lower> H{L, x_ad};
468 ad_setup_profilers.back().stop();
470 ad_setup_profilers[0].stop();
472#ifndef SLEIPNIR_DISABLE_DIAGNOSTICS
474 std::unique_ptr<Spy<Scalar>> H_spy;
475 std::unique_ptr<Spy<Scalar>> A_e_spy;
476 std::unique_ptr<Spy<Scalar>> A_i_spy;
479 H_spy = std::make_unique<Spy<Scalar>>(
480 "H.spy",
"Hessian",
"Decision variables",
"Decision variables",
481 num_decision_variables, num_decision_variables);
482 A_e_spy = std::make_unique<Spy<Scalar>>(
483 "A_e.spy",
"Equality constraint Jacobian",
"Constraints",
484 "Decision variables", num_equality_constraints,
485 num_decision_variables);
486 A_i_spy = std::make_unique<Spy<Scalar>>(
487 "A_i.spy",
"Inequality constraint Jacobian",
"Constraints",
488 "Decision variables", num_inequality_constraints,
489 num_decision_variables);
490 callbacks.push_back([&](
const IterationInfo<Scalar>& info) ->
bool {
492 A_e_spy->add(info.A_e);
493 A_i_spy->add(info.A_i);
499 const auto [bound_constraint_mask, bounds, conflicting_bound_indices] =
500 get_bounds<Scalar>(m_decision_variables, m_inequality_constraints,
502 if (!conflicting_bound_indices.empty()) {
503 if (options.diagnostics) {
504 print_bound_constraint_global_infeasibility_error(
505 conflicting_bound_indices);
507 return ExitStatus::GLOBALLY_INFEASIBLE;
510#ifdef SLEIPNIR_ENABLE_BOUND_PROJECTION
511 project_onto_bounds(x, bounds);
514 status = interior_point<Scalar>(
515 InteriorPointMatrixCallbacks<Scalar>{
516 [&](
const DenseVector& x) -> Scalar {
520 [&](
const DenseVector& x) -> SparseVector {
524 [&](
const DenseVector& x,
const DenseVector& y,
525 const DenseVector& z) -> SparseMatrix {
531 [&](
const DenseVector& x) -> DenseVector {
533 return c_e_ad.value();
535 [&](
const DenseVector& x) -> SparseMatrix {
539 [&](
const DenseVector& x) -> DenseVector {
541 return c_i_ad.value();
543 [&](
const DenseVector& x) -> SparseMatrix {
548#ifdef SLEIPNIR_ENABLE_BOUND_PROJECTION
549 bound_constraint_mask,
554 if (options.diagnostics) {
555 print_autodiff_diagnostics(ad_setup_profilers);
556 slp::println(
"\nExit: {}", status);
560 VariableMatrix<Scalar>{m_decision_variables}.set_value(x);