openscvx 0.5.3.dev47__tar.gz → 0.5.3.dev49__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.dev47/openscvx.egg-info → openscvx-0.5.3.dev49}/PKG-INFO +1 -1
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/docs/Foundations/constraint_reformulation.md +34 -2
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/docs/UsersGuide/02_drone_racing_constraints.md +1 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/__init__.py +9 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/_version.py +3 -3
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/augmentation.py +6 -4
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/expr/constraint.py +64 -14
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/expr/stl.py +4 -3
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/expr/stljax.py +4 -3
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49/openscvx.egg-info}/PKG-INFO +1 -1
- openscvx-0.5.3.dev49/openscvx.egg-info/scm_version.json +8 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/symbolic/expr/test_constraint.py +88 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/symbolic/expr/test_math.py +4 -2
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/symbolic/test_augmentation.py +27 -1
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/symbolic/test_hashing.py +47 -9
- openscvx-0.5.3.dev47/openscvx.egg-info/scm_version.json +0 -8
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/.github/assets/logo.svg +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/.github/release-drafter.yml +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/.github/workflows/_docs.yml +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/.github/workflows/_extra.yml +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/.github/workflows/branch-name.yml +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/.github/workflows/docs.yml +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/.github/workflows/lint.yml +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/.github/workflows/nightly.yml +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/.github/workflows/release-drafter.yml +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/.github/workflows/release.yml +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/.github/workflows/tests-cvxpygen.yml +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/.github/workflows/tests-examples.yml +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/.github/workflows/tests-lie.yml +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/.github/workflows/tests-mjx.yml +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/.github/workflows/tests-qpax.yml +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/.github/workflows/tests.yml +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/.gitignore +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/.gitmodules +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/CITATION.cff +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/CONTRIBUTING.md +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/LICENSE +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/README.md +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/docs/Foundations/control_parameterization.md +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/docs/Foundations/discretization.md +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/docs/Foundations/ocp.md +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/docs/Foundations/scvx.md +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/docs/Foundations/time_dilation.md +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/docs/UnderTheHood/batching_jit_grad.md +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/docs/UnderTheHood/custom_algorithms_autotuners.md +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/docs/UnderTheHood/lowering_architecture.md +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/docs/UnderTheHood/vectorization_and_vmapping.md +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/docs/UsersGuide/00_introduction.md +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/docs/UsersGuide/01_hello_world_brachistochrone.md +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/docs/UsersGuide/03_obstacle_avoidance_vmap.md +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/docs/UsersGuide/04_viewpoint_constraints.md +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/docs/UsersGuide/05_visualization.md +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/docs/UsersGuide/06_logic.md +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/docs/UsersGuide/07_lie.md +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/docs/UsersGuide/08_mpcc.md +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/docs/UsersGuide/09_mjx_dynamics.md +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/docs/assets/favicon.png +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/docs/assets/images/ct-scvx_dark.png +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/docs/assets/images/ct-scvx_light.png +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/docs/assets/images/ctcs_dark.png +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/docs/assets/images/ctcs_light.png +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/docs/assets/images/problem_class_dark.png +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/docs/assets/images/problem_class_light.png +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/docs/assets/logo.svg +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/docs/assets/openscvx_logo_square.png +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/docs/assets/viser-client/index.html +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/docs/assets/viser-recordings/drone_racing.viser +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/docs/assets/viser-recordings/franka_fr3v2_pick_place.viser +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/docs/changelog.md +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/docs/citation.md +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/docs/examples.md +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/docs/index.md +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/docs/installation.md +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/docs/javascripts/mathjax.js +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/docs/llms.txt +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/docs/versions.json +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/_viser_embed_export.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/abstract/brachistochrone.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/abstract/brachistochrone_batched.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/abstract/flappy_bird.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/abstract/hypersensitive.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/abstract/impulsive.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/abstract/stl_integer_variable.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/abstract/stl_or.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/aircraft/dynamic_soaring.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/aircraft/supersonic_time_to_climb.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/animations/7_dof_arm.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/animations/_camera.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/animations/_render.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/animations/_sensor_view.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/animations/dr_vp_polytope.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/animations/franka_fr3v2_pick_place.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/animations/logo.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/animations/obstacle_avoidance_vmap.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/arm/3_dof_arm.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/arm/7_dof_arm.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/arm/7_dof_arm_collision.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/arm/7_dof_arm_vp.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/arm/franka_fr3v2_pick_place.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/arm/franka_fr3v2_viewplanning.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/arm/franka_fr3v2_viewplanning_nodal.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/car/dubins_car.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/car/dubins_car_disjoint.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/car/dubins_car_obstacle_conditional.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/car/dubins_car_obstacle_stl.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/car/dubins_car_stl_or.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/car/dubins_car_waypoint_stl.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/double_integrator/_plotting.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/double_integrator/moving_safe_zones.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/drone/2d_obstacle_avoidance_batched_ic.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/drone/boresight_trace_mpcc.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/drone/cinema_vp.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/drone/cinema_vp_nodal.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/drone/dr_double_integrator.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/drone/dr_vp.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/drone/dr_vp_nodal.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/drone/dr_vp_polytope.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/drone/drone_racing.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/drone/drone_racing_batched_gates.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/drone/logo.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/drone/logo_utils/acl_logo.svg +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/drone/logo_utils/circle.svg +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/drone/logo_utils/openscvx_logo_single.svg +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/drone/logo_utils/quadrotor_mesh.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/drone/logo_utils/svg_path_utils.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/drone/multi_agent_circle_swap.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/drone/obstacle_avoidance.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/drone/obstacle_avoidance_nodal.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/drone/obstacle_avoidance_vmap.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/drone/obstacle_avoidance_vmap_2d.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/drone/openscvx_logo.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/frax/panda_frax.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/frax/panda_frax_pick_place.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/frax/panda_frax_viewplanning.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/frax/panda_frax_waypoint.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/frax/ur5e_assets/ur5e.urdf +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/frax/ur5e_pen_trace.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/frax/ur5e_pen_trace_mpcc.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/mjx/cartpole_mjx.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/mjx/double_cartpole_mjx.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/mjx/skydio_x2_mjx.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/mjx/triple_cartpole_3d_mjx.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/mjx/triple_cartpole_game.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/mjx/triple_cartpole_mjx.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/mpc/double_integrator_discrete.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/mpc/double_integrator_drone_racing.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/mpc/dubins_car_circle_analytical.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/mpc/dubins_car_circle_discrete.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/mpc/realtime_double_integrator_drone_racing.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/plotting.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/plotting_viser.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/realtime/3DoF_pdg_realtime.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/realtime/6DoF_pdg_realtime.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/realtime/base_problems/3DoF_pdg_realtime_base.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/realtime/base_problems/6DoF_pdg_realtime_base.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/realtime/base_problems/cinema_vp_realtime_base.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/realtime/base_problems/drone_racing_realtime_base.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/realtime/base_problems/dubins_car_realtime_base.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/realtime/base_problems/obstacle_avoidance_realtime_base.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/realtime/cinema_vp_realtime.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/realtime/drone_racing_realtime.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/realtime/dubins_car_realtime.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/realtime/obstacle_avoidance_realtime.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/rocket/3DoF_pdg.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/rocket/6DoF_pdg.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/rocket/6DoF_pdg_batched_ic.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/rocket/ascent_launch_vehicle.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/spacecraft/halo_orbit.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/spacecraft/hohmann_transfer.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/spacecraft/let_transfer.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/spacecraft/proxops_cw.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/examples/spacecraft/relative_loitering.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/figures/ctlos_cine.gif +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/figures/ctlos_dr.gif +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/figures/dtlos_cine.gif +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/figures/dtlos_dr.gif +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/figures/openscvx_logo.svg +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/figures/openscvx_logo_square.png +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/figures/oscvx_structure_full_dark.svg +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/figures/video_preview.png +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/material/__init__.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/material/overrides/assets/stylesheets/custom.css +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/material/overrides/assets/stylesheets/home-dropin.css +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/material/overrides/assets/stylesheets/home-hero.css +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/material/overrides/assets/stylesheets/home-viser.css +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/material/overrides/home.html +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/material/overrides/main.html +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/material/overrides/partials/home-diagram.html +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/material/overrides/partials/home-dropin-banner.html +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/material/overrides/partials/home-hero.html +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/material/overrides/partials/home-pipeline.html +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/material/overrides/partials/home-viser-strip.html +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/material/overrides/sitemap.xml +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/mkdocs.yml +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/__main__.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/algorithms/__init__.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/algorithms/autotuner/__init__.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/algorithms/autotuner/acceptance_ratio.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/algorithms/autotuner/adaptive_proximal_weight.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/algorithms/autotuner/augmented_lagrangian.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/algorithms/autotuner/base.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/algorithms/autotuner/constant_proximal_weight.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/algorithms/autotuner/ramp_proximal_weight.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/algorithms/base.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/algorithms/history.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/algorithms/hyperparams.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/algorithms/loop.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/algorithms/optimization_results.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/algorithms/penalty.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/algorithms/scvx/__init__.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/algorithms/scvx/iteration.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/algorithms/scvx/penalized_trust_region.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/algorithms/state.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/algorithms/weights.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/config.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/discretization/__init__.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/discretization/base.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/discretization/discretize_linearize.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/discretization/linearize_discretize.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/discretization/linearize_discretize_sparse.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/discretization/sparse_utils/__init__.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/discretization/sparse_utils/bcoo_helpers.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/discretization/sparse_utils/sparse_jacobian.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/expert/__init__.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/expert/byof.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/expert/lowering.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/expert/validation.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/init/__init__.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/init/interpolation.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/init/inverse_kinematics.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/integrations/__init__.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/integrations/_utils.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/integrations/base.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/integrations/frax.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/integrations/menagerie.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/integrations/mjx.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/integrators/__init__.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/integrators/diffrax.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/integrators/runge_kutta.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/loader.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/lowered/__init__.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/lowered/cvxpy_constraints.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/lowered/cvxpy_variables.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/lowered/dynamics.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/lowered/jax_constraints.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/lowered/parameters.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/lowered/problem.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/lowered/unified.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/plotting/__init__.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/plotting/plotting.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/plotting/publication.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/plotting/scp_iteration.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/plotting/viser/__init__.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/plotting/viser/animated.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/plotting/viser/coordinates.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/plotting/viser/orbits.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/plotting/viser/plotly_integration.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/plotting/viser/primitives.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/plotting/viser/scp.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/plotting/viser/server.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/problem.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/propagation/__init__.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/propagation/post_processing.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/propagation/propagation.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/solvers/__init__.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/solvers/base.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/solvers/cones.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/solvers/cvxpy_ptr_solver.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/solvers/moreau_ptr_solver.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/solvers/ptr_solver.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/solvers/qpax_ptr_solver.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/__init__.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/affine.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/builder.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/canonicalize.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/constraint_set.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/expr/__init__.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/expr/arithmetic.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/expr/array.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/expr/control.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/expr/expr.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/expr/lie/__init__.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/expr/lie/adjoint.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/expr/lie/se3.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/expr/lie/so3.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/expr/linalg.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/expr/logic.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/expr/math.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/expr/parameter.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/expr/spatial.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/expr/state.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/expr/time.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/expr/variable.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/expr/vmap.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/hashing.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/lower.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/lowerers/__init__.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/lowerers/cvxpy/__init__.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/lowerers/cvxpy/_lowerer.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/lowerers/cvxpy/_registry.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/lowerers/cvxpy/arithmetic.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/lowerers/cvxpy/array.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/lowerers/cvxpy/constraint.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/lowerers/cvxpy/control.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/lowerers/cvxpy/expr.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/lowerers/cvxpy/linalg.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/lowerers/cvxpy/logic.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/lowerers/cvxpy/math.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/lowerers/cvxpy/state.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/lowerers/jax/__init__.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/lowerers/jax/_lowerer.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/lowerers/jax/_registry.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/lowerers/jax/arithmetic.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/lowerers/jax/array.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/lowerers/jax/constraint.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/lowerers/jax/control.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/lowerers/jax/expr.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/lowerers/jax/lie.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/lowerers/jax/linalg.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/lowerers/jax/logic.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/lowerers/jax/math.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/lowerers/jax/spatial.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/lowerers/jax/state.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/lowerers/jax/stl.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/lowerers/jax/stljax.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/lowerers/jax/vmap.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/lowerers/latex/__init__.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/lowerers/latex/_lowerer.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/lowerers/latex/_registry.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/lowerers/latex/arithmetic.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/lowerers/latex/array.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/lowerers/latex/constraint.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/lowerers/latex/control.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/lowerers/latex/expr.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/lowerers/latex/formulation.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/lowerers/latex/lie.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/lowerers/latex/linalg.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/lowerers/latex/logic.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/lowerers/latex/math.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/lowerers/latex/spatial.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/lowerers/latex/state.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/lowerers/latex/stl.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/lowerers/latex/vmap.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/parser/__init__.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/parser/_registry.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/parser/array.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/parser/constraint.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/parser/lie.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/parser/linalg.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/parser/logic.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/parser/math.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/parser/parser.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/parser/spatial.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/parser/stl.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/parser/stljax.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/parser/tokenizer.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/preprocessing.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/problem.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/sparsity.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/symbolic/unified.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/utils/__init__.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/utils/cache.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/utils/caching.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/utils/printing.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/utils/profiling.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx/utils/utils.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx.egg-info/SOURCES.txt +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx.egg-info/dependency_links.txt +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx.egg-info/entry_points.txt +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx.egg-info/requires.txt +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx.egg-info/scm_file_list.json +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/openscvx.egg-info/top_level.txt +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/pyproject.toml +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/scripts/gen_example_pages.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/scripts/gen_ref_pages.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/scripts/mkdocs_copy_viser_client_hook.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/scripts/mkdocs_seo_hook.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/setup.cfg +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/__init__.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/algorithms/__init__.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/algorithms/_iteration_helpers.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/algorithms/autotuner/__init__.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/algorithms/autotuner/test_defaults_agreement.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/algorithms/autotuner/test_hyper_overrides.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/algorithms/autotuner/test_update_weights_jit.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/algorithms/test_algorithm_state_pytree.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/algorithms/test_iteration_fn_jit.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/algorithms/test_iteration_fn_parity.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/algorithms/test_make_solve_loop.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/brachistochrone_analytical.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/conftest.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/e2e/__init__.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/e2e/test_brachistochrone.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/e2e/test_impulsive.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/e2e/test_multishot_propagation.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/e2e/test_solve_batched_brachistochrone.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/e2e/test_solve_batched_cvxpy_export_errors.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/e2e/test_solve_batched_export_roundtrip.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/e2e/test_solve_jax_bare_brachistochrone.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/e2e/test_solve_jax_jit_brachistochrone.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/e2e/test_solve_jax_vmap_brachistochrone.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/e2e/test_solve_jax_vmap_converged_no_drift.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/fixtures/brachistochrone.json +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/fixtures/brachistochrone.yaml +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/hohmann_analytical.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/integrations/__init__.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/integrations/test_mjx.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/integrations/test_mjx_dynamics.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/solvers/__init__.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/solvers/_iteration_callback_helpers.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/solvers/test_cvxpy_callback_jit_spike.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/solvers/test_iteration_callback_cvxpy.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/solvers/test_iteration_callback_moreau.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/solvers/test_iteration_callback_qpax.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/solvers/test_iteration_callback_vmap.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/solvers/test_moreau_ptr_solver.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/solvers/test_qpax_ptr_solver.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/solvers/test_subproblem_pytree.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/symbolic/__init__.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/symbolic/expr/__init__.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/symbolic/expr/test_arithmetic.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/symbolic/expr/test_array.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/symbolic/expr/test_expr.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/symbolic/expr/test_lie.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/symbolic/expr/test_linalg.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/symbolic/expr/test_logic.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/symbolic/expr/test_node_reference.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/symbolic/expr/test_parameters.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/symbolic/expr/test_scaling.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/symbolic/expr/test_spatial.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/symbolic/expr/test_stl.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/symbolic/expr/test_variable.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/symbolic/expr/test_vmap.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/symbolic/parser/__init__.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/symbolic/parser/test_array.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/symbolic/parser/test_constraint.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/symbolic/parser/test_lie.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/symbolic/parser/test_linalg.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/symbolic/parser/test_load.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/symbolic/parser/test_logic.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/symbolic/parser/test_math.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/symbolic/parser/test_parser.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/symbolic/parser/test_spatial.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/symbolic/parser/test_stl.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/symbolic/parser/test_tokenizer.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/symbolic/parser/test_vmap.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/symbolic/test_gmsr.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/symbolic/test_latex_formulation.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/symbolic/test_lower_cvxpy.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/symbolic/test_lower_jax.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/symbolic/test_lower_latex.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/symbolic/test_preprocessing.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/symbolic/test_sparsity.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/symbolic/test_unified.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/test_autotuning.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/test_cvxpygen_optional.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/test_discretization.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/test_examples.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/test_expert.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/test_init.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/test_initialize_syncs_guesses.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/test_integrators.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/test_loader.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/test_optimization_results.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/test_plotting.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/test_post_process_batched_tau_clamp.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/test_propagation.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/test_results_parameters.py +0 -0
- {openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/tests/test_solve_batched_inference.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.dev49
|
|
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
|
|
@@ -29,8 +29,8 @@ $$
|
|
|
29
29
|
$$
|
|
30
30
|
|
|
31
31
|
where the default penalty is the squared ReLU $\max(0, g_j)^2$ (Huber and smooth
|
|
32
|
-
ReLU are also available
|
|
33
|
-
factor. Because the integrand is non-negative, $y$ is monotonically
|
|
32
|
+
ReLU are also available, or you can [write your own](#custom-penalties)), and $s$
|
|
33
|
+
is the [time-dilation](time_dilation.md) factor. Because the integrand is non-negative, $y$ is monotonically
|
|
34
34
|
non-decreasing and accumulates *any* violation occurring between nodes.
|
|
35
35
|
|
|
36
36
|
Enforcing $y \equiv 0$ then drives every penalty — and hence every constraint —
|
|
@@ -66,6 +66,38 @@ different intervals get separate states. The bound $y_{\max}$ is the constraint'
|
|
|
66
66
|
After solving, the achieved continuous-time violation is reported as
|
|
67
67
|
`results.ctcs_violation`.
|
|
68
68
|
|
|
69
|
+
## Custom penalties
|
|
70
|
+
|
|
71
|
+
The built-in penalties are selected by name — `"squared_relu"` (the default),
|
|
72
|
+
`"huber"`, and `"smooth_relu"` — which fixes their shape and their internal
|
|
73
|
+
constants. When you want to tune those constants or shape the penalty yourself,
|
|
74
|
+
pass a callable instead:
|
|
75
|
+
|
|
76
|
+
```python
|
|
77
|
+
# Widen Huber's quadratic region — not expressible with the string form.
|
|
78
|
+
ox.ctcs(altitude >= 10, penalty=lambda r: ox.Huber(ox.PositivePart(r), delta=0.5))
|
|
79
|
+
|
|
80
|
+
# Quadratic near the boundary, with a linear tail that keeps pushing far out.
|
|
81
|
+
ox.ctcs(
|
|
82
|
+
speed <= v_max,
|
|
83
|
+
penalty=lambda r: ox.Square(ox.PositivePart(r)) + 0.1 * ox.PositivePart(r),
|
|
84
|
+
)
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
The callable receives the canonicalized residual $g_j(x, u)$ — the constraint
|
|
88
|
+
already rearranged into $g_j \le 0$ form, so `speed <= v_max` arrives as
|
|
89
|
+
`speed - v_max` — and returns the expression to integrate. That result is summed
|
|
90
|
+
to a scalar, so a vector-valued residual may produce a vector-valued penalty. The
|
|
91
|
+
callable runs once, when the problem is built; from there its expression is
|
|
92
|
+
differentiated, sparsified, and cached exactly like a built-in penalty.
|
|
93
|
+
|
|
94
|
+
The body must be built from openscvx operations: `ox.PositivePart`, `ox.Square`,
|
|
95
|
+
`ox.Huber` (tunable `delta`), `ox.SmoothReLU` (tunable `c`), and ordinary
|
|
96
|
+
arithmetic on expressions. Reaching for `jax.numpy` instead — `jnp.maximum(r, 0)`
|
|
97
|
+
— returns an array rather than an expression and is rejected when the problem is
|
|
98
|
+
built: the penalty has to stay symbolic to be lowered into the augmented
|
|
99
|
+
dynamics.
|
|
100
|
+
|
|
69
101
|
## Related reading
|
|
70
102
|
|
|
71
103
|
- [Optimal Control Problem](ocp.md) — where the CTCS reset-and-bound constraints
|
{openscvx-0.5.3.dev47 → openscvx-0.5.3.dev49}/docs/UsersGuide/02_drone_racing_constraints.md
RENAMED
|
@@ -138,6 +138,7 @@ obstacle_constraint = (diff.T @ diff >= safe_distance**2).over((5, 10))
|
|
|
138
138
|
```
|
|
139
139
|
|
|
140
140
|
The `.over()` method also accepts optional parameters for the penalty function type (`penalty`), grouping index (`idx`), and whether to also check nodally (`check_nodally`).
|
|
141
|
+
`penalty` takes one of the built-in names (`"squared_relu"`, `"huber"`, `"smooth_relu"`) or a callable that builds a penalty of your own from the constraint residual; see [Custom penalties](../Foundations/constraint_reformulation.md#custom-penalties).
|
|
141
142
|
|
|
142
143
|
!!! note
|
|
143
144
|
You can also directly instantiate `NodalConstraint` or `CTCS` objects if you prefer:
|
|
@@ -60,6 +60,7 @@ from openscvx.symbolic.expr import (
|
|
|
60
60
|
Fixed,
|
|
61
61
|
Free,
|
|
62
62
|
Hstack,
|
|
63
|
+
Huber,
|
|
63
64
|
Index,
|
|
64
65
|
Inequality,
|
|
65
66
|
Inv,
|
|
@@ -76,9 +77,12 @@ from openscvx.symbolic.expr import (
|
|
|
76
77
|
Neg,
|
|
77
78
|
NodalConstraint,
|
|
78
79
|
Parameter,
|
|
80
|
+
PositivePart,
|
|
79
81
|
Power,
|
|
80
82
|
Sin,
|
|
83
|
+
SmoothReLU,
|
|
81
84
|
Sqrt,
|
|
85
|
+
Square,
|
|
82
86
|
Stack,
|
|
83
87
|
State,
|
|
84
88
|
Sub,
|
|
@@ -185,6 +189,11 @@ __all__ = [
|
|
|
185
189
|
"NodalConstraint",
|
|
186
190
|
"CTCS",
|
|
187
191
|
"ctcs",
|
|
192
|
+
# Penalty function building blocks
|
|
193
|
+
"PositivePart",
|
|
194
|
+
"Square",
|
|
195
|
+
"Huber",
|
|
196
|
+
"SmoothReLU",
|
|
188
197
|
# Data parallelism
|
|
189
198
|
"Vmap",
|
|
190
199
|
# LaTeX rendering
|
|
@@ -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.dev49'
|
|
22
|
+
__version_tuple__ = version_tuple = (0, 5, 3, 'dev49')
|
|
23
23
|
|
|
24
|
-
__commit_id__ = commit_id = '
|
|
24
|
+
__commit_id__ = commit_id = 'g02b83a786'
|
|
@@ -215,13 +215,15 @@ def separate_constraints(constraint_set: ConstraintSet, n_nodes: int) -> Constra
|
|
|
215
215
|
"Cross-node constraints should be specified as bare Constraint objects. "
|
|
216
216
|
f"Constraint: {c.constraint}"
|
|
217
217
|
)
|
|
218
|
-
# Validate that CTCS constraints are not equality constraints
|
|
219
|
-
#
|
|
220
|
-
#
|
|
218
|
+
# Validate that CTCS constraints are not equality constraints: the
|
|
219
|
+
# augmented state integrates a one-sided violation penalty, which
|
|
220
|
+
# only certifies satisfaction of an inequality
|
|
221
221
|
if isinstance(c.constraint, Equality):
|
|
222
222
|
raise ValueError(
|
|
223
223
|
f"CTCS constraints cannot be equality constraints. "
|
|
224
|
-
f"CTCS
|
|
224
|
+
f"A CTCS penalty measures violation of an inequality (how far the "
|
|
225
|
+
f"residual is above zero), so it cannot detect an equality being "
|
|
226
|
+
f"missed from below. "
|
|
225
227
|
f"For equality constraints, use nodal constraints with .convex() instead.\n"
|
|
226
228
|
f"Constraint: {c.constraint}"
|
|
227
229
|
)
|
|
@@ -37,7 +37,7 @@ Example:
|
|
|
37
37
|
|
|
38
38
|
import hashlib
|
|
39
39
|
import struct
|
|
40
|
-
from typing import List, Optional, Tuple, Union
|
|
40
|
+
from typing import Callable, List, Optional, Tuple, Union
|
|
41
41
|
|
|
42
42
|
import numpy as np
|
|
43
43
|
|
|
@@ -124,7 +124,7 @@ class Constraint(Expr):
|
|
|
124
124
|
def over(
|
|
125
125
|
self,
|
|
126
126
|
interval: tuple[int, int],
|
|
127
|
-
penalty: str = "squared_relu",
|
|
127
|
+
penalty: Union[str, Callable[[Expr], "Expr"]] = "squared_relu",
|
|
128
128
|
idx: Optional[int] = None,
|
|
129
129
|
check_nodally: bool = False,
|
|
130
130
|
licq_max: Optional[float] = None,
|
|
@@ -133,7 +133,10 @@ class Constraint(Expr):
|
|
|
133
133
|
|
|
134
134
|
Args:
|
|
135
135
|
interval: Tuple of (start, end) node indices for the continuous interval
|
|
136
|
-
penalty:
|
|
136
|
+
penalty: Built-in penalty name ("squared_relu", "huber", "smooth_relu")
|
|
137
|
+
or a callable that receives the constraint residual as an ``Expr``
|
|
138
|
+
and returns the penalty ``Expr``, e.g.
|
|
139
|
+
``lambda r: ox.Huber(ox.PositivePart(r), delta=0.5)``.
|
|
137
140
|
idx: Optional grouping index for multiple augmented states
|
|
138
141
|
check_nodally: Whether to also enforce this constraint nodally
|
|
139
142
|
licq_max: Optional upper bound on the augmented state that accumulates
|
|
@@ -611,9 +614,20 @@ class CTCS(Expr):
|
|
|
611
614
|
- **huber**: Huber(PositivePart(lhs)) - less sensitive to outliers than squared
|
|
612
615
|
- **smooth_relu**: SmoothReLU(lhs) - smooth approximation of ReLU
|
|
613
616
|
|
|
617
|
+
A penalty may also be written as a callable that receives the constraint
|
|
618
|
+
residual ``r`` (the canonical left-hand side, satisfying ``r <= 0``) as a
|
|
619
|
+
symbolic ``Expr`` and returns the penalty ``Expr``. This is how penalty
|
|
620
|
+
parameters are tuned::
|
|
621
|
+
|
|
622
|
+
ox.ctcs(altitude >= 10, penalty=lambda r: ox.Huber(ox.PositivePart(r), delta=0.5))
|
|
623
|
+
|
|
624
|
+
The callable is applied once, at problem-build time; the resulting
|
|
625
|
+
expression is summed and integrated exactly like a built-in penalty.
|
|
626
|
+
|
|
614
627
|
Attributes:
|
|
615
628
|
constraint: The wrapped Constraint (typically Inequality) to enforce continuously
|
|
616
|
-
penalty: Penalty function
|
|
629
|
+
penalty: Penalty function name ('squared_relu', 'huber', or 'smooth_relu')
|
|
630
|
+
or a callable ``Expr -> Expr`` applied to the constraint residual
|
|
617
631
|
nodes: Optional (start, end) tuple specifying the interval for enforcement,
|
|
618
632
|
or None to enforce over the entire trajectory
|
|
619
633
|
idx: Optional grouping index for managing multiple augmented states.
|
|
@@ -655,7 +669,7 @@ class CTCS(Expr):
|
|
|
655
669
|
def __init__(
|
|
656
670
|
self,
|
|
657
671
|
constraint: Constraint,
|
|
658
|
-
penalty: str = "squared_relu",
|
|
672
|
+
penalty: Union[str, Callable[[Expr], Expr]] = "squared_relu",
|
|
659
673
|
nodes: Optional[Tuple[int, int]] = None,
|
|
660
674
|
idx: Optional[int] = None,
|
|
661
675
|
check_nodally: bool = False,
|
|
@@ -665,10 +679,14 @@ class CTCS(Expr):
|
|
|
665
679
|
|
|
666
680
|
Args:
|
|
667
681
|
constraint: The Constraint to enforce continuously (typically an Inequality)
|
|
668
|
-
penalty: Penalty function
|
|
682
|
+
penalty: Penalty function name. Options:
|
|
669
683
|
- 'squared_relu': Square(PositivePart(lhs)) - default, smooth, differentiable
|
|
670
684
|
- 'huber': Huber(PositivePart(lhs)) - robust to outliers
|
|
671
685
|
- 'smooth_relu': SmoothReLU(lhs) - smooth ReLU approximation
|
|
686
|
+
|
|
687
|
+
Alternatively a callable ``Expr -> Expr`` that receives the
|
|
688
|
+
constraint residual and returns the penalty expression, e.g.
|
|
689
|
+
``lambda r: ox.Huber(ox.PositivePart(r), delta=0.5)``.
|
|
672
690
|
nodes: Optional (start, end) tuple of node indices defining the enforcement interval.
|
|
673
691
|
None means enforce over the entire trajectory. Must satisfy start < end.
|
|
674
692
|
CTCS constraints with the same nodes are automatically grouped together.
|
|
@@ -780,12 +798,16 @@ class CTCS(Expr):
|
|
|
780
798
|
def _hash_into(self, hasher: "hashlib._Hash") -> None:
|
|
781
799
|
"""Hash CTCS including all its parameters.
|
|
782
800
|
|
|
801
|
+
The penalty is hashed through the expression it builds rather than
|
|
802
|
+
through its spelling, so callable and named penalties hash alike and
|
|
803
|
+
two problems agree exactly when the same penalty tree gets lowered.
|
|
804
|
+
|
|
783
805
|
Args:
|
|
784
806
|
hasher: A hashlib hash object to update
|
|
785
807
|
"""
|
|
786
808
|
hasher.update(b"CTCS")
|
|
787
|
-
# Hash penalty
|
|
788
|
-
|
|
809
|
+
# Hash the penalty by what it builds, not how it was spelled
|
|
810
|
+
self.penalty_expr()._hash_into(hasher)
|
|
789
811
|
# Hash nodes interval
|
|
790
812
|
if self.nodes is not None:
|
|
791
813
|
hasher.update(struct.pack(">ii", self.nodes[0], self.nodes[1]))
|
|
@@ -837,9 +859,14 @@ class CTCS(Expr):
|
|
|
837
859
|
"""String representation of the CTCS constraint.
|
|
838
860
|
|
|
839
861
|
Returns:
|
|
840
|
-
str: String showing constraint, penalty
|
|
862
|
+
str: String showing constraint, penalty, and optional parameters
|
|
841
863
|
"""
|
|
842
|
-
|
|
864
|
+
penalty = (
|
|
865
|
+
repr(self.penalty)
|
|
866
|
+
if isinstance(self.penalty, str)
|
|
867
|
+
else getattr(self.penalty, "__name__", repr(self.penalty))
|
|
868
|
+
)
|
|
869
|
+
parts = [f"{self.constraint!r}", f"penalty={penalty}"]
|
|
843
870
|
if self.nodes is not None:
|
|
844
871
|
parts.append(f"nodes={self.nodes}")
|
|
845
872
|
if self.idx is not None:
|
|
@@ -863,11 +890,15 @@ class CTCS(Expr):
|
|
|
863
890
|
s_aug_i(t) = 0 for all t, we ensure all penalties in the group are zero,
|
|
864
891
|
which strictly enforces all constraints in the group continuously.
|
|
865
892
|
|
|
893
|
+
A callable penalty is applied here, once, to the residual expression; the
|
|
894
|
+
result is an ordinary Expr and rides the rest of the pipeline unchanged.
|
|
895
|
+
|
|
866
896
|
Returns:
|
|
867
897
|
Expr: Sum of the penalty function applied to the constraint violation
|
|
868
898
|
|
|
869
899
|
Raises:
|
|
870
|
-
ValueError: If an unknown penalty
|
|
900
|
+
ValueError: If an unknown penalty name is given, or if a callable
|
|
901
|
+
penalty returns something other than an Expr
|
|
871
902
|
|
|
872
903
|
Note:
|
|
873
904
|
This method is used internally during problem compilation to create
|
|
@@ -876,7 +907,18 @@ class CTCS(Expr):
|
|
|
876
907
|
"""
|
|
877
908
|
lhs = self.constraint.lhs
|
|
878
909
|
|
|
879
|
-
if self.penalty
|
|
910
|
+
if callable(self.penalty):
|
|
911
|
+
penalty = self.penalty(lhs)
|
|
912
|
+
if not isinstance(penalty, Expr):
|
|
913
|
+
raise ValueError(
|
|
914
|
+
f"CTCS penalty callable returned {type(penalty).__name__}, not a "
|
|
915
|
+
f"symbolic expression. The callable receives the constraint residual "
|
|
916
|
+
f"as an Expr and must return one built from openscvx operations, e.g. "
|
|
917
|
+
f"lambda r: ox.Square(ox.PositivePart(r)). Computing on the residual "
|
|
918
|
+
f"with jax.numpy or numpy will not work — the penalty is composed "
|
|
919
|
+
f"symbolically and only lowered to JAX later."
|
|
920
|
+
)
|
|
921
|
+
elif self.penalty == "squared_relu":
|
|
880
922
|
from openscvx.symbolic.expr.math import PositivePart, Square
|
|
881
923
|
|
|
882
924
|
penalty = Square(PositivePart(lhs))
|
|
@@ -896,7 +938,7 @@ class CTCS(Expr):
|
|
|
896
938
|
|
|
897
939
|
def ctcs(
|
|
898
940
|
constraint: Constraint,
|
|
899
|
-
penalty: str = "squared_relu",
|
|
941
|
+
penalty: Union[str, Callable[[Expr], Expr]] = "squared_relu",
|
|
900
942
|
nodes: Optional[Tuple[int, int]] = None,
|
|
901
943
|
idx: Optional[int] = None,
|
|
902
944
|
check_nodally: bool = False,
|
|
@@ -909,7 +951,8 @@ def ctcs(
|
|
|
909
951
|
|
|
910
952
|
Args:
|
|
911
953
|
constraint: The Constraint to enforce continuously
|
|
912
|
-
penalty: Penalty function
|
|
954
|
+
penalty: Penalty function name ('squared_relu', 'huber', or 'smooth_relu'),
|
|
955
|
+
or a callable ``Expr -> Expr`` receiving the constraint residual.
|
|
913
956
|
Defaults to 'squared_relu'.
|
|
914
957
|
nodes: Optional (start, end) tuple of node indices for enforcement interval.
|
|
915
958
|
None enforces over entire trajectory.
|
|
@@ -942,5 +985,12 @@ def ctcs(
|
|
|
942
985
|
Also equivalent to using .over() method on constraint:
|
|
943
986
|
|
|
944
987
|
altitude_constraint = (altitude >= 10).over((0, 100), penalty="huber")
|
|
988
|
+
|
|
989
|
+
Tuning a penalty with a callable:
|
|
990
|
+
|
|
991
|
+
altitude_constraint = ctcs(
|
|
992
|
+
altitude >= 10,
|
|
993
|
+
penalty=lambda r: ox.Huber(ox.PositivePart(r), delta=0.5),
|
|
994
|
+
)
|
|
945
995
|
"""
|
|
946
996
|
return CTCS(constraint, penalty, nodes, idx, check_nodally, licq_max)
|
|
@@ -57,7 +57,7 @@ See also:
|
|
|
57
57
|
"""
|
|
58
58
|
|
|
59
59
|
from dataclasses import dataclass
|
|
60
|
-
from typing import TYPE_CHECKING, Optional, Tuple, Union
|
|
60
|
+
from typing import TYPE_CHECKING, Callable, Optional, Tuple, Union
|
|
61
61
|
|
|
62
62
|
import numpy as np
|
|
63
63
|
|
|
@@ -307,7 +307,7 @@ class STLExpr(Expr):
|
|
|
307
307
|
def over(
|
|
308
308
|
self,
|
|
309
309
|
interval: "IntervalLike",
|
|
310
|
-
penalty: str = "smooth_relu",
|
|
310
|
+
penalty: Union[str, Callable[[Expr], Expr]] = "smooth_relu",
|
|
311
311
|
idx: Optional[int] = None,
|
|
312
312
|
check_nodally: bool = False,
|
|
313
313
|
licq_max: Optional[float] = None,
|
|
@@ -321,7 +321,8 @@ class STLExpr(Expr):
|
|
|
321
321
|
discretization indices and produces a :class:`NodeInterval`;
|
|
322
322
|
``"seconds"`` treats them as wall-time and produces a
|
|
323
323
|
:class:`TimeInterval` (lowering not yet implemented).
|
|
324
|
-
penalty:
|
|
324
|
+
penalty: CTCS penalty function name, or a callable ``Expr -> Expr``
|
|
325
|
+
receiving the constraint residual (see :class:`CTCS`)
|
|
325
326
|
idx: Optional grouping index for multiple augmented states
|
|
326
327
|
check_nodally: Whether to also enforce at discrete nodes
|
|
327
328
|
licq_max: Optional upper bound on the augmented state accumulating
|
|
@@ -9,7 +9,7 @@ STL operators accept Constraint objects (predicates) and extract robustness
|
|
|
9
9
|
expressions which are lowered to STLJax during compilation.
|
|
10
10
|
"""
|
|
11
11
|
|
|
12
|
-
from typing import TYPE_CHECKING, Optional, Tuple, Union
|
|
12
|
+
from typing import TYPE_CHECKING, Callable, Optional, Tuple, Union
|
|
13
13
|
|
|
14
14
|
import numpy as np
|
|
15
15
|
|
|
@@ -56,7 +56,7 @@ class STLJaxExpr(Expr):
|
|
|
56
56
|
def over(
|
|
57
57
|
self,
|
|
58
58
|
interval: tuple[int, int],
|
|
59
|
-
penalty: str = "squared_relu",
|
|
59
|
+
penalty: Union[str, Callable[[Expr], Expr]] = "squared_relu",
|
|
60
60
|
idx: Optional[int] = None,
|
|
61
61
|
check_nodally: bool = False,
|
|
62
62
|
licq_max: Optional[float] = None,
|
|
@@ -68,7 +68,8 @@ class STLJaxExpr(Expr):
|
|
|
68
68
|
|
|
69
69
|
Args:
|
|
70
70
|
interval: Tuple of (start, end) node indices for enforcement interval
|
|
71
|
-
penalty:
|
|
71
|
+
penalty: CTCS penalty function name, or a callable ``Expr -> Expr``
|
|
72
|
+
receiving the constraint residual (see :class:`CTCS`)
|
|
72
73
|
idx: Optional grouping index for multiple augmented states
|
|
73
74
|
check_nodally: Whether to also enforce at discrete nodes
|
|
74
75
|
licq_max: Optional upper bound on the augmented state accumulating
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: openscvx
|
|
3
|
-
Version: 0.5.3.
|
|
3
|
+
Version: 0.5.3.dev49
|
|
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
|
|
@@ -1121,6 +1121,94 @@ def test_ctcs_unknown_penalty():
|
|
|
1121
1121
|
ctcs_constraint.penalty_expr()
|
|
1122
1122
|
|
|
1123
1123
|
|
|
1124
|
+
# --- CTCS: Callable Penalties ---
|
|
1125
|
+
|
|
1126
|
+
|
|
1127
|
+
def test_ctcs_callable_penalty_builds_expected_ast():
|
|
1128
|
+
"""A callable penalty is applied to the residual and summed."""
|
|
1129
|
+
x = Variable("x", shape=(2,))
|
|
1130
|
+
constraint = x <= 1.0
|
|
1131
|
+
|
|
1132
|
+
ctcs_constraint = CTCS(constraint, penalty=lambda r: Square(PositivePart(r)))
|
|
1133
|
+
penalty = ctcs_constraint.penalty_expr()
|
|
1134
|
+
|
|
1135
|
+
assert isinstance(penalty, Sum)
|
|
1136
|
+
assert isinstance(penalty.operand, Square)
|
|
1137
|
+
assert isinstance(penalty.operand.x, PositivePart)
|
|
1138
|
+
assert penalty.operand.x.x is constraint.lhs
|
|
1139
|
+
|
|
1140
|
+
|
|
1141
|
+
def test_ctcs_callable_penalty_carries_parameters():
|
|
1142
|
+
"""A callable penalty can tune parameters the named penalties hardcode."""
|
|
1143
|
+
x = Variable("x", shape=(2,))
|
|
1144
|
+
constraint = x <= 1.0
|
|
1145
|
+
|
|
1146
|
+
ctcs_constraint = CTCS(constraint, penalty=lambda r: Huber(PositivePart(r), delta=0.5))
|
|
1147
|
+
penalty = ctcs_constraint.penalty_expr()
|
|
1148
|
+
|
|
1149
|
+
assert isinstance(penalty.operand, Huber)
|
|
1150
|
+
assert penalty.operand.delta == 0.5
|
|
1151
|
+
# The named 'huber' penalty leaves delta at its default
|
|
1152
|
+
assert CTCS(constraint, penalty="huber").penalty_expr().operand.delta != 0.5
|
|
1153
|
+
|
|
1154
|
+
|
|
1155
|
+
def test_ctcs_callable_penalty_must_return_expr():
|
|
1156
|
+
"""A callable penalty returning a non-Expr should say how to fix it."""
|
|
1157
|
+
import jax.numpy as jnp
|
|
1158
|
+
|
|
1159
|
+
x = Variable("x", shape=(1,))
|
|
1160
|
+
constraint = x <= 0.0
|
|
1161
|
+
|
|
1162
|
+
with pytest.raises(ValueError, match="must return one built from openscvx operations"):
|
|
1163
|
+
CTCS(constraint, penalty=lambda r: 42.0).penalty_expr()
|
|
1164
|
+
|
|
1165
|
+
with pytest.raises(ValueError, match="jax.numpy or numpy will not work"):
|
|
1166
|
+
CTCS(constraint, penalty=lambda r: jnp.maximum(0.0, 1.0)).penalty_expr()
|
|
1167
|
+
|
|
1168
|
+
|
|
1169
|
+
def test_ctcs_callable_penalty_rejected_at_build_time():
|
|
1170
|
+
"""Shape checking surfaces a bad callable penalty when the problem is built."""
|
|
1171
|
+
x = State("x", (3,))
|
|
1172
|
+
constraint = x <= np.ones((3,))
|
|
1173
|
+
|
|
1174
|
+
with pytest.raises(ValueError, match="penalty expression validation failed"):
|
|
1175
|
+
ctcs(constraint, penalty=lambda r: 42.0).check_shape()
|
|
1176
|
+
|
|
1177
|
+
|
|
1178
|
+
def test_ctcs_callable_penalty_repr():
|
|
1179
|
+
"""CTCS repr should name a callable penalty rather than dumping its address."""
|
|
1180
|
+
x = Variable("x", shape=(3,))
|
|
1181
|
+
constraint = x <= 1.5
|
|
1182
|
+
|
|
1183
|
+
def wide_huber(r):
|
|
1184
|
+
return Huber(PositivePart(r), delta=0.5)
|
|
1185
|
+
|
|
1186
|
+
assert repr(CTCS(constraint, penalty=wide_huber)) == (
|
|
1187
|
+
"CTCS(Var('x') <= Const(1.5), penalty=wide_huber)"
|
|
1188
|
+
)
|
|
1189
|
+
assert repr(CTCS(constraint, penalty=lambda r: Square(r))) == (
|
|
1190
|
+
"CTCS(Var('x') <= Const(1.5), penalty=<lambda>)"
|
|
1191
|
+
)
|
|
1192
|
+
|
|
1193
|
+
|
|
1194
|
+
def test_ctcs_over_preserves_callable_penalty():
|
|
1195
|
+
"""A callable penalty survives .over() on both Constraint and CTCS."""
|
|
1196
|
+
x = Variable("x", shape=(2,))
|
|
1197
|
+
|
|
1198
|
+
def wide_huber(r):
|
|
1199
|
+
return Huber(PositivePart(r), delta=0.5)
|
|
1200
|
+
|
|
1201
|
+
ctcs_constraint = (x <= 1.0).over((0, 10), penalty=wide_huber)
|
|
1202
|
+
assert ctcs_constraint.penalty is wide_huber
|
|
1203
|
+
assert ctcs_constraint.nodes == (0, 10)
|
|
1204
|
+
|
|
1205
|
+
retimed = ctcs_constraint.over((10, 20))
|
|
1206
|
+
assert retimed.penalty is wide_huber
|
|
1207
|
+
assert retimed.nodes == (10, 20)
|
|
1208
|
+
|
|
1209
|
+
assert ctcs_constraint.canonicalize().penalty is wide_huber
|
|
1210
|
+
|
|
1211
|
+
|
|
1124
1212
|
# --- CTCS: Shape Checking ---
|
|
1125
1213
|
|
|
1126
1214
|
|
|
@@ -3611,8 +3611,10 @@ def test_cinterp_symbolic_coeffs_update_between_evals_no_recompile():
|
|
|
3611
3611
|
result_a = fn(None, None, None, {"c": _reverse_coeffs(cs_a)})
|
|
3612
3612
|
result_b = fn(None, None, None, {"c": _reverse_coeffs(cs_b)})
|
|
3613
3613
|
|
|
3614
|
-
|
|
3615
|
-
|
|
3614
|
+
# float32 evaluation cannot pin the fp_b endpoint (exactly 0) tighter than
|
|
3615
|
+
# ~1 ulp of the O(1) coefficients, so the default atol=1e-8 is unattainable.
|
|
3616
|
+
assert jnp.allclose(result_a, cs_a(query), atol=1e-6)
|
|
3617
|
+
assert jnp.allclose(result_b, cs_b(query), atol=1e-6)
|
|
3616
3618
|
assert not jnp.allclose(result_a, result_b)
|
|
3617
3619
|
|
|
3618
3620
|
|
|
@@ -582,6 +582,29 @@ def test_inequality_constraint_penalty_activation():
|
|
|
582
582
|
)
|
|
583
583
|
|
|
584
584
|
|
|
585
|
+
def test_callable_penalty_matches_hand_built_expression():
|
|
586
|
+
"""A callable penalty lowers to the same values as the expression it builds."""
|
|
587
|
+
limit = 1.0
|
|
588
|
+
x = jnp.array([-2.0, 0.0, 1.0, 1.5, 4.0])
|
|
589
|
+
|
|
590
|
+
state = State("x", (5,))
|
|
591
|
+
state._slice = slice(0, 5)
|
|
592
|
+
|
|
593
|
+
constraint = state - limit <= 0
|
|
594
|
+
|
|
595
|
+
ctcs_constraint = CTCS(constraint, penalty=lambda r: Huber(PositivePart(r), delta=0.5))
|
|
596
|
+
from_callable = lower_to_jax(ctcs_constraint.penalty_expr())(x, None, None, None)
|
|
597
|
+
|
|
598
|
+
hand_built = lower_to_jax(Sum(Huber(PositivePart(constraint.lhs), delta=0.5)))(
|
|
599
|
+
x, None, None, None
|
|
600
|
+
)
|
|
601
|
+
|
|
602
|
+
assert jnp.allclose(from_callable, hand_built)
|
|
603
|
+
# And it is genuinely a different penalty from the built-in huber
|
|
604
|
+
built_in = lower_to_jax(CTCS(constraint, penalty="huber").penalty_expr())(x, None, None, None)
|
|
605
|
+
assert not jnp.allclose(from_callable, built_in)
|
|
606
|
+
|
|
607
|
+
|
|
585
608
|
def test_reverse_inequality_constraint_penalty():
|
|
586
609
|
"""Test penalties for x >= limit (satisfied when x >= limit)."""
|
|
587
610
|
# Constraint: x >= 2.0, equivalent to 2.0 <= x
|
|
@@ -1552,9 +1575,12 @@ def test_ctcs_equality_rejected():
|
|
|
1552
1575
|
with pytest.raises(ValueError) as exc_info:
|
|
1553
1576
|
separate_constraints(constraint_set, n_nodes=n_nodes)
|
|
1554
1577
|
|
|
1555
|
-
# Check error message is helpful
|
|
1578
|
+
# Check error message is helpful: it names the cause and the alternative,
|
|
1579
|
+
# without enumerating penalty names (penalties may be user-defined)
|
|
1556
1580
|
msg = str(exc_info.value)
|
|
1557
1581
|
assert "CTCS constraints cannot be equality" in msg
|
|
1582
|
+
assert "violation of an inequality" in msg
|
|
1583
|
+
assert ".convex()" in msg
|
|
1558
1584
|
|
|
1559
1585
|
|
|
1560
1586
|
def test_nonconvex_inequality_still_accepted():
|
|
@@ -22,7 +22,7 @@ from openscvx.symbolic.expr import (
|
|
|
22
22
|
)
|
|
23
23
|
from openscvx.symbolic.expr.constraint import CTCS
|
|
24
24
|
from openscvx.symbolic.expr.linalg import Norm
|
|
25
|
-
from openscvx.symbolic.expr.math import Cos, Huber, Sin, SmoothReLU
|
|
25
|
+
from openscvx.symbolic.expr.math import Cos, Huber, PositivePart, Sin, SmoothReLU, Square
|
|
26
26
|
from openscvx.symbolic.hashing import hash_symbolic_problem
|
|
27
27
|
|
|
28
28
|
|
|
@@ -528,8 +528,8 @@ def test_ctcs_same_params():
|
|
|
528
528
|
y = State("y", (2,))
|
|
529
529
|
y._slice = slice(0, 2)
|
|
530
530
|
|
|
531
|
-
ctcs1 = CTCS(x <= 5, penalty="
|
|
532
|
-
ctcs2 = CTCS(y <= 5, penalty="
|
|
531
|
+
ctcs1 = CTCS(x <= 5, penalty="huber")
|
|
532
|
+
ctcs2 = CTCS(y <= 5, penalty="huber")
|
|
533
533
|
|
|
534
534
|
assert hash_expr(ctcs1) == hash_expr(ctcs2)
|
|
535
535
|
|
|
@@ -539,10 +539,48 @@ def test_ctcs_different_penalty():
|
|
|
539
539
|
x = State("x", (2,))
|
|
540
540
|
x._slice = slice(0, 2)
|
|
541
541
|
|
|
542
|
-
|
|
543
|
-
|
|
542
|
+
ctcs_squared = CTCS(x <= 5, penalty="squared_relu")
|
|
543
|
+
ctcs_huber = CTCS(x <= 5, penalty="huber")
|
|
544
544
|
|
|
545
|
-
assert hash_expr(
|
|
545
|
+
assert hash_expr(ctcs_squared) != hash_expr(ctcs_huber)
|
|
546
|
+
|
|
547
|
+
|
|
548
|
+
def test_ctcs_same_callable_penalty():
|
|
549
|
+
"""CTCS with the same callable penalty should hash the same."""
|
|
550
|
+
x = State("x", (2,))
|
|
551
|
+
x._slice = slice(0, 2)
|
|
552
|
+
|
|
553
|
+
y = State("y", (2,))
|
|
554
|
+
y._slice = slice(0, 2)
|
|
555
|
+
|
|
556
|
+
ctcs1 = CTCS(x <= 5, penalty=lambda r: Huber(PositivePart(r), delta=0.5))
|
|
557
|
+
ctcs2 = CTCS(y <= 5, penalty=lambda r: Huber(PositivePart(r), delta=0.5))
|
|
558
|
+
|
|
559
|
+
assert hash_expr(ctcs1) == hash_expr(ctcs2)
|
|
560
|
+
|
|
561
|
+
|
|
562
|
+
def test_ctcs_different_callable_penalty():
|
|
563
|
+
"""CTCS callable penalties that build different trees should hash differently."""
|
|
564
|
+
x = State("x", (2,))
|
|
565
|
+
x._slice = slice(0, 2)
|
|
566
|
+
|
|
567
|
+
ctcs_wide = CTCS(x <= 5, penalty=lambda r: Huber(PositivePart(r), delta=0.5))
|
|
568
|
+
ctcs_narrow = CTCS(x <= 5, penalty=lambda r: Huber(PositivePart(r), delta=0.1))
|
|
569
|
+
ctcs_squared = CTCS(x <= 5, penalty=lambda r: Square(PositivePart(r)))
|
|
570
|
+
|
|
571
|
+
assert hash_expr(ctcs_wide) != hash_expr(ctcs_narrow)
|
|
572
|
+
assert hash_expr(ctcs_wide) != hash_expr(ctcs_squared)
|
|
573
|
+
|
|
574
|
+
|
|
575
|
+
def test_ctcs_callable_penalty_matches_equivalent_name():
|
|
576
|
+
"""A callable that rebuilds a named penalty hashes like the named penalty."""
|
|
577
|
+
x = State("x", (2,))
|
|
578
|
+
x._slice = slice(0, 2)
|
|
579
|
+
|
|
580
|
+
ctcs_named = CTCS(x <= 5, penalty="squared_relu")
|
|
581
|
+
ctcs_callable = CTCS(x <= 5, penalty=lambda r: Square(PositivePart(r)))
|
|
582
|
+
|
|
583
|
+
assert hash_expr(ctcs_named) == hash_expr(ctcs_callable)
|
|
546
584
|
|
|
547
585
|
|
|
548
586
|
def test_ctcs_with_nodes():
|
|
@@ -932,9 +970,9 @@ def test_problem_ctcs_constraint_order_invariant():
|
|
|
932
970
|
|
|
933
971
|
# Create CTCS constraints in the specified order
|
|
934
972
|
constraints_map = {
|
|
935
|
-
"ctcs_norm": CTCS(Norm(x) <= 3.0, penalty="
|
|
936
|
-
"ctcs_x0": CTCS(x[0] >= -1.0, penalty="
|
|
937
|
-
"ctcs_x1": CTCS(x[1] <= 2.0, penalty="
|
|
973
|
+
"ctcs_norm": CTCS(Norm(x) <= 3.0, penalty="squared_relu"),
|
|
974
|
+
"ctcs_x0": CTCS(x[0] >= -1.0, penalty="huber"),
|
|
975
|
+
"ctcs_x1": CTCS(x[1] <= 2.0, penalty="squared_relu"),
|
|
938
976
|
}
|
|
939
977
|
ordered_constraints = [constraints_map[name] for name in constraint_order]
|
|
940
978
|
|
|
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
|