openscvx 0.5.3.dev31__tar.gz → 0.5.3.dev32__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.3.dev31/openscvx.egg-info → openscvx-0.5.3.dev32}/PKG-INFO +1 -1
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/_version.py +3 -3
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/algorithms/autotuner/augmented_lagrangian.py +2 -2
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/algorithms/penalty.py +4 -2
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/algorithms/scvx/iteration.py +11 -2
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/lowered/jax_constraints.py +8 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/solvers/cvxpy_ptr_solver.py +6 -3
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/solvers/moreau_ptr_solver.py +6 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/solvers/qpax_ptr_solver.py +6 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/symbolic/augmentation.py +0 -36
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/symbolic/lower.py +3 -1
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32/openscvx.egg-info}/PKG-INFO +1 -1
- openscvx-0.5.3.dev32/openscvx.egg-info/scm_version.json +8 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/solvers/test_qpax_ptr_solver.py +40 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/symbolic/test_augmentation.py +12 -26
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/test_autotuning.py +25 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/test_brachistochrone.py +71 -0
- openscvx-0.5.3.dev31/openscvx.egg-info/scm_version.json +0 -8
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/.github/assets/logo.svg +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/.github/release-drafter.yml +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/.github/workflows/_docs.yml +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/.github/workflows/branch-name.yml +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/.github/workflows/docs.yml +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/.github/workflows/lint.yml +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/.github/workflows/nightly.yml +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/.github/workflows/release-drafter.yml +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/.github/workflows/release.yml +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/.github/workflows/tests-integration.yml +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/.github/workflows/tests-unit.yml +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/.gitignore +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/.gitmodules +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/CONTRIBUTING.md +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/LICENSE +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/README.md +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/docs/Foundations/constraint_reformulation.md +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/docs/Foundations/control_parameterization.md +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/docs/Foundations/discretization.md +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/docs/Foundations/ocp.md +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/docs/Foundations/scvx.md +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/docs/Foundations/time_dilation.md +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/docs/UnderTheHood/batching_jit_grad.md +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/docs/UnderTheHood/custom_algorithms_autotuners.md +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/docs/UnderTheHood/lowering_architecture.md +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/docs/UnderTheHood/vectorization_and_vmapping.md +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/docs/UsersGuide/00_introduction.md +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/docs/UsersGuide/01_hello_world_brachistochrone.md +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/docs/UsersGuide/02_drone_racing_constraints.md +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/docs/UsersGuide/03_obstacle_avoidance_vmap.md +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/docs/UsersGuide/04_viewpoint_constraints.md +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/docs/UsersGuide/05_visualization.md +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/docs/UsersGuide/06_logic.md +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/docs/UsersGuide/07_lie.md +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/docs/UsersGuide/08_mpcc.md +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/docs/UsersGuide/09_mjx_dynamics.md +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/docs/assets/favicon.png +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/docs/assets/images/ct-scvx_dark.png +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/docs/assets/images/ct-scvx_light.png +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/docs/assets/images/ctcs_dark.png +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/docs/assets/images/ctcs_light.png +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/docs/assets/images/problem_class_dark.png +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/docs/assets/images/problem_class_light.png +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/docs/assets/logo.svg +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/docs/assets/openscvx_logo_square.png +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/docs/assets/viser-client/index.html +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/docs/assets/viser-recordings/drone_racing.viser +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/docs/assets/viser-recordings/franka_fr3v2_pick_place.viser +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/docs/citation.md +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/docs/examples.md +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/docs/index.md +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/docs/javascripts/mathjax.js +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/docs/versions.json +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/_viser_embed_export.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/abstract/brachistochrone.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/abstract/brachistochrone_batched.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/abstract/flappy_bird.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/abstract/hypersensitive.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/abstract/impulsive.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/abstract/stl_integer_variable.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/abstract/stl_or.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/aircraft/supersonic_time_to_climb.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/animations/7_dof_arm.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/animations/_camera.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/animations/_render.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/animations/_sensor_view.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/animations/dr_vp_polytope.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/animations/franka_fr3v2_pick_place.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/animations/logo.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/animations/obstacle_avoidance_vmap.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/arm/3_dof_arm.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/arm/7_dof_arm.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/arm/7_dof_arm_collision.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/arm/7_dof_arm_vp.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/arm/franka_fr3v2_pick_place.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/arm/franka_fr3v2_viewplanning.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/arm/franka_fr3v2_viewplanning_nodal.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/car/dubins_car.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/car/dubins_car_disjoint.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/car/dubins_car_obstacle_conditional.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/car/dubins_car_obstacle_stl.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/car/dubins_car_stl_or.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/car/dubins_car_waypoint_stl.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/double_integrator/_plotting.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/double_integrator/moving_safe_zones.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/drone/2d_obstacle_avoidance_batched_ic.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/drone/cinema_vp.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/drone/cinema_vp_nodal.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/drone/dr_double_integrator.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/drone/dr_vp.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/drone/dr_vp_nodal.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/drone/dr_vp_polytope.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/drone/drone_racing.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/drone/drone_racing_batched_gates.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/drone/logo.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/drone/logo_utils/acl_logo.svg +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/drone/logo_utils/openscvx_logo_single.svg +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/drone/logo_utils/quadrotor_mesh.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/drone/logo_utils/svg_path_utils.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/drone/multi_agent_circle_swap.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/drone/obstacle_avoidance.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/drone/obstacle_avoidance_nodal.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/drone/obstacle_avoidance_vmap.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/drone/obstacle_avoidance_vmap_2d.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/drone/openscvx_logo.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/frax/panda_frax.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/frax/panda_frax_pick_place.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/frax/panda_frax_viewplanning.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/frax/panda_frax_waypoint.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/mjx/cartpole_mjx.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/mjx/double_cartpole_mjx.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/mjx/skydio_x2_mjx.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/mjx/triple_cartpole_3d_mjx.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/mjx/triple_cartpole_game.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/mjx/triple_cartpole_mjx.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/mpc/double_integrator_discrete.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/mpc/double_integrator_drone_racing.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/mpc/dubins_car_circle_analytical.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/mpc/dubins_car_circle_discrete.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/mpc/realtime_double_integrator_drone_racing.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/plotting.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/plotting_viser.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/realtime/3DoF_pdg_realtime.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/realtime/6DoF_pdg_realtime.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/realtime/base_problems/3DoF_pdg_realtime_base.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/realtime/base_problems/6DoF_pdg_realtime_base.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/realtime/base_problems/cinema_vp_realtime_base.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/realtime/base_problems/drone_racing_realtime_base.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/realtime/base_problems/dubins_car_realtime_base.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/realtime/base_problems/obstacle_avoidance_realtime_base.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/realtime/cinema_vp_realtime.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/realtime/drone_racing_realtime.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/realtime/dubins_car_realtime.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/realtime/obstacle_avoidance_realtime.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/rocket/3DoF_pdg.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/rocket/6DoF_pdg.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/rocket/6DoF_pdg_batched_ic.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/rocket/ascent_launch_vehicle.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/spacecraft/halo_orbit.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/spacecraft/hohmann_transfer.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/spacecraft/let_transfer.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/spacecraft/proxops_cw.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/examples/spacecraft/relative_loitering.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/figures/ctlos_cine.gif +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/figures/ctlos_dr.gif +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/figures/dtlos_cine.gif +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/figures/dtlos_dr.gif +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/figures/openscvx_logo.svg +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/figures/openscvx_logo_square.png +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/figures/oscvx_structure_full_dark.svg +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/figures/video_preview.png +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/material/__init__.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/material/overrides/assets/stylesheets/custom.css +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/material/overrides/assets/stylesheets/home-dropin.css +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/material/overrides/assets/stylesheets/home-hero.css +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/material/overrides/assets/stylesheets/home-viser.css +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/material/overrides/home.html +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/material/overrides/main.html +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/material/overrides/partials/home-diagram.html +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/material/overrides/partials/home-dropin-banner.html +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/material/overrides/partials/home-hero.html +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/material/overrides/partials/home-pipeline.html +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/material/overrides/partials/home-viser-strip.html +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/mkdocs.yml +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/__init__.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/__main__.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/algorithms/__init__.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/algorithms/autotuner/__init__.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/algorithms/autotuner/acceptance_ratio.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/algorithms/autotuner/adaptive_proximal_weight.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/algorithms/autotuner/base.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/algorithms/autotuner/constant_proximal_weight.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/algorithms/autotuner/ramp_proximal_weight.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/algorithms/base.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/algorithms/history.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/algorithms/hyperparams.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/algorithms/loop.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/algorithms/optimization_results.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/algorithms/scvx/__init__.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/algorithms/scvx/penalized_trust_region.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/algorithms/state.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/algorithms/weights.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/config.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/discretization/__init__.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/discretization/base.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/discretization/discretize_linearize.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/discretization/linearize_discretize.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/discretization/linearize_discretize_sparse.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/discretization/sparse_utils/__init__.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/discretization/sparse_utils/bcoo_helpers.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/discretization/sparse_utils/sparse_jacobian.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/expert/__init__.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/expert/byof.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/expert/lowering.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/expert/validation.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/init/__init__.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/init/interpolation.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/init/inverse_kinematics.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/integrations/__init__.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/integrations/_utils.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/integrations/base.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/integrations/frax.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/integrations/menagerie.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/integrations/mjx.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/integrators/__init__.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/integrators/diffrax.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/integrators/runge_kutta.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/loader.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/lowered/__init__.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/lowered/cvxpy_constraints.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/lowered/cvxpy_variables.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/lowered/dynamics.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/lowered/parameters.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/lowered/problem.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/lowered/unified.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/plotting/__init__.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/plotting/plotting.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/plotting/publication.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/plotting/scp_iteration.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/plotting/viser/__init__.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/plotting/viser/animated.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/plotting/viser/coordinates.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/plotting/viser/orbits.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/plotting/viser/plotly_integration.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/plotting/viser/primitives.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/plotting/viser/scp.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/plotting/viser/server.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/problem.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/propagation/__init__.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/propagation/post_processing.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/propagation/propagation.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/solvers/__init__.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/solvers/base.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/solvers/cones.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/solvers/ptr_solver.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/symbolic/__init__.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/symbolic/affine.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/symbolic/builder.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/symbolic/canonicalize.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/symbolic/constraint_set.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/symbolic/expr/__init__.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/symbolic/expr/arithmetic.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/symbolic/expr/array.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/symbolic/expr/constraint.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/symbolic/expr/control.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/symbolic/expr/expr.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/symbolic/expr/lie/__init__.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/symbolic/expr/lie/adjoint.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/symbolic/expr/lie/se3.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/symbolic/expr/lie/so3.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/symbolic/expr/linalg.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/symbolic/expr/logic.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/symbolic/expr/math.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/symbolic/expr/parameter.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/symbolic/expr/spatial.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/symbolic/expr/state.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/symbolic/expr/stl.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/symbolic/expr/stljax.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/symbolic/expr/time.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/symbolic/expr/variable.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/symbolic/expr/vmap.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/symbolic/hashing.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/symbolic/lowerers/__init__.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/symbolic/lowerers/cvxpy/__init__.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/symbolic/lowerers/cvxpy/_lowerer.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/symbolic/lowerers/cvxpy/_registry.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/symbolic/lowerers/cvxpy/arithmetic.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/symbolic/lowerers/cvxpy/array.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/symbolic/lowerers/cvxpy/constraint.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/symbolic/lowerers/cvxpy/control.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/symbolic/lowerers/cvxpy/expr.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/symbolic/lowerers/cvxpy/linalg.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/symbolic/lowerers/cvxpy/logic.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/symbolic/lowerers/cvxpy/math.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/symbolic/lowerers/cvxpy/state.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/symbolic/lowerers/jax/__init__.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/symbolic/lowerers/jax/_lowerer.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/symbolic/lowerers/jax/_registry.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/symbolic/lowerers/jax/arithmetic.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/symbolic/lowerers/jax/array.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/symbolic/lowerers/jax/constraint.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/symbolic/lowerers/jax/control.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/symbolic/lowerers/jax/expr.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/symbolic/lowerers/jax/lie.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/symbolic/lowerers/jax/linalg.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/symbolic/lowerers/jax/logic.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/symbolic/lowerers/jax/math.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/symbolic/lowerers/jax/spatial.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/symbolic/lowerers/jax/state.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/symbolic/lowerers/jax/stl.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/symbolic/lowerers/jax/stljax.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/symbolic/lowerers/jax/vmap.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/symbolic/parser/__init__.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/symbolic/parser/_registry.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/symbolic/parser/array.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/symbolic/parser/constraint.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/symbolic/parser/lie.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/symbolic/parser/linalg.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/symbolic/parser/logic.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/symbolic/parser/math.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/symbolic/parser/parser.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/symbolic/parser/spatial.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/symbolic/parser/stl.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/symbolic/parser/stljax.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/symbolic/parser/tokenizer.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/symbolic/preprocessing.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/symbolic/problem.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/symbolic/sparsity.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/symbolic/unified.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/utils/__init__.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/utils/cache.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/utils/caching.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/utils/printing.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/utils/profiling.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/utils/utils.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx.egg-info/SOURCES.txt +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx.egg-info/dependency_links.txt +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx.egg-info/entry_points.txt +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx.egg-info/requires.txt +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx.egg-info/scm_file_list.json +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx.egg-info/top_level.txt +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/pyproject.toml +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/scripts/gen_example_pages.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/scripts/gen_ref_pages.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/scripts/mkdocs_copy_viser_client_hook.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/setup.cfg +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/__init__.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/_marks.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/algorithms/__init__.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/algorithms/_iteration_helpers.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/algorithms/autotuner/__init__.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/algorithms/autotuner/test_defaults_agreement.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/algorithms/autotuner/test_hyper_overrides.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/algorithms/autotuner/test_update_weights_jit.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/algorithms/test_algorithm_state_pytree.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/algorithms/test_iteration_fn_jit.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/algorithms/test_iteration_fn_parity.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/algorithms/test_make_solve_loop.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/brachistochrone_analytical.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/conftest.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/expr/__init__.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/expr/test_gmsr.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/fixtures/brachistochrone.json +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/fixtures/brachistochrone.yaml +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/hohmann_analytical.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/integrations/__init__.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/integrations/test_mjx.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/integrations/test_mjx_dynamics.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/solvers/__init__.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/solvers/_iteration_callback_helpers.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/solvers/test_cvxpy_callback_jit_spike.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/solvers/test_iteration_callback_cvxpy.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/solvers/test_iteration_callback_moreau.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/solvers/test_iteration_callback_qpax.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/solvers/test_iteration_callback_vmap.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/solvers/test_moreau_ptr_solver.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/solvers/test_subproblem_pytree.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/symbolic/__init__.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/symbolic/expr/__init__.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/symbolic/expr/test_arithmetic.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/symbolic/expr/test_array.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/symbolic/expr/test_constraint.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/symbolic/expr/test_expr.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/symbolic/expr/test_lie.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/symbolic/expr/test_linalg.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/symbolic/expr/test_logic.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/symbolic/expr/test_math.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/symbolic/expr/test_node_reference.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/symbolic/expr/test_parameters.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/symbolic/expr/test_scaling.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/symbolic/expr/test_spatial.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/symbolic/expr/test_stl.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/symbolic/expr/test_variable.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/symbolic/expr/test_vmap.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/symbolic/parser/__init__.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/symbolic/parser/test_array.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/symbolic/parser/test_constraint.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/symbolic/parser/test_lie.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/symbolic/parser/test_linalg.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/symbolic/parser/test_load.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/symbolic/parser/test_logic.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/symbolic/parser/test_math.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/symbolic/parser/test_parser.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/symbolic/parser/test_spatial.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/symbolic/parser/test_stl.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/symbolic/parser/test_tokenizer.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/symbolic/parser/test_vmap.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/symbolic/test_hashing.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/symbolic/test_lower_cvxpy.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/symbolic/test_lower_jax.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/symbolic/test_preprocessing.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/symbolic/test_sparsity.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/symbolic/test_unified.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/test_cvxpygen_optional.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/test_discretization.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/test_examples.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/test_expert.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/test_impulsive.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/test_init.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/test_integrators.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/test_loader.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/test_multishot_propagation.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/test_optimization_results.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/test_plotting.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/test_propagation.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/test_solve_batched_brachistochrone.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/test_solve_batched_cvxpy_export_errors.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/test_solve_batched_export_roundtrip.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/test_solve_batched_inference.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/test_solve_jax_bare_brachistochrone.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/test_solve_jax_jit_brachistochrone.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/test_solve_jax_vmap_brachistochrone.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/tests/test_solve_jax_vmap_converged_no_drift.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: openscvx
|
|
3
|
-
Version: 0.5.3.
|
|
3
|
+
Version: 0.5.3.dev32
|
|
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
|
|
@@ -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.3.
|
|
22
|
-
__version_tuple__ = version_tuple = (0, 5, 3, '
|
|
21
|
+
__version__ = version = '0.5.3.dev32'
|
|
22
|
+
__version_tuple__ = version_tuple = (0, 5, 3, 'dev32')
|
|
23
23
|
|
|
24
|
-
__commit_id__ = commit_id = '
|
|
24
|
+
__commit_id__ = commit_id = 'gd1964080e'
|
{openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/openscvx/algorithms/autotuner/augmented_lagrangian.py
RENAMED
|
@@ -206,7 +206,7 @@ class AugmentedLagrangian(AcceptanceRatioAutotuner):
|
|
|
206
206
|
|
|
207
207
|
for idx, constraint in enumerate(nodal_constraints.nodal):
|
|
208
208
|
g = constraint.func(candidate.x, candidate.u, 0, params)
|
|
209
|
-
nu = jnp.maximum(0.0, g)
|
|
209
|
+
nu = jnp.abs(g) if constraint.is_equality else jnp.maximum(0.0, g)
|
|
210
210
|
|
|
211
211
|
if constraint.nodes is not None:
|
|
212
212
|
nodes_array = jnp.asarray(constraint.nodes)
|
|
@@ -245,7 +245,7 @@ class AugmentedLagrangian(AcceptanceRatioAutotuner):
|
|
|
245
245
|
|
|
246
246
|
for idx, constraint in enumerate(nodal_constraints.cross_node):
|
|
247
247
|
g = constraint.func(candidate.x, candidate.u, params)
|
|
248
|
-
nu = jnp.sum(jnp.maximum(0.0, g))
|
|
248
|
+
nu = jnp.sum(jnp.abs(g) if constraint.is_equality else jnp.maximum(0.0, g))
|
|
249
249
|
current = state.lam_vb_cross[idx]
|
|
250
250
|
case1 = current + nu * scale
|
|
251
251
|
case2 = current + (nu**2) / state.hyper.ep * scale
|
|
@@ -96,12 +96,14 @@ def calculate_nonlinear_penalty(
|
|
|
96
96
|
else:
|
|
97
97
|
g_filtered = g
|
|
98
98
|
w = lam_vb_nodal[:, idx]
|
|
99
|
-
|
|
99
|
+
viol = jnp.abs(g_filtered) if constraint.is_equality else jnp.maximum(0.0, g_filtered)
|
|
100
|
+
nodal_penalty = nodal_penalty + jnp.sum(w * viol)
|
|
100
101
|
|
|
101
102
|
for idx, constraint in enumerate(nodal_constraints.cross_node):
|
|
102
103
|
w = lam_vb_cross[idx]
|
|
103
104
|
g = constraint.func(x_bar, u_bar, params)
|
|
104
|
-
|
|
105
|
+
viol = jnp.abs(g) if constraint.is_equality else jnp.maximum(0.0, g)
|
|
106
|
+
nodal_penalty = nodal_penalty + w * jnp.sum(viol)
|
|
105
107
|
|
|
106
108
|
cost = calculate_cost_from_state(x_bar, settings, lam_cost)
|
|
107
109
|
x_diff = settings.sim.inv_S_x @ (x_bar[1:, :] - x_prop).T
|
|
@@ -145,6 +145,11 @@ def make_scp_iteration(
|
|
|
145
145
|
n_u = settings.sim.n_controls
|
|
146
146
|
n_nodal = len(jax_constraints.nodal)
|
|
147
147
|
|
|
148
|
+
# Equality columns measure violation two-sided (|nu_vb|); inequalities use
|
|
149
|
+
# the positive part. Built once at trace time as static boolean masks.
|
|
150
|
+
nodal_eq_mask = jnp.asarray([c.is_equality for c in jax_constraints.nodal], dtype=bool)
|
|
151
|
+
cross_eq_mask = jnp.asarray([c.is_equality for c in jax_constraints.cross_node], dtype=bool)
|
|
152
|
+
|
|
148
153
|
# Accept either a bare ``jax.jit`` callable or a ``jax.export`` wrapper.
|
|
149
154
|
dis_continuous = dis_continuous.call if hasattr(dis_continuous, "call") else dis_continuous
|
|
150
155
|
dis_impulsive = dis_impulsive.call if hasattr(dis_impulsive, "call") else dis_impulsive
|
|
@@ -311,9 +316,13 @@ def make_scp_iteration(
|
|
|
311
316
|
VC = jnp.abs(inv_S_x @ solution.nu.T).T
|
|
312
317
|
J_tr = jnp.sum(TR**2)
|
|
313
318
|
J_vc = jnp.sum(VC)
|
|
314
|
-
|
|
315
|
-
jnp.maximum(0.0, solution.
|
|
319
|
+
nodal_vb = jnp.where(
|
|
320
|
+
nodal_eq_mask, jnp.abs(solution.nu_vb), jnp.maximum(0.0, solution.nu_vb)
|
|
321
|
+
)
|
|
322
|
+
cross_vb = jnp.where(
|
|
323
|
+
cross_eq_mask, jnp.abs(solution.nu_vb_cross), jnp.maximum(0.0, solution.nu_vb_cross)
|
|
316
324
|
)
|
|
325
|
+
J_vb = jnp.sum(nodal_vb) + jnp.sum(cross_vb)
|
|
317
326
|
state = state.replace(
|
|
318
327
|
J_tr=jnp.asarray(J_tr, dtype=state.J_tr.dtype),
|
|
319
328
|
J_vb=jnp.asarray(J_vb, dtype=state.J_vb.dtype),
|
|
@@ -37,12 +37,19 @@ class LoweredNodalConstraint:
|
|
|
37
37
|
|
|
38
38
|
nodes (Optional[List[int]]): List of node indices where this constraint applies.
|
|
39
39
|
Set after lowering from NodalConstraint.
|
|
40
|
+
|
|
41
|
+
is_equality (bool): True if the source constraint was an ``Equality``
|
|
42
|
+
(``g == 0``), False for an ``Inequality`` (``g <= 0``). Controls the
|
|
43
|
+
virtual-buffer penalty shape downstream: equalities are penalized
|
|
44
|
+
two-sided (``|nu_vb|``), inequalities one-sided (``pos(nu_vb)``).
|
|
45
|
+
Defaults to False, preserving the inequality behavior.
|
|
40
46
|
"""
|
|
41
47
|
|
|
42
48
|
func: Callable[[jnp.ndarray, jnp.ndarray], jnp.ndarray]
|
|
43
49
|
grad_g_x: Optional[Callable[[jnp.ndarray, jnp.ndarray], jnp.ndarray]] = None
|
|
44
50
|
grad_g_u: Optional[Callable[[jnp.ndarray, jnp.ndarray], jnp.ndarray]] = None
|
|
45
51
|
nodes: Optional[List[int]] = None
|
|
52
|
+
is_equality: bool = False
|
|
46
53
|
|
|
47
54
|
|
|
48
55
|
@dataclass
|
|
@@ -110,6 +117,7 @@ class LoweredCrossNodeConstraint:
|
|
|
110
117
|
func: Callable[[jnp.ndarray, jnp.ndarray, dict], jnp.ndarray]
|
|
111
118
|
grad_g_X: Callable[[jnp.ndarray, jnp.ndarray, dict], jnp.ndarray]
|
|
112
119
|
grad_g_U: Callable[[jnp.ndarray, jnp.ndarray, dict], jnp.ndarray]
|
|
120
|
+
is_equality: bool = False
|
|
113
121
|
|
|
114
122
|
|
|
115
123
|
@dataclass
|
|
@@ -490,18 +490,21 @@ class CVXPyPTRSolver(PTRSolver):
|
|
|
490
490
|
# Virtual Control Slack
|
|
491
491
|
cost += sum(cp.sum(lam_vc[i - 1] * cp.abs(nu[i - 1])) for i in range(1, settings.sim.n))
|
|
492
492
|
|
|
493
|
-
# Virtual buffer penalty for nodal constraints (per-node weighting)
|
|
493
|
+
# Virtual buffer penalty for nodal constraints (per-node weighting).
|
|
494
|
+
# Equalities penalize |nu_vb|, inequalities penalize pos(nu_vb).
|
|
494
495
|
idx_ncvx = 0
|
|
495
496
|
if jax_constraints.nodal:
|
|
496
497
|
for constraint in jax_constraints.nodal:
|
|
497
|
-
|
|
498
|
+
pen = cp.abs if constraint.is_equality else cp.pos
|
|
499
|
+
cost += lam_vb_nodal[:, idx_ncvx] @ pen(nu_vb[idx_ncvx])
|
|
498
500
|
idx_ncvx += 1
|
|
499
501
|
|
|
500
502
|
# Virtual slack penalty for cross-node constraints
|
|
501
503
|
idx_cross = 0
|
|
502
504
|
if jax_constraints.cross_node:
|
|
503
505
|
for constraint in jax_constraints.cross_node:
|
|
504
|
-
|
|
506
|
+
pen = cp.abs if constraint.is_equality else cp.pos
|
|
507
|
+
cost += lam_vb_cross[idx_cross] * pen(nu_vb_cross[idx_cross])
|
|
505
508
|
idx_cross += 1
|
|
506
509
|
|
|
507
510
|
return cost
|
|
@@ -490,6 +490,12 @@ class MoreauPTRSolver(PTRSolver):
|
|
|
490
490
|
self._c_u_j = jnp.asarray(self._c_u, dtype=f)
|
|
491
491
|
self._jax_dtype = f
|
|
492
492
|
|
|
493
|
+
if any(c.is_equality for c in jax_constraints.nodal):
|
|
494
|
+
raise NotImplementedError(
|
|
495
|
+
"MoreauPTRSolver does not support L1-penalized equality "
|
|
496
|
+
"constraints. Use CVXPyPTRSolver."
|
|
497
|
+
)
|
|
498
|
+
|
|
493
499
|
self.layout = _ConicLayout(N=N, n_x=n_x, n_u=n_u, n_nodal=len(jax_constraints.nodal))
|
|
494
500
|
self._jax_constraints = jax_constraints
|
|
495
501
|
self._x_unified = x_unified
|
|
@@ -329,6 +329,12 @@ class QPAXPTRSolver(PTRSolver):
|
|
|
329
329
|
self._c_u_j = jnp.asarray(self._c_u, dtype=f)
|
|
330
330
|
self._jax_dtype = f
|
|
331
331
|
|
|
332
|
+
if any(c.is_equality for c in jax_constraints.nodal):
|
|
333
|
+
raise NotImplementedError(
|
|
334
|
+
"QPAXPTRSolver does not support L1-penalized equality "
|
|
335
|
+
"constraints. Use CVXPyPTRSolver."
|
|
336
|
+
)
|
|
337
|
+
|
|
332
338
|
self.layout = _QPLayout(N=N, n_x=n_x, n_u=n_u, n_nodal=len(jax_constraints.nodal))
|
|
333
339
|
self._jax_constraints = jax_constraints
|
|
334
340
|
self._x_unified = x_unified
|
|
@@ -75,30 +75,6 @@ from openscvx.symbolic.expr.state import State
|
|
|
75
75
|
from openscvx.symbolic.expr.time import Time
|
|
76
76
|
|
|
77
77
|
|
|
78
|
-
def _check_nonconvex_equality(constraint: Constraint, context: str) -> None:
|
|
79
|
-
"""Raise a helpful error if constraint is a non-convex equality.
|
|
80
|
-
|
|
81
|
-
Non-convex equality constraints are not supported.
|
|
82
|
-
|
|
83
|
-
Args:
|
|
84
|
-
constraint: The constraint to check
|
|
85
|
-
context: Description of where this constraint appears (for error message)
|
|
86
|
-
|
|
87
|
-
Raises:
|
|
88
|
-
ValueError: If constraint is an Equality and not marked as convex
|
|
89
|
-
"""
|
|
90
|
-
if isinstance(constraint, Equality) and not constraint.is_convex:
|
|
91
|
-
raise ValueError(
|
|
92
|
-
f"Non-convex equality constraint in {context}. "
|
|
93
|
-
f"Equality constraints must be affine (linear) and marked as convex "
|
|
94
|
-
f"using .convex(). For example:\n"
|
|
95
|
-
f" (velocity.at(0) == velocity.at(n-1)).convex()\n"
|
|
96
|
-
f"If your equality constraint is nonlinear, consider reformulating it "
|
|
97
|
-
f"as two inequality constraints or using a different approach.\n"
|
|
98
|
-
f"Constraint: {constraint}"
|
|
99
|
-
)
|
|
100
|
-
|
|
101
|
-
|
|
102
78
|
def sort_ctcs_constraints(
|
|
103
79
|
constraints_ctcs: List[CTCS],
|
|
104
80
|
) -> Tuple[List[CTCS], List[Tuple[int, int]], int]:
|
|
@@ -265,9 +241,6 @@ def separate_constraints(constraint_set: ConstraintSet, n_nodes: int) -> Constra
|
|
|
265
241
|
f"Constraint: {c.constraint}"
|
|
266
242
|
)
|
|
267
243
|
|
|
268
|
-
# Check for non-convex equality constraints
|
|
269
|
-
_check_nonconvex_equality(c.constraint, "nodal constraint")
|
|
270
|
-
|
|
271
244
|
# Regular nodal constraint - categorize by convexity
|
|
272
245
|
if c.constraint.is_convex:
|
|
273
246
|
constraint_set.nodal_convex.append(c)
|
|
@@ -277,9 +250,6 @@ def separate_constraints(constraint_set: ConstraintSet, n_nodes: int) -> Constra
|
|
|
277
250
|
elif isinstance(c, Constraint):
|
|
278
251
|
# Bare constraint - check if it's a cross-node constraint
|
|
279
252
|
if _contains_node_reference(c):
|
|
280
|
-
# Check for non-convex equality constraints
|
|
281
|
-
_check_nonconvex_equality(c, "cross-node constraint")
|
|
282
|
-
|
|
283
253
|
# Cross-node constraint: wrap in CrossNodeConstraint
|
|
284
254
|
cross_node = CrossNodeConstraint(c)
|
|
285
255
|
if c.is_convex:
|
|
@@ -287,9 +257,6 @@ def separate_constraints(constraint_set: ConstraintSet, n_nodes: int) -> Constra
|
|
|
287
257
|
else:
|
|
288
258
|
constraint_set.cross_node.append(cross_node)
|
|
289
259
|
else:
|
|
290
|
-
# Check for non-convex equality constraints
|
|
291
|
-
_check_nonconvex_equality(c, "nodal constraint")
|
|
292
|
-
|
|
293
260
|
# Regular constraint: apply at all nodes
|
|
294
261
|
all_nodes = list(range(n_nodes))
|
|
295
262
|
nodal_constraint = NodalConstraint(c, all_nodes)
|
|
@@ -310,9 +277,6 @@ def separate_constraints(constraint_set: ConstraintSet, n_nodes: int) -> Constra
|
|
|
310
277
|
# Add nodal constraints from CTCS constraints that have check_nodally=True
|
|
311
278
|
ctcs_nodal_constraints = get_nodal_constraints_from_ctcs(constraint_set.ctcs)
|
|
312
279
|
for constraint, interval in ctcs_nodal_constraints:
|
|
313
|
-
# Check for non-convex equality constraints
|
|
314
|
-
_check_nonconvex_equality(constraint, "CTCS check_nodally constraint")
|
|
315
|
-
|
|
316
280
|
# CTCS check_nodally constraints cannot have NodeReferences (validated above)
|
|
317
281
|
# Convert CTCS interval (start, end) to list of nodes [start, start+1, ..., end-1]
|
|
318
282
|
interval_nodes = list(range(interval[0], interval[1]))
|
|
@@ -73,7 +73,7 @@ from openscvx.lowered import (
|
|
|
73
73
|
LoweredProblem,
|
|
74
74
|
)
|
|
75
75
|
from openscvx.symbolic.constraint_set import ConstraintSet
|
|
76
|
-
from openscvx.symbolic.expr import Expr, NodeReference, traverse
|
|
76
|
+
from openscvx.symbolic.expr import Equality, Expr, NodeReference, traverse
|
|
77
77
|
from openscvx.symbolic.expr.control import Control
|
|
78
78
|
from openscvx.symbolic.unified import unify_controls, unify_states
|
|
79
79
|
|
|
@@ -628,6 +628,7 @@ def _lower_jax_constraints(
|
|
|
628
628
|
grad_g_x=jax.vmap(jacfwd(fn, argnums=0), in_axes=(0, 0, None, None)),
|
|
629
629
|
grad_g_u=jax.vmap(jacfwd(fn, argnums=1), in_axes=(0, 0, None, None)),
|
|
630
630
|
nodes=constraints.nodal[i].nodes,
|
|
631
|
+
is_equality=isinstance(constraints.nodal[i].constraint, Equality),
|
|
631
632
|
)
|
|
632
633
|
lowered_nodal.append(constraint)
|
|
633
634
|
|
|
@@ -644,6 +645,7 @@ def _lower_jax_constraints(
|
|
|
644
645
|
func=constraint_fn,
|
|
645
646
|
grad_g_X=grad_g_X,
|
|
646
647
|
grad_g_U=grad_g_U,
|
|
648
|
+
is_equality=isinstance(cross_node_constraint.constraint, Equality),
|
|
647
649
|
)
|
|
648
650
|
lowered_cross_node.append(cross_node_lowered)
|
|
649
651
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: openscvx
|
|
3
|
-
Version: 0.5.3.
|
|
3
|
+
Version: 0.5.3.dev32
|
|
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
|
|
@@ -231,6 +231,46 @@ def test_qpax_rejects_user_convex_constraints():
|
|
|
231
231
|
)
|
|
232
232
|
|
|
233
233
|
|
|
234
|
+
def test_qpax_rejects_nodal_equality():
|
|
235
|
+
"""L1-penalized nodal equalities need a two-sided slack penalty, which the
|
|
236
|
+
QPAX one-sided positive-part reformulation can't express; lowering must
|
|
237
|
+
raise ``NotImplementedError`` naming CVXPyPTRSolver."""
|
|
238
|
+
n = 5
|
|
239
|
+
pos = ox.State("pos", shape=(2,))
|
|
240
|
+
pos.min = np.array([-10.0, -10.0])
|
|
241
|
+
pos.max = np.array([10.0, 10.0])
|
|
242
|
+
pos.initial = np.array([0.0, 0.0])
|
|
243
|
+
pos.final = np.array([3.0, 3.0])
|
|
244
|
+
vel = ox.State("vel", shape=(2,))
|
|
245
|
+
vel.min = np.array([-5.0, -5.0])
|
|
246
|
+
vel.max = np.array([5.0, 5.0])
|
|
247
|
+
vel.initial = np.array([0.0, 0.0])
|
|
248
|
+
vel.final = [("free", 0.0), ("free", 0.0)]
|
|
249
|
+
u = ox.Control("u", shape=(2,))
|
|
250
|
+
u.min = np.array([-3.0, -3.0])
|
|
251
|
+
u.max = np.array([3.0, 3.0])
|
|
252
|
+
u.guess = np.zeros((n, 2))
|
|
253
|
+
dyn = {"pos": vel, "vel": u}
|
|
254
|
+
time = ox.Time(initial=0.0, final=("minimize", 2.0), min=0.0, max=10.0)
|
|
255
|
+
|
|
256
|
+
eq_constraint = (pos == np.array([1.0, 1.0])).at([2])
|
|
257
|
+
|
|
258
|
+
with pytest.raises(
|
|
259
|
+
NotImplementedError,
|
|
260
|
+
match=r"QPAXPTRSolver does not support L1-penalized equality",
|
|
261
|
+
):
|
|
262
|
+
Problem(
|
|
263
|
+
dynamics=dyn,
|
|
264
|
+
states=[pos, vel],
|
|
265
|
+
controls=[u],
|
|
266
|
+
time=time,
|
|
267
|
+
constraints=[eq_constraint],
|
|
268
|
+
N=n,
|
|
269
|
+
float_dtype="float64",
|
|
270
|
+
solver={"backend": "qpax"},
|
|
271
|
+
)
|
|
272
|
+
|
|
273
|
+
|
|
234
274
|
# ============================================================================
|
|
235
275
|
# Round-trip parity with CVXPyPTRSolver
|
|
236
276
|
# ============================================================================
|
|
@@ -1442,28 +1442,21 @@ def test_regular_convex_constraint_without_node_reference_accepted():
|
|
|
1442
1442
|
# =============================================================================
|
|
1443
1443
|
|
|
1444
1444
|
|
|
1445
|
-
def
|
|
1446
|
-
"""
|
|
1445
|
+
def test_nonconvex_cross_node_equality_accepted():
|
|
1446
|
+
"""Non-convex cross-node equalities are accepted as soft L1-penalized constraints."""
|
|
1447
1447
|
n_nodes = 10
|
|
1448
1448
|
velocity = State("vel", shape=(3,))
|
|
1449
1449
|
|
|
1450
|
-
# Create a non-convex cross-node equality (periodic boundary condition without .convex())
|
|
1451
1450
|
cross_node_equality = velocity.at(0) == velocity.at(9)
|
|
1452
|
-
|
|
1453
|
-
# Verify it's an Equality and not marked convex
|
|
1454
1451
|
assert isinstance(cross_node_equality, Equality)
|
|
1455
1452
|
assert not cross_node_equality.is_convex
|
|
1456
1453
|
|
|
1457
|
-
# Should raise a helpful error
|
|
1458
1454
|
constraint_set = ConstraintSet(unsorted=[cross_node_equality])
|
|
1459
|
-
|
|
1460
|
-
separate_constraints(constraint_set, n_nodes=n_nodes)
|
|
1455
|
+
result = separate_constraints(constraint_set, n_nodes=n_nodes)
|
|
1461
1456
|
|
|
1462
|
-
#
|
|
1463
|
-
|
|
1464
|
-
assert
|
|
1465
|
-
assert ".convex()" in msg
|
|
1466
|
-
assert "cross-node" in msg
|
|
1457
|
+
# Routed into the non-convex cross-node list (penalized), not the convex list
|
|
1458
|
+
assert len(result.cross_node) == 1
|
|
1459
|
+
assert len(result.cross_node_convex) == 0
|
|
1467
1460
|
|
|
1468
1461
|
|
|
1469
1462
|
def test_convex_cross_node_equality_accepted():
|
|
@@ -1486,28 +1479,21 @@ def test_convex_cross_node_equality_accepted():
|
|
|
1486
1479
|
assert len(result.cross_node) == 0
|
|
1487
1480
|
|
|
1488
1481
|
|
|
1489
|
-
def
|
|
1490
|
-
"""
|
|
1482
|
+
def test_nonconvex_nodal_equality_accepted():
|
|
1483
|
+
"""Non-convex nodal equalities are accepted as soft L1-penalized constraints."""
|
|
1491
1484
|
n_nodes = 10
|
|
1492
1485
|
position = State("pos", shape=(3,))
|
|
1493
1486
|
|
|
1494
|
-
# Create a non-convex nodal equality (without .convex())
|
|
1495
1487
|
nodal_equality = (position == np.zeros(3)).at([0, 5, 9])
|
|
1496
|
-
|
|
1497
|
-
# Verify it's an Equality and not marked convex
|
|
1498
1488
|
assert isinstance(nodal_equality.constraint, Equality)
|
|
1499
1489
|
assert not nodal_equality.constraint.is_convex
|
|
1500
1490
|
|
|
1501
|
-
# Should raise a helpful error
|
|
1502
1491
|
constraint_set = ConstraintSet(unsorted=[nodal_equality])
|
|
1503
|
-
|
|
1504
|
-
separate_constraints(constraint_set, n_nodes=n_nodes)
|
|
1492
|
+
result = separate_constraints(constraint_set, n_nodes=n_nodes)
|
|
1505
1493
|
|
|
1506
|
-
#
|
|
1507
|
-
|
|
1508
|
-
assert
|
|
1509
|
-
assert ".convex()" in msg
|
|
1510
|
-
assert "nodal" in msg
|
|
1494
|
+
# Routed into the non-convex nodal list (penalized), not the convex list
|
|
1495
|
+
assert len(result.nodal) == 1
|
|
1496
|
+
assert len(result.nodal_convex) == 0
|
|
1511
1497
|
|
|
1512
1498
|
|
|
1513
1499
|
def test_ctcs_equality_rejected():
|
|
@@ -435,6 +435,31 @@ def test_calculate_nonlinear_penalty_with_nodal_violations(
|
|
|
435
435
|
assert nonlinear_penalty >= 0.0
|
|
436
436
|
|
|
437
437
|
|
|
438
|
+
def test_calculate_nonlinear_penalty_equality_is_two_sided(settings):
|
|
439
|
+
"""Equality nodal constraints penalize |g| (two-sided), inequalities use max(0, g)."""
|
|
440
|
+
|
|
441
|
+
def nodal_func(x, u, node, params):
|
|
442
|
+
return x[:, 0] - 1.5 # negative residual at x=0 (satisfied as inequality)
|
|
443
|
+
|
|
444
|
+
x_prop = np.array([[0.0, 0.0], [0.0, 0.0]])
|
|
445
|
+
x_bar = np.zeros((3, 2))
|
|
446
|
+
u_bar = np.zeros((3, 1))
|
|
447
|
+
args = (np.array([1.0, 1.0]), np.full((3, 1), 1.0), np.full(1, 1.0), 1.0)
|
|
448
|
+
|
|
449
|
+
eq = LoweredJaxConstraints(
|
|
450
|
+
nodal=[LoweredNodalConstraint(func=nodal_func, nodes=None, is_equality=True)],
|
|
451
|
+
)
|
|
452
|
+
ineq = LoweredJaxConstraints(
|
|
453
|
+
nodal=[LoweredNodalConstraint(func=nodal_func, nodes=None, is_equality=False)],
|
|
454
|
+
)
|
|
455
|
+
|
|
456
|
+
_, _, eq_pen = calculate_nonlinear_penalty(x_prop, x_bar, u_bar, *args, eq, {}, settings)
|
|
457
|
+
_, _, ineq_pen = calculate_nonlinear_penalty(x_prop, x_bar, u_bar, *args, ineq, {}, settings)
|
|
458
|
+
|
|
459
|
+
assert eq_pen > 0.0 # |−1.5| penalized
|
|
460
|
+
assert ineq_pen == 0.0 # max(0, −1.5) == 0
|
|
461
|
+
|
|
462
|
+
|
|
438
463
|
def test_calculate_nonlinear_penalty_with_cross_node_violations(settings, cross_node_constraints):
|
|
439
464
|
"""Test penalty calculation with cross-node constraint violations."""
|
|
440
465
|
x_prop = np.array([[0.5, 0.5], [1.5, 1.5]])
|
|
@@ -536,6 +536,77 @@ def test_backend_float32_raises():
|
|
|
536
536
|
jax.clear_caches()
|
|
537
537
|
|
|
538
538
|
|
|
539
|
+
def test_nodal_equality_waypoint():
|
|
540
|
+
"""Soft L1-penalized nodal equality drives an off-path waypoint to target."""
|
|
541
|
+
import jax.numpy as jnp
|
|
542
|
+
|
|
543
|
+
import openscvx as ox
|
|
544
|
+
from openscvx import Problem
|
|
545
|
+
|
|
546
|
+
n = 12
|
|
547
|
+
g = 9.81
|
|
548
|
+
mid = n // 2
|
|
549
|
+
# Natural (unconstrained) node-mid position is ~(2.62, 6.69); this is a
|
|
550
|
+
# deliberate off-path deviation the soft equality must pull the iterate to.
|
|
551
|
+
waypoint = np.array([3.0, 6.4])
|
|
552
|
+
|
|
553
|
+
position = ox.State("position", shape=(2,))
|
|
554
|
+
position.max = np.array([10.0, 10.0])
|
|
555
|
+
position.min = np.array([0.0, 0.0])
|
|
556
|
+
position.initial = np.array([0.0, 10.0])
|
|
557
|
+
position.final = [10.0, 5.0]
|
|
558
|
+
|
|
559
|
+
velocity = ox.State("velocity", shape=(1,))
|
|
560
|
+
velocity.max = np.array([15.0])
|
|
561
|
+
velocity.min = np.array([0.0])
|
|
562
|
+
velocity.initial = np.array([0.0])
|
|
563
|
+
velocity.final = [("free", 10.0)]
|
|
564
|
+
|
|
565
|
+
theta = ox.Control("theta", shape=(1,))
|
|
566
|
+
theta.max = np.array([179.0 * jnp.pi / 180])
|
|
567
|
+
theta.min = np.array([0.0])
|
|
568
|
+
theta.guess = np.linspace(5 * jnp.pi / 180, 100.5 * jnp.pi / 180, n).reshape(-1, 1)
|
|
569
|
+
|
|
570
|
+
states = [position, velocity]
|
|
571
|
+
dynamics = {
|
|
572
|
+
"position": ox.Concat(velocity[0] * ox.Sin(theta[0]), -velocity[0] * ox.Cos(theta[0])),
|
|
573
|
+
"velocity": g * ox.Cos(theta[0]),
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
constraint_exprs = []
|
|
577
|
+
for state in states:
|
|
578
|
+
constraint_exprs.extend([ox.ctcs(state <= state.max), ox.ctcs(state.min <= state)])
|
|
579
|
+
constraint_exprs.append((position == waypoint).at([mid]).weight(1e3))
|
|
580
|
+
|
|
581
|
+
time = ox.Time(initial=0.0, final=("minimize", 2.0), min=0.0, max=2.0, uniform_time_grid=True)
|
|
582
|
+
|
|
583
|
+
problem = Problem(
|
|
584
|
+
dynamics=dynamics,
|
|
585
|
+
states=states,
|
|
586
|
+
controls=[theta],
|
|
587
|
+
time=time,
|
|
588
|
+
constraints=constraint_exprs,
|
|
589
|
+
N=n,
|
|
590
|
+
licq_max=1e-8,
|
|
591
|
+
algorithm={"lam_prox": 1e0, "lam_cost": 1e-1, "lam_vc": 1e0, "k_max": 200},
|
|
592
|
+
)
|
|
593
|
+
problem.settings.prp.dt = 0.01
|
|
594
|
+
problem.solver.solver_args = {"abstol": 1e-8, "reltol": 1e-10}
|
|
595
|
+
problem.settings.sim.save_compiled = False
|
|
596
|
+
if hasattr(problem.settings, "dev"):
|
|
597
|
+
problem.settings.dev.printing = False
|
|
598
|
+
|
|
599
|
+
problem.initialize()
|
|
600
|
+
problem.solve()
|
|
601
|
+
result = problem.post_process()
|
|
602
|
+
|
|
603
|
+
assert result["converged"], "Soft-equality problem failed to converge"
|
|
604
|
+
err = np.linalg.norm(result.nodes["position"][mid] - waypoint)
|
|
605
|
+
assert err < 1e-4, f"Waypoint not satisfied at node {mid}: err={err:.4f}"
|
|
606
|
+
|
|
607
|
+
jax.clear_caches()
|
|
608
|
+
|
|
609
|
+
|
|
539
610
|
@pytest.mark.parametrize("constraint_type", ["ctcs", "nodal", "convex", "over", "at"])
|
|
540
611
|
def test_constraint_types(constraint_type):
|
|
541
612
|
"""
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/docs/UnderTheHood/custom_algorithms_autotuners.md
RENAMED
|
File without changes
|
|
File without changes
|
{openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/docs/UnderTheHood/vectorization_and_vmapping.md
RENAMED
|
File without changes
|
|
File without changes
|
{openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/docs/UsersGuide/01_hello_world_brachistochrone.md
RENAMED
|
File without changes
|
{openscvx-0.5.3.dev31 → openscvx-0.5.3.dev32}/docs/UsersGuide/02_drone_racing_constraints.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|