openscvx 2.dev6__tar.gz → 2.dev8__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-2.dev6/openscvx.egg-info → openscvx-2.dev8}/PKG-INFO +3 -1
- {openscvx-2.dev6 → openscvx-2.dev8}/docs/UnderTheHood/lowering_architecture.md +31 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/examples/rocket/6DoF_pdg.py +0 -5
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/__init__.py +16 -1
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/_version.py +3 -3
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/loader.py +2 -2
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/lowered/cvxpy_constraints.py +4 -1
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/problem.py +19 -13
- openscvx-2.dev8/openscvx/solvers/__init__.py +93 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/solvers/base.py +117 -36
- openscvx-2.dev6/openscvx/solvers/ptr_solver.py → openscvx-2.dev8/openscvx/solvers/cvxpy_ptr_solver.py +49 -86
- openscvx-2.dev8/openscvx/solvers/ptr_solver.py +196 -0
- openscvx-2.dev8/openscvx/solvers/qpax_ptr_solver.py +776 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/symbolic/lower.py +6 -7
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/utils/printing.py +9 -1
- {openscvx-2.dev6 → openscvx-2.dev8/openscvx.egg-info}/PKG-INFO +3 -1
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx.egg-info/SOURCES.txt +4 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx.egg-info/requires.txt +3 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/pyproject.toml +3 -0
- openscvx-2.dev8/tests/solvers/test_qpax_ptr_solver.py +238 -0
- openscvx-2.dev8/tests/symbolic/parser/__init__.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/tests/test_brachistochrone.py +184 -3
- openscvx-2.dev6/openscvx/solvers/__init__.py +0 -76
- {openscvx-2.dev6 → openscvx-2.dev8}/.github/assets/logo.svg +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/.github/release-drafter.yml +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/.github/workflows/_docs.yml +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/.github/workflows/branch-name.yml +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/.github/workflows/docs.yml +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/.github/workflows/lint.yml +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/.github/workflows/nightly.yml +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/.github/workflows/release-drafter.yml +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/.github/workflows/release.yml +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/.github/workflows/tests-integration.yml +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/.github/workflows/tests-unit.yml +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/.gitignore +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/.gitmodules +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/CONTRIBUTING.md +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/LICENSE +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/README.md +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/docs/Foundations/constraint_reformulation.md +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/docs/Foundations/control_parameterization.md +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/docs/Foundations/discretization.md +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/docs/Foundations/ocp.md +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/docs/Foundations/scvx.md +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/docs/Foundations/time_dilation.md +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/docs/UnderTheHood/vectorization_and_vmapping.md +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/docs/UsersGuide/00_introduction.md +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/docs/UsersGuide/01_hello_world_brachistochrone.md +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/docs/UsersGuide/02_drone_racing_constraints.md +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/docs/UsersGuide/03_obstacle_avoidance_vmap.md +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/docs/UsersGuide/04_viewpoint_constraints.md +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/docs/UsersGuide/05_visualization.md +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/docs/UsersGuide/06_logic.md +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/docs/UsersGuide/07_lie.md +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/docs/UsersGuide/08_mpcc.md +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/docs/assets/favicon.png +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/docs/assets/images/ct-scvx_dark.png +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/docs/assets/images/ct-scvx_light.png +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/docs/assets/images/ctcs_dark.png +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/docs/assets/images/ctcs_light.png +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/docs/assets/images/problem_class_dark.png +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/docs/assets/images/problem_class_light.png +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/docs/assets/logo.svg +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/docs/assets/openscvx_logo_square.png +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/docs/assets/viser-client/index.html +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/docs/assets/viser-recordings/drone_racing.viser +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/docs/assets/viser-recordings/franka_fr3v2_pick_place.viser +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/docs/citation.md +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/docs/examples.md +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/docs/index.md +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/docs/javascripts/mathjax.js +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/docs/versions.json +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/examples/_viser_embed_export.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/examples/abstract/brachistochrone.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/examples/abstract/hypersensitive.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/examples/abstract/impulsive.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/examples/abstract/stl_integer_variable.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/examples/abstract/stl_or.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/examples/animations/7_dof_arm.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/examples/animations/_camera.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/examples/animations/_render.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/examples/animations/_sensor_view.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/examples/animations/dr_vp_polytope.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/examples/animations/franka_fr3v2_pick_place.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/examples/animations/logo.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/examples/animations/obstacle_avoidance_vmap.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/examples/arm/3_dof_arm.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/examples/arm/7_dof_arm.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/examples/arm/7_dof_arm_collision.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/examples/arm/7_dof_arm_vp.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/examples/arm/franka_fr3v2_pick_place.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/examples/arm/franka_fr3v2_viewplanning.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/examples/car/dubins_car.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/examples/car/dubins_car_disjoint.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/examples/car/dubins_car_obstacle_conditional.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/examples/car/dubins_car_obstacle_stl.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/examples/car/dubins_car_stl_or.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/examples/car/dubins_car_waypoint_stl.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/examples/drone/cinema_vp.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/examples/drone/dr_double_integrator.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/examples/drone/dr_vp.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/examples/drone/dr_vp_nodal.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/examples/drone/dr_vp_polytope.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/examples/drone/drone_racing.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/examples/drone/logo.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/examples/drone/logo_utils/acl_logo.svg +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/examples/drone/logo_utils/svg_path_utils.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/examples/drone/obstacle_avoidance.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/examples/drone/obstacle_avoidance_nodal.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/examples/drone/obstacle_avoidance_vmap.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/examples/mjx/cartpole_mjx.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/examples/mjx/double_cartpole_mjx.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/examples/mjx/skydio_x2_mjx.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/examples/mjx/triple_cartpole_3d_mjx.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/examples/mjx/triple_cartpole_game.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/examples/mjx/triple_cartpole_mjx.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/examples/mpc/double_integrator_discrete.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/examples/mpc/double_integrator_drone_racing.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/examples/mpc/dubins_car_circle_analytical.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/examples/mpc/dubins_car_circle_discrete.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/examples/mpc/realtime_double_integrator_drone_racing.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/examples/plotting.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/examples/plotting_viser.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/examples/realtime/3DoF_pdg_realtime.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/examples/realtime/6DoF_pdg_realtime.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/examples/realtime/base_problems/3DoF_pdg_realtime_base.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/examples/realtime/base_problems/6DoF_pdg_realtime_base.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/examples/realtime/base_problems/cinema_vp_realtime_base.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/examples/realtime/base_problems/drone_racing_realtime_base.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/examples/realtime/base_problems/dubins_car_realtime_base.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/examples/realtime/base_problems/obstacle_avoidance_realtime_base.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/examples/realtime/cinema_vp_realtime.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/examples/realtime/drone_racing_realtime.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/examples/realtime/dubins_car_realtime.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/examples/realtime/obstacle_avoidance_realtime.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/examples/rocket/3DoF_pdg.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/examples/spacecraft/halo_orbit.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/examples/spacecraft/hohmann_transfer.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/examples/spacecraft/let_transfer.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/examples/spacecraft/proxops_cw.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/figures/ctlos_cine.gif +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/figures/ctlos_dr.gif +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/figures/dtlos_cine.gif +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/figures/dtlos_dr.gif +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/figures/openscvx_logo.svg +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/figures/openscvx_logo_square.png +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/figures/oscvx_structure_full_dark.svg +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/figures/video_preview.png +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/material/__init__.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/material/overrides/assets/stylesheets/custom.css +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/material/overrides/assets/stylesheets/home-dropin.css +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/material/overrides/assets/stylesheets/home-hero.css +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/material/overrides/assets/stylesheets/home-viser.css +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/material/overrides/home.html +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/material/overrides/main.html +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/material/overrides/partials/home-diagram.html +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/material/overrides/partials/home-dropin-banner.html +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/material/overrides/partials/home-hero.html +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/material/overrides/partials/home-pipeline.html +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/material/overrides/partials/home-viser-strip.html +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/mkdocs.yml +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/__main__.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/algorithms/__init__.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/algorithms/autotuner/__init__.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/algorithms/autotuner/adaptive_proximal_weight.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/algorithms/autotuner/augmented_lagrangian.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/algorithms/autotuner/constant_proximal_weight.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/algorithms/autotuner/ramp_proximal_weight.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/algorithms/base.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/algorithms/optimization_results.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/algorithms/scvx/__init__.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/algorithms/scvx/penalized_trust_region.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/algorithms/weights.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/config.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/discretization/__init__.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/discretization/base.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/discretization/discretize_linearize.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/discretization/linearize_discretize.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/discretization/linearize_discretize_sparse.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/discretization/sparse_utils/__init__.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/discretization/sparse_utils/bcoo_helpers.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/discretization/sparse_utils/sparse_jacobian.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/expert/__init__.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/expert/byof.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/expert/lowering.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/expert/validation.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/init/__init__.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/init/interpolation.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/init/inverse_kinematics.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/integrations/__init__.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/integrations/base.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/integrations/menagerie.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/integrations/mjx.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/integrators/__init__.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/integrators/diffrax.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/integrators/runge_kutta.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/lowered/__init__.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/lowered/cvxpy_variables.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/lowered/dynamics.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/lowered/jax_constraints.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/lowered/parameters.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/lowered/problem.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/lowered/unified.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/plotting/__init__.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/plotting/plotting.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/plotting/scp_iteration.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/plotting/viser/__init__.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/plotting/viser/animated.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/plotting/viser/orbits.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/plotting/viser/plotly_integration.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/plotting/viser/primitives.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/plotting/viser/scp.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/plotting/viser/server.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/propagation/__init__.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/propagation/post_processing.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/propagation/propagation.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/symbolic/__init__.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/symbolic/augmentation.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/symbolic/builder.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/symbolic/constraint_set.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/symbolic/expr/__init__.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/symbolic/expr/arithmetic.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/symbolic/expr/array.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/symbolic/expr/constraint.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/symbolic/expr/control.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/symbolic/expr/expr.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/symbolic/expr/lie/__init__.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/symbolic/expr/lie/adjoint.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/symbolic/expr/lie/se3.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/symbolic/expr/lie/so3.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/symbolic/expr/linalg.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/symbolic/expr/logic.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/symbolic/expr/math.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/symbolic/expr/parameter.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/symbolic/expr/spatial.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/symbolic/expr/state.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/symbolic/expr/stl.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/symbolic/expr/stljax.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/symbolic/expr/time.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/symbolic/expr/variable.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/symbolic/expr/vmap.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/symbolic/hashing.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/symbolic/lowerers/__init__.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/symbolic/lowerers/cvxpy/__init__.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/symbolic/lowerers/cvxpy/_lowerer.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/symbolic/lowerers/cvxpy/_registry.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/symbolic/lowerers/cvxpy/arithmetic.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/symbolic/lowerers/cvxpy/array.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/symbolic/lowerers/cvxpy/constraint.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/symbolic/lowerers/cvxpy/control.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/symbolic/lowerers/cvxpy/expr.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/symbolic/lowerers/cvxpy/linalg.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/symbolic/lowerers/cvxpy/logic.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/symbolic/lowerers/cvxpy/math.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/symbolic/lowerers/cvxpy/state.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/symbolic/lowerers/jax/__init__.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/symbolic/lowerers/jax/_lowerer.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/symbolic/lowerers/jax/_registry.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/symbolic/lowerers/jax/arithmetic.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/symbolic/lowerers/jax/array.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/symbolic/lowerers/jax/constraint.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/symbolic/lowerers/jax/control.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/symbolic/lowerers/jax/expr.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/symbolic/lowerers/jax/lie.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/symbolic/lowerers/jax/linalg.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/symbolic/lowerers/jax/logic.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/symbolic/lowerers/jax/math.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/symbolic/lowerers/jax/spatial.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/symbolic/lowerers/jax/state.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/symbolic/lowerers/jax/stl.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/symbolic/lowerers/jax/stljax.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/symbolic/lowerers/jax/vmap.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/symbolic/parser/__init__.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/symbolic/parser/_registry.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/symbolic/parser/array.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/symbolic/parser/constraint.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/symbolic/parser/lie.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/symbolic/parser/linalg.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/symbolic/parser/logic.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/symbolic/parser/math.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/symbolic/parser/parser.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/symbolic/parser/spatial.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/symbolic/parser/stl.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/symbolic/parser/stljax.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/symbolic/parser/tokenizer.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/symbolic/preprocessing.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/symbolic/problem.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/symbolic/sparsity.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/symbolic/unified.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/utils/__init__.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/utils/cache.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/utils/caching.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/utils/profiling.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx/utils/utils.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx.egg-info/dependency_links.txt +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx.egg-info/entry_points.txt +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/openscvx.egg-info/top_level.txt +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/scripts/gen_example_pages.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/scripts/gen_ref_pages.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/scripts/mkdocs_copy_viser_client_hook.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/setup.cfg +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/tests/__init__.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/tests/brachistochrone_analytical.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/tests/expr/__init__.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/tests/expr/test_gmsr.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/tests/fixtures/brachistochrone.json +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/tests/fixtures/brachistochrone.yaml +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/tests/hohmann_analytical.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/tests/integrations/__init__.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/tests/integrations/test_mjx.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/tests/integrations/test_mjx_dynamics.py +0 -0
- {openscvx-2.dev6/tests/symbolic → openscvx-2.dev8/tests/solvers}/__init__.py +0 -0
- {openscvx-2.dev6/tests/symbolic/expr → openscvx-2.dev8/tests/symbolic}/__init__.py +0 -0
- {openscvx-2.dev6/tests/symbolic/parser → openscvx-2.dev8/tests/symbolic/expr}/__init__.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/tests/symbolic/expr/test_arithmetic.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/tests/symbolic/expr/test_array.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/tests/symbolic/expr/test_constraint.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/tests/symbolic/expr/test_expr.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/tests/symbolic/expr/test_lie.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/tests/symbolic/expr/test_linalg.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/tests/symbolic/expr/test_logic.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/tests/symbolic/expr/test_math.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/tests/symbolic/expr/test_node_reference.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/tests/symbolic/expr/test_parameters.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/tests/symbolic/expr/test_scaling.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/tests/symbolic/expr/test_spatial.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/tests/symbolic/expr/test_stl.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/tests/symbolic/expr/test_variable.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/tests/symbolic/expr/test_vmap.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/tests/symbolic/parser/test_array.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/tests/symbolic/parser/test_constraint.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/tests/symbolic/parser/test_lie.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/tests/symbolic/parser/test_linalg.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/tests/symbolic/parser/test_load.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/tests/symbolic/parser/test_logic.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/tests/symbolic/parser/test_math.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/tests/symbolic/parser/test_parser.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/tests/symbolic/parser/test_spatial.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/tests/symbolic/parser/test_stl.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/tests/symbolic/parser/test_tokenizer.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/tests/symbolic/parser/test_vmap.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/tests/symbolic/test_augmentation.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/tests/symbolic/test_hashing.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/tests/symbolic/test_lower_cvxpy.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/tests/symbolic/test_lower_jax.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/tests/symbolic/test_preprocessing.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/tests/symbolic/test_sparsity.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/tests/symbolic/test_unified.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/tests/test_autotuning.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/tests/test_cvxpygen_optional.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/tests/test_discretization.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/tests/test_examples.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/tests/test_expert.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/tests/test_impulsive.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/tests/test_init.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/tests/test_integrators.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/tests/test_loader.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/tests/test_optimization_results.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/tests/test_plotting.py +0 -0
- {openscvx-2.dev6 → openscvx-2.dev8}/tests/test_propagation.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: openscvx
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.dev8
|
|
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
|
|
@@ -26,6 +26,8 @@ Requires-Dist: pydantic>=2.0
|
|
|
26
26
|
Provides-Extra: cvxpygen
|
|
27
27
|
Requires-Dist: cvxpygen; extra == "cvxpygen"
|
|
28
28
|
Requires-Dist: qocogen; extra == "cvxpygen"
|
|
29
|
+
Provides-Extra: qpax
|
|
30
|
+
Requires-Dist: qpax>=0.1.1; extra == "qpax"
|
|
29
31
|
Provides-Extra: stl
|
|
30
32
|
Requires-Dist: stljax; extra == "stl"
|
|
31
33
|
Provides-Extra: lie
|
|
@@ -160,9 +160,40 @@ JAX lowering has no dependency on:
|
|
|
160
160
|
|
|
161
161
|
This means JAX-lowered dynamics and constraints could be used with alternative solvers.
|
|
162
162
|
|
|
163
|
+
## Convex Subproblem Backends
|
|
164
|
+
|
|
165
|
+
The convex subproblem at each SCP iteration is solved by a concrete subclass
|
|
166
|
+
of the abstract `PTRSolver` base. Two backends ship today:
|
|
167
|
+
|
|
168
|
+
| Backend | Class | Selector | Notes |
|
|
169
|
+
|---------|-------|----------|-------|
|
|
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()`, cross-node, and impulsive 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
|
+
|
|
173
|
+
Picking a backend at construction time:
|
|
174
|
+
|
|
175
|
+
```python
|
|
176
|
+
import openscvx as ox
|
|
177
|
+
|
|
178
|
+
# Default — same as today's CVXPyPTRSolver.
|
|
179
|
+
problem = ox.Problem(...)
|
|
180
|
+
|
|
181
|
+
# Explicit CVXPy with a different inner solver.
|
|
182
|
+
problem = ox.Problem(..., solver={"backend": "cvxpy", "cvx_solver": "CLARABEL"})
|
|
183
|
+
|
|
184
|
+
# JAX-native QPAX (requires the `qpax` extra: pip install openscvx[qpax]).
|
|
185
|
+
problem = ox.Problem(..., solver={"backend": "qpax"})
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
QPAX consumes the global JAX dtype — pass `float_dtype="float64"` to `Problem`
|
|
189
|
+
if you need tight inner-solver tolerances; the default `float32` is enough for
|
|
190
|
+
many problems but caps the QP's conditioning.
|
|
191
|
+
|
|
163
192
|
## Further Reading
|
|
164
193
|
|
|
165
194
|
- `openscvx/symbolic/lower.py` — Main lowering implementation
|
|
166
195
|
- `openscvx/lowered/` — Dataclass definitions
|
|
167
196
|
- `openscvx/symbolic/lowerers/jax.py` — JAX visitor implementation
|
|
168
197
|
- `openscvx/symbolic/lowerers/cvxpy.py` — CVXPy visitor implementation
|
|
198
|
+
- `openscvx/solvers/ptr_solver.py` — Abstract `PTRSolver` contract
|
|
199
|
+
- `openscvx/solvers/cvxpy_ptr_solver.py` / `qpax_ptr_solver.py` — Concrete backends
|
|
@@ -218,11 +218,6 @@ problem = Problem(
|
|
|
218
218
|
discretizer={
|
|
219
219
|
"diffrax_kwargs": {"stepsize_controller": dfx.StepTo(np.linspace(0.0, 1 / (n - 1), 3))}
|
|
220
220
|
},
|
|
221
|
-
solver={
|
|
222
|
-
"cvxpygen": True,
|
|
223
|
-
"cvx_solver": "qocogen",
|
|
224
|
-
"solver_args": {},
|
|
225
|
-
},
|
|
226
221
|
)
|
|
227
222
|
|
|
228
223
|
problem.settings.dev.printing = False
|
|
@@ -29,7 +29,10 @@ from openscvx.expert import ByofSpec
|
|
|
29
29
|
from openscvx.integrations import DynamicsAdapter, MjxDynamics
|
|
30
30
|
from openscvx.loader import load_dict, load_json, load_yaml
|
|
31
31
|
from openscvx.problem import Problem
|
|
32
|
-
from openscvx.solvers import PTRSolver
|
|
32
|
+
from openscvx.solvers import CVXPyPTRSolver, PTRSolver
|
|
33
|
+
|
|
34
|
+
# QPAXPTRSolver is exposed lazily via __getattr__ below to keep `import qpax`
|
|
35
|
+
# off the hot import path for users who don't install the optional extra.
|
|
33
36
|
from openscvx.symbolic.expr import (
|
|
34
37
|
CTCS,
|
|
35
38
|
Abs,
|
|
@@ -91,6 +94,16 @@ from openscvx.utils.cache import clear_cache, get_cache_dir, get_cache_size
|
|
|
91
94
|
|
|
92
95
|
load_results = OptimizationResults.load
|
|
93
96
|
|
|
97
|
+
|
|
98
|
+
def __getattr__(name: str):
|
|
99
|
+
"""Lazy export for backends that depend on optional packages."""
|
|
100
|
+
if name == "QPAXPTRSolver":
|
|
101
|
+
from openscvx.solvers.qpax_ptr_solver import QPAXPTRSolver
|
|
102
|
+
|
|
103
|
+
return QPAXPTRSolver
|
|
104
|
+
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
|
105
|
+
|
|
106
|
+
|
|
94
107
|
__all__ = [
|
|
95
108
|
# Main Trajectory Optimization Entrypoint
|
|
96
109
|
"Problem",
|
|
@@ -188,6 +201,8 @@ __all__ = [
|
|
|
188
201
|
"VectorizeDiscretizeLinearize",
|
|
189
202
|
# Convex Solver
|
|
190
203
|
"PTRSolver",
|
|
204
|
+
"CVXPyPTRSolver",
|
|
205
|
+
"QPAXPTRSolver",
|
|
191
206
|
# Algorithm & Autotuning
|
|
192
207
|
"PenalizedTrustRegion",
|
|
193
208
|
"AugmentedLagrangian",
|
|
@@ -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 = '2.
|
|
22
|
-
__version_tuple__ = version_tuple = (2, '
|
|
21
|
+
__version__ = version = '2.dev8'
|
|
22
|
+
__version_tuple__ = version_tuple = (2, 'dev8')
|
|
23
23
|
|
|
24
|
-
__commit_id__ = commit_id = '
|
|
24
|
+
__commit_id__ = commit_id = 'g69d91aabb'
|
|
@@ -40,7 +40,7 @@ from pydantic import BaseModel, ConfigDict
|
|
|
40
40
|
from openscvx.algorithms import PenalizedTrustRegionConfig
|
|
41
41
|
from openscvx.config import SettingsSpec
|
|
42
42
|
from openscvx.discretization import DiscretizerSpec
|
|
43
|
-
from openscvx.solvers import
|
|
43
|
+
from openscvx.solvers import PTRSolverSpec
|
|
44
44
|
from openscvx.symbolic.expr.control import ControlSpec
|
|
45
45
|
from openscvx.symbolic.expr.expr import Expr
|
|
46
46
|
from openscvx.symbolic.expr.parameter import ParameterSpec
|
|
@@ -66,7 +66,7 @@ class ProblemSpec(BaseModel):
|
|
|
66
66
|
constraints: List[str] = []
|
|
67
67
|
algorithm: Optional[PenalizedTrustRegionConfig] = None
|
|
68
68
|
discretizer: Optional[DiscretizerSpec] = None
|
|
69
|
-
solver: Optional[
|
|
69
|
+
solver: Optional[PTRSolverSpec] = None
|
|
70
70
|
settings: Optional[SettingsSpec] = None
|
|
71
71
|
states_prop: Optional[List[StateSpec]] = None
|
|
72
72
|
dynamics_prop: Optional[Dict[str, Any]] = None
|
|
@@ -17,7 +17,10 @@ class LoweredCvxpyConstraints:
|
|
|
17
17
|
|
|
18
18
|
Attributes:
|
|
19
19
|
constraints: List of CVXPy constraint objects (cp.Constraint).
|
|
20
|
-
Includes both nodal and cross-node convex constraints.
|
|
20
|
+
Includes both nodal and cross-node convex constraints. Empty
|
|
21
|
+
for backends that don't accept ``.convex()`` constraints — the
|
|
22
|
+
refusal happens earlier, in
|
|
23
|
+
:meth:`openscvx.solvers.base.ConvexSolver.lower_convex_constraints`.
|
|
21
24
|
"""
|
|
22
25
|
|
|
23
26
|
constraints: list["cp.Constraint"] = field(default_factory=list)
|
|
@@ -201,9 +201,11 @@ class Problem:
|
|
|
201
201
|
discretizer=ox.LinearizeDiscretize(dis_type="ZOH", ode_solver="Dopri8")
|
|
202
202
|
solver: Convex subproblem solver configuration. Accepts:
|
|
203
203
|
|
|
204
|
-
- ``None`` — uses ``
|
|
204
|
+
- ``None`` — uses ``CVXPyPTRSolver()`` with defaults (QOCO backend).
|
|
205
205
|
- A ``ConvexSolver`` instance — used directly.
|
|
206
|
-
- A ``dict`` —
|
|
206
|
+
- A ``dict`` — validated as ``PTRSolverSpec``; the ``backend``
|
|
207
|
+
field (``"cvxpy"`` or ``"qpax"``) selects the concrete
|
|
208
|
+
backend.
|
|
207
209
|
|
|
208
210
|
Examples::
|
|
209
211
|
|
|
@@ -216,8 +218,12 @@ class Problem:
|
|
|
216
218
|
# Enable cvxpygen code generation
|
|
217
219
|
solver={"cvxpygen": True}
|
|
218
220
|
|
|
221
|
+
# JAX-native QPAX backend (no cvx_solver / cvxpygen fields)
|
|
222
|
+
solver={"backend": "qpax"}
|
|
223
|
+
|
|
219
224
|
# Instance
|
|
220
|
-
solver=ox.
|
|
225
|
+
solver=ox.CVXPyPTRSolver(cvx_solver="CLARABEL")
|
|
226
|
+
solver=ox.QPAXPTRSolver()
|
|
221
227
|
byof (ByofSpec, optional): Expert mode only. Raw JAX functions to
|
|
222
228
|
bypass symbolic layer. See :class:`openscvx.expert.ByofSpec` for
|
|
223
229
|
detailed documentation.
|
|
@@ -393,9 +399,9 @@ class Problem:
|
|
|
393
399
|
def solver(self) -> ConvexSolver:
|
|
394
400
|
"""Access the convex subproblem solver instance.
|
|
395
401
|
|
|
396
|
-
|
|
397
|
-
``cvxpygen_override``
|
|
398
|
-
is called::
|
|
402
|
+
Backend-specific attributes (e.g. ``cvx_solver``, ``solver_args``,
|
|
403
|
+
``cvxpygen``, ``cvxpygen_override`` on :class:`CVXPyPTRSolver`) can
|
|
404
|
+
be modified freely before ``initialize`` is called::
|
|
399
405
|
|
|
400
406
|
problem.solver.solver_args = {"abstol": 1e-6, "reltol": 1e-9}
|
|
401
407
|
problem.solver.cvxpygen = True
|
|
@@ -407,7 +413,7 @@ class Problem:
|
|
|
407
413
|
will have no effect on subsequent solves.
|
|
408
414
|
|
|
409
415
|
Returns:
|
|
410
|
-
The solver instance
|
|
416
|
+
The solver instance — a concrete :class:`PTRSolver` subclass.
|
|
411
417
|
"""
|
|
412
418
|
return self._solver
|
|
413
419
|
|
|
@@ -510,12 +516,12 @@ class Problem:
|
|
|
510
516
|
self._lowered.x_prop_unified.final[state._slice] = state.final
|
|
511
517
|
self._lowered.x_prop_unified.final_type[state._slice] = state.final_type
|
|
512
518
|
|
|
513
|
-
#
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
+
# Push to the solver — both backends short-circuit on a pre-initialize
|
|
520
|
+
# call, so this is safe to invoke from any lifecycle point.
|
|
521
|
+
self._solver.update_boundary_conditions(
|
|
522
|
+
x_init=self._lowered.x_unified.initial,
|
|
523
|
+
x_term=self._lowered.x_unified.final,
|
|
524
|
+
)
|
|
519
525
|
|
|
520
526
|
def _sync_guesses(self):
|
|
521
527
|
"""Sync trajectory guesses from State/Control objects to lowered representation.
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
"""Convex subproblem solvers for trajectory optimization.
|
|
2
|
+
|
|
3
|
+
This module provides implementations of convex subproblem solvers used within
|
|
4
|
+
SCvx algorithms. At each iteration of a successive convexification algorithm,
|
|
5
|
+
the non-convex problem is approximated by a convex subproblem, which is then
|
|
6
|
+
solved using one of these solver backends.
|
|
7
|
+
|
|
8
|
+
All solvers inherit from :class:`ConvexSolver`, enabling pluggable solver
|
|
9
|
+
implementations and custom backends:
|
|
10
|
+
|
|
11
|
+
```python
|
|
12
|
+
class ConvexSolver(ABC):
|
|
13
|
+
@abstractmethod
|
|
14
|
+
def create_variables(self, N, x_unified, u_unified, jax_constraints) -> None:
|
|
15
|
+
'''Create backend-specific optimization variables (called once).'''
|
|
16
|
+
...
|
|
17
|
+
|
|
18
|
+
@abstractmethod
|
|
19
|
+
def initialize(self, lowered, settings) -> None:
|
|
20
|
+
'''Build the convex subproblem structure (called once).'''
|
|
21
|
+
...
|
|
22
|
+
|
|
23
|
+
@abstractmethod
|
|
24
|
+
def solve(self, state, params, settings) -> Any:
|
|
25
|
+
'''Update parameters and solve (called each iteration).'''
|
|
26
|
+
...
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
The Penalized Trust-Region (PTR) subproblem ships with two concrete backends:
|
|
30
|
+
|
|
31
|
+
- :class:`CVXPyPTRSolver` — DCP graph via CVXPy, dispatched to any of its
|
|
32
|
+
supported conic solvers (QOCO, CLARABEL, ...). Optional code generation
|
|
33
|
+
via cvxpygen for improved per-iteration performance.
|
|
34
|
+
- :class:`QPAXPTRSolver` — flat ``(Q, q, A, b, G, h)`` assembled as JAX
|
|
35
|
+
arrays and solved with ``qpax.solve_qp``. Aimed at end-to-end JAX
|
|
36
|
+
differentiability of the SCP loop (follow-up work).
|
|
37
|
+
|
|
38
|
+
Both share the abstract :class:`PTRSolver` contract.
|
|
39
|
+
|
|
40
|
+
Note:
|
|
41
|
+
Solvers own their optimization variables (e.g., ``CVXPySolver.ocp_vars``).
|
|
42
|
+
The lowering process calls ``solver.create_variables()`` before constraint
|
|
43
|
+
lowering, then ``solver.initialize()`` after. See :mod:`openscvx.solvers.base`
|
|
44
|
+
for the interface details.
|
|
45
|
+
"""
|
|
46
|
+
|
|
47
|
+
import warnings
|
|
48
|
+
from typing import Any
|
|
49
|
+
|
|
50
|
+
from .base import ConvexSolver, PTRSolverSpec
|
|
51
|
+
from .cvxpy_ptr_solver import CVXPyPTRSolver
|
|
52
|
+
from .ptr_solver import PTRSolver, PTRSolveResult
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def resolve_solver_config(val: Any) -> PTRSolverSpec:
|
|
56
|
+
"""Validate a dict / Spec into a :class:`PTRSolverSpec` instance."""
|
|
57
|
+
if isinstance(val, PTRSolverSpec):
|
|
58
|
+
return val
|
|
59
|
+
return PTRSolverSpec.model_validate(val)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def __getattr__(name: str):
|
|
63
|
+
"""Deprecated alias: ``SolverSpec`` → :class:`PTRSolverSpec`."""
|
|
64
|
+
if name == "SolverSpec":
|
|
65
|
+
warnings.warn(
|
|
66
|
+
"openscvx.solvers.SolverSpec is deprecated; use PTRSolverSpec.",
|
|
67
|
+
DeprecationWarning,
|
|
68
|
+
stacklevel=2,
|
|
69
|
+
)
|
|
70
|
+
return PTRSolverSpec
|
|
71
|
+
if name == "QPAXPTRSolver":
|
|
72
|
+
# Lazy import so users without the qpax extra don't pay a hard
|
|
73
|
+
# ImportError just for `from openscvx.solvers import QPAXPTRSolver`
|
|
74
|
+
# — the import error gets deferred to instantiation time, where the
|
|
75
|
+
# error message points at the install command.
|
|
76
|
+
from .qpax_ptr_solver import QPAXPTRSolver
|
|
77
|
+
|
|
78
|
+
return QPAXPTRSolver
|
|
79
|
+
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
__all__ = [
|
|
83
|
+
# Base classes
|
|
84
|
+
"ConvexSolver",
|
|
85
|
+
"PTRSolver",
|
|
86
|
+
"PTRSolveResult",
|
|
87
|
+
# PTR backends
|
|
88
|
+
"CVXPyPTRSolver",
|
|
89
|
+
"QPAXPTRSolver",
|
|
90
|
+
# Config
|
|
91
|
+
"PTRSolverSpec",
|
|
92
|
+
"resolve_solver_config",
|
|
93
|
+
]
|
|
@@ -5,40 +5,29 @@ must follow for use within successive convexification algorithms.
|
|
|
5
5
|
|
|
6
6
|
!!! note
|
|
7
7
|
|
|
8
|
-
Solvers own their optimization variables
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
2. **Solver determines the lowerer**: The solver references which lowerer
|
|
18
|
-
to use, but the lowering logic stays in ``lower.py``. Example:
|
|
19
|
-
|
|
20
|
-
```python
|
|
21
|
-
# In solver
|
|
22
|
-
@property
|
|
23
|
-
def lowerer(self):
|
|
24
|
-
from openscvx.symbolic.lower import lower_cvxpy_constraints
|
|
25
|
-
return lower_cvxpy_constraints
|
|
26
|
-
|
|
27
|
-
# In lower_symbolic_problem()
|
|
28
|
-
lowered_constraints = solver.lowerer(constraints, solver.variables, parameters)
|
|
29
|
-
```
|
|
8
|
+
Solvers own both their optimization variables (``create_variables()``) and
|
|
9
|
+
the lowering of any user ``.convex()`` constraints
|
|
10
|
+
(``lower_convex_constraints()``). The default ``lower_convex_constraints``
|
|
11
|
+
refuses user ``.convex()`` constraints with a clear error — backends that
|
|
12
|
+
accept them override it. This keeps ``openscvx.symbolic.lower``
|
|
13
|
+
backend-agnostic: it never branches on solver type, it just delegates.
|
|
14
|
+
|
|
15
|
+
See :class:`openscvx.solvers.ptr_solver.PTRSolver` for the PTR-specific
|
|
16
|
+
interface every PTR backend implements.
|
|
30
17
|
"""
|
|
31
18
|
|
|
19
|
+
import warnings
|
|
32
20
|
from abc import ABC, abstractmethod
|
|
33
|
-
from typing import TYPE_CHECKING, Any, Dict, List, Literal, Optional
|
|
21
|
+
from typing import TYPE_CHECKING, Any, Dict, List, Literal, Optional, Tuple
|
|
34
22
|
|
|
35
|
-
from pydantic import BaseModel, ConfigDict
|
|
23
|
+
from pydantic import BaseModel, ConfigDict, model_validator
|
|
36
24
|
|
|
37
25
|
if TYPE_CHECKING:
|
|
38
26
|
from openscvx.config import Config
|
|
39
27
|
from openscvx.lowered import LoweredProblem
|
|
40
28
|
from openscvx.lowered.jax_constraints import LoweredJaxConstraints
|
|
41
29
|
from openscvx.lowered.unified import UnifiedControl, UnifiedState
|
|
30
|
+
from openscvx.symbolic.constraint_set import ConstraintSet
|
|
42
31
|
|
|
43
32
|
|
|
44
33
|
class ConvexSolver(ABC):
|
|
@@ -91,10 +80,6 @@ class ConvexSolver(ABC):
|
|
|
91
80
|
return MyResult(...)
|
|
92
81
|
"""
|
|
93
82
|
|
|
94
|
-
#: Backend solver name (e.g., ``"QOCO"``, ``"CLARABEL"``). Subclasses
|
|
95
|
-
#: must set this in ``__init__``.
|
|
96
|
-
cvx_solver: str
|
|
97
|
-
|
|
98
83
|
@abstractmethod
|
|
99
84
|
def create_variables(
|
|
100
85
|
self,
|
|
@@ -128,6 +113,50 @@ class ConvexSolver(ABC):
|
|
|
128
113
|
"""
|
|
129
114
|
raise NotImplementedError
|
|
130
115
|
|
|
116
|
+
def lower_convex_constraints(
|
|
117
|
+
self,
|
|
118
|
+
constraints: "ConstraintSet",
|
|
119
|
+
parameters: Optional[Dict[str, Any]] = None,
|
|
120
|
+
) -> Tuple[List[Any], Dict[str, Any]]:
|
|
121
|
+
"""Lower user ``.convex()`` constraints into this backend's form.
|
|
122
|
+
|
|
123
|
+
Called once by :func:`openscvx.symbolic.lower.lower_symbolic_problem`
|
|
124
|
+
after ``create_variables()`` and before ``initialize()``.
|
|
125
|
+
|
|
126
|
+
The default implementation refuses any user ``.convex()``
|
|
127
|
+
constraints — appropriate for backends like
|
|
128
|
+
:class:`openscvx.solvers.qpax_ptr_solver.QPAXPTRSolver` that don't
|
|
129
|
+
accept second-order-cone constraints. Backends that do accept them
|
|
130
|
+
(e.g. :class:`openscvx.solvers.cvxpy_ptr_solver.CVXPyPTRSolver`)
|
|
131
|
+
override this to invoke their backend-specific lowerer.
|
|
132
|
+
|
|
133
|
+
Args:
|
|
134
|
+
constraints: Categorized symbolic constraints. Only the
|
|
135
|
+
``nodal_convex`` / ``cross_node_convex`` lists matter here;
|
|
136
|
+
non-convex constraints go through the JAX lowering pipeline.
|
|
137
|
+
parameters: Optional dict of symbolic ``Parameter`` objects
|
|
138
|
+
referenced by the constraints. May be ``None``.
|
|
139
|
+
|
|
140
|
+
Returns:
|
|
141
|
+
``(lowered_list, parameter_map)``. The first is a list of
|
|
142
|
+
backend-specific constraint objects (e.g. ``cp.Constraint``);
|
|
143
|
+
the second maps parameter names to backend-specific parameter
|
|
144
|
+
objects. Both are empty for the default refusal path.
|
|
145
|
+
|
|
146
|
+
Raises:
|
|
147
|
+
NotImplementedError: if the user defined any ``.convex()``
|
|
148
|
+
constraints and this backend doesn't override.
|
|
149
|
+
"""
|
|
150
|
+
n = len(constraints.nodal_convex) + len(constraints.cross_node_convex)
|
|
151
|
+
if n:
|
|
152
|
+
raise NotImplementedError(
|
|
153
|
+
f"{type(self).__name__} does not support user-defined "
|
|
154
|
+
f".convex() constraints ({n} defined). Drop the .convex() "
|
|
155
|
+
"constraint or switch to a backend that supports them "
|
|
156
|
+
"(e.g. openscvx.CVXPyPTRSolver)."
|
|
157
|
+
)
|
|
158
|
+
return [], {}
|
|
159
|
+
|
|
131
160
|
@abstractmethod
|
|
132
161
|
def initialize(
|
|
133
162
|
self,
|
|
@@ -241,11 +270,17 @@ class ConvexSolver(ABC):
|
|
|
241
270
|
# Pydantic spec for dict / YAML validation
|
|
242
271
|
# =============================================================================
|
|
243
272
|
|
|
244
|
-
_SOLVER_MAP: Dict[str, type] = {} # populated by __init__.py after all classes are imported
|
|
245
273
|
|
|
274
|
+
class PTRSolverSpec(BaseModel):
|
|
275
|
+
"""Validates PTR solver configuration from dict/YAML input.
|
|
246
276
|
|
|
247
|
-
|
|
248
|
-
""
|
|
277
|
+
The ``backend`` discriminator selects which concrete PTR backend to build:
|
|
278
|
+
``"cvxpy"`` (the default,
|
|
279
|
+
:class:`openscvx.solvers.cvxpy_ptr_solver.CVXPyPTRSolver`) or ``"qpax"``
|
|
280
|
+
(:class:`openscvx.solvers.qpax_ptr_solver.QPAXPTRSolver`).
|
|
281
|
+
|
|
282
|
+
``cvx_solver``, ``cvxpygen``, and ``cvxpygen_override`` are CVXPy-only;
|
|
283
|
+
setting them under ``backend="qpax"`` is a configuration error.
|
|
249
284
|
|
|
250
285
|
!!! warning
|
|
251
286
|
Enabling ``cvxpygen`` currently disables sparse parameter declarations.
|
|
@@ -255,15 +290,61 @@ class SolverSpec(BaseModel):
|
|
|
255
290
|
"""
|
|
256
291
|
|
|
257
292
|
type: Literal["PTRSolver"] = "PTRSolver"
|
|
258
|
-
|
|
293
|
+
backend: Literal["cvxpy", "qpax"] = "cvxpy"
|
|
294
|
+
cvx_solver: Optional[str] = None
|
|
259
295
|
solver_args: Optional[Dict[str, Any]] = None
|
|
260
296
|
cvxpygen: bool = False
|
|
261
297
|
cvxpygen_override: bool = False
|
|
262
298
|
|
|
263
299
|
model_config = ConfigDict(extra="forbid")
|
|
264
300
|
|
|
301
|
+
@model_validator(mode="after")
|
|
302
|
+
def _check_backend_fields(self):
|
|
303
|
+
if self.backend == "qpax":
|
|
304
|
+
offenders = [
|
|
305
|
+
name
|
|
306
|
+
for name, value in (
|
|
307
|
+
("cvx_solver", self.cvx_solver),
|
|
308
|
+
("cvxpygen", self.cvxpygen),
|
|
309
|
+
("cvxpygen_override", self.cvxpygen_override),
|
|
310
|
+
)
|
|
311
|
+
if value
|
|
312
|
+
]
|
|
313
|
+
if offenders:
|
|
314
|
+
raise ValueError(
|
|
315
|
+
f"{offenders} only valid for backend='cvxpy'; "
|
|
316
|
+
"remove these fields or set backend='cvxpy'."
|
|
317
|
+
)
|
|
318
|
+
return self
|
|
319
|
+
|
|
265
320
|
def build(self) -> ConvexSolver:
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
321
|
+
# Local imports keep CVXPy / qpax out of the import path until the
|
|
322
|
+
# corresponding backend is actually requested.
|
|
323
|
+
if self.backend == "cvxpy":
|
|
324
|
+
from .cvxpy_ptr_solver import CVXPyPTRSolver
|
|
325
|
+
|
|
326
|
+
return CVXPyPTRSolver(
|
|
327
|
+
cvx_solver=self.cvx_solver or "QOCO",
|
|
328
|
+
solver_args=self.solver_args,
|
|
329
|
+
cvxpygen=self.cvxpygen,
|
|
330
|
+
cvxpygen_override=self.cvxpygen_override,
|
|
331
|
+
)
|
|
332
|
+
from .qpax_ptr_solver import QPAXPTRSolver
|
|
333
|
+
|
|
334
|
+
return QPAXPTRSolver(solver_args=self.solver_args)
|
|
335
|
+
|
|
336
|
+
|
|
337
|
+
def __getattr__(name: str):
|
|
338
|
+
"""Deprecated alias: ``SolverSpec`` → :class:`PTRSolverSpec`.
|
|
339
|
+
|
|
340
|
+
Kept for one release so existing dict/YAML configs and tests that import
|
|
341
|
+
``SolverSpec`` continue to work. Emit a ``DeprecationWarning`` on access.
|
|
342
|
+
"""
|
|
343
|
+
if name == "SolverSpec":
|
|
344
|
+
warnings.warn(
|
|
345
|
+
"openscvx.solvers.base.SolverSpec is deprecated; use PTRSolverSpec.",
|
|
346
|
+
DeprecationWarning,
|
|
347
|
+
stacklevel=2,
|
|
348
|
+
)
|
|
349
|
+
return PTRSolverSpec
|
|
350
|
+
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|