sleipnirgroup-jormungandr 0.6.7.dev56__tar.gz → 0.6.7.dev59__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.
Potentially problematic release.
This version of sleipnirgroup-jormungandr might be problematic. Click here for more details.
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/CMakeLists.txt +34 -22
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/PKG-INFO +1 -1
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/cmake/Pybind11Mkdoc.cmake +14 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/pyproject.toml +23 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/python/cpp/autodiff/bind_variable_block.cpp +51 -23
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/python/cpp/autodiff/bind_variable_matrix.cpp +59 -52
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/python/cpp/optimization/bind_ocp.cpp +17 -0
- sleipnirgroup_jormungandr-0.6.7.dev59/python/cpp/slice_tuple.hpp +21 -0
- sleipnirgroup_jormungandr-0.6.7.dev59/python/postprocess_stubs.py +166 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/python/src/sleipnir/__init__.py +1 -1
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/python/src/sleipnir/autodiff/__init__.py +1 -3
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/python/src/sleipnir/optimization/__init__.py +5 -1
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/python/test/autodiff/gradient_test.py +20 -20
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/python/test/autodiff/hessian_test.py +31 -30
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/python/test/autodiff/jacobian_test.py +11 -11
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/python/test/autodiff/variable_matrix_test.py +21 -21
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/python/test/autodiff/variable_test.py +3 -3
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/python/test/optimization/arm_on_elevator_problem_test.py +1 -1
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/python/test/optimization/cart_pole_ocp_test.py +3 -3
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/python/test/optimization/cart_pole_problem_test.py +2 -2
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/python/test/optimization/cart_pole_util.py +8 -3
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/python/test/optimization/constraints_test.py +4 -4
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/python/test/optimization/decision_variable_test.py +4 -4
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/python/test/optimization/differential_drive_ocp_test.py +1 -1
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/python/test/optimization/differential_drive_problem_test.py +2 -2
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/python/test/optimization/differential_drive_util.py +8 -3
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/python/test/optimization/double_integrator_problem_test.py +1 -1
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/python/test/optimization/flywheel_ocp_test.py +5 -5
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/python/test/optimization/flywheel_problem_test.py +1 -1
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/python/test/optimization/linear_problem_test.py +2 -2
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/python/test/optimization/multistart_test.py +5 -3
- sleipnirgroup_jormungandr-0.6.7.dev59/python/test/optimization/near.py +2 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/python/test/optimization/nonlinear_problem_test.py +7 -7
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/python/test/optimization/problem_spy_test.py +7 -5
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/python/test/optimization/quadratic_problem_test.py +6 -6
- sleipnirgroup_jormungandr-0.6.7.dev59/python/test/optimization/rk4.py +44 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/python/test/optimization/solver/exit_status_test.py +15 -15
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/python/test/optimization/trivial_problem_test.py +3 -3
- sleipnirgroup_jormungandr-0.6.7.dev56/python/test/optimization/near.py +0 -2
- sleipnirgroup_jormungandr-0.6.7.dev56/python/test/optimization/rk4.py +0 -18
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/LICENSE.txt +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/README.md +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/SleipnirConfig.cmake.in +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/cmake/BuildTypes.cmake +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/cmake/CompilerFlags.cmake +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/cmake/SubdirList.cmake +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/cmake/arm-none-eabi.cmake +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/include/sleipnir/autodiff/expression.hpp +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/include/sleipnir/autodiff/expression_graph.hpp +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/include/sleipnir/autodiff/expression_type.hpp +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/include/sleipnir/autodiff/gradient.hpp +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/include/sleipnir/autodiff/hessian.hpp +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/include/sleipnir/autodiff/jacobian.hpp +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/include/sleipnir/autodiff/sleipnir_base.hpp +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/include/sleipnir/autodiff/slice.hpp +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/include/sleipnir/autodiff/variable.hpp +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/include/sleipnir/autodiff/variable_block.hpp +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/include/sleipnir/autodiff/variable_matrix.hpp +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/include/sleipnir/optimization/multistart.hpp +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/include/sleipnir/optimization/ocp/dynamics_type.hpp +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/include/sleipnir/optimization/ocp/timestep_method.hpp +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/include/sleipnir/optimization/ocp/transcription_method.hpp +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/include/sleipnir/optimization/ocp.hpp +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/include/sleipnir/optimization/problem.hpp +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/include/sleipnir/optimization/solver/exit_status.hpp +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/include/sleipnir/optimization/solver/ipm.hpp +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/include/sleipnir/optimization/solver/ipm_matrix_callbacks.hpp +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/include/sleipnir/optimization/solver/iteration_info.hpp +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/include/sleipnir/optimization/solver/newton.hpp +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/include/sleipnir/optimization/solver/newton_matrix_callbacks.hpp +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/include/sleipnir/optimization/solver/options.hpp +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/include/sleipnir/optimization/solver/sqp.hpp +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/include/sleipnir/optimization/solver/sqp_matrix_callbacks.hpp +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/include/sleipnir/optimization/solver/util/all_finite.hpp +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/include/sleipnir/optimization/solver/util/append_as_triplets.hpp +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/include/sleipnir/optimization/solver/util/bounds.hpp +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/include/sleipnir/optimization/solver/util/dense_kkt_solver.hpp +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/include/sleipnir/optimization/solver/util/feasibility_restoration.hpp +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/include/sleipnir/optimization/solver/util/filter.hpp +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/include/sleipnir/optimization/solver/util/fraction_to_the_boundary_rule.hpp +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/include/sleipnir/optimization/solver/util/inertia.hpp +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/include/sleipnir/optimization/solver/util/kkt_error.hpp +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/include/sleipnir/optimization/solver/util/kkt_solver.hpp +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/include/sleipnir/optimization/solver/util/problem_scaling.hpp +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/include/sleipnir/optimization/solver/util/sparse_inf_norms.hpp +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/include/sleipnir/optimization/solver/util/sparse_kkt_solver.hpp +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/include/sleipnir/util/assert.hpp +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/include/sleipnir/util/concepts.hpp +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/include/sleipnir/util/empty.hpp +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/include/sleipnir/util/function_ref.hpp +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/include/sleipnir/util/intrusive_shared_ptr.hpp +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/include/sleipnir/util/pool.hpp +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/include/sleipnir/util/print.hpp +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/include/sleipnir/util/print_diagnostics.hpp +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/include/sleipnir/util/profiler.hpp +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/include/sleipnir/util/scope_exit.hpp +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/include/sleipnir/util/spy.hpp +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/include/sleipnir/util/symbol_exports.hpp +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/python/cpp/autodiff/bind_expression_type.cpp +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/python/cpp/autodiff/bind_gradient.cpp +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/python/cpp/autodiff/bind_hessian.cpp +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/python/cpp/autodiff/bind_jacobian.cpp +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/python/cpp/autodiff/bind_variable.cpp +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/python/cpp/binders.hpp +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/python/cpp/docstrings.hpp +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/python/cpp/for_each_type.hpp +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/python/cpp/main.cpp +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/python/cpp/optimization/bind_equality_constraints.cpp +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/python/cpp/optimization/bind_inequality_constraints.cpp +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/python/cpp/optimization/bind_problem.cpp +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/python/cpp/optimization/ocp/bind_dynamics_type.cpp +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/python/cpp/optimization/ocp/bind_timestep_method.cpp +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/python/cpp/optimization/ocp/bind_transcription_method.cpp +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/python/cpp/optimization/solver/bind_exit_status.cpp +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/python/cpp/optimization/solver/bind_iteration_info.cpp +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/python/cpp/try_cast.hpp +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/src/autodiff/gradient.cpp +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/src/autodiff/hessian.cpp +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/src/autodiff/jacobian.cpp +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/src/autodiff/variable_matrix.cpp +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/src/optimization/ocp.cpp +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/src/optimization/problem.cpp +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/src/optimization/solver/ipm.cpp +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/src/optimization/solver/newton.cpp +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/src/optimization/solver/sqp.cpp +0 -0
- {sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/src/util/pool.cpp +0 -0
{sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/CMakeLists.txt
RENAMED
|
@@ -301,7 +301,9 @@ if(SLEIPNIR_BUILD_PYTHON)
|
|
|
301
301
|
if(DEFINED PY_BUILD_CMAKE_MODULE_NAME)
|
|
302
302
|
set(PY_DEST ${PY_BUILD_CMAKE_MODULE_NAME})
|
|
303
303
|
else()
|
|
304
|
-
set(PY_DEST
|
|
304
|
+
set(PY_DEST
|
|
305
|
+
lib/python${Python_VERSION_MAJOR}.${Python_VERSION_MINOR}/sleipnir
|
|
306
|
+
)
|
|
305
307
|
endif()
|
|
306
308
|
|
|
307
309
|
# nanobind dependency
|
|
@@ -343,47 +345,57 @@ if(SLEIPNIR_BUILD_PYTHON)
|
|
|
343
345
|
LIBRARY DESTINATION ${PY_DEST}
|
|
344
346
|
)
|
|
345
347
|
|
|
348
|
+
# Generate stubs at install time because only the install tree has the
|
|
349
|
+
# sleipnir/ package layout needed to import the module by its fully
|
|
350
|
+
# qualified name `sleipnir._sleipnir`.
|
|
351
|
+
#
|
|
352
|
+
# Importing sleipnir._sleipnir requires the directory containing the
|
|
353
|
+
# sleipnir package (i.e., PY_DEST's parent) to be on the Python path. For
|
|
354
|
+
# py-build-cmake builds, PY_DEST has no parent. For plain CMake installs,
|
|
355
|
+
# PY_DEST's parent is lib/pythonX.Y.
|
|
356
|
+
cmake_path(GET PY_DEST PARENT_PATH PY_DEST_PARENT)
|
|
346
357
|
nanobind_add_stub(
|
|
347
358
|
_sleipnir_stub
|
|
348
359
|
INSTALL_TIME
|
|
349
|
-
MARKER_FILE
|
|
350
|
-
MODULE _sleipnir
|
|
351
|
-
OUTPUT
|
|
352
|
-
PYTHON_PATH
|
|
360
|
+
MARKER_FILE ${PY_DEST}/py.typed
|
|
361
|
+
MODULE sleipnir._sleipnir
|
|
362
|
+
OUTPUT ${PY_DEST}/_sleipnir/__init__.pyi
|
|
363
|
+
PYTHON_PATH ${PY_DEST_PARENT}
|
|
353
364
|
DEPENDS _sleipnir
|
|
354
365
|
COMPONENT python_modules
|
|
355
366
|
)
|
|
356
367
|
nanobind_add_stub(
|
|
357
368
|
_sleipnir_autodiff_stub
|
|
358
369
|
INSTALL_TIME
|
|
359
|
-
MODULE _sleipnir.autodiff
|
|
360
|
-
OUTPUT
|
|
361
|
-
PYTHON_PATH
|
|
370
|
+
MODULE sleipnir._sleipnir.autodiff
|
|
371
|
+
OUTPUT ${PY_DEST}/_sleipnir/autodiff.pyi
|
|
372
|
+
PYTHON_PATH ${PY_DEST_PARENT}
|
|
362
373
|
DEPENDS _sleipnir
|
|
363
374
|
COMPONENT python_modules
|
|
364
375
|
)
|
|
365
376
|
nanobind_add_stub(
|
|
366
377
|
_sleipnir_optimization_stub
|
|
367
378
|
INSTALL_TIME
|
|
368
|
-
MODULE _sleipnir.optimization
|
|
369
|
-
OUTPUT
|
|
370
|
-
PYTHON_PATH
|
|
379
|
+
MODULE sleipnir._sleipnir.optimization
|
|
380
|
+
OUTPUT ${PY_DEST}/_sleipnir/optimization.pyi
|
|
381
|
+
PYTHON_PATH ${PY_DEST_PARENT}
|
|
371
382
|
DEPENDS _sleipnir
|
|
372
383
|
COMPONENT python_modules
|
|
373
384
|
)
|
|
385
|
+
install(
|
|
386
|
+
CODE
|
|
387
|
+
"execute_process(
|
|
388
|
+
COMMAND \"${Python_EXECUTABLE}\"
|
|
389
|
+
\"${CMAKE_CURRENT_SOURCE_DIR}/python/postprocess_stubs.py\"
|
|
390
|
+
${PY_DEST}/_sleipnir/autodiff.pyi
|
|
391
|
+
${PY_DEST}/_sleipnir/optimization.pyi
|
|
392
|
+
WORKING_DIRECTORY \"\${CMAKE_INSTALL_PREFIX}\"
|
|
393
|
+
COMMAND_ERROR_IS_FATAL ANY
|
|
394
|
+
)"
|
|
395
|
+
COMPONENT python_modules
|
|
396
|
+
)
|
|
374
397
|
|
|
375
398
|
if(NOT CMAKE_CROSSCOMPILING)
|
|
376
|
-
# pybind11_mkdoc dependency
|
|
377
|
-
FetchContent_Declare(
|
|
378
|
-
pybind11_mkdoc
|
|
379
|
-
GIT_REPOSITORY https://github.com/pybind/pybind11_mkdoc.git
|
|
380
|
-
GIT_TAG v3.0.0
|
|
381
|
-
GIT_SHALLOW ON
|
|
382
|
-
EXCLUDE_FROM_ALL
|
|
383
|
-
SYSTEM
|
|
384
|
-
)
|
|
385
|
-
FetchContent_MakeAvailable(pybind11_mkdoc)
|
|
386
|
-
|
|
387
399
|
set(sleipnir_headers
|
|
388
400
|
${CMAKE_CURRENT_SOURCE_DIR}/include/sleipnir/autodiff/expression_type.hpp
|
|
389
401
|
${CMAKE_CURRENT_SOURCE_DIR}/include/sleipnir/autodiff/gradient.hpp
|
|
@@ -1,6 +1,20 @@
|
|
|
1
1
|
function(pybind11_mkdoc target headers)
|
|
2
2
|
find_package(Python3 REQUIRED COMPONENTS Interpreter)
|
|
3
3
|
|
|
4
|
+
# Check that pybind11_mkdoc is installed
|
|
5
|
+
execute_process(
|
|
6
|
+
COMMAND ${Python3_EXECUTABLE} -c "import pybind11_mkdoc"
|
|
7
|
+
RESULT_VARIABLE pybind11_mkdoc_result
|
|
8
|
+
OUTPUT_QUIET
|
|
9
|
+
ERROR_QUIET
|
|
10
|
+
)
|
|
11
|
+
if(NOT pybind11_mkdoc_result EQUAL 0)
|
|
12
|
+
message(
|
|
13
|
+
FATAL_ERROR
|
|
14
|
+
"pybind11_mkdoc not found for ${Python3_EXECUTABLE}. Install it with `pip install --group docstrings`."
|
|
15
|
+
)
|
|
16
|
+
endif()
|
|
17
|
+
|
|
4
18
|
# Target compiler flags
|
|
5
19
|
get_target_property(target_flags ${target} INCLUDE_DIRECTORIES)
|
|
6
20
|
list(TRANSFORM target_flags PREPEND "-I")
|
{sleipnirgroup_jormungandr-0.6.7.dev56 → sleipnirgroup_jormungandr-0.6.7.dev59}/pyproject.toml
RENAMED
|
@@ -21,8 +21,11 @@ build-backend = "py_build_cmake.build"
|
|
|
21
21
|
|
|
22
22
|
[dependency-groups]
|
|
23
23
|
dev = [
|
|
24
|
+
"mypy>=2.4.0",
|
|
24
25
|
"pytest>=9.1.1",
|
|
26
|
+
"scipy-stubs",
|
|
25
27
|
]
|
|
28
|
+
docstrings = ["pybind11-mkdoc~=3.0.0"]
|
|
26
29
|
|
|
27
30
|
[tool.py-build-cmake.cmake]
|
|
28
31
|
build_type = "Release"
|
|
@@ -54,8 +57,27 @@ exclude = []
|
|
|
54
57
|
python_abi = "abi3"
|
|
55
58
|
abi3_minimum_cpython_version = 312
|
|
56
59
|
|
|
60
|
+
[tool.mypy]
|
|
61
|
+
files = [
|
|
62
|
+
"benchmarks",
|
|
63
|
+
"docs/generate_website.py",
|
|
64
|
+
"examples",
|
|
65
|
+
"python/postprocess_stubs.py",
|
|
66
|
+
"python/test",
|
|
67
|
+
"tools",
|
|
68
|
+
]
|
|
69
|
+
allow_redefinition_new = true
|
|
70
|
+
explicit_package_bases = true
|
|
71
|
+
local_partial_types = true
|
|
72
|
+
mypy_path = ["examples/current_manager", "python/test/optimization"]
|
|
73
|
+
|
|
74
|
+
[[tool.mypy.overrides]]
|
|
75
|
+
module = "mpl_toolkits.*"
|
|
76
|
+
ignore_missing_imports = true
|
|
77
|
+
|
|
57
78
|
[tool.pytest.ini_options]
|
|
58
79
|
minversion = "6.0"
|
|
80
|
+
pythonpath = ["examples/current_manager"]
|
|
59
81
|
testpaths = ["python/test", "examples/current_manager/test"]
|
|
60
82
|
|
|
61
83
|
[tool.uv]
|
|
@@ -68,6 +90,7 @@ cache-keys = [
|
|
|
68
90
|
{ file = "python/cpp/**/*.cpp" },
|
|
69
91
|
{ file = "python/cpp/binders.hpp" },
|
|
70
92
|
{ file = "python/cpp/for_each_type.hpp" },
|
|
93
|
+
{ file = "python/cpp/slice_tuple.hpp" },
|
|
71
94
|
{ file = "python/cpp/try_cast.hpp" },
|
|
72
95
|
{ file = "python/src/**" },
|
|
73
96
|
{ file = "src/**" },
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
#include <nanobind/operators.h>
|
|
7
7
|
#include <nanobind/stl/function.h>
|
|
8
8
|
#include <nanobind/stl/string.h>
|
|
9
|
+
#include <nanobind/stl/tuple.h>
|
|
9
10
|
#include <nanobind/stl/vector.h>
|
|
10
11
|
|
|
11
12
|
#include <stdint.h>
|
|
@@ -15,6 +16,7 @@
|
|
|
15
16
|
#include <functional>
|
|
16
17
|
#include <stdexcept>
|
|
17
18
|
#include <string>
|
|
19
|
+
#include <tuple>
|
|
18
20
|
|
|
19
21
|
#include <Eigen/Core>
|
|
20
22
|
#include <sleipnir/autodiff/slice.hpp>
|
|
@@ -25,6 +27,7 @@
|
|
|
25
27
|
|
|
26
28
|
#include "docstrings.hpp"
|
|
27
29
|
#include "for_each_type.hpp"
|
|
30
|
+
#include "slice_tuple.hpp"
|
|
28
31
|
#include "try_cast.hpp"
|
|
29
32
|
|
|
30
33
|
namespace nb = nanobind;
|
|
@@ -68,7 +71,7 @@ void bind_variable_block(
|
|
|
68
71
|
"row"_a, "value"_a);
|
|
69
72
|
cls.def(
|
|
70
73
|
"__setitem__",
|
|
71
|
-
[](VariableBlock<VariableMatrix<double>>& self,
|
|
74
|
+
[](VariableBlock<VariableMatrix<double>>& self, SliceTuple slices,
|
|
72
75
|
nb::object value) {
|
|
73
76
|
if (slices.size() != 2) {
|
|
74
77
|
throw nb::index_error(
|
|
@@ -151,31 +154,32 @@ void bind_variable_block(
|
|
|
151
154
|
cls.def(
|
|
152
155
|
"__getitem__",
|
|
153
156
|
[](VariableBlock<VariableMatrix<double>>& self,
|
|
154
|
-
|
|
157
|
+
std::tuple<int, int> slices) -> Variable<double>& {
|
|
158
|
+
auto [row, col] = slices;
|
|
159
|
+
|
|
160
|
+
if (row >= self.rows() || col >= self.cols()) {
|
|
161
|
+
throw std::out_of_range("Index out of bounds");
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
if (row < 0) {
|
|
165
|
+
row += self.rows();
|
|
166
|
+
}
|
|
167
|
+
if (col < 0) {
|
|
168
|
+
col += self.cols();
|
|
169
|
+
}
|
|
170
|
+
return self[row, col];
|
|
171
|
+
},
|
|
172
|
+
nb::rv_policy::reference_internal, "slices"_a,
|
|
173
|
+
DOC(slp, VariableBlock, operator, array));
|
|
174
|
+
cls.def(
|
|
175
|
+
"__getitem__",
|
|
176
|
+
[](VariableBlock<VariableMatrix<double>>& self,
|
|
177
|
+
SliceTuple slices) -> VariableBlock<VariableMatrix<double>> {
|
|
155
178
|
if (slices.size() != 2) {
|
|
156
179
|
throw nb::index_error(
|
|
157
180
|
std::format("Expected 2 slices, got {}.", slices.size()).c_str());
|
|
158
181
|
}
|
|
159
182
|
|
|
160
|
-
// If both indices are integers instead of slices, return Variable
|
|
161
|
-
// instead of VariableBlock
|
|
162
|
-
if (nb::isinstance<int>(slices[0]) && nb::isinstance<int>(slices[1])) {
|
|
163
|
-
int row = nb::cast<int>(slices[0]);
|
|
164
|
-
int col = nb::cast<int>(slices[1]);
|
|
165
|
-
|
|
166
|
-
if (row >= self.rows() || col >= self.cols()) {
|
|
167
|
-
throw std::out_of_range("Index out of bounds");
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
if (row < 0) {
|
|
171
|
-
row += self.rows();
|
|
172
|
-
}
|
|
173
|
-
if (col < 0) {
|
|
174
|
-
col += self.cols();
|
|
175
|
-
}
|
|
176
|
-
return nb::cast(self[row, col]);
|
|
177
|
-
}
|
|
178
|
-
|
|
179
183
|
Slice row_slice;
|
|
180
184
|
int row_slice_length;
|
|
181
185
|
Slice col_slice;
|
|
@@ -211,8 +215,7 @@ void bind_variable_block(
|
|
|
211
215
|
col_slice_length = 1;
|
|
212
216
|
}
|
|
213
217
|
|
|
214
|
-
return
|
|
215
|
-
self[row_slice, row_slice_length, col_slice, col_slice_length]);
|
|
218
|
+
return self[row_slice, row_slice_length, col_slice, col_slice_length];
|
|
216
219
|
},
|
|
217
220
|
nb::keep_alive<0, 1>(), DOC(slp, VariableBlock, operator, array),
|
|
218
221
|
"slices"_a);
|
|
@@ -223,6 +226,31 @@ void bind_variable_block(
|
|
|
223
226
|
nb::overload_cast<int>(&VariableBlock<VariableMatrix<double>>::col),
|
|
224
227
|
"col"_a, DOC(slp, VariableBlock, col));
|
|
225
228
|
|
|
229
|
+
// Matrix-matrix multiplication. Products with a VariableMatrix on the left
|
|
230
|
+
// are bound on VariableMatrix.
|
|
231
|
+
for (const char* name : {"__mul__", "__matmul__"}) {
|
|
232
|
+
cls.def(
|
|
233
|
+
name,
|
|
234
|
+
[](const VariableBlock<VariableMatrix<double>>& lhs,
|
|
235
|
+
const VariableBlock<VariableMatrix<double>>& rhs) {
|
|
236
|
+
return lhs * rhs;
|
|
237
|
+
},
|
|
238
|
+
nb::is_operator(), "rhs"_a);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
// Matrix multiplication with NumPy arrays. These are also handled by
|
|
242
|
+
// __array_ufunc__ below, but type checkers only see these overloads.
|
|
243
|
+
cls.def(
|
|
244
|
+
"__matmul__",
|
|
245
|
+
[](const VariableBlock<VariableMatrix<double>>& lhs,
|
|
246
|
+
nb::DRef<Eigen::MatrixXd> rhs) { return lhs * rhs; },
|
|
247
|
+
nb::is_operator(), "rhs"_a);
|
|
248
|
+
cls.def(
|
|
249
|
+
"__rmatmul__",
|
|
250
|
+
[](const VariableBlock<VariableMatrix<double>>& rhs,
|
|
251
|
+
nb::DRef<Eigen::MatrixXd> lhs) { return lhs * rhs; },
|
|
252
|
+
nb::is_operator(), "lhs"_a);
|
|
253
|
+
|
|
226
254
|
// https://numpy.org/doc/stable/user/basics.dispatch.html
|
|
227
255
|
cls.def(
|
|
228
256
|
"__array_ufunc__",
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
#include <nanobind/operators.h>
|
|
7
7
|
#include <nanobind/stl/function.h>
|
|
8
8
|
#include <nanobind/stl/string.h>
|
|
9
|
+
#include <nanobind/stl/tuple.h>
|
|
9
10
|
#include <nanobind/stl/vector.h>
|
|
10
11
|
|
|
11
12
|
#include <stdint.h>
|
|
@@ -15,6 +16,7 @@
|
|
|
15
16
|
#include <functional>
|
|
16
17
|
#include <stdexcept>
|
|
17
18
|
#include <string>
|
|
19
|
+
#include <tuple>
|
|
18
20
|
#include <vector>
|
|
19
21
|
|
|
20
22
|
#include <Eigen/Core>
|
|
@@ -26,6 +28,7 @@
|
|
|
26
28
|
|
|
27
29
|
#include "docstrings.hpp"
|
|
28
30
|
#include "for_each_type.hpp"
|
|
31
|
+
#include "slice_tuple.hpp"
|
|
29
32
|
#include "try_cast.hpp"
|
|
30
33
|
|
|
31
34
|
namespace nb = nanobind;
|
|
@@ -90,7 +93,7 @@ void bind_variable_matrix(nb::module_& autodiff,
|
|
|
90
93
|
"row"_a, "value"_a);
|
|
91
94
|
cls.def(
|
|
92
95
|
"__setitem__",
|
|
93
|
-
[](VariableMatrix<double>& self,
|
|
96
|
+
[](VariableMatrix<double>& self, SliceTuple slices, nb::object value) {
|
|
94
97
|
if (slices.size() != 2) {
|
|
95
98
|
throw nb::index_error(
|
|
96
99
|
std::format("Expected 2 slices, got {}.", slices.size()).c_str());
|
|
@@ -170,31 +173,33 @@ void bind_variable_matrix(nb::module_& autodiff,
|
|
|
170
173
|
DOC(slp, VariableMatrix, operator, array, 3));
|
|
171
174
|
cls.def(
|
|
172
175
|
"__getitem__",
|
|
173
|
-
[](VariableMatrix<double>& self,
|
|
176
|
+
[](VariableMatrix<double>& self,
|
|
177
|
+
std::tuple<int, int> slices) -> Variable<double>& {
|
|
178
|
+
auto [row, col] = slices;
|
|
179
|
+
|
|
180
|
+
if (row >= self.rows() || col >= self.cols()) {
|
|
181
|
+
throw std::out_of_range("Index out of bounds");
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
if (row < 0) {
|
|
185
|
+
row += self.rows();
|
|
186
|
+
}
|
|
187
|
+
if (col < 0) {
|
|
188
|
+
col += self.cols();
|
|
189
|
+
}
|
|
190
|
+
return self[row, col];
|
|
191
|
+
},
|
|
192
|
+
nb::rv_policy::reference_internal, "slices"_a,
|
|
193
|
+
DOC(slp, VariableMatrix, operator, array));
|
|
194
|
+
cls.def(
|
|
195
|
+
"__getitem__",
|
|
196
|
+
[](VariableMatrix<double>& self,
|
|
197
|
+
SliceTuple slices) -> VariableBlock<VariableMatrix<double>> {
|
|
174
198
|
if (slices.size() != 2) {
|
|
175
199
|
throw nb::index_error(
|
|
176
200
|
std::format("Expected 2 slices, got {}.", slices.size()).c_str());
|
|
177
201
|
}
|
|
178
202
|
|
|
179
|
-
// If both indices are integers instead of slices, return Variable
|
|
180
|
-
// instead of VariableBlock
|
|
181
|
-
if (nb::isinstance<int>(slices[0]) && nb::isinstance<int>(slices[1])) {
|
|
182
|
-
int row = nb::cast<int>(slices[0]);
|
|
183
|
-
int col = nb::cast<int>(slices[1]);
|
|
184
|
-
|
|
185
|
-
if (row >= self.rows() || col >= self.cols()) {
|
|
186
|
-
throw std::out_of_range("Index out of bounds");
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
if (row < 0) {
|
|
190
|
-
row += self.rows();
|
|
191
|
-
}
|
|
192
|
-
if (col < 0) {
|
|
193
|
-
col += self.cols();
|
|
194
|
-
}
|
|
195
|
-
return nb::cast(self[row, col]);
|
|
196
|
-
}
|
|
197
|
-
|
|
198
203
|
Slice row_slice;
|
|
199
204
|
int row_slice_length;
|
|
200
205
|
Slice col_slice;
|
|
@@ -227,8 +232,7 @@ void bind_variable_matrix(nb::module_& autodiff,
|
|
|
227
232
|
col_slice_length = 1;
|
|
228
233
|
}
|
|
229
234
|
|
|
230
|
-
return
|
|
231
|
-
self[row_slice, row_slice_length, col_slice, col_slice_length]);
|
|
235
|
+
return self[row_slice, row_slice_length, col_slice, col_slice_length];
|
|
232
236
|
},
|
|
233
237
|
nb::keep_alive<0, 1>(), "slices"_a,
|
|
234
238
|
DOC(slp, VariableMatrix, operator, array));
|
|
@@ -237,43 +241,46 @@ void bind_variable_matrix(nb::module_& autodiff,
|
|
|
237
241
|
cls.def("col", nb::overload_cast<int>(&VariableMatrix<double>::col), "col"_a,
|
|
238
242
|
DOC(slp, VariableMatrix, col));
|
|
239
243
|
|
|
240
|
-
// Matrix-matrix multiplication
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
244
|
+
// Matrix-matrix multiplication. Products with a VariableBlock on the left are
|
|
245
|
+
// bound on VariableBlock.
|
|
246
|
+
for (const char* name : {"__mul__", "__matmul__"}) {
|
|
247
|
+
cls.def(
|
|
248
|
+
name,
|
|
249
|
+
[](const VariableMatrix<double>& lhs,
|
|
250
|
+
const VariableMatrix<double>& rhs) { return lhs * rhs; },
|
|
251
|
+
nb::is_operator(), "rhs"_a);
|
|
252
|
+
cls.def(
|
|
253
|
+
name,
|
|
254
|
+
[](const VariableMatrix<double>& lhs,
|
|
255
|
+
const VariableBlock<VariableMatrix<double>>& rhs) {
|
|
256
|
+
return lhs * rhs;
|
|
257
|
+
},
|
|
258
|
+
nb::is_operator(), "rhs"_a);
|
|
259
|
+
}
|
|
260
|
+
for (const char* name : {"__rmul__", "__rmatmul__"}) {
|
|
261
|
+
cls.def(
|
|
262
|
+
name,
|
|
263
|
+
[](const VariableMatrix<double>& rhs,
|
|
264
|
+
const VariableBlock<VariableMatrix<double>>& lhs) {
|
|
265
|
+
return lhs * rhs;
|
|
266
|
+
},
|
|
267
|
+
nb::is_operator(), "lhs"_a);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// Matrix multiplication with NumPy arrays. These are also handled by
|
|
271
|
+
// __array_ufunc__ below, but type checkers only see these overloads.
|
|
247
272
|
cls.def(
|
|
248
|
-
"
|
|
249
|
-
[](const VariableMatrix<double>& lhs,
|
|
250
|
-
const VariableBlock<VariableMatrix<double>>& rhs) {
|
|
273
|
+
"__matmul__",
|
|
274
|
+
[](const VariableMatrix<double>& lhs, nb::DRef<Eigen::MatrixXd> rhs) {
|
|
251
275
|
return lhs * rhs;
|
|
252
276
|
},
|
|
253
277
|
nb::is_operator(), "rhs"_a);
|
|
254
278
|
cls.def(
|
|
255
|
-
"
|
|
256
|
-
[](const VariableMatrix<double>& rhs,
|
|
257
|
-
const VariableBlock<VariableMatrix<double>>& lhs) {
|
|
279
|
+
"__rmatmul__",
|
|
280
|
+
[](const VariableMatrix<double>& rhs, nb::DRef<Eigen::MatrixXd> lhs) {
|
|
258
281
|
return lhs * rhs;
|
|
259
282
|
},
|
|
260
283
|
nb::is_operator(), "lhs"_a);
|
|
261
|
-
cls.def(
|
|
262
|
-
"__mul__",
|
|
263
|
-
[](const VariableBlock<VariableMatrix<double>>& lhs,
|
|
264
|
-
const VariableBlock<VariableMatrix<double>>& rhs) {
|
|
265
|
-
return lhs * rhs;
|
|
266
|
-
},
|
|
267
|
-
nb::is_operator(), "rhs"_a);
|
|
268
|
-
for_each_type<VariableMatrix<double>, VariableBlock<VariableMatrix<double>>>(
|
|
269
|
-
[&]<typename L> {
|
|
270
|
-
for_each_type<VariableMatrix<double>,
|
|
271
|
-
VariableBlock<VariableMatrix<double>>>([&]<typename R> {
|
|
272
|
-
cls.def(
|
|
273
|
-
"__matmul__", [](L&& lhs, R&& rhs) { return lhs * rhs; },
|
|
274
|
-
nb::is_operator(), "rhs"_a);
|
|
275
|
-
});
|
|
276
|
-
});
|
|
277
284
|
|
|
278
285
|
// https://numpy.org/doc/stable/user/basics.dispatch.html
|
|
279
286
|
cls.def(
|
|
@@ -21,6 +21,23 @@
|
|
|
21
21
|
|
|
22
22
|
namespace nb = nanobind;
|
|
23
23
|
|
|
24
|
+
namespace nanobind::detail {
|
|
25
|
+
|
|
26
|
+
// nanobind's duration caster accepts a float in seconds as well as a
|
|
27
|
+
// timedelta, but its type annotation only advertises timedelta because float is
|
|
28
|
+
// an implicit conversion. Advertise float in the stub's input type so mypy
|
|
29
|
+
// accepts passing a float to the dt parameter of OCP's constructor,
|
|
30
|
+
// set_min_timestep(), and set_max_timestep().
|
|
31
|
+
template <>
|
|
32
|
+
class type_caster<std::chrono::duration<double>>
|
|
33
|
+
: public duration_caster<std::chrono::duration<double>> {
|
|
34
|
+
public:
|
|
35
|
+
static constexpr auto Name =
|
|
36
|
+
io_name("datetime.timedelta | float", "datetime.timedelta");
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
} // namespace nanobind::detail
|
|
40
|
+
|
|
24
41
|
namespace slp {
|
|
25
42
|
|
|
26
43
|
void bind_ocp(nb::class_<OCP<double>, Problem<double>>& cls) {
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// Copyright (c) Sleipnir contributors
|
|
2
|
+
|
|
3
|
+
#pragma once
|
|
4
|
+
|
|
5
|
+
#include <nanobind/nanobind.h>
|
|
6
|
+
#include <nanobind/stl/variant.h>
|
|
7
|
+
|
|
8
|
+
#include <variant>
|
|
9
|
+
|
|
10
|
+
namespace nb = nanobind;
|
|
11
|
+
|
|
12
|
+
namespace slp {
|
|
13
|
+
|
|
14
|
+
/// A 2D index of the form (row, col) where each element is an int or a slice.
|
|
15
|
+
///
|
|
16
|
+
/// The element types only affect the generated type stubs; the tuple's contents
|
|
17
|
+
/// are checked at runtime.
|
|
18
|
+
using SliceTuple = nb::typed<nb::tuple, std::variant<int, nb::slice>,
|
|
19
|
+
std::variant<int, nb::slice>>;
|
|
20
|
+
|
|
21
|
+
} // namespace slp
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
Fixes up type stubs generated by nanobind's stubgen.
|
|
5
|
+
|
|
6
|
+
stubgen can't express some things the bindings support at runtime:
|
|
7
|
+
|
|
8
|
+
1. VariableBlock implicitly converts to VariableMatrix, so every VariableMatrix
|
|
9
|
+
parameter also accepts a VariableBlock. Return types and callback arguments
|
|
10
|
+
are left alone since those are always VariableMatrix.
|
|
11
|
+
2. Sparse matrices are annotated as scipy.sparse.csc_matrix[float], but
|
|
12
|
+
scipy-stubs expects a NumPy numeric scalar type argument.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
import argparse
|
|
16
|
+
import ast
|
|
17
|
+
import re
|
|
18
|
+
from pathlib import Path
|
|
19
|
+
|
|
20
|
+
PREFIX = r"(?:sleipnir\._sleipnir\.autodiff\.)?"
|
|
21
|
+
|
|
22
|
+
# VariableMatrix, optionally module-qualified. The lookahead prevents
|
|
23
|
+
# already-widened annotations from matching again.
|
|
24
|
+
#
|
|
25
|
+
# x: VariableMatrix | None
|
|
26
|
+
# -> x: VariableMatrix | VariableBlock | None
|
|
27
|
+
VARIABLE_MATRIX = re.compile(
|
|
28
|
+
rf"""
|
|
29
|
+
(?<![\w.]) # Not part of another name
|
|
30
|
+
({PREFIX}) # Optional module prefix
|
|
31
|
+
VariableMatrix\b # Type name
|
|
32
|
+
(?!\ \|\ {PREFIX}VariableBlock\b) # Not already widened
|
|
33
|
+
""",
|
|
34
|
+
re.VERBOSE,
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def is_callable(annotation: ast.expr) -> bool:
|
|
39
|
+
"""Returns True if an annotation contains a Callable type."""
|
|
40
|
+
return any(
|
|
41
|
+
(isinstance(node, ast.Name) and node.id == "Callable")
|
|
42
|
+
or (isinstance(node, ast.Attribute) and node.attr == "Callable")
|
|
43
|
+
for node in ast.walk(annotation)
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def parameters(node: ast.FunctionDef) -> list[ast.arg | None]:
|
|
48
|
+
"""Returns a function's parameters in signature order."""
|
|
49
|
+
args = node.args
|
|
50
|
+
return [
|
|
51
|
+
*args.posonlyargs,
|
|
52
|
+
None, # Separates positional-only parameters from the rest
|
|
53
|
+
*args.args,
|
|
54
|
+
args.vararg,
|
|
55
|
+
*args.kwonlyargs,
|
|
56
|
+
args.kwarg,
|
|
57
|
+
]
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def signature(node: ast.FunctionDef) -> list[str | None]:
|
|
61
|
+
"""Returns a function's parameter annotations as source strings."""
|
|
62
|
+
return [
|
|
63
|
+
None if arg is None or arg.annotation is None else ast.unparse(arg.annotation)
|
|
64
|
+
for arg in parameters(node)
|
|
65
|
+
]
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def widen_signatures(stub: str) -> str:
|
|
69
|
+
"""
|
|
70
|
+
Widens every VariableMatrix in function parameter annotations to
|
|
71
|
+
VariableMatrix | VariableBlock.
|
|
72
|
+
|
|
73
|
+
A parameter isn't widened if a sibling overload is identical except it
|
|
74
|
+
takes VariableBlock there; widening it would make that overload
|
|
75
|
+
unreachable.
|
|
76
|
+
"""
|
|
77
|
+
# Group overloads by name within each module or class body
|
|
78
|
+
overload_sets: dict[tuple[int, str], list[ast.FunctionDef]] = {}
|
|
79
|
+
for node in ast.walk(ast.parse(stub)):
|
|
80
|
+
for child in getattr(node, "body", []):
|
|
81
|
+
if isinstance(child, ast.FunctionDef):
|
|
82
|
+
overload_sets.setdefault((id(node), child.name), []).append(child)
|
|
83
|
+
|
|
84
|
+
annotations = []
|
|
85
|
+
for overloads in overload_sets.values():
|
|
86
|
+
signatures = [signature(overload) for overload in overloads]
|
|
87
|
+
for overload, sig in zip(overloads, signatures):
|
|
88
|
+
for i, arg in enumerate(parameters(overload)):
|
|
89
|
+
# Callbacks receive VariableMatrix, so their annotations are
|
|
90
|
+
# left alone
|
|
91
|
+
if arg is None or arg.annotation is None or is_callable(arg.annotation):
|
|
92
|
+
continue
|
|
93
|
+
|
|
94
|
+
# Skip if a sibling overload already takes VariableBlock here
|
|
95
|
+
block_sig = sig.copy()
|
|
96
|
+
block_sig[i] = VARIABLE_MATRIX.sub(
|
|
97
|
+
r"\1VariableBlock", ast.unparse(arg.annotation)
|
|
98
|
+
)
|
|
99
|
+
if block_sig != sig and block_sig in signatures:
|
|
100
|
+
continue
|
|
101
|
+
|
|
102
|
+
annotations.append(arg.annotation)
|
|
103
|
+
|
|
104
|
+
# Encode stub string into UTF-8 bytes
|
|
105
|
+
source_bytes = stub.encode()
|
|
106
|
+
|
|
107
|
+
# Compute byte offsets of each source line
|
|
108
|
+
line_byte_offsets = [0]
|
|
109
|
+
for line in source_bytes.splitlines(keepends=True):
|
|
110
|
+
line_byte_offsets.append(line_byte_offsets[-1] + len(line))
|
|
111
|
+
|
|
112
|
+
# Edit back to front so earlier offsets stay valid
|
|
113
|
+
for annotation in sorted(
|
|
114
|
+
annotations, key=lambda node: (node.lineno, node.col_offset), reverse=True
|
|
115
|
+
):
|
|
116
|
+
# Assertions to satisfy mypy. They can't fail in practice because
|
|
117
|
+
# ast.parse() always sets those fields.
|
|
118
|
+
assert annotation.end_lineno is not None
|
|
119
|
+
assert annotation.end_col_offset is not None
|
|
120
|
+
|
|
121
|
+
# Compute annotation's byte offsets relative to start of file
|
|
122
|
+
start = line_byte_offsets[annotation.lineno - 1] + annotation.col_offset
|
|
123
|
+
end = line_byte_offsets[annotation.end_lineno - 1] + annotation.end_col_offset
|
|
124
|
+
|
|
125
|
+
# Splice widened type annotations into source_bytes
|
|
126
|
+
#
|
|
127
|
+
# \1 is "sleipnir._sleipnir.autodiff." prefix or empty
|
|
128
|
+
widened = VARIABLE_MATRIX.sub(
|
|
129
|
+
r"\1VariableMatrix | \1VariableBlock", source_bytes[start:end].decode()
|
|
130
|
+
)
|
|
131
|
+
source_bytes = source_bytes[:start] + widened.encode() + source_bytes[end:]
|
|
132
|
+
return source_bytes.decode()
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def fix_sparse_matrices(stub: str) -> str:
|
|
136
|
+
"""
|
|
137
|
+
Replaces scipy.sparse.csc_matrix[float] with
|
|
138
|
+
scipy.sparse.csc_matrix[numpy.float64], since scipy-stubs requires a NumPy
|
|
139
|
+
numeric scalar type argument.
|
|
140
|
+
"""
|
|
141
|
+
return stub.replace(
|
|
142
|
+
"scipy.sparse.csc_matrix[float]", "scipy.sparse.csc_matrix[numpy.float64]"
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def main() -> None:
|
|
147
|
+
parser = argparse.ArgumentParser(
|
|
148
|
+
description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter
|
|
149
|
+
)
|
|
150
|
+
parser.add_argument(
|
|
151
|
+
"stubs",
|
|
152
|
+
nargs="+",
|
|
153
|
+
type=Path,
|
|
154
|
+
help="stub files (.pyi) to fix up in place",
|
|
155
|
+
)
|
|
156
|
+
args = parser.parse_args()
|
|
157
|
+
|
|
158
|
+
for path in args.stubs:
|
|
159
|
+
stub = path.read_text(encoding="utf-8")
|
|
160
|
+
stub = widen_signatures(stub)
|
|
161
|
+
stub = fix_sparse_matrices(stub)
|
|
162
|
+
path.write_text(stub, encoding="utf-8")
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
if __name__ == "__main__":
|
|
166
|
+
main()
|