openscvx 0.5.2.dev12__tar.gz → 0.5.2.dev13__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.
- {openscvx-0.5.2.dev12/openscvx.egg-info → openscvx-0.5.2.dev13}/PKG-INFO +1 -1
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/docs/UnderTheHood/lowering_architecture.md +2 -2
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/_version.py +3 -3
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/solvers/moreau_ptr_solver.py +140 -44
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/solvers/ptr_solver.py +47 -1
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/solvers/qpax_ptr_solver.py +182 -64
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13/openscvx.egg-info}/PKG-INFO +1 -1
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/tests/solvers/test_moreau_ptr_solver.py +1 -1
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/tests/solvers/test_qpax_ptr_solver.py +1 -1
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/tests/test_impulsive.py +112 -16
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/.github/assets/logo.svg +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/.github/release-drafter.yml +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/.github/workflows/_docs.yml +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/.github/workflows/branch-name.yml +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/.github/workflows/docs.yml +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/.github/workflows/lint.yml +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/.github/workflows/nightly.yml +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/.github/workflows/release-drafter.yml +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/.github/workflows/release.yml +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/.github/workflows/tests-integration.yml +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/.github/workflows/tests-unit.yml +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/.gitignore +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/.gitmodules +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/CONTRIBUTING.md +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/LICENSE +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/README.md +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/docs/Foundations/constraint_reformulation.md +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/docs/Foundations/control_parameterization.md +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/docs/Foundations/discretization.md +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/docs/Foundations/ocp.md +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/docs/Foundations/scvx.md +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/docs/Foundations/time_dilation.md +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/docs/UnderTheHood/vectorization_and_vmapping.md +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/docs/UsersGuide/00_introduction.md +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/docs/UsersGuide/01_hello_world_brachistochrone.md +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/docs/UsersGuide/02_drone_racing_constraints.md +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/docs/UsersGuide/03_obstacle_avoidance_vmap.md +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/docs/UsersGuide/04_viewpoint_constraints.md +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/docs/UsersGuide/05_visualization.md +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/docs/UsersGuide/06_logic.md +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/docs/UsersGuide/07_lie.md +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/docs/UsersGuide/08_mpcc.md +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/docs/assets/favicon.png +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/docs/assets/images/ct-scvx_dark.png +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/docs/assets/images/ct-scvx_light.png +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/docs/assets/images/ctcs_dark.png +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/docs/assets/images/ctcs_light.png +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/docs/assets/images/problem_class_dark.png +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/docs/assets/images/problem_class_light.png +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/docs/assets/logo.svg +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/docs/assets/openscvx_logo_square.png +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/docs/assets/viser-client/index.html +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/docs/assets/viser-recordings/drone_racing.viser +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/docs/assets/viser-recordings/franka_fr3v2_pick_place.viser +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/docs/citation.md +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/docs/examples.md +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/docs/index.md +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/docs/javascripts/mathjax.js +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/docs/versions.json +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/examples/_viser_embed_export.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/examples/abstract/brachistochrone.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/examples/abstract/hypersensitive.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/examples/abstract/impulsive.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/examples/abstract/stl_integer_variable.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/examples/abstract/stl_or.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/examples/animations/7_dof_arm.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/examples/animations/_camera.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/examples/animations/_render.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/examples/animations/_sensor_view.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/examples/animations/dr_vp_polytope.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/examples/animations/franka_fr3v2_pick_place.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/examples/animations/logo.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/examples/animations/obstacle_avoidance_vmap.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/examples/arm/3_dof_arm.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/examples/arm/7_dof_arm.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/examples/arm/7_dof_arm_collision.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/examples/arm/7_dof_arm_vp.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/examples/arm/franka_fr3v2_pick_place.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/examples/arm/franka_fr3v2_viewplanning.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/examples/car/dubins_car.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/examples/car/dubins_car_disjoint.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/examples/car/dubins_car_obstacle_conditional.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/examples/car/dubins_car_obstacle_stl.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/examples/car/dubins_car_stl_or.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/examples/car/dubins_car_waypoint_stl.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/examples/drone/cinema_vp.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/examples/drone/dr_double_integrator.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/examples/drone/dr_vp.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/examples/drone/dr_vp_nodal.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/examples/drone/dr_vp_polytope.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/examples/drone/drone_racing.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/examples/drone/logo.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/examples/drone/logo_utils/acl_logo.svg +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/examples/drone/logo_utils/svg_path_utils.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/examples/drone/obstacle_avoidance.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/examples/drone/obstacle_avoidance_nodal.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/examples/drone/obstacle_avoidance_vmap.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/examples/mjx/cartpole_mjx.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/examples/mjx/double_cartpole_mjx.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/examples/mjx/skydio_x2_mjx.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/examples/mjx/triple_cartpole_3d_mjx.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/examples/mjx/triple_cartpole_game.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/examples/mjx/triple_cartpole_mjx.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/examples/mpc/double_integrator_discrete.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/examples/mpc/double_integrator_drone_racing.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/examples/mpc/dubins_car_circle_analytical.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/examples/mpc/dubins_car_circle_discrete.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/examples/mpc/realtime_double_integrator_drone_racing.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/examples/plotting.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/examples/plotting_viser.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/examples/realtime/3DoF_pdg_realtime.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/examples/realtime/6DoF_pdg_realtime.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/examples/realtime/base_problems/3DoF_pdg_realtime_base.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/examples/realtime/base_problems/6DoF_pdg_realtime_base.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/examples/realtime/base_problems/cinema_vp_realtime_base.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/examples/realtime/base_problems/drone_racing_realtime_base.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/examples/realtime/base_problems/dubins_car_realtime_base.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/examples/realtime/base_problems/obstacle_avoidance_realtime_base.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/examples/realtime/cinema_vp_realtime.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/examples/realtime/drone_racing_realtime.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/examples/realtime/dubins_car_realtime.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/examples/realtime/obstacle_avoidance_realtime.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/examples/rocket/3DoF_pdg.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/examples/rocket/6DoF_pdg.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/examples/spacecraft/halo_orbit.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/examples/spacecraft/hohmann_transfer.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/examples/spacecraft/let_transfer.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/examples/spacecraft/proxops_cw.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/figures/ctlos_cine.gif +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/figures/ctlos_dr.gif +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/figures/dtlos_cine.gif +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/figures/dtlos_dr.gif +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/figures/openscvx_logo.svg +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/figures/openscvx_logo_square.png +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/figures/oscvx_structure_full_dark.svg +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/figures/video_preview.png +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/material/__init__.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/material/overrides/assets/stylesheets/custom.css +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/material/overrides/assets/stylesheets/home-dropin.css +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/material/overrides/assets/stylesheets/home-hero.css +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/material/overrides/assets/stylesheets/home-viser.css +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/material/overrides/home.html +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/material/overrides/main.html +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/material/overrides/partials/home-diagram.html +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/material/overrides/partials/home-dropin-banner.html +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/material/overrides/partials/home-hero.html +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/material/overrides/partials/home-pipeline.html +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/material/overrides/partials/home-viser-strip.html +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/mkdocs.yml +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/__init__.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/__main__.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/algorithms/__init__.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/algorithms/autotuner/__init__.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/algorithms/autotuner/adaptive_proximal_weight.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/algorithms/autotuner/augmented_lagrangian.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/algorithms/autotuner/constant_proximal_weight.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/algorithms/autotuner/ramp_proximal_weight.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/algorithms/base.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/algorithms/optimization_results.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/algorithms/scvx/__init__.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/algorithms/scvx/penalized_trust_region.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/algorithms/weights.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/config.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/discretization/__init__.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/discretization/base.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/discretization/discretize_linearize.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/discretization/linearize_discretize.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/discretization/linearize_discretize_sparse.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/discretization/sparse_utils/__init__.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/discretization/sparse_utils/bcoo_helpers.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/discretization/sparse_utils/sparse_jacobian.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/expert/__init__.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/expert/byof.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/expert/lowering.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/expert/validation.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/init/__init__.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/init/interpolation.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/init/inverse_kinematics.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/integrations/__init__.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/integrations/base.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/integrations/menagerie.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/integrations/mjx.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/integrators/__init__.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/integrators/diffrax.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/integrators/runge_kutta.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/loader.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/lowered/__init__.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/lowered/cvxpy_constraints.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/lowered/cvxpy_variables.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/lowered/dynamics.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/lowered/jax_constraints.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/lowered/parameters.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/lowered/problem.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/lowered/unified.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/plotting/__init__.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/plotting/plotting.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/plotting/scp_iteration.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/plotting/viser/__init__.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/plotting/viser/animated.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/plotting/viser/orbits.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/plotting/viser/plotly_integration.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/plotting/viser/primitives.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/plotting/viser/scp.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/plotting/viser/server.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/problem.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/propagation/__init__.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/propagation/post_processing.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/propagation/propagation.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/solvers/__init__.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/solvers/base.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/solvers/cvxpy_ptr_solver.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/symbolic/__init__.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/symbolic/augmentation.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/symbolic/builder.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/symbolic/constraint_set.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/symbolic/expr/__init__.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/symbolic/expr/arithmetic.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/symbolic/expr/array.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/symbolic/expr/constraint.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/symbolic/expr/control.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/symbolic/expr/expr.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/symbolic/expr/lie/__init__.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/symbolic/expr/lie/adjoint.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/symbolic/expr/lie/se3.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/symbolic/expr/lie/so3.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/symbolic/expr/linalg.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/symbolic/expr/logic.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/symbolic/expr/math.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/symbolic/expr/parameter.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/symbolic/expr/spatial.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/symbolic/expr/state.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/symbolic/expr/stl.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/symbolic/expr/stljax.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/symbolic/expr/time.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/symbolic/expr/variable.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/symbolic/expr/vmap.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/symbolic/hashing.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/symbolic/lower.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/symbolic/lowerers/__init__.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/symbolic/lowerers/cvxpy/__init__.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/symbolic/lowerers/cvxpy/_lowerer.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/symbolic/lowerers/cvxpy/_registry.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/symbolic/lowerers/cvxpy/arithmetic.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/symbolic/lowerers/cvxpy/array.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/symbolic/lowerers/cvxpy/constraint.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/symbolic/lowerers/cvxpy/control.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/symbolic/lowerers/cvxpy/expr.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/symbolic/lowerers/cvxpy/linalg.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/symbolic/lowerers/cvxpy/logic.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/symbolic/lowerers/cvxpy/math.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/symbolic/lowerers/cvxpy/state.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/symbolic/lowerers/jax/__init__.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/symbolic/lowerers/jax/_lowerer.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/symbolic/lowerers/jax/_registry.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/symbolic/lowerers/jax/arithmetic.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/symbolic/lowerers/jax/array.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/symbolic/lowerers/jax/constraint.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/symbolic/lowerers/jax/control.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/symbolic/lowerers/jax/expr.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/symbolic/lowerers/jax/lie.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/symbolic/lowerers/jax/linalg.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/symbolic/lowerers/jax/logic.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/symbolic/lowerers/jax/math.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/symbolic/lowerers/jax/spatial.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/symbolic/lowerers/jax/state.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/symbolic/lowerers/jax/stl.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/symbolic/lowerers/jax/stljax.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/symbolic/lowerers/jax/vmap.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/symbolic/parser/__init__.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/symbolic/parser/_registry.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/symbolic/parser/array.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/symbolic/parser/constraint.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/symbolic/parser/lie.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/symbolic/parser/linalg.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/symbolic/parser/logic.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/symbolic/parser/math.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/symbolic/parser/parser.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/symbolic/parser/spatial.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/symbolic/parser/stl.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/symbolic/parser/stljax.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/symbolic/parser/tokenizer.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/symbolic/preprocessing.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/symbolic/problem.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/symbolic/sparsity.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/symbolic/unified.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/utils/__init__.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/utils/cache.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/utils/caching.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/utils/printing.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/utils/profiling.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx/utils/utils.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx.egg-info/SOURCES.txt +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx.egg-info/dependency_links.txt +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx.egg-info/entry_points.txt +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx.egg-info/requires.txt +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/openscvx.egg-info/top_level.txt +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/pyproject.toml +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/scripts/gen_example_pages.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/scripts/gen_ref_pages.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/scripts/mkdocs_copy_viser_client_hook.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/setup.cfg +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/tests/__init__.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/tests/_marks.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/tests/brachistochrone_analytical.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/tests/conftest.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/tests/expr/__init__.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/tests/expr/test_gmsr.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/tests/fixtures/brachistochrone.json +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/tests/fixtures/brachistochrone.yaml +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/tests/hohmann_analytical.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/tests/integrations/__init__.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/tests/integrations/test_mjx.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/tests/integrations/test_mjx_dynamics.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/tests/solvers/__init__.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/tests/symbolic/__init__.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/tests/symbolic/expr/__init__.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/tests/symbolic/expr/test_arithmetic.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/tests/symbolic/expr/test_array.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/tests/symbolic/expr/test_constraint.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/tests/symbolic/expr/test_expr.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/tests/symbolic/expr/test_lie.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/tests/symbolic/expr/test_linalg.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/tests/symbolic/expr/test_logic.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/tests/symbolic/expr/test_math.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/tests/symbolic/expr/test_node_reference.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/tests/symbolic/expr/test_parameters.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/tests/symbolic/expr/test_scaling.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/tests/symbolic/expr/test_spatial.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/tests/symbolic/expr/test_stl.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/tests/symbolic/expr/test_variable.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/tests/symbolic/expr/test_vmap.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/tests/symbolic/parser/__init__.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/tests/symbolic/parser/test_array.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/tests/symbolic/parser/test_constraint.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/tests/symbolic/parser/test_lie.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/tests/symbolic/parser/test_linalg.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/tests/symbolic/parser/test_load.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/tests/symbolic/parser/test_logic.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/tests/symbolic/parser/test_math.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/tests/symbolic/parser/test_parser.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/tests/symbolic/parser/test_spatial.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/tests/symbolic/parser/test_stl.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/tests/symbolic/parser/test_tokenizer.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/tests/symbolic/parser/test_vmap.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/tests/symbolic/test_augmentation.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/tests/symbolic/test_hashing.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/tests/symbolic/test_lower_cvxpy.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/tests/symbolic/test_lower_jax.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/tests/symbolic/test_preprocessing.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/tests/symbolic/test_sparsity.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/tests/symbolic/test_unified.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/tests/test_autotuning.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/tests/test_brachistochrone.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/tests/test_cvxpygen_optional.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/tests/test_discretization.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/tests/test_examples.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/tests/test_expert.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/tests/test_init.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/tests/test_integrators.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/tests/test_loader.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/tests/test_optimization_results.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/tests/test_plotting.py +0 -0
- {openscvx-0.5.2.dev12 → openscvx-0.5.2.dev13}/tests/test_propagation.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: openscvx
|
|
3
|
-
Version: 0.5.2.
|
|
3
|
+
Version: 0.5.2.dev13
|
|
4
4
|
Summary: A general Python-based successive convexification implementation which uses a JAX backend.
|
|
5
5
|
Author-email: Chris Hayner and Griffin Norris <haynec@uw.edu>
|
|
6
6
|
License: Apache Software License
|
|
@@ -168,8 +168,8 @@ of the abstract `PTRSolver` base. Three backends ship today:
|
|
|
168
168
|
| Backend | Class | Selector | Notes |
|
|
169
169
|
|---------|-------|----------|-------|
|
|
170
170
|
| CVXPy (default) | `CVXPyPTRSolver` | `solver={"backend": "cvxpy"}` (default) | DCP graph via CVXPy, dispatched to QOCO / CLARABEL / etc. Supports user `.convex()` constraints, cross-node constraints, CTCS, and impulsive controls. Optional cvxpygen code generation. |
|
|
171
|
-
| QPAX | `QPAXPTRSolver` | `solver={"backend": "qpax"}` | JAX-native QP via `qpax.solve_qp`. Flat `(Q, q, A, b, G, h)` assembly. Supports box / dynamics / CTCS / boundary-Fix; **rejects** user `.convex()
|
|
172
|
-
| Moreau | `MoreauPTRSolver` | `solver={"backend": "moreau"}` | JAX-native conic solver (`moreau.jax.Solver`). Sparse CSR assembly; SOC epigraphs for the L1 / pos PTR penalties (fewer variables and rows than QPAX). Warm-starts between SCP iterations. Same supported subset as QPAX. Paves the way for user `.convex()` SOC support in a follow-up. |
|
|
171
|
+
| QPAX | `QPAXPTRSolver` | `solver={"backend": "qpax"}` | JAX-native QP via `qpax.solve_qp`. Flat `(Q, q, A, b, G, h)` assembly. Supports box / dynamics (continuous and impulsive) / CTCS / boundary-Fix; **rejects** user `.convex()` and cross-node at `initialize()` with a clear "use `CVXPyPTRSolver`" message. Enables a path toward an end-to-end JAX-differentiable SCP loop in follow-up work. |
|
|
172
|
+
| Moreau | `MoreauPTRSolver` | `solver={"backend": "moreau"}` | JAX-native conic solver (`moreau.jax.Solver`). Sparse CSR assembly; SOC epigraphs for the L1 / pos PTR penalties (fewer variables and rows than QPAX). Warm-starts between SCP iterations. Same supported subset as QPAX (continuous and impulsive dynamics). Paves the way for user `.convex()` SOC support in a follow-up. |
|
|
173
173
|
|
|
174
174
|
Picking a backend at construction time:
|
|
175
175
|
|
|
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
|
|
|
18
18
|
commit_id: str | None
|
|
19
19
|
__commit_id__: str | None
|
|
20
20
|
|
|
21
|
-
__version__ = version = '0.5.2.
|
|
22
|
-
__version_tuple__ = version_tuple = (0, 5, 2, '
|
|
21
|
+
__version__ = version = '0.5.2.dev13'
|
|
22
|
+
__version_tuple__ = version_tuple = (0, 5, 2, 'dev13')
|
|
23
23
|
|
|
24
|
-
__commit_id__ = commit_id = '
|
|
24
|
+
__commit_id__ = commit_id = 'ga445685bf'
|
|
@@ -22,8 +22,15 @@ in ``jit``, ``jax.grad`` / ``jax.vmap`` can reach through a full SCvx solve
|
|
|
22
22
|
Scope:
|
|
23
23
|
* No user ``.convex()`` constraints — rejected upstream by
|
|
24
24
|
:meth:`ConvexSolver.lower_convex_constraints`.
|
|
25
|
-
* No cross-node
|
|
26
|
-
:
|
|
25
|
+
* No cross-node constraints — raises :class:`NotImplementedError` at
|
|
26
|
+
:meth:`MoreauPTRSolver.initialize`.
|
|
27
|
+
* Impulsive controls (``parameterization="impulsive"``) are supported.
|
|
28
|
+
``D_d`` is absorbed numerically into ``A_d / B_d / C_d`` at update
|
|
29
|
+
time and ``E_d`` enters the dynamics row on the impulsive control
|
|
30
|
+
slice; the initial Fix boundary condition picks up the linearized
|
|
31
|
+
impulse at node 0. The static CSR pattern reserves the
|
|
32
|
+
``du[0, slice_imp]`` columns in the initial-Fix rows so warm-start
|
|
33
|
+
structure stays valid across iterations.
|
|
27
34
|
* CTCS constraints are supported; LICQ-style absolute-value inequalities
|
|
28
35
|
are affine and fit in the nonneg cone.
|
|
29
36
|
|
|
@@ -75,6 +82,7 @@ if TYPE_CHECKING:
|
|
|
75
82
|
from openscvx.lowered import LoweredProblem
|
|
76
83
|
from openscvx.lowered.jax_constraints import LoweredJaxConstraints
|
|
77
84
|
from openscvx.lowered.unified import UnifiedControl, UnifiedState
|
|
85
|
+
from openscvx.symbolic.constraint_set import ConstraintSet
|
|
78
86
|
|
|
79
87
|
# Tiny diagonal regularisation added to P on dx/du slots. Moreau's IPM
|
|
80
88
|
# Cholesky factors (P + Gᵀ diag(z/s) G); keeping the diagonal positive avoids
|
|
@@ -218,12 +226,12 @@ class MoreauPTRSolver(PTRSolver):
|
|
|
218
226
|
SOCP support in a follow-up.
|
|
219
227
|
|
|
220
228
|
Scope:
|
|
221
|
-
Supported — state/control box, dynamics linearization
|
|
222
|
-
uniform time grid, linearized nodal
|
|
229
|
+
Supported — state/control box, dynamics linearization (continuous
|
|
230
|
+
and impulsive), boundary Fix, uniform time grid, linearized nodal
|
|
231
|
+
nonconvex, CTCS LICQ rows.
|
|
223
232
|
|
|
224
|
-
Not supported — user ``.convex()`` constraints
|
|
225
|
-
constraints
|
|
226
|
-
:class:`NotImplementedError` with a "use
|
|
233
|
+
Not supported — user ``.convex()`` constraints and cross-node
|
|
234
|
+
constraints. Each raises :class:`NotImplementedError` with a "use
|
|
227
235
|
:class:`openscvx.solvers.cvxpy_ptr_solver.CVXPyPTRSolver`" pointer.
|
|
228
236
|
|
|
229
237
|
Differentiability hook for future work:
|
|
@@ -274,6 +282,11 @@ class MoreauPTRSolver(PTRSolver):
|
|
|
274
282
|
self._coo_cols: Optional[np.ndarray] = None
|
|
275
283
|
self._n_con: int = 0
|
|
276
284
|
|
|
285
|
+
# Populated by lower_convex_constraints. Auto-augmented impulsive
|
|
286
|
+
# zero-pin constraints land here; any genuine user .convex() trips
|
|
287
|
+
# the default refusal.
|
|
288
|
+
self._impulsive_pins: List[Tuple[List[int], slice]] = []
|
|
289
|
+
|
|
277
290
|
# Per-iteration data, set by update_* methods.
|
|
278
291
|
self._dyn: dict = {}
|
|
279
292
|
self._cons: dict = {}
|
|
@@ -313,23 +326,12 @@ class MoreauPTRSolver(PTRSolver):
|
|
|
313
326
|
jax_constraints: Lowered JAX constraints (nodal structure only).
|
|
314
327
|
dynamics_sparsity: Ignored.
|
|
315
328
|
constraint_sparsity: Ignored.
|
|
316
|
-
|
|
317
|
-
Raises:
|
|
318
|
-
NotImplementedError: If impulsive controls are present.
|
|
319
329
|
"""
|
|
320
330
|
del dynamics_sparsity, constraint_sparsity
|
|
321
331
|
|
|
322
332
|
n_x = len(x_unified.max)
|
|
323
333
|
n_u = len(u_unified.max)
|
|
324
334
|
|
|
325
|
-
slice_imp = u_unified.slice_impulsive
|
|
326
|
-
if slice_imp.stop > slice_imp.start:
|
|
327
|
-
raise NotImplementedError(
|
|
328
|
-
"MoreauPTRSolver does not support impulsive controls "
|
|
329
|
-
f"(u.slice_impulsive = {slice_imp!r}). "
|
|
330
|
-
"Use CVXPyPTRSolver for problems with impulsive dynamics."
|
|
331
|
-
)
|
|
332
|
-
|
|
333
335
|
S_x, c_x = self._scaling(x_unified)
|
|
334
336
|
S_u, c_u = self._scaling(u_unified)
|
|
335
337
|
|
|
@@ -345,6 +347,28 @@ class MoreauPTRSolver(PTRSolver):
|
|
|
345
347
|
self.layout = _ConicLayout(N=N, n_x=n_x, n_u=n_u, n_nodal=len(jax_constraints.nodal))
|
|
346
348
|
self._jax_constraints = jax_constraints
|
|
347
349
|
|
|
350
|
+
def lower_convex_constraints(
|
|
351
|
+
self,
|
|
352
|
+
constraints: "ConstraintSet",
|
|
353
|
+
parameters: Optional[Dict] = None,
|
|
354
|
+
) -> Tuple[List, Dict]:
|
|
355
|
+
"""Absorb auto-generated impulsive zero-pin constraints; refuse the rest.
|
|
356
|
+
|
|
357
|
+
:func:`openscvx.symbolic.lower._augment_impulsive_constraints` injects
|
|
358
|
+
``Control == 0`` equalities at non-impulse nodes for every impulsive
|
|
359
|
+
control. Those constraints live in ``constraints.nodal_convex`` even
|
|
360
|
+
though no user ``.convex()`` was written; we recognize their fixed
|
|
361
|
+
shape and stash a pin list for the structural pass / assembler to
|
|
362
|
+
emit as plain zero-cone rows. Anything that doesn't match the
|
|
363
|
+
auto-augmentation shape (e.g. a genuine user ``.convex()`` SOC) falls
|
|
364
|
+
through to the default refusal in :class:`ConvexSolver`.
|
|
365
|
+
"""
|
|
366
|
+
pins = self._extract_impulsive_pins(constraints)
|
|
367
|
+
if pins is None:
|
|
368
|
+
return super().lower_convex_constraints(constraints, parameters)
|
|
369
|
+
self._impulsive_pins = pins
|
|
370
|
+
return [], {}
|
|
371
|
+
|
|
348
372
|
def initialize(self, lowered: "LoweredProblem", settings: "Config") -> None:
|
|
349
373
|
"""Build the static conic structure and construct ``moreau.jax.Solver``.
|
|
350
374
|
|
|
@@ -359,7 +383,7 @@ class MoreauPTRSolver(PTRSolver):
|
|
|
359
383
|
|
|
360
384
|
Raises:
|
|
361
385
|
RuntimeError: If :meth:`create_variables` was not called first.
|
|
362
|
-
NotImplementedError: If cross-node
|
|
386
|
+
NotImplementedError: If cross-node constraints are present.
|
|
363
387
|
"""
|
|
364
388
|
if self.layout is None:
|
|
365
389
|
raise RuntimeError(
|
|
@@ -373,11 +397,6 @@ class MoreauPTRSolver(PTRSolver):
|
|
|
373
397
|
f"({len(lowered.jax_constraints.cross_node)} defined). "
|
|
374
398
|
"Use CVXPyPTRSolver."
|
|
375
399
|
)
|
|
376
|
-
slice_imp = settings.sim.u.slice_impulsive
|
|
377
|
-
if slice_imp.stop > slice_imp.start:
|
|
378
|
-
raise NotImplementedError(
|
|
379
|
-
"MoreauPTRSolver does not support impulsive controls. Use CVXPyPTRSolver."
|
|
380
|
-
)
|
|
381
400
|
|
|
382
401
|
self._settings = settings
|
|
383
402
|
# Reset warm-start on new initialization (problem structure may change).
|
|
@@ -456,15 +475,42 @@ class MoreauPTRSolver(PTRSolver):
|
|
|
456
475
|
D_d: Optional[np.ndarray] = None,
|
|
457
476
|
E_d: Optional[np.ndarray] = None,
|
|
458
477
|
) -> None:
|
|
459
|
-
|
|
460
|
-
|
|
478
|
+
A_eff = np.asarray(A_d, dtype=float)
|
|
479
|
+
B_eff = np.asarray(B_d, dtype=float)
|
|
480
|
+
C_eff = np.asarray(C_d, dtype=float)
|
|
481
|
+
|
|
482
|
+
# Absorb the impulsive state Jacobian into the continuous step
|
|
483
|
+
# matrices so the assembly row keeps a single A_d·dx + B_d·du term,
|
|
484
|
+
# matching the recipe in CVXPyPTRSolver.update_dynamics_linearization
|
|
485
|
+
# at openscvx/solvers/cvxpy_ptr_solver.py:636-654.
|
|
486
|
+
if D_d is not None:
|
|
487
|
+
D_arr = np.asarray(D_d, dtype=float)
|
|
488
|
+
if D_arr.ndim == 3 and D_arr.shape[0] == A_eff.shape[0] + 1:
|
|
489
|
+
D_steps = D_arr[1:]
|
|
490
|
+
elif D_arr.ndim == 3 and D_arr.shape[0] == A_eff.shape[0]:
|
|
491
|
+
D_steps = D_arr
|
|
492
|
+
else:
|
|
493
|
+
raise ValueError(
|
|
494
|
+
"Unexpected D_d shape for dynamics update: "
|
|
495
|
+
f"{D_arr.shape}, expected "
|
|
496
|
+
f"{(A_eff.shape[0] + 1, A_eff.shape[1], A_eff.shape[2])} "
|
|
497
|
+
f"or {(A_eff.shape[0], A_eff.shape[1], A_eff.shape[2])}."
|
|
498
|
+
)
|
|
499
|
+
A_eff = np.einsum("kij,kjl->kil", D_steps, A_eff)
|
|
500
|
+
B_eff = np.einsum("kij,kjl->kil", D_steps, B_eff)
|
|
501
|
+
C_eff = np.einsum("kij,kjl->kil", D_steps, C_eff)
|
|
502
|
+
|
|
461
503
|
self._dyn = {
|
|
462
504
|
"x_bar": np.asarray(x_bar, dtype=float),
|
|
463
505
|
"u_bar": np.asarray(u_bar, dtype=float),
|
|
464
|
-
"A_d":
|
|
465
|
-
"B_d":
|
|
466
|
-
"C_d":
|
|
506
|
+
"A_d": A_eff,
|
|
507
|
+
"B_d": B_eff,
|
|
508
|
+
"C_d": C_eff,
|
|
467
509
|
"x_prop": np.asarray(x_prop, dtype=float),
|
|
510
|
+
"x_prop_plus": (
|
|
511
|
+
np.asarray(x_prop_plus, dtype=float) if x_prop_plus is not None else None
|
|
512
|
+
),
|
|
513
|
+
"E_d": np.asarray(E_d, dtype=float) if E_d is not None else None,
|
|
468
514
|
}
|
|
469
515
|
|
|
470
516
|
def update_constraint_linearizations(
|
|
@@ -591,15 +637,32 @@ class MoreauPTRSolver(PTRSolver):
|
|
|
591
637
|
add(row, L.nu_vb_idx(c_idx, node))
|
|
592
638
|
row += 1
|
|
593
639
|
|
|
594
|
-
# Fix boundary conditions (initial / terminal)
|
|
640
|
+
# Fix boundary conditions (initial / terminal). Under impulsive
|
|
641
|
+
# control the initial Fix row couples the post-impulse state at
|
|
642
|
+
# node 0 to du[0, slice_imp]; declare those columns structurally
|
|
643
|
+
# nonzero here so the static CSR pattern accommodates the
|
|
644
|
+
# numerical values emitted in _assemble_conic.
|
|
645
|
+
slice_imp = settings.sim.u.slice_impulsive
|
|
646
|
+
has_impulsive = slice_imp.stop > slice_imp.start
|
|
595
647
|
for i in range(settings.sim.true_state_slice.start, settings.sim.true_state_slice.stop):
|
|
596
648
|
if settings.sim.x.initial_type[i] == "Fix":
|
|
597
649
|
add(row, L.x_idx(0, i))
|
|
650
|
+
if has_impulsive:
|
|
651
|
+
for j in range(slice_imp.start, slice_imp.stop):
|
|
652
|
+
add(row, L.du_idx(0, j))
|
|
598
653
|
row += 1
|
|
599
654
|
if settings.sim.x.final_type[i] == "Fix":
|
|
600
655
|
add(row, L.x_idx(N - 1, i))
|
|
601
656
|
row += 1
|
|
602
657
|
|
|
658
|
+
# Impulsive zero-pin equalities: u[node, j] = const, one row per
|
|
659
|
+
# (node, j) absorbed by lower_convex_constraints.
|
|
660
|
+
for nodes, ctrl_slice in self._impulsive_pins:
|
|
661
|
+
for node in nodes:
|
|
662
|
+
for j in range(ctrl_slice.start, ctrl_slice.stop):
|
|
663
|
+
add(row, L.u_idx(node, j))
|
|
664
|
+
row += 1
|
|
665
|
+
|
|
603
666
|
# Uniform time grid: u[k,j] − u[k-1,j] = 0
|
|
604
667
|
if settings.sim._uniform_time_grid:
|
|
605
668
|
td = settings.sim.time_dilation_slice
|
|
@@ -725,8 +788,11 @@ class MoreauPTRSolver(PTRSolver):
|
|
|
725
788
|
inv_S_x = self._inv_S_x_diag
|
|
726
789
|
inv_S_u = self._inv_S_u_diag
|
|
727
790
|
S_x = self._S_x_diag
|
|
791
|
+
S_u = self._S_u_diag
|
|
728
792
|
c_x = self._c_x
|
|
729
793
|
c_u = self._c_u
|
|
794
|
+
slice_imp = settings.sim.u.slice_impulsive
|
|
795
|
+
has_impulsive = slice_imp.stop > slice_imp.start
|
|
730
796
|
|
|
731
797
|
lam_prox = self._pen["lam_prox"] # (N, n_x + n_u)
|
|
732
798
|
lam_cost = self._pen["lam_cost"] # scalar or (n_x,)
|
|
@@ -739,6 +805,8 @@ class MoreauPTRSolver(PTRSolver):
|
|
|
739
805
|
B_d = self._dyn["B_d"] # (N-1, n_x, n_u)
|
|
740
806
|
C_d = self._dyn["C_d"] # (N-1, n_x, n_u)
|
|
741
807
|
x_prop = self._dyn["x_prop"] # (N-1, n_x)
|
|
808
|
+
E_d_arr = self._dyn["E_d"] # (N, n_x, n_u) or None
|
|
809
|
+
x_prop_plus_arr = self._dyn["x_prop_plus"] # (N, n_x) or None
|
|
742
810
|
|
|
743
811
|
lam_cost_arr = np.broadcast_to(lam_cost, (settings.sim.n_states,))
|
|
744
812
|
|
|
@@ -801,15 +869,23 @@ class MoreauPTRSolver(PTRSolver):
|
|
|
801
869
|
for j in range(n_u):
|
|
802
870
|
emit([1.0, -1.0], inv_S_u[j] * (u_bar[k, j] - c_u[j]))
|
|
803
871
|
|
|
804
|
-
# Dynamics (continuous FOH):
|
|
805
|
-
# x[k] − A_blk·dx[k-1] − B_blk·du[k-1] − C_blk·du[k]
|
|
806
|
-
#
|
|
872
|
+
# Dynamics (continuous FOH, with optional impulsive coupling at node k):
|
|
873
|
+
# x[k] − A_blk·dx[k-1] − B_blk·du[k-1] − C_blk·du[k]
|
|
874
|
+
# − E_blk·du[k][slice_imp] − nu[k-1]
|
|
875
|
+
# = inv_S_x·(x_prop_plus[k] − c_x) if has_impulsive
|
|
876
|
+
# = inv_S_x·(x_prop[k-1] − c_x) otherwise
|
|
877
|
+
# Mirrors CVXPyPTRSolver.constraints at cvxpy_ptr_solver.py:506-530.
|
|
807
878
|
for k in range(1, N):
|
|
808
879
|
kp = k - 1
|
|
809
880
|
A_blk = (inv_S_x[:, None] * A_d[kp]) * S_x[None, :]
|
|
810
|
-
B_blk = (inv_S_x[:, None] * B_d[kp]) *
|
|
811
|
-
C_blk = (inv_S_x[:, None] * C_d[kp]) *
|
|
812
|
-
|
|
881
|
+
B_blk = (inv_S_x[:, None] * B_d[kp]) * S_u[None, :]
|
|
882
|
+
C_blk = (inv_S_x[:, None] * C_d[kp]) * S_u[None, :]
|
|
883
|
+
if has_impulsive:
|
|
884
|
+
E_blk = (inv_S_x[:, None] * E_d_arr[k]) * S_u[None, :]
|
|
885
|
+
rhs_k = inv_S_x * (x_prop_plus_arr[k] - c_x)
|
|
886
|
+
else:
|
|
887
|
+
E_blk = None
|
|
888
|
+
rhs_k = inv_S_x * (x_prop[kp] - c_x)
|
|
813
889
|
for i in range(n_x):
|
|
814
890
|
# Coefficients in the same col order as _structural_pass added them,
|
|
815
891
|
# then sorted by scipy within the row — values line up correctly.
|
|
@@ -818,7 +894,10 @@ class MoreauPTRSolver(PTRSolver):
|
|
|
818
894
|
coeffs.append(-A_blk[i, j]) # dx[kp, j]
|
|
819
895
|
for j in range(n_u):
|
|
820
896
|
coeffs.append(-B_blk[i, j]) # du[kp, j]
|
|
821
|
-
|
|
897
|
+
c_kj = -C_blk[i, j]
|
|
898
|
+
if has_impulsive and slice_imp.start <= j < slice_imp.stop:
|
|
899
|
+
c_kj -= E_blk[i, j]
|
|
900
|
+
coeffs.append(c_kj) # du[k, j]
|
|
822
901
|
coeffs.append(-1.0) # nu[kp, i]
|
|
823
902
|
emit(coeffs, rhs_k[i])
|
|
824
903
|
|
|
@@ -839,15 +918,25 @@ class MoreauPTRSolver(PTRSolver):
|
|
|
839
918
|
coeffs.append(-1.0) # nu_vb[c, node]
|
|
840
919
|
emit(coeffs, -g[node])
|
|
841
920
|
|
|
842
|
-
# Fix boundary conditions
|
|
921
|
+
# Fix boundary conditions. Under impulsive control the initial Fix
|
|
922
|
+
# row couples x[0, i] to du[0, slice_imp] via the linearized impulse
|
|
923
|
+
# Jacobian (CVXPy reference: cvxpy_ptr_solver.py:484-495). Emit
|
|
924
|
+
# coefficients in ascending column-index order so they match the
|
|
925
|
+
# CSR sort applied to the structural pass.
|
|
843
926
|
for i in range(settings.sim.true_state_slice.start, settings.sim.true_state_slice.stop):
|
|
844
927
|
if settings.sim.x.initial_type[i] == "Fix":
|
|
845
|
-
if
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
)
|
|
850
|
-
|
|
928
|
+
if has_impulsive:
|
|
929
|
+
coeffs = [S_x[i]]
|
|
930
|
+
for j in range(slice_imp.start, slice_imp.stop):
|
|
931
|
+
coeffs.append(-E_d_arr[0, i, j] * S_u[j])
|
|
932
|
+
emit(coeffs, x_prop_plus_arr[0, i] - c_x[i])
|
|
933
|
+
else:
|
|
934
|
+
if self._x_init is None:
|
|
935
|
+
raise RuntimeError(
|
|
936
|
+
f"Fix initial condition on state {i} requires x_init; "
|
|
937
|
+
"call update_boundary_conditions() before solve()."
|
|
938
|
+
)
|
|
939
|
+
emit([S_x[i]], self._x_init[i] - c_x[i])
|
|
851
940
|
if settings.sim.x.final_type[i] == "Fix":
|
|
852
941
|
if self._x_term is None:
|
|
853
942
|
raise RuntimeError(
|
|
@@ -856,6 +945,13 @@ class MoreauPTRSolver(PTRSolver):
|
|
|
856
945
|
)
|
|
857
946
|
emit([S_x[i]], self._x_term[i] - c_x[i])
|
|
858
947
|
|
|
948
|
+
# Impulsive zero-pin equalities: u[node, j] = −inv_S_u[j]·c_u[j].
|
|
949
|
+
# Mirrors CVXPy's lowering of ``u_nonscaled[node][slice_imp] == 0``.
|
|
950
|
+
for nodes, ctrl_slice in self._impulsive_pins:
|
|
951
|
+
for node in nodes:
|
|
952
|
+
for j in range(ctrl_slice.start, ctrl_slice.stop):
|
|
953
|
+
emit([1.0], -inv_S_u[j] * c_u[j])
|
|
954
|
+
|
|
859
955
|
# Uniform time grid: u[k,j] − u[k-1,j] = 0
|
|
860
956
|
if settings.sim._uniform_time_grid:
|
|
861
957
|
td = settings.sim.time_dilation_slice
|
|
@@ -22,7 +22,7 @@ Backends:
|
|
|
22
22
|
|
|
23
23
|
from abc import abstractmethod
|
|
24
24
|
from dataclasses import dataclass
|
|
25
|
-
from typing import TYPE_CHECKING, List, Tuple, Union
|
|
25
|
+
from typing import TYPE_CHECKING, List, Optional, Tuple, Union
|
|
26
26
|
|
|
27
27
|
import numpy as np
|
|
28
28
|
|
|
@@ -30,6 +30,7 @@ from .base import ConvexSolver
|
|
|
30
30
|
|
|
31
31
|
if TYPE_CHECKING:
|
|
32
32
|
from openscvx.lowered.unified import UnifiedControl, UnifiedState
|
|
33
|
+
from openscvx.symbolic.constraint_set import ConstraintSet
|
|
33
34
|
|
|
34
35
|
|
|
35
36
|
@dataclass
|
|
@@ -174,6 +175,51 @@ class PTRSolver(ConvexSolver):
|
|
|
174
175
|
"""
|
|
175
176
|
raise NotImplementedError
|
|
176
177
|
|
|
178
|
+
@staticmethod
|
|
179
|
+
def _extract_impulsive_pins(
|
|
180
|
+
constraints: "ConstraintSet",
|
|
181
|
+
) -> Optional[List[Tuple[List[int], slice]]]:
|
|
182
|
+
"""Recognize auto-generated impulsive zero-pin constraints.
|
|
183
|
+
|
|
184
|
+
:func:`openscvx.symbolic.lower._augment_impulsive_constraints` injects
|
|
185
|
+
a ``Control == 0`` equality at every non-impulse node for each
|
|
186
|
+
impulsive control. CVXPy lowers these alongside user ``.convex()``
|
|
187
|
+
constraints, but JAX backends that otherwise refuse user
|
|
188
|
+
``.convex()`` constraints still need to honor them.
|
|
189
|
+
|
|
190
|
+
This helper detects that exact shape — a ``NodalConstraint`` wrapping
|
|
191
|
+
``Equality(Control, Constant(0))`` over a list of nodes — and
|
|
192
|
+
returns the implied ``(nodes, slice)`` pin list. If any
|
|
193
|
+
``nodal_convex`` entry doesn't match the auto-augmentation shape,
|
|
194
|
+
returns ``None`` so the caller can fall back to the default
|
|
195
|
+
refusal.
|
|
196
|
+
|
|
197
|
+
Cross-node convex constraints are never produced by the
|
|
198
|
+
auto-augmentation, so any presence aborts recognition.
|
|
199
|
+
"""
|
|
200
|
+
from openscvx.symbolic.expr.constraint import Equality, NodalConstraint
|
|
201
|
+
from openscvx.symbolic.expr.control import Control
|
|
202
|
+
from openscvx.symbolic.expr.expr import Constant
|
|
203
|
+
|
|
204
|
+
if constraints.cross_node_convex:
|
|
205
|
+
return None
|
|
206
|
+
|
|
207
|
+
pins: List[Tuple[List[int], slice]] = []
|
|
208
|
+
for entry in constraints.nodal_convex:
|
|
209
|
+
if not isinstance(entry, NodalConstraint):
|
|
210
|
+
return None
|
|
211
|
+
inner = entry.constraint
|
|
212
|
+
if not isinstance(inner, Equality):
|
|
213
|
+
return None
|
|
214
|
+
rhs = inner.rhs
|
|
215
|
+
if not isinstance(rhs, Constant) or not np.all(np.asarray(rhs.value) == 0):
|
|
216
|
+
return None
|
|
217
|
+
lhs = inner.lhs
|
|
218
|
+
if not isinstance(lhs, Control) or lhs._slice is None:
|
|
219
|
+
return None
|
|
220
|
+
pins.append(([int(k) for k in entry.nodes], lhs._slice))
|
|
221
|
+
return pins
|
|
222
|
+
|
|
177
223
|
@staticmethod
|
|
178
224
|
def _scaling(unified: Union["UnifiedState", "UnifiedControl"]) -> Tuple[np.ndarray, np.ndarray]:
|
|
179
225
|
"""Compute the affine scaling matrices ``(S, c)`` for a unified
|