sleipnirgroup-jormungandr 0.0.1.dev475__tar.gz → 0.0.1.dev477__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/CMakeLists.txt +9 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/PKG-INFO +1 -1
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/include/sleipnir/autodiff/expression.hpp +41 -81
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/include/sleipnir/optimization/solver/exit_status.hpp +11 -6
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/include/sleipnir/optimization/solver/interior_point.hpp +5 -1
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/jormungandr/cpp/docstrings.hpp +4 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/jormungandr/cpp/optimization/solver/bind_exit_status.cpp +2 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/jormungandr/test/optimization/nonlinear_problem_test.py +19 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/pyproject.toml +1 -1
- sleipnirgroup_jormungandr-0.0.1.dev477/src/optimization/bounds.hpp +220 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/src/optimization/problem.cpp +19 -1
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/src/optimization/solver/interior_point.cpp +9 -1
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/src/util/print_diagnostics.hpp +19 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/LICENSE.txt +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/README.md +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/SleipnirConfig.cmake.in +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/cmake/modules/BuildTypes.cmake +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/cmake/modules/CompilerFlags.cmake +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/cmake/modules/Pybind11Mkdoc.cmake +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/cmake/modules/SubdirList.cmake +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/include/.styleguide +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/include/sleipnir/autodiff/adjoint_expression_graph.hpp +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/include/sleipnir/autodiff/expression_graph.hpp +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/include/sleipnir/autodiff/expression_type.hpp +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/include/sleipnir/autodiff/gradient.hpp +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/include/sleipnir/autodiff/hessian.hpp +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/include/sleipnir/autodiff/jacobian.hpp +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/include/sleipnir/autodiff/slice.hpp +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/include/sleipnir/autodiff/variable.hpp +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/include/sleipnir/autodiff/variable_block.hpp +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/include/sleipnir/autodiff/variable_matrix.hpp +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/include/sleipnir/control/ocp.hpp +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/include/sleipnir/optimization/multistart.hpp +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/include/sleipnir/optimization/problem.hpp +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/include/sleipnir/optimization/solver/iteration_info.hpp +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/include/sleipnir/optimization/solver/newton.hpp +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/include/sleipnir/optimization/solver/options.hpp +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/include/sleipnir/optimization/solver/sqp.hpp +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/include/sleipnir/util/assert.hpp +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/include/sleipnir/util/concepts.hpp +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/include/sleipnir/util/function_ref.hpp +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/include/sleipnir/util/intrusive_shared_ptr.hpp +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/include/sleipnir/util/pool.hpp +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/include/sleipnir/util/print.hpp +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/include/sleipnir/util/spy.hpp +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/include/sleipnir/util/symbol_exports.hpp +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/jormungandr/__init__.py +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/jormungandr/autodiff/__init__.py +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/jormungandr/control/__init__.py +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/jormungandr/cpp/autodiff/bind_expression_type.cpp +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/jormungandr/cpp/autodiff/bind_gradient.cpp +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/jormungandr/cpp/autodiff/bind_hessian.cpp +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/jormungandr/cpp/autodiff/bind_jacobian.cpp +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/jormungandr/cpp/autodiff/bind_variable.cpp +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/jormungandr/cpp/autodiff/bind_variable_block.cpp +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/jormungandr/cpp/autodiff/bind_variable_matrix.cpp +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/jormungandr/cpp/binders.hpp +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/jormungandr/cpp/control/bind_ocp.cpp +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/jormungandr/cpp/main.cpp +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/jormungandr/cpp/optimization/bind_equality_constraints.cpp +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/jormungandr/cpp/optimization/bind_inequality_constraints.cpp +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/jormungandr/cpp/optimization/bind_problem.cpp +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/jormungandr/cpp/optimization/solver/bind_iteration_info.cpp +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/jormungandr/cpp/try_cast.hpp +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/jormungandr/optimization/__init__.py +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/jormungandr/test/autodiff/gradient_test.py +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/jormungandr/test/autodiff/hessian_test.py +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/jormungandr/test/autodiff/jacobian_test.py +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/jormungandr/test/autodiff/variable_matrix_test.py +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/jormungandr/test/autodiff/variable_test.py +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/jormungandr/test/cart_pole_util.py +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/jormungandr/test/control/cart_pole_ocp_test.py +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/jormungandr/test/control/differential_drive_ocp_test.py +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/jormungandr/test/control/flywheel_ocp_test.py +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/jormungandr/test/differential_drive_util.py +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/jormungandr/test/optimization/arm_on_elevator_problem_test.py +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/jormungandr/test/optimization/cart_pole_problem_test.py +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/jormungandr/test/optimization/constraints_test.py +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/jormungandr/test/optimization/decision_variable_test.py +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/jormungandr/test/optimization/differential_drive_problem_test.py +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/jormungandr/test/optimization/double_integrator_problem_test.py +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/jormungandr/test/optimization/exit_status_test.py +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/jormungandr/test/optimization/flywheel_problem_test.py +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/jormungandr/test/optimization/linear_problem_test.py +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/jormungandr/test/optimization/multistart_test.py +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/jormungandr/test/optimization/quadratic_problem_test.py +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/jormungandr/test/optimization/trivial_problem_test.py +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/jormungandr/test/rk4.py +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/src/.styleguide +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/src/autodiff/variable_matrix.cpp +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/src/optimization/inertia.hpp +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/src/optimization/regularized_ldlt.hpp +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/src/optimization/solver/newton.cpp +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/src/optimization/solver/sqp.cpp +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/src/optimization/solver/util/error_estimate.hpp +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/src/optimization/solver/util/filter.hpp +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/src/optimization/solver/util/fraction_to_the_boundary_rule.hpp +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/src/optimization/solver/util/is_locally_infeasible.hpp +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/src/optimization/solver/util/kkt_error.hpp +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/src/util/pool.cpp +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/src/util/scope_exit.hpp +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/src/util/scoped_profiler.hpp +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/src/util/setup_profiler.hpp +0 -0
- {sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/src/util/solve_profiler.hpp +0 -0
{sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/CMakeLists.txt
RENAMED
@@ -71,6 +71,11 @@ option(BUILD_BENCHMARKS "Build CasADi and Sleipnir benchmarks" OFF)
|
|
71
71
|
option(BUILD_EXAMPLES "Build examples" OFF)
|
72
72
|
option(BUILD_PYTHON "Build Python module" OFF)
|
73
73
|
option(DISABLE_DIAGNOSTICS "Disable diagnostics support at compile-time" OFF)
|
74
|
+
option(
|
75
|
+
ENABLE_BOUND_PROJECTION
|
76
|
+
"Enable projecting the state onto bound inequality constraints inside problem setup"
|
77
|
+
OFF
|
78
|
+
)
|
74
79
|
|
75
80
|
include(CompilerFlags)
|
76
81
|
|
@@ -104,6 +109,10 @@ if(DISABLE_DIAGNOSTICS)
|
|
104
109
|
target_compile_definitions(Sleipnir PUBLIC SLEIPNIR_DISABLE_DIAGNOSTICS)
|
105
110
|
endif()
|
106
111
|
|
112
|
+
if(ENABLE_BOUND_PROJECTION)
|
113
|
+
target_compile_definitions(Sleipnir PUBLIC SLEIPNIR_ENABLE_BOUND_PROJECTION)
|
114
|
+
endif()
|
115
|
+
|
107
116
|
# Eigen dependency
|
108
117
|
if(NOT USE_SYSTEM_EIGEN)
|
109
118
|
set(EIGEN_BUILD_CMAKE_PACKAGE TRUE)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: sleipnirgroup-jormungandr
|
3
|
-
Version: 0.0.1.
|
3
|
+
Version: 0.0.1.dev477
|
4
4
|
Summary: A linearity-exploiting sparse nonlinear constrained optimization problem solver that uses the interior-point method.
|
5
5
|
License: Copyright (c) Sleipnir contributors
|
6
6
|
|
@@ -436,9 +436,7 @@ struct BinaryMinusExpression final : Expression {
|
|
436
436
|
* @param rhs Binary operator's right operand.
|
437
437
|
*/
|
438
438
|
constexpr BinaryMinusExpression(ExpressionPtr lhs, ExpressionPtr rhs)
|
439
|
-
: Expression{std::move(lhs), std::move(rhs)} {
|
440
|
-
val = args[0]->val - args[1]->val;
|
441
|
-
}
|
439
|
+
: Expression{std::move(lhs), std::move(rhs)} {}
|
442
440
|
|
443
441
|
double value(double lhs, double rhs) const override { return lhs - rhs; }
|
444
442
|
|
@@ -479,9 +477,7 @@ struct BinaryPlusExpression final : Expression {
|
|
479
477
|
* @param rhs Binary operator's right operand.
|
480
478
|
*/
|
481
479
|
constexpr BinaryPlusExpression(ExpressionPtr lhs, ExpressionPtr rhs)
|
482
|
-
: Expression{std::move(lhs), std::move(rhs)} {
|
483
|
-
val = args[0]->val + args[1]->val;
|
484
|
-
}
|
480
|
+
: Expression{std::move(lhs), std::move(rhs)} {}
|
485
481
|
|
486
482
|
double value(double lhs, double rhs) const override { return lhs + rhs; }
|
487
483
|
|
@@ -565,9 +561,7 @@ struct DivExpression final : Expression {
|
|
565
561
|
* @param rhs Binary operator's right operand.
|
566
562
|
*/
|
567
563
|
constexpr DivExpression(ExpressionPtr lhs, ExpressionPtr rhs)
|
568
|
-
: Expression{std::move(lhs), std::move(rhs)} {
|
569
|
-
val = args[0]->val / args[1]->val;
|
570
|
-
}
|
564
|
+
: Expression{std::move(lhs), std::move(rhs)} {}
|
571
565
|
|
572
566
|
double value(double lhs, double rhs) const override { return lhs / rhs; }
|
573
567
|
|
@@ -608,9 +602,7 @@ struct MultExpression final : Expression {
|
|
608
602
|
* @param rhs Binary operator's right operand.
|
609
603
|
*/
|
610
604
|
constexpr MultExpression(ExpressionPtr lhs, ExpressionPtr rhs)
|
611
|
-
: Expression{std::move(lhs), std::move(rhs)} {
|
612
|
-
val = args[0]->val * args[1]->val;
|
613
|
-
}
|
605
|
+
: Expression{std::move(lhs), std::move(rhs)} {}
|
614
606
|
|
615
607
|
double value(double lhs, double rhs) const override { return lhs * rhs; }
|
616
608
|
|
@@ -652,9 +644,7 @@ struct UnaryMinusExpression final : Expression {
|
|
652
644
|
* @param lhs Unary operator's operand.
|
653
645
|
*/
|
654
646
|
explicit constexpr UnaryMinusExpression(ExpressionPtr lhs)
|
655
|
-
: Expression{std::move(lhs)} {
|
656
|
-
val = -args[0]->val;
|
657
|
-
}
|
647
|
+
: Expression{std::move(lhs)} {}
|
658
648
|
|
659
649
|
double value(double lhs, double) const override { return -lhs; }
|
660
650
|
|
@@ -735,9 +725,7 @@ struct AbsExpression final : Expression {
|
|
735
725
|
* @param lhs Unary operator's operand.
|
736
726
|
*/
|
737
727
|
explicit constexpr AbsExpression(ExpressionPtr lhs)
|
738
|
-
: Expression{std::move(lhs)} {
|
739
|
-
val = args[0]->val < 0 ? -args[0]->val : args[0]->val;
|
740
|
-
}
|
728
|
+
: Expression{std::move(lhs)} {}
|
741
729
|
|
742
730
|
double value(double x, double) const override { return std::abs(x); }
|
743
731
|
|
@@ -798,9 +786,8 @@ struct AcosExpression final : Expression {
|
|
798
786
|
*
|
799
787
|
* @param lhs Unary operator's operand.
|
800
788
|
*/
|
801
|
-
explicit AcosExpression(ExpressionPtr lhs)
|
802
|
-
|
803
|
-
}
|
789
|
+
explicit constexpr AcosExpression(ExpressionPtr lhs)
|
790
|
+
: Expression{std::move(lhs)} {}
|
804
791
|
|
805
792
|
double value(double x, double) const override { return std::acos(x); }
|
806
793
|
|
@@ -848,9 +835,8 @@ struct AsinExpression final : Expression {
|
|
848
835
|
*
|
849
836
|
* @param lhs Unary operator's operand.
|
850
837
|
*/
|
851
|
-
explicit AsinExpression(ExpressionPtr lhs)
|
852
|
-
|
853
|
-
}
|
838
|
+
explicit constexpr AsinExpression(ExpressionPtr lhs)
|
839
|
+
: Expression{std::move(lhs)} {}
|
854
840
|
|
855
841
|
double value(double x, double) const override { return std::asin(x); }
|
856
842
|
|
@@ -899,9 +885,8 @@ struct AtanExpression final : Expression {
|
|
899
885
|
*
|
900
886
|
* @param lhs Unary operator's operand.
|
901
887
|
*/
|
902
|
-
explicit AtanExpression(ExpressionPtr lhs)
|
903
|
-
|
904
|
-
}
|
888
|
+
explicit constexpr AtanExpression(ExpressionPtr lhs)
|
889
|
+
: Expression{std::move(lhs)} {}
|
905
890
|
|
906
891
|
double value(double x, double) const override { return std::atan(x); }
|
907
892
|
|
@@ -950,10 +935,8 @@ struct Atan2Expression final : Expression {
|
|
950
935
|
* @param lhs Binary operator's left operand.
|
951
936
|
* @param rhs Binary operator's right operand.
|
952
937
|
*/
|
953
|
-
Atan2Expression(ExpressionPtr lhs, ExpressionPtr rhs)
|
954
|
-
: Expression{std::move(lhs), std::move(rhs)} {
|
955
|
-
val = std::atan2(args[0]->val, args[1]->val);
|
956
|
-
}
|
938
|
+
constexpr Atan2Expression(ExpressionPtr lhs, ExpressionPtr rhs)
|
939
|
+
: Expression{std::move(lhs), std::move(rhs)} {}
|
957
940
|
|
958
941
|
double value(double y, double x) const override { return std::atan2(y, x); }
|
959
942
|
|
@@ -1014,9 +997,8 @@ struct CosExpression final : Expression {
|
|
1014
997
|
*
|
1015
998
|
* @param lhs Unary operator's operand.
|
1016
999
|
*/
|
1017
|
-
explicit CosExpression(ExpressionPtr lhs)
|
1018
|
-
|
1019
|
-
}
|
1000
|
+
explicit constexpr CosExpression(ExpressionPtr lhs)
|
1001
|
+
: Expression{std::move(lhs)} {}
|
1020
1002
|
|
1021
1003
|
double value(double x, double) const override { return std::cos(x); }
|
1022
1004
|
|
@@ -1063,9 +1045,8 @@ struct CoshExpression final : Expression {
|
|
1063
1045
|
*
|
1064
1046
|
* @param lhs Unary operator's operand.
|
1065
1047
|
*/
|
1066
|
-
explicit CoshExpression(ExpressionPtr lhs)
|
1067
|
-
|
1068
|
-
}
|
1048
|
+
explicit constexpr CoshExpression(ExpressionPtr lhs)
|
1049
|
+
: Expression{std::move(lhs)} {}
|
1069
1050
|
|
1070
1051
|
double value(double x, double) const override { return std::cosh(x); }
|
1071
1052
|
|
@@ -1112,9 +1093,8 @@ struct ErfExpression final : Expression {
|
|
1112
1093
|
*
|
1113
1094
|
* @param lhs Unary operator's operand.
|
1114
1095
|
*/
|
1115
|
-
explicit ErfExpression(ExpressionPtr lhs)
|
1116
|
-
|
1117
|
-
}
|
1096
|
+
explicit constexpr ErfExpression(ExpressionPtr lhs)
|
1097
|
+
: Expression{std::move(lhs)} {}
|
1118
1098
|
|
1119
1099
|
double value(double x, double) const override { return std::erf(x); }
|
1120
1100
|
|
@@ -1165,9 +1145,8 @@ struct ExpExpression final : Expression {
|
|
1165
1145
|
*
|
1166
1146
|
* @param lhs Unary operator's operand.
|
1167
1147
|
*/
|
1168
|
-
explicit ExpExpression(ExpressionPtr lhs)
|
1169
|
-
|
1170
|
-
}
|
1148
|
+
explicit constexpr ExpExpression(ExpressionPtr lhs)
|
1149
|
+
: Expression{std::move(lhs)} {}
|
1171
1150
|
|
1172
1151
|
double value(double x, double) const override { return std::exp(x); }
|
1173
1152
|
|
@@ -1217,10 +1196,8 @@ struct HypotExpression final : Expression {
|
|
1217
1196
|
* @param lhs Binary operator's left operand.
|
1218
1197
|
* @param rhs Binary operator's right operand.
|
1219
1198
|
*/
|
1220
|
-
HypotExpression(ExpressionPtr lhs, ExpressionPtr rhs)
|
1221
|
-
: Expression{std::move(lhs), std::move(rhs)} {
|
1222
|
-
val = std::hypot(args[0]->val, args[1]->val);
|
1223
|
-
}
|
1199
|
+
constexpr HypotExpression(ExpressionPtr lhs, ExpressionPtr rhs)
|
1200
|
+
: Expression{std::move(lhs), std::move(rhs)} {}
|
1224
1201
|
|
1225
1202
|
double value(double x, double y) const override { return std::hypot(x, y); }
|
1226
1203
|
|
@@ -1280,9 +1257,8 @@ struct LogExpression final : Expression {
|
|
1280
1257
|
*
|
1281
1258
|
* @param lhs Unary operator's operand.
|
1282
1259
|
*/
|
1283
|
-
explicit LogExpression(ExpressionPtr lhs)
|
1284
|
-
|
1285
|
-
}
|
1260
|
+
explicit constexpr LogExpression(ExpressionPtr lhs)
|
1261
|
+
: Expression{std::move(lhs)} {}
|
1286
1262
|
|
1287
1263
|
double value(double x, double) const override { return std::log(x); }
|
1288
1264
|
|
@@ -1330,9 +1306,8 @@ struct Log10Expression final : Expression {
|
|
1330
1306
|
*
|
1331
1307
|
* @param lhs Unary operator's operand.
|
1332
1308
|
*/
|
1333
|
-
explicit Log10Expression(ExpressionPtr lhs)
|
1334
|
-
|
1335
|
-
}
|
1309
|
+
explicit constexpr Log10Expression(ExpressionPtr lhs)
|
1310
|
+
: Expression{std::move(lhs)} {}
|
1336
1311
|
|
1337
1312
|
double value(double x, double) const override { return std::log10(x); }
|
1338
1313
|
|
@@ -1387,10 +1362,8 @@ struct PowExpression final : Expression {
|
|
1387
1362
|
* @param lhs Binary operator's left operand.
|
1388
1363
|
* @param rhs Binary operator's right operand.
|
1389
1364
|
*/
|
1390
|
-
PowExpression(ExpressionPtr lhs, ExpressionPtr rhs)
|
1391
|
-
: Expression{std::move(lhs), std::move(rhs)} {
|
1392
|
-
val = std::pow(args[0]->val, args[1]->val);
|
1393
|
-
}
|
1365
|
+
constexpr PowExpression(ExpressionPtr lhs, ExpressionPtr rhs)
|
1366
|
+
: Expression{std::move(lhs), std::move(rhs)} {}
|
1394
1367
|
|
1395
1368
|
double value(double base, double power) const override {
|
1396
1369
|
return std::pow(base, power);
|
@@ -1489,15 +1462,7 @@ struct SignExpression final : Expression {
|
|
1489
1462
|
* @param lhs Unary operator's operand.
|
1490
1463
|
*/
|
1491
1464
|
explicit constexpr SignExpression(ExpressionPtr lhs)
|
1492
|
-
: Expression{std::move(lhs)} {
|
1493
|
-
if (args[0]->val < 0.0) {
|
1494
|
-
val = -1.0;
|
1495
|
-
} else if (args[0]->val == 0.0) {
|
1496
|
-
val = 0.0;
|
1497
|
-
} else {
|
1498
|
-
val = 1.0;
|
1499
|
-
}
|
1500
|
-
}
|
1465
|
+
: Expression{std::move(lhs)} {}
|
1501
1466
|
|
1502
1467
|
double value(double x, double) const override {
|
1503
1468
|
if (x < 0.0) {
|
@@ -1552,9 +1517,8 @@ struct SinExpression final : Expression {
|
|
1552
1517
|
*
|
1553
1518
|
* @param lhs Unary operator's operand.
|
1554
1519
|
*/
|
1555
|
-
explicit SinExpression(ExpressionPtr lhs)
|
1556
|
-
|
1557
|
-
}
|
1520
|
+
explicit constexpr SinExpression(ExpressionPtr lhs)
|
1521
|
+
: Expression{std::move(lhs)} {}
|
1558
1522
|
|
1559
1523
|
double value(double x, double) const override { return std::sin(x); }
|
1560
1524
|
|
@@ -1602,9 +1566,8 @@ struct SinhExpression final : Expression {
|
|
1602
1566
|
*
|
1603
1567
|
* @param lhs Unary operator's operand.
|
1604
1568
|
*/
|
1605
|
-
explicit SinhExpression(ExpressionPtr lhs)
|
1606
|
-
|
1607
|
-
}
|
1569
|
+
explicit constexpr SinhExpression(ExpressionPtr lhs)
|
1570
|
+
: Expression{std::move(lhs)} {}
|
1608
1571
|
|
1609
1572
|
double value(double x, double) const override { return std::sinh(x); }
|
1610
1573
|
|
@@ -1652,9 +1615,8 @@ struct SqrtExpression final : Expression {
|
|
1652
1615
|
*
|
1653
1616
|
* @param lhs Unary operator's operand.
|
1654
1617
|
*/
|
1655
|
-
explicit SqrtExpression(ExpressionPtr lhs)
|
1656
|
-
|
1657
|
-
}
|
1618
|
+
explicit constexpr SqrtExpression(ExpressionPtr lhs)
|
1619
|
+
: Expression{std::move(lhs)} {}
|
1658
1620
|
|
1659
1621
|
double value(double x, double) const override { return std::sqrt(x); }
|
1660
1622
|
|
@@ -1704,9 +1666,8 @@ struct TanExpression final : Expression {
|
|
1704
1666
|
*
|
1705
1667
|
* @param lhs Unary operator's operand.
|
1706
1668
|
*/
|
1707
|
-
explicit TanExpression(ExpressionPtr lhs)
|
1708
|
-
|
1709
|
-
}
|
1669
|
+
explicit constexpr TanExpression(ExpressionPtr lhs)
|
1670
|
+
: Expression{std::move(lhs)} {}
|
1710
1671
|
|
1711
1672
|
double value(double x, double) const override { return std::tan(x); }
|
1712
1673
|
|
@@ -1754,9 +1715,8 @@ struct TanhExpression final : Expression {
|
|
1754
1715
|
*
|
1755
1716
|
* @param lhs Unary operator's operand.
|
1756
1717
|
*/
|
1757
|
-
explicit TanhExpression(ExpressionPtr lhs)
|
1758
|
-
|
1759
|
-
}
|
1718
|
+
explicit constexpr TanhExpression(ExpressionPtr lhs)
|
1719
|
+
: Expression{std::move(lhs)} {}
|
1760
1720
|
|
1761
1721
|
double value(double x, double) const override { return std::tanh(x); }
|
1762
1722
|
|
@@ -22,21 +22,24 @@ enum class ExitStatus : int8_t {
|
|
22
22
|
TOO_FEW_DOFS = -1,
|
23
23
|
/// The solver determined the problem to be locally infeasible and gave up.
|
24
24
|
LOCALLY_INFEASIBLE = -2,
|
25
|
+
/// The problem setup frontend determined the problem to have an empty
|
26
|
+
/// feasible region.
|
27
|
+
GLOBALLY_INFEASIBLE = -3,
|
25
28
|
/// The linear system factorization failed.
|
26
|
-
FACTORIZATION_FAILED = -
|
29
|
+
FACTORIZATION_FAILED = -4,
|
27
30
|
/// The backtracking line search failed, and the problem isn't locally
|
28
31
|
/// infeasible.
|
29
|
-
LINE_SEARCH_FAILED = -
|
32
|
+
LINE_SEARCH_FAILED = -5,
|
30
33
|
/// The solver encountered nonfinite initial cost or constraints and gave up.
|
31
|
-
NONFINITE_INITIAL_COST_OR_CONSTRAINTS = -
|
34
|
+
NONFINITE_INITIAL_COST_OR_CONSTRAINTS = -6,
|
32
35
|
/// The solver encountered diverging primal iterates xₖ and/or sₖ and gave up.
|
33
|
-
DIVERGING_ITERATES = -
|
36
|
+
DIVERGING_ITERATES = -7,
|
34
37
|
/// The solver returned its solution so far after exceeding the maximum number
|
35
38
|
/// of iterations.
|
36
|
-
MAX_ITERATIONS_EXCEEDED = -
|
39
|
+
MAX_ITERATIONS_EXCEEDED = -8,
|
37
40
|
/// The solver returned its solution so far after exceeding the maximum
|
38
41
|
/// elapsed wall clock time.
|
39
|
-
TIMEOUT = -
|
42
|
+
TIMEOUT = -9,
|
40
43
|
};
|
41
44
|
|
42
45
|
/**
|
@@ -57,6 +60,8 @@ SLEIPNIR_DLLEXPORT constexpr std::string_view to_message(
|
|
57
60
|
return "too few degrees of freedom";
|
58
61
|
case LOCALLY_INFEASIBLE:
|
59
62
|
return "locally infeasible";
|
63
|
+
case GLOBALLY_INFEASIBLE:
|
64
|
+
return "globally infeasible";
|
60
65
|
case FACTORIZATION_FAILED:
|
61
66
|
return "factorization failed";
|
62
67
|
case LINE_SEARCH_FAILED:
|
@@ -223,6 +223,10 @@ SLEIPNIR_DLLEXPORT ExitStatus
|
|
223
223
|
interior_point(const InteriorPointMatrixCallbacks& matrix_callbacks,
|
224
224
|
std::span<std::function<bool(const IterationInfo& info)>>
|
225
225
|
iteration_callbacks,
|
226
|
-
const Options& options,
|
226
|
+
const Options& options,
|
227
|
+
#ifdef SLEIPNIR_ENABLE_BOUND_PROJECTION
|
228
|
+
const Eigen::ArrayX<bool>& bound_constraint_mask,
|
229
|
+
#endif
|
230
|
+
Eigen::VectorXd& x);
|
227
231
|
|
228
232
|
} // namespace slp
|
@@ -78,6 +78,10 @@ up.)doc";
|
|
78
78
|
|
79
79
|
static const char *__doc_slp_ExitStatus_FACTORIZATION_FAILED = R"doc(The linear system factorization failed.)doc";
|
80
80
|
|
81
|
+
static const char *__doc_slp_ExitStatus_GLOBALLY_INFEASIBLE =
|
82
|
+
R"doc(The problem setup frontend determined the problem to have an empty
|
83
|
+
feasible region.)doc";
|
84
|
+
|
81
85
|
static const char *__doc_slp_ExitStatus_LINE_SEARCH_FAILED =
|
82
86
|
R"doc(The backtracking line search failed, and the problem isn't locally
|
83
87
|
infeasible.)doc";
|
@@ -17,6 +17,8 @@ void bind_exit_status(nb::enum_<ExitStatus>& e) {
|
|
17
17
|
DOC(slp, ExitStatus, TOO_FEW_DOFS));
|
18
18
|
e.value("LOCALLY_INFEASIBLE", ExitStatus::LOCALLY_INFEASIBLE,
|
19
19
|
DOC(slp, ExitStatus, LOCALLY_INFEASIBLE));
|
20
|
+
e.value("GLOBALLY_INFEASIBLE", ExitStatus::GLOBALLY_INFEASIBLE,
|
21
|
+
DOC(slp, ExitStatus, GLOBALLY_INFEASIBLE));
|
20
22
|
e.value("FACTORIZATION_FAILED", ExitStatus::FACTORIZATION_FAILED,
|
21
23
|
DOC(slp, ExitStatus, FACTORIZATION_FAILED));
|
22
24
|
e.value("LINE_SEARCH_FAILED", ExitStatus::LINE_SEARCH_FAILED,
|
@@ -116,6 +116,25 @@ def test_minimum_2d_distance_with_linear_constraint():
|
|
116
116
|
assert y.value() == pytest.approx(2.5, abs=1e-2)
|
117
117
|
|
118
118
|
|
119
|
+
def test_conflicting_bounds():
|
120
|
+
problem = Problem()
|
121
|
+
|
122
|
+
x = problem.decision_variable()
|
123
|
+
y = problem.decision_variable()
|
124
|
+
|
125
|
+
problem.minimize(autodiff.hypot(x, y))
|
126
|
+
|
127
|
+
problem.subject_to(autodiff.hypot(x, y) <= 1)
|
128
|
+
problem.subject_to(x >= 0.5)
|
129
|
+
problem.subject_to(x <= -0.5)
|
130
|
+
|
131
|
+
assert problem.cost_function_type() == ExpressionType.NONLINEAR
|
132
|
+
assert problem.equality_constraint_type() == ExpressionType.NONE
|
133
|
+
assert problem.inequality_constraint_type() == ExpressionType.NONLINEAR
|
134
|
+
|
135
|
+
assert problem.solve(diagnostics=True) == ExitStatus.GLOBALLY_INFEASIBLE
|
136
|
+
|
137
|
+
|
119
138
|
def test_wachter_and_biegler_line_search_failure():
|
120
139
|
# See example 19.2 of [1]
|
121
140
|
|
{sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/pyproject.toml
RENAMED
@@ -1,7 +1,7 @@
|
|
1
1
|
[project]
|
2
2
|
name = "sleipnirgroup-jormungandr"
|
3
3
|
description = "A linearity-exploiting sparse nonlinear constrained optimization problem solver that uses the interior-point method."
|
4
|
-
version = "0.0.1.
|
4
|
+
version = "0.0.1.dev477"
|
5
5
|
readme = "README.md"
|
6
6
|
requires-python = ">=3.9"
|
7
7
|
dependencies = [ "matplotlib", "numpy", "scipy" ]
|
@@ -0,0 +1,220 @@
|
|
1
|
+
// Copyright (c) Sleipnir contributors
|
2
|
+
|
3
|
+
#pragma once
|
4
|
+
|
5
|
+
#include <algorithm>
|
6
|
+
#include <limits>
|
7
|
+
#include <span>
|
8
|
+
#include <utility>
|
9
|
+
|
10
|
+
#include <Eigen/Core>
|
11
|
+
#include <Eigen/SparseCore>
|
12
|
+
#include <gch/small_vector.hpp>
|
13
|
+
|
14
|
+
#include "sleipnir/autodiff/expression_type.hpp"
|
15
|
+
#include "sleipnir/autodiff/variable.hpp"
|
16
|
+
#include "sleipnir/util/assert.hpp"
|
17
|
+
|
18
|
+
// See docs/algorithms.md#Works_cited for citation definitions
|
19
|
+
|
20
|
+
namespace slp {
|
21
|
+
|
22
|
+
struct Bounds {
|
23
|
+
/// Which constraints, if any, are bound constraints.
|
24
|
+
Eigen::ArrayX<bool> bound_constraint_mask;
|
25
|
+
|
26
|
+
/// The tightest bounds on each decision variable.
|
27
|
+
gch::small_vector<std::pair<double, double>> bounds;
|
28
|
+
|
29
|
+
/// Whether or not the constraints are feasible (given previously encountered
|
30
|
+
/// bounds).
|
31
|
+
gch::small_vector<std::pair<Eigen::Index, Eigen::Index>>
|
32
|
+
conflicting_bound_indices;
|
33
|
+
};
|
34
|
+
|
35
|
+
/**
|
36
|
+
* A "bound constraint" is any linear constraint in one scalar variable.
|
37
|
+
*
|
38
|
+
* Computes which constraints, if any, are bound constraints, the tightest
|
39
|
+
* bounds on each decision variable, and whether or not they're feasible (given
|
40
|
+
* previously encountered bounds),
|
41
|
+
*
|
42
|
+
* @param decision_variables Decision variables corresponding to each column of
|
43
|
+
* A_i.
|
44
|
+
* @param inequality_constraints Variables representing the left-hand side of
|
45
|
+
* cᵢ(decision_variables) ≥ 0.
|
46
|
+
* @param A_i The Jacobian of inequality_constraints wrt decision_variables,
|
47
|
+
* evaluated anywhere, in *row-major* storage; in practice, since we typically
|
48
|
+
* store Jacobians column-major, the user of this function must perform a
|
49
|
+
* transpose.
|
50
|
+
*/
|
51
|
+
inline Bounds get_bounds(
|
52
|
+
std::span<Variable> decision_variables,
|
53
|
+
std::span<Variable> inequality_constraints,
|
54
|
+
const Eigen::SparseMatrix<double, Eigen::RowMajor>& A_i) {
|
55
|
+
// TODO: A blocked, out-of-place transpose should be much faster than
|
56
|
+
// traversing row major on a column major matrix unless we have few linear
|
57
|
+
// constraints (using a heuristic to choose between this and staying column
|
58
|
+
// major based on the number of constraints would be an easy performance
|
59
|
+
// improvement.)
|
60
|
+
|
61
|
+
// NB: Casting to long is unspecified if the size of decision_variable.size()
|
62
|
+
// is greater than the max long value, but then we wouldn't be able to fill
|
63
|
+
// A_i correctly anyway.
|
64
|
+
slp_assert(static_cast<Eigen::Index>(decision_variables.size()) ==
|
65
|
+
A_i.innerSize());
|
66
|
+
slp_assert(static_cast<Eigen::Index>(inequality_constraints.size()) ==
|
67
|
+
A_i.outerSize());
|
68
|
+
|
69
|
+
// Maps each decision variable's index to the indices of its upper and lower
|
70
|
+
// bounds if they exist, or NO_BOUND if they do not; used only for bookkeeping
|
71
|
+
// to compute conflicting bounds
|
72
|
+
constexpr Eigen::Index NO_BOUND = -1;
|
73
|
+
gch::small_vector<std::pair<Eigen::Index, Eigen::Index>>
|
74
|
+
decision_var_indices_to_constraint_indices{decision_variables.size(),
|
75
|
+
{NO_BOUND, NO_BOUND}};
|
76
|
+
// Lists pairs of indices of bound constraints in the inequality constraint
|
77
|
+
// list that conflict with each other
|
78
|
+
gch::small_vector<std::pair<Eigen::Index, Eigen::Index>>
|
79
|
+
conflicting_bound_indices;
|
80
|
+
|
81
|
+
// Maps each decision variable's index to its upper and lower bounds
|
82
|
+
gch::small_vector<std::pair<double, double>> decision_var_indices_to_bounds{
|
83
|
+
decision_variables.size(),
|
84
|
+
{-std::numeric_limits<double>::infinity(),
|
85
|
+
std::numeric_limits<double>::infinity()}};
|
86
|
+
|
87
|
+
// Vector corresponding to the inequality constraints where the i-th element
|
88
|
+
// is 1 if the i-th inequality constraint is a bound and 0 otherwise.
|
89
|
+
Eigen::ArrayX<bool> bound_constraint_mask{inequality_constraints.size()};
|
90
|
+
bound_constraint_mask.fill(false);
|
91
|
+
|
92
|
+
for (decltype(inequality_constraints)::size_type constraint_index = 0;
|
93
|
+
constraint_index < inequality_constraints.size(); ++constraint_index) {
|
94
|
+
// A constraint is a bound iff it is linear and its gradient has a
|
95
|
+
// single nonzero value.
|
96
|
+
if (inequality_constraints[constraint_index].type() !=
|
97
|
+
ExpressionType::LINEAR) {
|
98
|
+
continue;
|
99
|
+
}
|
100
|
+
const Eigen::SparseVector<double>& row_A_i =
|
101
|
+
A_i.innerVector(constraint_index);
|
102
|
+
const auto non_zeros = row_A_i.nonZeros();
|
103
|
+
slp_assert(non_zeros != 0);
|
104
|
+
if (non_zeros > 1) {
|
105
|
+
// Constraint is in more than one variable and therefore not a bound.
|
106
|
+
continue;
|
107
|
+
}
|
108
|
+
|
109
|
+
// Claim: The bound given by a bound constraint is the constraint evaluated
|
110
|
+
// at zero divided by the nonzero element of the constraint's gradient.
|
111
|
+
//
|
112
|
+
// Proof: If c(x) is a bound constraint, then by definition c is a linear
|
113
|
+
// function in one variable, hence there exist a, b ∈ ℝ s.t. c(x) = axᵢ + b
|
114
|
+
// and a ≠ 0. The gradient of c is then aeᵢ (where eᵢ denotes the i-th basis
|
115
|
+
// element), and c(0) = b. If c(x) ≥ 0, then since either a < 0 or a > 0, we
|
116
|
+
// have either x ≤ -b/a or x ≥ -b/a, respectively. ∎
|
117
|
+
Eigen::SparseVector<double>::InnerIterator row_iter(row_A_i);
|
118
|
+
const auto constraint_coefficient =
|
119
|
+
row_iter
|
120
|
+
.value(); // The nonzero value of the j-th constraint's gradient.
|
121
|
+
const auto decision_variable_index = row_iter.index();
|
122
|
+
const auto decision_variable_value =
|
123
|
+
decision_variables[decision_variable_index].value();
|
124
|
+
double constraint_constant;
|
125
|
+
// We need to evaluate this constraint *exactly* at zero.
|
126
|
+
if (decision_variable_value != 0.0) {
|
127
|
+
decision_variables[decision_variable_index].set_value(0.0);
|
128
|
+
constraint_constant = inequality_constraints[constraint_index].value();
|
129
|
+
decision_variables[decision_variable_index].set_value(
|
130
|
+
decision_variable_value);
|
131
|
+
} else {
|
132
|
+
constraint_constant = inequality_constraints[constraint_index].value();
|
133
|
+
}
|
134
|
+
|
135
|
+
// Shouldn't happen since the constraint is supposed to be linear and not a
|
136
|
+
// constant.
|
137
|
+
slp_assert(constraint_coefficient != 0.0);
|
138
|
+
|
139
|
+
// We should always get a finite value when evaluating the constraint at
|
140
|
+
// x = 0 since the constraint is linear.
|
141
|
+
slp_assert(std::isfinite(constraint_constant));
|
142
|
+
|
143
|
+
// This is possible if the user has provided a starting point at which their
|
144
|
+
// problem is ill-defined.
|
145
|
+
slp_assert(std::isfinite(constraint_coefficient));
|
146
|
+
|
147
|
+
// Update bounds; we assume constraints of the form c(x) ≥ 0.
|
148
|
+
auto& [lower_bound, upper_bound] =
|
149
|
+
decision_var_indices_to_bounds[decision_variable_index];
|
150
|
+
auto& [lower_index, upper_index] =
|
151
|
+
decision_var_indices_to_constraint_indices[decision_variable_index];
|
152
|
+
const auto detected_bound = -constraint_constant / constraint_coefficient;
|
153
|
+
if (constraint_coefficient < 0.0 && detected_bound < upper_bound) {
|
154
|
+
upper_bound = detected_bound;
|
155
|
+
upper_index = constraint_index;
|
156
|
+
} else if (constraint_coefficient > 0.0 && detected_bound > lower_bound) {
|
157
|
+
lower_bound = detected_bound;
|
158
|
+
lower_index = constraint_index;
|
159
|
+
}
|
160
|
+
|
161
|
+
// Update conflicting bounds
|
162
|
+
if (lower_bound > upper_bound) {
|
163
|
+
conflicting_bound_indices.emplace_back(lower_index, upper_index);
|
164
|
+
}
|
165
|
+
|
166
|
+
// Set the bound constraint mask appropriately.
|
167
|
+
bound_constraint_mask[constraint_index] = true;
|
168
|
+
}
|
169
|
+
return {bound_constraint_mask, decision_var_indices_to_bounds,
|
170
|
+
conflicting_bound_indices};
|
171
|
+
}
|
172
|
+
|
173
|
+
/**
|
174
|
+
* Projects the decision variables onto the given bounds, while ensuring some
|
175
|
+
* configurable distance from the boundary if possible. This is designed to
|
176
|
+
* match the algorithm given in section 3.6 of [2].
|
177
|
+
*
|
178
|
+
* @param x A vector of decision variables.
|
179
|
+
* @param decision_variable_indices_to_bounds An array of bounds (stored [lower,
|
180
|
+
* upper]) for each decision variable in x.
|
181
|
+
* @param κ_1 A constant controlling distance from the lower or upper bound when
|
182
|
+
* the difference between the upper and lower bound is small.
|
183
|
+
* @param κ_2 A constant controlling distance from the lower or upper bound when
|
184
|
+
* the difference between the upper and lower bound is large (including when
|
185
|
+
* one of the bounds is ±∞).
|
186
|
+
*/
|
187
|
+
template <typename Derived>
|
188
|
+
requires(static_cast<bool>(Eigen::DenseBase<Derived>::IsVectorAtCompileTime))
|
189
|
+
inline void project_onto_bounds(
|
190
|
+
Eigen::DenseBase<Derived>& x,
|
191
|
+
std::span<const std::pair<typename Eigen::DenseBase<Derived>::Scalar,
|
192
|
+
typename Eigen::DenseBase<Derived>::Scalar>>
|
193
|
+
decision_variable_indices_to_bounds,
|
194
|
+
const typename Eigen::DenseBase<Derived>::Scalar κ_1 = 1e-2,
|
195
|
+
const typename Eigen::DenseBase<Derived>::Scalar κ_2 = 1e-2) {
|
196
|
+
slp_assert(κ_1 > 0 && κ_2 > 0 && κ_2 < 0.5);
|
197
|
+
|
198
|
+
Eigen::Index decision_variable_idx = 0;
|
199
|
+
for (const auto& [lower, upper] : decision_variable_indices_to_bounds) {
|
200
|
+
typename Eigen::DenseBase<Derived>::Scalar& x_i =
|
201
|
+
x[decision_variable_idx++];
|
202
|
+
|
203
|
+
// We assume that bound infeasibility is handled elsewhere.
|
204
|
+
slp_assert(lower <= upper);
|
205
|
+
|
206
|
+
// See B.2 in [5] and section 3.6 in [2]
|
207
|
+
if (std::isfinite(lower) && std::isfinite(upper)) {
|
208
|
+
auto p_L =
|
209
|
+
std::min(κ_1 * std::max(1.0, std::abs(lower)), κ_2 * (upper - lower));
|
210
|
+
auto p_U =
|
211
|
+
std::min(κ_1 * std::max(1.0, std::abs(upper)), κ_2 * (upper - lower));
|
212
|
+
x_i = std::min(std::max(lower + p_L, x_i), upper - p_U);
|
213
|
+
} else if (std::isfinite(lower)) {
|
214
|
+
x_i = std::max(x_i, lower + κ_1 * std::max(1.0, std::abs(lower)));
|
215
|
+
} else if (std::isfinite(upper)) {
|
216
|
+
x_i = std::min(x_i, upper - κ_1 * std::max(1.0, std::abs(upper)));
|
217
|
+
}
|
218
|
+
}
|
219
|
+
}
|
220
|
+
} // namespace slp
|
@@ -13,6 +13,7 @@
|
|
13
13
|
#include <Eigen/SparseCore>
|
14
14
|
#include <gch/small_vector.hpp>
|
15
15
|
|
16
|
+
#include "optimization/bounds.hpp"
|
16
17
|
#include "sleipnir/autodiff/expression_type.hpp"
|
17
18
|
#include "sleipnir/autodiff/gradient.hpp"
|
18
19
|
#include "sleipnir/autodiff/hessian.hpp"
|
@@ -252,6 +253,19 @@ ExitStatus Problem::solve(const Options& options, [[maybe_unused]] bool spy) {
|
|
252
253
|
}
|
253
254
|
#endif
|
254
255
|
|
256
|
+
const auto [bound_constraint_mask, bounds, conflicting_bound_indices] =
|
257
|
+
get_bounds(m_decision_variables, m_inequality_constraints, A_i.value());
|
258
|
+
if (!conflicting_bound_indices.empty()) {
|
259
|
+
if (options.diagnostics) {
|
260
|
+
print_bound_constraint_global_infeasibility_error(
|
261
|
+
conflicting_bound_indices);
|
262
|
+
}
|
263
|
+
return ExitStatus::GLOBALLY_INFEASIBLE;
|
264
|
+
}
|
265
|
+
|
266
|
+
#ifdef SLEIPNIR_ENABLE_BOUND_PROJECTION
|
267
|
+
project_onto_bounds(x, bounds);
|
268
|
+
#endif
|
255
269
|
// Invoke interior-point method solver
|
256
270
|
status = interior_point(
|
257
271
|
InteriorPointMatrixCallbacks{
|
@@ -286,7 +300,11 @@ ExitStatus Problem::solve(const Options& options, [[maybe_unused]] bool spy) {
|
|
286
300
|
x_ad.set_value(x);
|
287
301
|
return A_i.value();
|
288
302
|
}},
|
289
|
-
m_iteration_callbacks, options,
|
303
|
+
m_iteration_callbacks, options,
|
304
|
+
#ifdef SLEIPNIR_ENABLE_BOUND_PROJECTION
|
305
|
+
bound_constraint_mask,
|
306
|
+
#endif
|
307
|
+
x);
|
290
308
|
}
|
291
309
|
|
292
310
|
#ifndef SLEIPNIR_DISABLE_DIAGNOSTICS
|
@@ -56,7 +56,11 @@ ExitStatus interior_point(
|
|
56
56
|
const InteriorPointMatrixCallbacks& matrix_callbacks,
|
57
57
|
std::span<std::function<bool(const IterationInfo& info)>>
|
58
58
|
iteration_callbacks,
|
59
|
-
const Options& options,
|
59
|
+
const Options& options,
|
60
|
+
#ifdef SLEIPNIR_ENABLE_BOUND_PROJECTION
|
61
|
+
const Eigen::ArrayX<bool>& bound_constraint_mask,
|
62
|
+
#endif
|
63
|
+
Eigen::VectorXd& x) {
|
60
64
|
const auto solve_start_time = std::chrono::steady_clock::now();
|
61
65
|
|
62
66
|
gch::small_vector<SolveProfiler> solve_profilers;
|
@@ -160,6 +164,10 @@ ExitStatus interior_point(
|
|
160
164
|
Eigen::SparseMatrix<double> A_i = matrices.A_i(x);
|
161
165
|
|
162
166
|
Eigen::VectorXd s = Eigen::VectorXd::Ones(num_inequality_constraints);
|
167
|
+
#ifdef SLEIPNIR_ENABLE_BOUND_PROJECTION
|
168
|
+
// We set sʲ = cᵢʲ(x) for each bound inequality constraint index j
|
169
|
+
s = bound_constraint_mask.select(c_i, s);
|
170
|
+
#endif
|
163
171
|
Eigen::VectorXd y = Eigen::VectorXd::Zero(num_equality_constraints);
|
164
172
|
Eigen::VectorXd z = Eigen::VectorXd::Ones(num_inequality_constraints);
|
165
173
|
|
@@ -149,6 +149,25 @@ inline void print_c_i_local_infeasibility_error(const Eigen::VectorXd& c_i) {
|
|
149
149
|
#define print_c_i_local_infeasibility_error(...)
|
150
150
|
#endif
|
151
151
|
|
152
|
+
#ifndef SLEIPNIR_DISABLE_DIAGNOSTICS
|
153
|
+
inline void print_bound_constraint_global_infeasibility_error(
|
154
|
+
const std::span<const std::pair<Eigen::Index, Eigen::Index>>
|
155
|
+
conflicting_lower_upper_bound_indices) {
|
156
|
+
slp::println(
|
157
|
+
"The problem is globally infeasible due to conflicting bound "
|
158
|
+
"constraints:");
|
159
|
+
for (const auto& [lower_bound_idx, upper_bound_idx] :
|
160
|
+
conflicting_lower_upper_bound_indices) {
|
161
|
+
slp::println(
|
162
|
+
" Inequality constraint {} gives a lower bound that is greater than "
|
163
|
+
"the upper bound given by inequality constraint {}",
|
164
|
+
lower_bound_idx, upper_bound_idx);
|
165
|
+
}
|
166
|
+
}
|
167
|
+
#else
|
168
|
+
#define print_bound_constraint_global_infeasibility_error(...)
|
169
|
+
#endif
|
170
|
+
|
152
171
|
#ifndef SLEIPNIR_DISABLE_DIAGNOSTICS
|
153
172
|
/**
|
154
173
|
* Prints diagnostics for the current iteration.
|
{sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/LICENSE.txt
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/src/.styleguide
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{sleipnirgroup_jormungandr-0.0.1.dev475 → sleipnirgroup_jormungandr-0.0.1.dev477}/src/util/pool.cpp
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|