openscvx 0.5.2.dev13__tar.gz → 0.5.2.dev15__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.dev13/openscvx.egg-info → openscvx-0.5.2.dev15}/PKG-INFO +1 -1
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/docs/UsersGuide/00_introduction.md +1 -0
- openscvx-0.5.2.dev15/docs/UsersGuide/09_mjx_dynamics.md +265 -0
- openscvx-0.5.2.dev15/docs/examples.md +36 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/material/overrides/partials/home-pipeline.html +1 -1
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/mkdocs.yml +1 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/_version.py +3 -3
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/solvers/base.py +97 -6
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/solvers/moreau_ptr_solver.py +58 -7
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/solvers/qpax_ptr_solver.py +26 -7
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15/openscvx.egg-info}/PKG-INFO +1 -1
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx.egg-info/SOURCES.txt +1 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/tests/solvers/test_moreau_ptr_solver.py +75 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/tests/solvers/test_qpax_ptr_solver.py +71 -0
- openscvx-0.5.2.dev13/docs/examples.md +0 -63
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/.github/assets/logo.svg +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/.github/release-drafter.yml +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/.github/workflows/_docs.yml +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/.github/workflows/branch-name.yml +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/.github/workflows/docs.yml +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/.github/workflows/lint.yml +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/.github/workflows/nightly.yml +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/.github/workflows/release-drafter.yml +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/.github/workflows/release.yml +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/.github/workflows/tests-integration.yml +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/.github/workflows/tests-unit.yml +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/.gitignore +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/.gitmodules +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/CONTRIBUTING.md +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/LICENSE +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/README.md +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/docs/Foundations/constraint_reformulation.md +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/docs/Foundations/control_parameterization.md +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/docs/Foundations/discretization.md +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/docs/Foundations/ocp.md +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/docs/Foundations/scvx.md +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/docs/Foundations/time_dilation.md +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/docs/UnderTheHood/lowering_architecture.md +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/docs/UnderTheHood/vectorization_and_vmapping.md +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/docs/UsersGuide/01_hello_world_brachistochrone.md +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/docs/UsersGuide/02_drone_racing_constraints.md +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/docs/UsersGuide/03_obstacle_avoidance_vmap.md +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/docs/UsersGuide/04_viewpoint_constraints.md +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/docs/UsersGuide/05_visualization.md +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/docs/UsersGuide/06_logic.md +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/docs/UsersGuide/07_lie.md +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/docs/UsersGuide/08_mpcc.md +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/docs/assets/favicon.png +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/docs/assets/images/ct-scvx_dark.png +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/docs/assets/images/ct-scvx_light.png +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/docs/assets/images/ctcs_dark.png +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/docs/assets/images/ctcs_light.png +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/docs/assets/images/problem_class_dark.png +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/docs/assets/images/problem_class_light.png +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/docs/assets/logo.svg +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/docs/assets/openscvx_logo_square.png +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/docs/assets/viser-client/index.html +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/docs/assets/viser-recordings/drone_racing.viser +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/docs/assets/viser-recordings/franka_fr3v2_pick_place.viser +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/docs/citation.md +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/docs/index.md +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/docs/javascripts/mathjax.js +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/docs/versions.json +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/examples/_viser_embed_export.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/examples/abstract/brachistochrone.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/examples/abstract/hypersensitive.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/examples/abstract/impulsive.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/examples/abstract/stl_integer_variable.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/examples/abstract/stl_or.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/examples/animations/7_dof_arm.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/examples/animations/_camera.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/examples/animations/_render.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/examples/animations/_sensor_view.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/examples/animations/dr_vp_polytope.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/examples/animations/franka_fr3v2_pick_place.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/examples/animations/logo.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/examples/animations/obstacle_avoidance_vmap.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/examples/arm/3_dof_arm.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/examples/arm/7_dof_arm.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/examples/arm/7_dof_arm_collision.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/examples/arm/7_dof_arm_vp.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/examples/arm/franka_fr3v2_pick_place.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/examples/arm/franka_fr3v2_viewplanning.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/examples/car/dubins_car.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/examples/car/dubins_car_disjoint.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/examples/car/dubins_car_obstacle_conditional.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/examples/car/dubins_car_obstacle_stl.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/examples/car/dubins_car_stl_or.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/examples/car/dubins_car_waypoint_stl.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/examples/drone/cinema_vp.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/examples/drone/dr_double_integrator.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/examples/drone/dr_vp.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/examples/drone/dr_vp_nodal.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/examples/drone/dr_vp_polytope.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/examples/drone/drone_racing.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/examples/drone/logo.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/examples/drone/logo_utils/acl_logo.svg +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/examples/drone/logo_utils/svg_path_utils.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/examples/drone/obstacle_avoidance.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/examples/drone/obstacle_avoidance_nodal.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/examples/drone/obstacle_avoidance_vmap.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/examples/mjx/cartpole_mjx.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/examples/mjx/double_cartpole_mjx.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/examples/mjx/skydio_x2_mjx.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/examples/mjx/triple_cartpole_3d_mjx.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/examples/mjx/triple_cartpole_game.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/examples/mjx/triple_cartpole_mjx.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/examples/mpc/double_integrator_discrete.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/examples/mpc/double_integrator_drone_racing.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/examples/mpc/dubins_car_circle_analytical.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/examples/mpc/dubins_car_circle_discrete.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/examples/mpc/realtime_double_integrator_drone_racing.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/examples/plotting.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/examples/plotting_viser.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/examples/realtime/3DoF_pdg_realtime.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/examples/realtime/6DoF_pdg_realtime.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/examples/realtime/base_problems/3DoF_pdg_realtime_base.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/examples/realtime/base_problems/6DoF_pdg_realtime_base.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/examples/realtime/base_problems/cinema_vp_realtime_base.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/examples/realtime/base_problems/drone_racing_realtime_base.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/examples/realtime/base_problems/dubins_car_realtime_base.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/examples/realtime/base_problems/obstacle_avoidance_realtime_base.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/examples/realtime/cinema_vp_realtime.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/examples/realtime/drone_racing_realtime.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/examples/realtime/dubins_car_realtime.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/examples/realtime/obstacle_avoidance_realtime.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/examples/rocket/3DoF_pdg.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/examples/rocket/6DoF_pdg.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/examples/spacecraft/halo_orbit.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/examples/spacecraft/hohmann_transfer.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/examples/spacecraft/let_transfer.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/examples/spacecraft/proxops_cw.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/figures/ctlos_cine.gif +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/figures/ctlos_dr.gif +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/figures/dtlos_cine.gif +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/figures/dtlos_dr.gif +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/figures/openscvx_logo.svg +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/figures/openscvx_logo_square.png +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/figures/oscvx_structure_full_dark.svg +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/figures/video_preview.png +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/material/__init__.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/material/overrides/assets/stylesheets/custom.css +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/material/overrides/assets/stylesheets/home-dropin.css +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/material/overrides/assets/stylesheets/home-hero.css +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/material/overrides/assets/stylesheets/home-viser.css +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/material/overrides/home.html +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/material/overrides/main.html +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/material/overrides/partials/home-diagram.html +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/material/overrides/partials/home-dropin-banner.html +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/material/overrides/partials/home-hero.html +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/material/overrides/partials/home-viser-strip.html +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/__init__.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/__main__.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/algorithms/__init__.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/algorithms/autotuner/__init__.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/algorithms/autotuner/adaptive_proximal_weight.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/algorithms/autotuner/augmented_lagrangian.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/algorithms/autotuner/constant_proximal_weight.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/algorithms/autotuner/ramp_proximal_weight.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/algorithms/base.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/algorithms/optimization_results.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/algorithms/scvx/__init__.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/algorithms/scvx/penalized_trust_region.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/algorithms/weights.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/config.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/discretization/__init__.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/discretization/base.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/discretization/discretize_linearize.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/discretization/linearize_discretize.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/discretization/linearize_discretize_sparse.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/discretization/sparse_utils/__init__.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/discretization/sparse_utils/bcoo_helpers.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/discretization/sparse_utils/sparse_jacobian.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/expert/__init__.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/expert/byof.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/expert/lowering.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/expert/validation.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/init/__init__.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/init/interpolation.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/init/inverse_kinematics.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/integrations/__init__.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/integrations/base.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/integrations/menagerie.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/integrations/mjx.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/integrators/__init__.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/integrators/diffrax.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/integrators/runge_kutta.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/loader.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/lowered/__init__.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/lowered/cvxpy_constraints.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/lowered/cvxpy_variables.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/lowered/dynamics.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/lowered/jax_constraints.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/lowered/parameters.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/lowered/problem.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/lowered/unified.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/plotting/__init__.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/plotting/plotting.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/plotting/scp_iteration.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/plotting/viser/__init__.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/plotting/viser/animated.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/plotting/viser/orbits.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/plotting/viser/plotly_integration.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/plotting/viser/primitives.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/plotting/viser/scp.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/plotting/viser/server.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/problem.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/propagation/__init__.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/propagation/post_processing.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/propagation/propagation.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/solvers/__init__.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/solvers/cvxpy_ptr_solver.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/solvers/ptr_solver.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/symbolic/__init__.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/symbolic/augmentation.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/symbolic/builder.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/symbolic/constraint_set.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/symbolic/expr/__init__.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/symbolic/expr/arithmetic.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/symbolic/expr/array.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/symbolic/expr/constraint.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/symbolic/expr/control.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/symbolic/expr/expr.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/symbolic/expr/lie/__init__.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/symbolic/expr/lie/adjoint.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/symbolic/expr/lie/se3.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/symbolic/expr/lie/so3.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/symbolic/expr/linalg.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/symbolic/expr/logic.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/symbolic/expr/math.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/symbolic/expr/parameter.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/symbolic/expr/spatial.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/symbolic/expr/state.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/symbolic/expr/stl.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/symbolic/expr/stljax.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/symbolic/expr/time.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/symbolic/expr/variable.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/symbolic/expr/vmap.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/symbolic/hashing.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/symbolic/lower.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/symbolic/lowerers/__init__.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/symbolic/lowerers/cvxpy/__init__.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/symbolic/lowerers/cvxpy/_lowerer.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/symbolic/lowerers/cvxpy/_registry.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/symbolic/lowerers/cvxpy/arithmetic.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/symbolic/lowerers/cvxpy/array.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/symbolic/lowerers/cvxpy/constraint.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/symbolic/lowerers/cvxpy/control.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/symbolic/lowerers/cvxpy/expr.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/symbolic/lowerers/cvxpy/linalg.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/symbolic/lowerers/cvxpy/logic.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/symbolic/lowerers/cvxpy/math.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/symbolic/lowerers/cvxpy/state.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/symbolic/lowerers/jax/__init__.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/symbolic/lowerers/jax/_lowerer.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/symbolic/lowerers/jax/_registry.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/symbolic/lowerers/jax/arithmetic.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/symbolic/lowerers/jax/array.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/symbolic/lowerers/jax/constraint.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/symbolic/lowerers/jax/control.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/symbolic/lowerers/jax/expr.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/symbolic/lowerers/jax/lie.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/symbolic/lowerers/jax/linalg.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/symbolic/lowerers/jax/logic.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/symbolic/lowerers/jax/math.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/symbolic/lowerers/jax/spatial.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/symbolic/lowerers/jax/state.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/symbolic/lowerers/jax/stl.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/symbolic/lowerers/jax/stljax.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/symbolic/lowerers/jax/vmap.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/symbolic/parser/__init__.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/symbolic/parser/_registry.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/symbolic/parser/array.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/symbolic/parser/constraint.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/symbolic/parser/lie.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/symbolic/parser/linalg.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/symbolic/parser/logic.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/symbolic/parser/math.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/symbolic/parser/parser.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/symbolic/parser/spatial.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/symbolic/parser/stl.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/symbolic/parser/stljax.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/symbolic/parser/tokenizer.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/symbolic/preprocessing.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/symbolic/problem.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/symbolic/sparsity.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/symbolic/unified.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/utils/__init__.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/utils/cache.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/utils/caching.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/utils/printing.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/utils/profiling.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx/utils/utils.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx.egg-info/dependency_links.txt +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx.egg-info/entry_points.txt +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx.egg-info/requires.txt +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/openscvx.egg-info/top_level.txt +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/pyproject.toml +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/scripts/gen_example_pages.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/scripts/gen_ref_pages.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/scripts/mkdocs_copy_viser_client_hook.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/setup.cfg +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/tests/__init__.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/tests/_marks.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/tests/brachistochrone_analytical.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/tests/conftest.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/tests/expr/__init__.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/tests/expr/test_gmsr.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/tests/fixtures/brachistochrone.json +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/tests/fixtures/brachistochrone.yaml +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/tests/hohmann_analytical.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/tests/integrations/__init__.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/tests/integrations/test_mjx.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/tests/integrations/test_mjx_dynamics.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/tests/solvers/__init__.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/tests/symbolic/__init__.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/tests/symbolic/expr/__init__.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/tests/symbolic/expr/test_arithmetic.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/tests/symbolic/expr/test_array.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/tests/symbolic/expr/test_constraint.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/tests/symbolic/expr/test_expr.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/tests/symbolic/expr/test_lie.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/tests/symbolic/expr/test_linalg.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/tests/symbolic/expr/test_logic.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/tests/symbolic/expr/test_math.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/tests/symbolic/expr/test_node_reference.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/tests/symbolic/expr/test_parameters.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/tests/symbolic/expr/test_scaling.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/tests/symbolic/expr/test_spatial.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/tests/symbolic/expr/test_stl.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/tests/symbolic/expr/test_variable.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/tests/symbolic/expr/test_vmap.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/tests/symbolic/parser/__init__.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/tests/symbolic/parser/test_array.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/tests/symbolic/parser/test_constraint.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/tests/symbolic/parser/test_lie.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/tests/symbolic/parser/test_linalg.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/tests/symbolic/parser/test_load.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/tests/symbolic/parser/test_logic.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/tests/symbolic/parser/test_math.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/tests/symbolic/parser/test_parser.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/tests/symbolic/parser/test_spatial.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/tests/symbolic/parser/test_stl.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/tests/symbolic/parser/test_tokenizer.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/tests/symbolic/parser/test_vmap.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/tests/symbolic/test_augmentation.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/tests/symbolic/test_hashing.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/tests/symbolic/test_lower_cvxpy.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/tests/symbolic/test_lower_jax.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/tests/symbolic/test_preprocessing.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/tests/symbolic/test_sparsity.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/tests/symbolic/test_unified.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/tests/test_autotuning.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/tests/test_brachistochrone.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/tests/test_cvxpygen_optional.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/tests/test_discretization.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/tests/test_examples.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/tests/test_expert.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/tests/test_impulsive.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/tests/test_init.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/tests/test_integrators.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/tests/test_loader.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/tests/test_optimization_results.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/tests/test_plotting.py +0 -0
- {openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/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.dev15
|
|
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
|
|
@@ -16,6 +16,7 @@ The tutorials are designed to be read in order. Each builds on concepts from the
|
|
|
16
16
|
| [06 Dubin's Car](06_logic.md) | Conditional path planning | Conditional statements, signal temporal logic (STL) |
|
|
17
17
|
| [07 Multi-Link Arms](07_lie.md) | Articulated robot control | Lie algebra, propagated states |
|
|
18
18
|
| [08 Model Predictive Control](08_mpcc.md) | Closed-loop drone racing | Receding horizon control, warm starting, cubic spline interpolation |
|
|
19
|
+
| [09 MuJoCo MJX Dynamics](09_mjx_dynamics.md) | Cartpole swing-up, quadrotor racing | `MjxDynamics`, MuJoCo MJCF, free-joint quaternions, `examples/mjx/` |
|
|
19
20
|
|
|
20
21
|
## Quick Start
|
|
21
22
|
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
# 09 MuJoCo MJX Dynamics
|
|
2
|
+
|
|
3
|
+
In earlier tutorials we wrote dynamics by hand as symbolic expressions. Many real systems already have a MuJoCo model — articulated robots, cartpoles, quadrotors — and re-deriving those equations is tedious and error-prone.
|
|
4
|
+
|
|
5
|
+
This tutorial shows how to plug a **MuJoCo MJX** model directly into OpenSCvx via `ox.MjxDynamics`. We use the cartpole swing-up as the main walkthrough (the same problem as `examples/mjx/cartpole_mjx.py`), then point to richer examples: multi-link cartpoles, 3D triple pendulums, and Skydio X2 gate racing.
|
|
6
|
+
|
|
7
|
+
This tutorial covers:
|
|
8
|
+
|
|
9
|
+
- Installing the optional MJX extra (`openscvx[mjx]`)
|
|
10
|
+
- Loading a MuJoCo model and uploading it to MJX
|
|
11
|
+
- The `MjxDynamics` adapter: states, controls, and `Problem` wiring
|
|
12
|
+
- Contact-free models and why contacts are disabled
|
|
13
|
+
- Free-joint models (`nq > nv`) and automatic quaternion kinematics
|
|
14
|
+
- The full set of MJX examples in `examples/mjx/`
|
|
15
|
+
|
|
16
|
+
!!! tip "Prerequisites"
|
|
17
|
+
You should be comfortable with the core workflow from [Hello Brachistochrone](01_hello_world_brachistochrone.md): `State`, `Control`, `Time`, CTCS constraints, `initialize` / `solve` / `post_process`, and accessing results by variable name.
|
|
18
|
+
|
|
19
|
+
## Installation
|
|
20
|
+
|
|
21
|
+
MJX is an optional dependency. Install OpenSCvx with the MJX extra:
|
|
22
|
+
|
|
23
|
+
```sh
|
|
24
|
+
pip install openscvx[mjx]
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
This pulls in `mujoco` with JAX-backed MJX support. All examples under `examples/mjx/` guard-import MuJoCo and print a clear message if the extra is missing.
|
|
28
|
+
|
|
29
|
+
## Why MJX?
|
|
30
|
+
|
|
31
|
+
[MuJoCo MJX](https://mujoco.readthedocs.io/en/stable/mjx.html) runs the same physics as classic MuJoCo, but on JAX arrays so the forward dynamics are compatible with OpenSCvx's JAX compilation and autodiff pipeline.
|
|
32
|
+
|
|
33
|
+
The integration layer (`openscvx.integrations`) wraps an MJX model as a **dynamics adapter** you pass to `Problem` in the same slot as a symbolic dynamics dict. You still set boundary conditions, costs, and constraints the usual way — only the equations of motion come from MuJoCo.
|
|
34
|
+
|
|
35
|
+
## The Cartpole Swing-Up Problem
|
|
36
|
+
|
|
37
|
+
We optimize a horizontal force on a cart with a passive hinged pole. The goal is to swing the pole from hanging down ($\theta = \pi$) to upright ($\theta = 0$) in minimum time.
|
|
38
|
+
|
|
39
|
+
In MuJoCo coordinates:
|
|
40
|
+
|
|
41
|
+
- **Position** $\mathbf{q} = [x, \theta]^\top$ — cart slide and hinge angle
|
|
42
|
+
- **Velocity** $\dot{\mathbf{q}} = [\dot{x}, \dot{\theta}]^\top$
|
|
43
|
+
- **Control** $u$ — normalized motor command on the slider joint
|
|
44
|
+
|
|
45
|
+
The continuous dynamics $\ddot{\mathbf{q}} = f(\mathbf{q}, \dot{\mathbf{q}}, u)$ are computed by MJX's `forward` pass; OpenSCvx does not require you to write them symbolically.
|
|
46
|
+
|
|
47
|
+
## Loading a MuJoCo Model
|
|
48
|
+
|
|
49
|
+
Examples typically define MJCF inline (self-contained) or load from a file:
|
|
50
|
+
|
|
51
|
+
```python
|
|
52
|
+
import mujoco
|
|
53
|
+
import mujoco.mjx as mjx
|
|
54
|
+
|
|
55
|
+
CARTPOLE_XML = """
|
|
56
|
+
<mujoco model="cartpole">
|
|
57
|
+
<option gravity="0 0 -9.81" timestep="0.01" integrator="Euler"/>
|
|
58
|
+
...
|
|
59
|
+
</mujoco>
|
|
60
|
+
"""
|
|
61
|
+
|
|
62
|
+
mj_model = mujoco.MjModel.from_xml_string(CARTPOLE_XML)
|
|
63
|
+
# For assets on disk: mujoco.MjModel.from_xml_path("cartpole.xml")
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Disable contacts for differentiability
|
|
67
|
+
|
|
68
|
+
MJX's contact solver uses `lax.while_loop`, which is **not** reverse-mode differentiable. For manipulation and locomotion models that do not need contact forces in the optimizer, disable contacts before uploading:
|
|
69
|
+
|
|
70
|
+
```python
|
|
71
|
+
mj_model.opt.disableflags |= mujoco.mjtDisableBit.mjDSBL_CONTACT
|
|
72
|
+
mjx_model = mjx.put_model(mj_model)
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Cartpoles, serial arms without collision, and quadrotors in free flight all fit this pattern. If you need contact-rich dynamics, treat that as an advanced case and consult the lower-level `mjx_dynamics` API in the [reference](../Reference/integrations/mjx.md).
|
|
76
|
+
|
|
77
|
+
After `put_model`, read off dimensions:
|
|
78
|
+
|
|
79
|
+
```python
|
|
80
|
+
n_q = int(mjx_model.nq) # generalized positions
|
|
81
|
+
n_v = int(mjx_model.nv) # generalized velocities
|
|
82
|
+
n_u = int(mjx_model.nu) # actuators
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
For a simple cartpole, `nq == nv == 2` and `nu == 1`.
|
|
86
|
+
|
|
87
|
+
## The `MjxDynamics` Adapter
|
|
88
|
+
|
|
89
|
+
`ox.MjxDynamics(mjx_model)` is the recommended entry point. It:
|
|
90
|
+
|
|
91
|
+
1. Creates default `qpos`, `qvel`, and `ctrl` variables matching `nq`, `nv`, and `nu`
|
|
92
|
+
2. Exposes them on `.states` and `.controls`
|
|
93
|
+
3. Routes MJX forward dynamics through the internal BYOF channel — you do **not** pass `byof=` yourself
|
|
94
|
+
|
|
95
|
+
```python
|
|
96
|
+
import openscvx as ox
|
|
97
|
+
|
|
98
|
+
dyn = ox.MjxDynamics(mjx_model)
|
|
99
|
+
qpos, qvel = dyn.states
|
|
100
|
+
(ctrl,) = dyn.controls
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
`MjxDynamics` also seeds `.min` / `.max` from joint and actuator limits declared in MJCF (`jnt_range`, `actuator_ctrlrange`). Override them for your OCP as needed.
|
|
104
|
+
|
|
105
|
+
### Boundary conditions
|
|
106
|
+
|
|
107
|
+
Set initial and final values on the adapter's states like any other `ox.State`:
|
|
108
|
+
|
|
109
|
+
```python
|
|
110
|
+
qpos.min = np.array([-3.0, -2.0 * np.pi])
|
|
111
|
+
qpos.max = np.array([3.0, 2.0 * np.pi])
|
|
112
|
+
qpos.initial = np.array([0.0, np.pi]) # cart at origin, pole hanging
|
|
113
|
+
qpos.final = np.array([0.0, 0.0]) # upright
|
|
114
|
+
|
|
115
|
+
qvel.initial = np.zeros(2)
|
|
116
|
+
qvel.final = np.zeros(2)
|
|
117
|
+
|
|
118
|
+
ctrl.min = np.array([-1.0])
|
|
119
|
+
ctrl.max = np.array([1.0])
|
|
120
|
+
ctrl.guess = np.zeros((n, 1))
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Use the same boundary-condition syntax as earlier tutorials (`ox.Free`, `ox.Minimize`, tuples, etc.) — see [Hello Brachistochrone](01_hello_world_brachistochrone.md).
|
|
124
|
+
|
|
125
|
+
### Initial guess
|
|
126
|
+
|
|
127
|
+
A good state guess helps underactuated swing-up problems converge:
|
|
128
|
+
|
|
129
|
+
```python
|
|
130
|
+
theta_guess = np.linspace(np.pi, 0.0, n)
|
|
131
|
+
qpos.guess = np.column_stack([np.zeros(n), theta_guess])
|
|
132
|
+
qvel.guess = np.zeros((n, 2))
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### Constraints and time
|
|
136
|
+
|
|
137
|
+
CTCS box constraints follow the same pattern as tutorial 01:
|
|
138
|
+
|
|
139
|
+
```python
|
|
140
|
+
constraints = []
|
|
141
|
+
for state in dyn.states:
|
|
142
|
+
constraints.extend([ox.ctcs(state <= state.max), ox.ctcs(state.min <= state)])
|
|
143
|
+
for control in dyn.controls:
|
|
144
|
+
constraints.extend([ox.ctcs(control <= control.max), ox.ctcs(control.min <= control)])
|
|
145
|
+
|
|
146
|
+
time = ox.Time(
|
|
147
|
+
initial=0.0,
|
|
148
|
+
final=ox.Minimize(total_time),
|
|
149
|
+
min=0.0,
|
|
150
|
+
max=2.0 * total_time,
|
|
151
|
+
)
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### Defining and solving the problem
|
|
155
|
+
|
|
156
|
+
Pass the adapter as `dynamics=` and reuse its states and controls:
|
|
157
|
+
|
|
158
|
+
```python
|
|
159
|
+
problem = ox.Problem(
|
|
160
|
+
dynamics=dyn,
|
|
161
|
+
states=dyn.states,
|
|
162
|
+
controls=dyn.controls,
|
|
163
|
+
time=time,
|
|
164
|
+
constraints=constraints,
|
|
165
|
+
N=n,
|
|
166
|
+
)
|
|
167
|
+
|
|
168
|
+
problem.initialize()
|
|
169
|
+
problem.solve()
|
|
170
|
+
results = problem.post_process()
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
Results are accessed by the same names:
|
|
174
|
+
|
|
175
|
+
```python
|
|
176
|
+
theta_traj = results.trajectory["qpos"][:, 1]
|
|
177
|
+
u_traj = results.trajectory["ctrl"]
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### Run the full example
|
|
181
|
+
|
|
182
|
+
The complete script adds a Viser animation of the cart and pole:
|
|
183
|
+
|
|
184
|
+
```sh
|
|
185
|
+
python examples/mjx/cartpole_mjx.py
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
## How It Works Internally
|
|
189
|
+
|
|
190
|
+
For models with `nq == nv` (no quaternion free joint), `MjxDynamics` sets symbolic kinematics `qpos_dot = qvel` and uses MJX to provide `qvel_dot` (generalized accelerations) from `mjx.forward`.
|
|
191
|
+
|
|
192
|
+
For models with `nq > nv` (a floating base with a quaternion), the adapter inserts quaternion kinematics for `qpos` and MJX accelerations for `qvel`. You do not need to write the $\dot{q}$ equation for the attitude quaternion — that is handled automatically.
|
|
193
|
+
|
|
194
|
+
Supported joint types: **free**, **slide**, and **hinge**. All free joints must appear before slide/hinge joints in the MJCF layout. Ball joints are explicitly rejected with a clear error; use the lower-level `mjx_dynamics` helper if you need them.
|
|
195
|
+
|
|
196
|
+
## Free-Joint Example: Skydio X2 Gate Racing
|
|
197
|
+
|
|
198
|
+
`examples/mjx/skydio_x2_mjx.py` mirrors [Drone Racing](02_drone_racing_constraints.md) but uses a Menagerie (or inline fallback) quadrotor model:
|
|
199
|
+
|
|
200
|
+
- `nq = 7` — position plus unit quaternion `[w, x, y, z]`
|
|
201
|
+
- `nv = 6` — linear and angular velocity
|
|
202
|
+
- `nu = 4` — per-rotor thrusts
|
|
203
|
+
|
|
204
|
+
The problem setup is identical in spirit to tutorial 02: nodal gate constraints with `.at()`, minimum-time objective, loop closure in position. The only change is `dynamics=dyn` instead of a hand-written double-integrator dict.
|
|
205
|
+
|
|
206
|
+
```python
|
|
207
|
+
dyn = ox.MjxDynamics(mjx_model)
|
|
208
|
+
qpos, qvel = dyn.states
|
|
209
|
+
(ctrl,) = dyn.controls
|
|
210
|
+
|
|
211
|
+
# qpos: [x, y, z, qw, qx, qy, qz]
|
|
212
|
+
qpos.initial = np.concatenate([start_pos, hover_quat])
|
|
213
|
+
qpos.final = [10.0, 0.0, 20.0, ("free", 1.0), ("free", 0.0), ("free", 0.0), ("free", 0.0)]
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
Optional: initialize the MuJoCo Menagerie submodule for the textured mesh used in Viser:
|
|
217
|
+
|
|
218
|
+
```sh
|
|
219
|
+
git submodule update --init third_party/mujoco_menagerie
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
## MJX Examples Overview
|
|
223
|
+
|
|
224
|
+
| Example | Description | Highlights |
|
|
225
|
+
|---------|-------------|------------|
|
|
226
|
+
| [`cartpole_mjx`](../Examples/mjx/cartpole_mjx.md) | Single-link swing-up | Minimal `MjxDynamics` workflow, Viser animation |
|
|
227
|
+
| [`double_cartpole_mjx`](../Examples/mjx/double_cartpole_mjx.md) | Two-link cartpole | Underactuated serial links, `ox.Free` terminal cart |
|
|
228
|
+
| [`triple_cartpole_mjx`](../Examples/mjx/triple_cartpole_mjx.md) | Three-link cartpole | Longer horizon, ZOH control parameterization |
|
|
229
|
+
| [`triple_cartpole_3d_mjx`](../Examples/mjx/triple_cartpole_3d_mjx.md) | 3D triple pendulum on a cart | Higher DOF, 3D Viser scene |
|
|
230
|
+
| [`triple_cartpole_game`](../Examples/mjx/triple_cartpole_game.md) | Game-style triple cartpole | Variant with different cost / setup |
|
|
231
|
+
| [`skydio_x2_mjx`](../Examples/mjx/skydio_x2_mjx.md) | Gate racing quadrotor | Free joint, Menagerie model, nodal constraints |
|
|
232
|
+
|
|
233
|
+
All live under `examples/mjx/` and require `pip install openscvx[mjx]`.
|
|
234
|
+
|
|
235
|
+
## Advanced: `mjx_dynamics` and Custom Names
|
|
236
|
+
|
|
237
|
+
If you need custom `State` / `Control` names, extra states alongside MJX, or ball joints, drop to `openscvx.integrations.mjx_dynamics` and assemble `byof` manually:
|
|
238
|
+
|
|
239
|
+
```python
|
|
240
|
+
from openscvx.integrations import mjx_dynamics
|
|
241
|
+
|
|
242
|
+
qpos = ox.State("cart_and_pole", shape=(mjx_model.nq,))
|
|
243
|
+
qvel = ox.State("rates", shape=(mjx_model.nv,))
|
|
244
|
+
ctrl = ox.Control("force", shape=(mjx_model.nu,))
|
|
245
|
+
|
|
246
|
+
qvel_dot = mjx_dynamics(mjx_model, qpos=qpos, qvel=qvel, ctrl=ctrl)
|
|
247
|
+
|
|
248
|
+
problem = ox.Problem(
|
|
249
|
+
dynamics={"cart_and_pole": qvel},
|
|
250
|
+
byof={"dynamics": {"rates": qvel_dot}},
|
|
251
|
+
states=[qpos, qvel],
|
|
252
|
+
controls=[ctrl],
|
|
253
|
+
...
|
|
254
|
+
)
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
See the [API reference](../Reference/integrations/mjx.md) for `return_component`, `extra_postprocess`, and full signatures.
|
|
258
|
+
|
|
259
|
+
## Further Reading
|
|
260
|
+
|
|
261
|
+
- [Complete Cartpole MJX Example](../Examples/mjx/cartpole_mjx.md)
|
|
262
|
+
- [Skydio X2 MJX Gate Racing](../Examples/mjx/skydio_x2_mjx.md)
|
|
263
|
+
- [Drone Racing: Constraints](02_drone_racing_constraints.md) — same gate constraints without MJX
|
|
264
|
+
- [Visualization](05_visualization.md) — Plotly and Viser patterns used in MJX examples
|
|
265
|
+
- [API Reference: `MjxDynamics`](../Reference/integrations/mjx.md)
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Examples
|
|
2
|
+
|
|
3
|
+
OpenSCvx comes with a comprehensive set of examples demonstrating various trajectory optimization problems. These examples are located in the `examples/` folder and cover different applications and complexity levels.
|
|
4
|
+
|
|
5
|
+
## Running Examples
|
|
6
|
+
|
|
7
|
+
See `examples/` folder for several example trajectory optimization problems.
|
|
8
|
+
To run a problem simply run any of the examples directly, for example:
|
|
9
|
+
|
|
10
|
+
```sh
|
|
11
|
+
python3 examples/brachistochrone.py
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
and adjust the plotting as needed (see [Tutorial 05: Visualization](UsersGuide/05_visualization.md)).
|
|
15
|
+
|
|
16
|
+
## Creating Your Own Problems
|
|
17
|
+
|
|
18
|
+
Check out the problem definitions inside `examples/params` to see how to define your own problems. Each example demonstrates:
|
|
19
|
+
|
|
20
|
+
- State and control variable definition
|
|
21
|
+
- Dynamics specification
|
|
22
|
+
- Constraint formulation
|
|
23
|
+
- Problem instantiation and solving
|
|
24
|
+
- Results visualization
|
|
25
|
+
|
|
26
|
+
## Example Structure
|
|
27
|
+
|
|
28
|
+
Most examples follow this structure:
|
|
29
|
+
|
|
30
|
+
1. **Imports**: Import necessary OpenSCvx modules
|
|
31
|
+
2. **Problem Setup**: Define parameters, state, and control variables
|
|
32
|
+
3. **Dynamics**: Specify the system dynamics
|
|
33
|
+
4. **Constraints**: Define path and boundary constraints
|
|
34
|
+
5. **Problem Instantiation**: Create and configure the Problem
|
|
35
|
+
6. **Solving**: Run the optimization
|
|
36
|
+
7. **Visualization**: Plot and analyze results
|
{openscvx-0.5.2.dev13 → openscvx-0.5.2.dev15}/material/overrides/partials/home-pipeline.html
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{#- Problem → OpenSCvx → solution — minimal copy, scales without inner scroll. -#}
|
|
2
2
|
<section class="osc-home-pipeline" aria-labelledby="osc-home-pipeline-title">
|
|
3
|
-
<h2 id="osc-home-pipeline-title" class="osc-home-pipeline__title">From
|
|
3
|
+
<h2 id="osc-home-pipeline-title" class="osc-home-pipeline__title">From nonlinear optimal control problems to dynamically feasible trajectories.</h2>
|
|
4
4
|
<p class="osc-home-pipeline__lede">
|
|
5
5
|
Model in Python, compile with JAX, and scale batches on CPU or GPU—successive convexification turns a nonlinear OCP into a sequence of convex subproblems.
|
|
6
6
|
</p>
|
|
@@ -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.dev15'
|
|
22
|
+
__version_tuple__ = version_tuple = (0, 5, 2, 'dev15')
|
|
23
23
|
|
|
24
|
-
__commit_id__ = commit_id = '
|
|
24
|
+
__commit_id__ = commit_id = 'gbbe5a3732'
|
|
@@ -281,9 +281,24 @@ class PTRSolverSpec(BaseModel):
|
|
|
281
281
|
or ``"moreau"``
|
|
282
282
|
(:class:`openscvx.solvers.moreau_ptr_solver.MoreauPTRSolver`).
|
|
283
283
|
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
284
|
+
Backend-specific fields mirror the constructor parameters of each class.
|
|
285
|
+
Fields that don't belong to the active backend are a configuration error
|
|
286
|
+
and raise ``ValidationError``.
|
|
287
|
+
|
|
288
|
+
CVXPy-only:
|
|
289
|
+
``cvx_solver``, ``cvxpygen``, ``cvxpygen_override``.
|
|
290
|
+
|
|
291
|
+
QPAX-only:
|
|
292
|
+
``solver_tol``.
|
|
293
|
+
|
|
294
|
+
Moreau-only:
|
|
295
|
+
``verbose``, ``device``, ``tol_gap_abs``, ``tol_feas``.
|
|
296
|
+
|
|
297
|
+
Shared between QPAX and Moreau:
|
|
298
|
+
``max_iter``.
|
|
299
|
+
|
|
300
|
+
All backends:
|
|
301
|
+
``solver_args`` (escape hatch for settings not covered by named fields).
|
|
287
302
|
|
|
288
303
|
!!! warning
|
|
289
304
|
Enabling ``cvxpygen`` currently disables sparse parameter declarations.
|
|
@@ -294,11 +309,27 @@ class PTRSolverSpec(BaseModel):
|
|
|
294
309
|
|
|
295
310
|
type: Literal["PTRSolver"] = "PTRSolver"
|
|
296
311
|
backend: Literal["cvxpy", "qpax", "moreau"] = "cvxpy"
|
|
312
|
+
|
|
313
|
+
# CVXPy-only
|
|
297
314
|
cvx_solver: Optional[str] = None
|
|
298
|
-
solver_args: Optional[Dict[str, Any]] = None
|
|
299
315
|
cvxpygen: bool = False
|
|
300
316
|
cvxpygen_override: bool = False
|
|
301
317
|
|
|
318
|
+
# QPAX-specific
|
|
319
|
+
solver_tol: Optional[float] = None
|
|
320
|
+
|
|
321
|
+
# Shared between QPAX and Moreau
|
|
322
|
+
max_iter: Optional[int] = None
|
|
323
|
+
|
|
324
|
+
# Moreau-specific
|
|
325
|
+
verbose: Optional[bool] = None
|
|
326
|
+
device: Optional[str] = None
|
|
327
|
+
tol_gap_abs: Optional[float] = None
|
|
328
|
+
tol_feas: Optional[float] = None
|
|
329
|
+
|
|
330
|
+
# Escape hatch for all backends
|
|
331
|
+
solver_args: Optional[Dict[str, Any]] = None
|
|
332
|
+
|
|
302
333
|
model_config = ConfigDict(extra="forbid")
|
|
303
334
|
|
|
304
335
|
@model_validator(mode="after")
|
|
@@ -318,6 +349,45 @@ class PTRSolverSpec(BaseModel):
|
|
|
318
349
|
f"{offenders} only valid for backend='cvxpy'; "
|
|
319
350
|
"remove these fields or set backend='cvxpy'."
|
|
320
351
|
)
|
|
352
|
+
if self.backend == "cvxpy":
|
|
353
|
+
offenders = [
|
|
354
|
+
name
|
|
355
|
+
for name, value in (
|
|
356
|
+
("solver_tol", self.solver_tol),
|
|
357
|
+
("max_iter", self.max_iter),
|
|
358
|
+
("verbose", self.verbose),
|
|
359
|
+
("device", self.device),
|
|
360
|
+
("tol_gap_abs", self.tol_gap_abs),
|
|
361
|
+
("tol_feas", self.tol_feas),
|
|
362
|
+
)
|
|
363
|
+
if value is not None
|
|
364
|
+
]
|
|
365
|
+
if offenders:
|
|
366
|
+
raise ValueError(
|
|
367
|
+
f"{offenders} not valid for backend='cvxpy'; pass these "
|
|
368
|
+
"via solver_args or switch to the qpax / moreau backend."
|
|
369
|
+
)
|
|
370
|
+
if self.backend == "qpax":
|
|
371
|
+
offenders = [
|
|
372
|
+
name
|
|
373
|
+
for name, value in (
|
|
374
|
+
("verbose", self.verbose),
|
|
375
|
+
("device", self.device),
|
|
376
|
+
("tol_gap_abs", self.tol_gap_abs),
|
|
377
|
+
("tol_feas", self.tol_feas),
|
|
378
|
+
)
|
|
379
|
+
if value is not None
|
|
380
|
+
]
|
|
381
|
+
if offenders:
|
|
382
|
+
raise ValueError(
|
|
383
|
+
f"{offenders} only valid for backend='moreau'; "
|
|
384
|
+
"remove these fields or set backend='moreau'."
|
|
385
|
+
)
|
|
386
|
+
if self.backend == "moreau" and self.solver_tol is not None:
|
|
387
|
+
raise ValueError(
|
|
388
|
+
"solver_tol is only valid for backend='qpax'; "
|
|
389
|
+
"remove this field or set backend='qpax'."
|
|
390
|
+
)
|
|
321
391
|
return self
|
|
322
392
|
|
|
323
393
|
def build(self) -> ConvexSolver:
|
|
@@ -335,10 +405,31 @@ class PTRSolverSpec(BaseModel):
|
|
|
335
405
|
if self.backend == "moreau":
|
|
336
406
|
from .moreau_ptr_solver import MoreauPTRSolver
|
|
337
407
|
|
|
338
|
-
|
|
408
|
+
kwargs: Dict[str, Any] = {}
|
|
409
|
+
if self.max_iter is not None:
|
|
410
|
+
kwargs["max_iter"] = self.max_iter
|
|
411
|
+
if self.verbose is not None:
|
|
412
|
+
kwargs["verbose"] = self.verbose
|
|
413
|
+
if self.device is not None:
|
|
414
|
+
kwargs["device"] = self.device
|
|
415
|
+
if self.tol_gap_abs is not None:
|
|
416
|
+
kwargs["tol_gap_abs"] = self.tol_gap_abs
|
|
417
|
+
if self.tol_feas is not None:
|
|
418
|
+
kwargs["tol_feas"] = self.tol_feas
|
|
419
|
+
if self.solver_args is not None:
|
|
420
|
+
kwargs["solver_args"] = self.solver_args
|
|
421
|
+
return MoreauPTRSolver(**kwargs)
|
|
422
|
+
|
|
339
423
|
from .qpax_ptr_solver import QPAXPTRSolver
|
|
340
424
|
|
|
341
|
-
|
|
425
|
+
kwargs = {}
|
|
426
|
+
if self.solver_tol is not None:
|
|
427
|
+
kwargs["solver_tol"] = self.solver_tol
|
|
428
|
+
if self.max_iter is not None:
|
|
429
|
+
kwargs["max_iter"] = self.max_iter
|
|
430
|
+
if self.solver_args is not None:
|
|
431
|
+
kwargs["solver_args"] = self.solver_args
|
|
432
|
+
return QPAXPTRSolver(**kwargs)
|
|
342
433
|
|
|
343
434
|
|
|
344
435
|
def __getattr__(name: str):
|
|
@@ -241,24 +241,75 @@ class MoreauPTRSolver(PTRSolver):
|
|
|
241
241
|
through a full SCvx solve.
|
|
242
242
|
|
|
243
243
|
Args:
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
244
|
+
max_iter: Maximum number of IPM iterations forwarded to
|
|
245
|
+
:class:`moreau.Settings`. Defaults to ``200``.
|
|
246
|
+
verbose: Whether Moreau prints per-iteration diagnostics.
|
|
247
|
+
Forwarded to :class:`moreau.Settings`. Defaults to ``False``.
|
|
248
|
+
device: Compute device for Moreau's JAX kernels. One of
|
|
249
|
+
``"auto"``, ``"cpu"``, or ``"cuda"``. Forwarded to
|
|
250
|
+
:class:`moreau.Settings`. Defaults to ``"auto"``.
|
|
251
|
+
tol_gap_abs: Absolute duality-gap tolerance forwarded to
|
|
252
|
+
:class:`moreau.IPMSettings`. ``None`` uses Moreau's default.
|
|
253
|
+
tol_feas: Primal/dual feasibility tolerance forwarded to
|
|
254
|
+
:class:`moreau.IPMSettings`. ``None`` uses Moreau's default.
|
|
255
|
+
solver_args: Additional keyword arguments forwarded verbatim to
|
|
256
|
+
:class:`moreau.Settings`. Use for settings not covered by the
|
|
257
|
+
named params above. ``solver_args["ipm_settings"]`` may be a
|
|
258
|
+
dict or a :class:`moreau.IPMSettings` object; if it is a dict,
|
|
259
|
+
``tol_gap_abs`` / ``tol_feas`` are merged into it. Raises
|
|
260
|
+
``ValueError`` at construction time if any top-level key or
|
|
261
|
+
IPM tolerance overlaps with a named param.
|
|
249
262
|
|
|
250
263
|
Attributes:
|
|
251
264
|
layout: :class:`_ConicLayout` describing flat decision-vector slot
|
|
252
265
|
ranges. Populated by :meth:`create_variables`.
|
|
253
266
|
"""
|
|
254
267
|
|
|
255
|
-
def __init__(
|
|
268
|
+
def __init__(
|
|
269
|
+
self,
|
|
270
|
+
*,
|
|
271
|
+
max_iter: int = 200,
|
|
272
|
+
verbose: bool = False,
|
|
273
|
+
device: str = "auto",
|
|
274
|
+
tol_gap_abs: Optional[float] = None,
|
|
275
|
+
tol_feas: Optional[float] = None,
|
|
276
|
+
solver_args: Optional[Dict] = None,
|
|
277
|
+
):
|
|
256
278
|
if not _MOREAU_AVAILABLE:
|
|
257
279
|
raise ImportError(
|
|
258
280
|
"MoreauPTRSolver requires the `moreau` package. "
|
|
259
281
|
"Install it with: pip install openscvx[moreau]"
|
|
260
282
|
)
|
|
261
|
-
|
|
283
|
+
|
|
284
|
+
_named = {"max_iter": max_iter, "verbose": verbose, "device": device}
|
|
285
|
+
_extra = dict(solver_args) if solver_args else {}
|
|
286
|
+
_overlap = _named.keys() & _extra.keys()
|
|
287
|
+
if _overlap:
|
|
288
|
+
raise ValueError(
|
|
289
|
+
f"Moreau settings {sorted(_overlap)} appear as both named arguments "
|
|
290
|
+
"and inside solver_args; use one or the other."
|
|
291
|
+
)
|
|
292
|
+
merged = {**_named, **_extra}
|
|
293
|
+
|
|
294
|
+
_ipm = {
|
|
295
|
+
k: v for k, v in [("tol_gap_abs", tol_gap_abs), ("tol_feas", tol_feas)] if v is not None
|
|
296
|
+
}
|
|
297
|
+
if _ipm:
|
|
298
|
+
existing_ipm = merged.get("ipm_settings", {})
|
|
299
|
+
if not isinstance(existing_ipm, dict):
|
|
300
|
+
raise ValueError(
|
|
301
|
+
"Cannot combine tol_gap_abs / tol_feas named arguments with an "
|
|
302
|
+
"ipm_settings object in solver_args; use one form or the other."
|
|
303
|
+
)
|
|
304
|
+
ipm_overlap = _ipm.keys() & existing_ipm.keys()
|
|
305
|
+
if ipm_overlap:
|
|
306
|
+
raise ValueError(
|
|
307
|
+
f"Moreau IPM settings {sorted(ipm_overlap)} appear as both named "
|
|
308
|
+
"arguments and inside solver_args['ipm_settings']; use one or the other."
|
|
309
|
+
)
|
|
310
|
+
merged["ipm_settings"] = {**_ipm, **existing_ipm}
|
|
311
|
+
|
|
312
|
+
self.solver_args = merged
|
|
262
313
|
|
|
263
314
|
self.layout: Optional[_ConicLayout] = None
|
|
264
315
|
self._S_x: Optional[np.ndarray] = None
|
|
@@ -177,25 +177,44 @@ class QPAXPTRSolver(PTRSolver):
|
|
|
177
177
|
what lets ``jax.grad`` / ``jax.vmap`` reach through a full SCvx solve.
|
|
178
178
|
|
|
179
179
|
Args:
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
180
|
+
solver_tol: Convergence tolerance forwarded to ``qpax.solve_qp``
|
|
181
|
+
as ``solver_tol``. Defaults to ``1e-5``.
|
|
182
|
+
max_iter: Maximum number of PDIP iterations forwarded to
|
|
183
|
+
``qpax.solve_qp`` as ``max_iter``. Defaults to ``30``.
|
|
184
|
+
solver_args: Additional keyword arguments forwarded verbatim to
|
|
185
|
+
``qpax.solve_qp``. Use for settings not covered by the named
|
|
186
|
+
params above — e.g. ``backend="e"`` for the explicit
|
|
187
|
+
predictor-corrector path, or ``linear_solver``. Raises
|
|
188
|
+
``ValueError`` at construction time if any key overlaps with a
|
|
189
|
+
named param.
|
|
185
190
|
|
|
186
191
|
Attributes:
|
|
187
192
|
layout: ``_QPLayout`` describing the flat decision-vector slot ranges.
|
|
188
193
|
Populated by :meth:`create_variables`.
|
|
189
194
|
"""
|
|
190
195
|
|
|
191
|
-
def __init__(
|
|
196
|
+
def __init__(
|
|
197
|
+
self,
|
|
198
|
+
*,
|
|
199
|
+
solver_tol: float = 1e-5,
|
|
200
|
+
max_iter: int = 30,
|
|
201
|
+
solver_args: Optional[dict] = None,
|
|
202
|
+
):
|
|
192
203
|
if not _QPAX_AVAILABLE:
|
|
193
204
|
raise ImportError(
|
|
194
205
|
"QPAXPTRSolver requires the `qpax` package. "
|
|
195
206
|
"Install it with: pip install openscvx[qpax]"
|
|
196
207
|
)
|
|
197
208
|
|
|
198
|
-
|
|
209
|
+
_named = {"solver_tol": solver_tol, "max_iter": max_iter}
|
|
210
|
+
_extra = dict(solver_args) if solver_args else {}
|
|
211
|
+
_overlap = _named.keys() & _extra.keys()
|
|
212
|
+
if _overlap:
|
|
213
|
+
raise ValueError(
|
|
214
|
+
f"QPAX settings {sorted(_overlap)} appear as both named arguments "
|
|
215
|
+
"and inside solver_args; use one or the other."
|
|
216
|
+
)
|
|
217
|
+
self.solver_args = {**_named, **_extra}
|
|
199
218
|
|
|
200
219
|
# Populated by create_variables / initialize.
|
|
201
220
|
self.layout: Optional[_QPLayout] = None
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: openscvx
|
|
3
|
-
Version: 0.5.2.
|
|
3
|
+
Version: 0.5.2.dev15
|
|
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
|