openscvx 0.5.3.dev43__tar.gz → 0.5.3.dev45__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.dev43/openscvx.egg-info → openscvx-0.5.3.dev45}/PKG-INFO +2 -2
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/abstract/brachistochrone.py +1 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/_version.py +3 -3
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/solvers/cvxpy_ptr_solver.py +1 -1
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/expr/math.py +125 -26
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/lowerers/jax/math.py +26 -11
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/lowerers/latex/math.py +5 -6
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45/openscvx.egg-info}/PKG-INFO +2 -2
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx.egg-info/requires.txt +1 -1
- openscvx-0.5.3.dev45/openscvx.egg-info/scm_version.json +8 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/pyproject.toml +1 -1
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/e2e/test_brachistochrone.py +8 -8
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/symbolic/expr/test_math.py +166 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/test_loader.py +2 -2
- openscvx-0.5.3.dev43/openscvx.egg-info/scm_version.json +0 -8
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/.github/assets/logo.svg +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/.github/release-drafter.yml +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/.github/workflows/_docs.yml +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/.github/workflows/_extra.yml +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/.github/workflows/branch-name.yml +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/.github/workflows/docs.yml +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/.github/workflows/lint.yml +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/.github/workflows/nightly.yml +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/.github/workflows/release-drafter.yml +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/.github/workflows/release.yml +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/.github/workflows/tests-cvxpygen.yml +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/.github/workflows/tests-examples.yml +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/.github/workflows/tests-lie.yml +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/.github/workflows/tests-mjx.yml +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/.github/workflows/tests-qpax.yml +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/.github/workflows/tests.yml +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/.gitignore +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/.gitmodules +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/CITATION.cff +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/CONTRIBUTING.md +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/LICENSE +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/README.md +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/docs/Foundations/constraint_reformulation.md +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/docs/Foundations/control_parameterization.md +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/docs/Foundations/discretization.md +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/docs/Foundations/ocp.md +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/docs/Foundations/scvx.md +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/docs/Foundations/time_dilation.md +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/docs/UnderTheHood/batching_jit_grad.md +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/docs/UnderTheHood/custom_algorithms_autotuners.md +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/docs/UnderTheHood/lowering_architecture.md +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/docs/UnderTheHood/vectorization_and_vmapping.md +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/docs/UsersGuide/00_introduction.md +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/docs/UsersGuide/01_hello_world_brachistochrone.md +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/docs/UsersGuide/02_drone_racing_constraints.md +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/docs/UsersGuide/03_obstacle_avoidance_vmap.md +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/docs/UsersGuide/04_viewpoint_constraints.md +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/docs/UsersGuide/05_visualization.md +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/docs/UsersGuide/06_logic.md +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/docs/UsersGuide/07_lie.md +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/docs/UsersGuide/08_mpcc.md +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/docs/UsersGuide/09_mjx_dynamics.md +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/docs/assets/favicon.png +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/docs/assets/images/ct-scvx_dark.png +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/docs/assets/images/ct-scvx_light.png +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/docs/assets/images/ctcs_dark.png +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/docs/assets/images/ctcs_light.png +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/docs/assets/images/problem_class_dark.png +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/docs/assets/images/problem_class_light.png +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/docs/assets/logo.svg +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/docs/assets/openscvx_logo_square.png +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/docs/assets/viser-client/index.html +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/docs/assets/viser-recordings/drone_racing.viser +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/docs/assets/viser-recordings/franka_fr3v2_pick_place.viser +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/docs/changelog.md +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/docs/citation.md +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/docs/examples.md +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/docs/index.md +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/docs/installation.md +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/docs/javascripts/mathjax.js +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/docs/llms.txt +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/docs/versions.json +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/_viser_embed_export.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/abstract/brachistochrone_batched.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/abstract/flappy_bird.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/abstract/hypersensitive.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/abstract/impulsive.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/abstract/stl_integer_variable.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/abstract/stl_or.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/aircraft/dynamic_soaring.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/aircraft/supersonic_time_to_climb.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/animations/7_dof_arm.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/animations/_camera.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/animations/_render.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/animations/_sensor_view.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/animations/dr_vp_polytope.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/animations/franka_fr3v2_pick_place.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/animations/logo.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/animations/obstacle_avoidance_vmap.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/arm/3_dof_arm.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/arm/7_dof_arm.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/arm/7_dof_arm_collision.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/arm/7_dof_arm_vp.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/arm/franka_fr3v2_pick_place.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/arm/franka_fr3v2_viewplanning.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/arm/franka_fr3v2_viewplanning_nodal.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/car/dubins_car.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/car/dubins_car_disjoint.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/car/dubins_car_obstacle_conditional.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/car/dubins_car_obstacle_stl.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/car/dubins_car_stl_or.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/car/dubins_car_waypoint_stl.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/double_integrator/_plotting.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/double_integrator/moving_safe_zones.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/drone/2d_obstacle_avoidance_batched_ic.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/drone/boresight_trace_mpcc.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/drone/cinema_vp.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/drone/cinema_vp_nodal.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/drone/dr_double_integrator.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/drone/dr_vp.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/drone/dr_vp_nodal.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/drone/dr_vp_polytope.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/drone/drone_racing.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/drone/drone_racing_batched_gates.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/drone/logo.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/drone/logo_utils/acl_logo.svg +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/drone/logo_utils/circle.svg +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/drone/logo_utils/openscvx_logo_single.svg +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/drone/logo_utils/quadrotor_mesh.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/drone/logo_utils/svg_path_utils.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/drone/multi_agent_circle_swap.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/drone/obstacle_avoidance.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/drone/obstacle_avoidance_nodal.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/drone/obstacle_avoidance_vmap.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/drone/obstacle_avoidance_vmap_2d.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/drone/openscvx_logo.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/frax/panda_frax.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/frax/panda_frax_pick_place.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/frax/panda_frax_viewplanning.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/frax/panda_frax_waypoint.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/frax/ur5e_assets/ur5e.urdf +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/frax/ur5e_pen_trace.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/mjx/cartpole_mjx.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/mjx/double_cartpole_mjx.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/mjx/skydio_x2_mjx.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/mjx/triple_cartpole_3d_mjx.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/mjx/triple_cartpole_game.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/mjx/triple_cartpole_mjx.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/mpc/double_integrator_discrete.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/mpc/double_integrator_drone_racing.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/mpc/dubins_car_circle_analytical.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/mpc/dubins_car_circle_discrete.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/mpc/realtime_double_integrator_drone_racing.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/plotting.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/plotting_viser.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/realtime/3DoF_pdg_realtime.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/realtime/6DoF_pdg_realtime.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/realtime/base_problems/3DoF_pdg_realtime_base.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/realtime/base_problems/6DoF_pdg_realtime_base.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/realtime/base_problems/cinema_vp_realtime_base.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/realtime/base_problems/drone_racing_realtime_base.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/realtime/base_problems/dubins_car_realtime_base.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/realtime/base_problems/obstacle_avoidance_realtime_base.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/realtime/cinema_vp_realtime.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/realtime/drone_racing_realtime.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/realtime/dubins_car_realtime.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/realtime/obstacle_avoidance_realtime.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/rocket/3DoF_pdg.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/rocket/6DoF_pdg.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/rocket/6DoF_pdg_batched_ic.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/rocket/ascent_launch_vehicle.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/spacecraft/halo_orbit.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/spacecraft/hohmann_transfer.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/spacecraft/let_transfer.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/spacecraft/proxops_cw.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/examples/spacecraft/relative_loitering.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/figures/ctlos_cine.gif +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/figures/ctlos_dr.gif +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/figures/dtlos_cine.gif +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/figures/dtlos_dr.gif +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/figures/openscvx_logo.svg +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/figures/openscvx_logo_square.png +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/figures/oscvx_structure_full_dark.svg +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/figures/video_preview.png +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/material/__init__.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/material/overrides/assets/stylesheets/custom.css +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/material/overrides/assets/stylesheets/home-dropin.css +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/material/overrides/assets/stylesheets/home-hero.css +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/material/overrides/assets/stylesheets/home-viser.css +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/material/overrides/home.html +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/material/overrides/main.html +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/material/overrides/partials/home-diagram.html +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/material/overrides/partials/home-dropin-banner.html +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/material/overrides/partials/home-hero.html +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/material/overrides/partials/home-pipeline.html +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/material/overrides/partials/home-viser-strip.html +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/material/overrides/sitemap.xml +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/mkdocs.yml +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/__init__.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/__main__.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/algorithms/__init__.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/algorithms/autotuner/__init__.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/algorithms/autotuner/acceptance_ratio.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/algorithms/autotuner/adaptive_proximal_weight.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/algorithms/autotuner/augmented_lagrangian.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/algorithms/autotuner/base.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/algorithms/autotuner/constant_proximal_weight.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/algorithms/autotuner/ramp_proximal_weight.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/algorithms/base.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/algorithms/history.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/algorithms/hyperparams.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/algorithms/loop.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/algorithms/optimization_results.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/algorithms/penalty.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/algorithms/scvx/__init__.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/algorithms/scvx/iteration.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/algorithms/scvx/penalized_trust_region.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/algorithms/state.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/algorithms/weights.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/config.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/discretization/__init__.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/discretization/base.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/discretization/discretize_linearize.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/discretization/linearize_discretize.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/discretization/linearize_discretize_sparse.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/discretization/sparse_utils/__init__.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/discretization/sparse_utils/bcoo_helpers.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/discretization/sparse_utils/sparse_jacobian.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/expert/__init__.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/expert/byof.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/expert/lowering.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/expert/validation.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/init/__init__.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/init/interpolation.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/init/inverse_kinematics.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/integrations/__init__.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/integrations/_utils.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/integrations/base.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/integrations/frax.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/integrations/menagerie.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/integrations/mjx.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/integrators/__init__.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/integrators/diffrax.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/integrators/runge_kutta.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/loader.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/lowered/__init__.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/lowered/cvxpy_constraints.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/lowered/cvxpy_variables.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/lowered/dynamics.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/lowered/jax_constraints.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/lowered/parameters.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/lowered/problem.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/lowered/unified.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/plotting/__init__.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/plotting/plotting.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/plotting/publication.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/plotting/scp_iteration.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/plotting/viser/__init__.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/plotting/viser/animated.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/plotting/viser/coordinates.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/plotting/viser/orbits.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/plotting/viser/plotly_integration.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/plotting/viser/primitives.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/plotting/viser/scp.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/plotting/viser/server.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/problem.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/propagation/__init__.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/propagation/post_processing.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/propagation/propagation.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/solvers/__init__.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/solvers/base.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/solvers/cones.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/solvers/moreau_ptr_solver.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/solvers/ptr_solver.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/solvers/qpax_ptr_solver.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/__init__.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/affine.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/augmentation.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/builder.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/canonicalize.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/constraint_set.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/expr/__init__.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/expr/arithmetic.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/expr/array.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/expr/constraint.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/expr/control.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/expr/expr.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/expr/lie/__init__.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/expr/lie/adjoint.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/expr/lie/se3.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/expr/lie/so3.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/expr/linalg.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/expr/logic.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/expr/parameter.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/expr/spatial.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/expr/state.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/expr/stl.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/expr/stljax.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/expr/time.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/expr/variable.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/expr/vmap.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/hashing.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/lower.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/lowerers/__init__.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/lowerers/cvxpy/__init__.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/lowerers/cvxpy/_lowerer.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/lowerers/cvxpy/_registry.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/lowerers/cvxpy/arithmetic.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/lowerers/cvxpy/array.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/lowerers/cvxpy/constraint.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/lowerers/cvxpy/control.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/lowerers/cvxpy/expr.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/lowerers/cvxpy/linalg.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/lowerers/cvxpy/logic.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/lowerers/cvxpy/math.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/lowerers/cvxpy/state.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/lowerers/jax/__init__.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/lowerers/jax/_lowerer.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/lowerers/jax/_registry.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/lowerers/jax/arithmetic.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/lowerers/jax/array.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/lowerers/jax/constraint.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/lowerers/jax/control.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/lowerers/jax/expr.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/lowerers/jax/lie.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/lowerers/jax/linalg.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/lowerers/jax/logic.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/lowerers/jax/spatial.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/lowerers/jax/state.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/lowerers/jax/stl.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/lowerers/jax/stljax.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/lowerers/jax/vmap.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/lowerers/latex/__init__.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/lowerers/latex/_lowerer.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/lowerers/latex/_registry.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/lowerers/latex/arithmetic.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/lowerers/latex/array.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/lowerers/latex/constraint.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/lowerers/latex/control.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/lowerers/latex/expr.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/lowerers/latex/formulation.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/lowerers/latex/lie.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/lowerers/latex/linalg.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/lowerers/latex/logic.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/lowerers/latex/spatial.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/lowerers/latex/state.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/lowerers/latex/stl.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/lowerers/latex/vmap.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/parser/__init__.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/parser/_registry.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/parser/array.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/parser/constraint.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/parser/lie.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/parser/linalg.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/parser/logic.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/parser/math.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/parser/parser.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/parser/spatial.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/parser/stl.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/parser/stljax.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/parser/tokenizer.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/preprocessing.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/problem.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/sparsity.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/symbolic/unified.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/utils/__init__.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/utils/cache.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/utils/caching.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/utils/printing.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/utils/profiling.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx/utils/utils.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx.egg-info/SOURCES.txt +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx.egg-info/dependency_links.txt +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx.egg-info/entry_points.txt +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx.egg-info/scm_file_list.json +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/openscvx.egg-info/top_level.txt +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/scripts/gen_example_pages.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/scripts/gen_ref_pages.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/scripts/mkdocs_copy_viser_client_hook.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/scripts/mkdocs_seo_hook.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/setup.cfg +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/__init__.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/algorithms/__init__.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/algorithms/_iteration_helpers.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/algorithms/autotuner/__init__.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/algorithms/autotuner/test_defaults_agreement.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/algorithms/autotuner/test_hyper_overrides.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/algorithms/autotuner/test_update_weights_jit.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/algorithms/test_algorithm_state_pytree.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/algorithms/test_iteration_fn_jit.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/algorithms/test_iteration_fn_parity.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/algorithms/test_make_solve_loop.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/brachistochrone_analytical.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/conftest.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/e2e/__init__.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/e2e/test_impulsive.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/e2e/test_multishot_propagation.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/e2e/test_solve_batched_brachistochrone.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/e2e/test_solve_batched_cvxpy_export_errors.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/e2e/test_solve_batched_export_roundtrip.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/e2e/test_solve_jax_bare_brachistochrone.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/e2e/test_solve_jax_jit_brachistochrone.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/e2e/test_solve_jax_vmap_brachistochrone.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/e2e/test_solve_jax_vmap_converged_no_drift.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/fixtures/brachistochrone.json +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/fixtures/brachistochrone.yaml +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/hohmann_analytical.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/integrations/__init__.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/integrations/test_mjx.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/integrations/test_mjx_dynamics.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/solvers/__init__.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/solvers/_iteration_callback_helpers.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/solvers/test_cvxpy_callback_jit_spike.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/solvers/test_iteration_callback_cvxpy.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/solvers/test_iteration_callback_moreau.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/solvers/test_iteration_callback_qpax.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/solvers/test_iteration_callback_vmap.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/solvers/test_moreau_ptr_solver.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/solvers/test_qpax_ptr_solver.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/solvers/test_subproblem_pytree.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/symbolic/__init__.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/symbolic/expr/__init__.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/symbolic/expr/test_arithmetic.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/symbolic/expr/test_array.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/symbolic/expr/test_constraint.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/symbolic/expr/test_expr.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/symbolic/expr/test_lie.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/symbolic/expr/test_linalg.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/symbolic/expr/test_logic.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/symbolic/expr/test_node_reference.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/symbolic/expr/test_parameters.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/symbolic/expr/test_scaling.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/symbolic/expr/test_spatial.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/symbolic/expr/test_stl.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/symbolic/expr/test_variable.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/symbolic/expr/test_vmap.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/symbolic/parser/__init__.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/symbolic/parser/test_array.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/symbolic/parser/test_constraint.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/symbolic/parser/test_lie.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/symbolic/parser/test_linalg.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/symbolic/parser/test_load.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/symbolic/parser/test_logic.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/symbolic/parser/test_math.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/symbolic/parser/test_parser.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/symbolic/parser/test_spatial.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/symbolic/parser/test_stl.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/symbolic/parser/test_tokenizer.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/symbolic/parser/test_vmap.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/symbolic/test_augmentation.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/symbolic/test_gmsr.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/symbolic/test_hashing.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/symbolic/test_latex_formulation.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/symbolic/test_lower_cvxpy.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/symbolic/test_lower_jax.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/symbolic/test_lower_latex.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/symbolic/test_preprocessing.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/symbolic/test_sparsity.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/symbolic/test_unified.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/test_autotuning.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/test_cvxpygen_optional.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/test_discretization.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/test_examples.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/test_expert.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/test_init.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/test_initialize_syncs_guesses.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/test_integrators.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/test_optimization_results.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/test_plotting.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/test_post_process_batched_tau_clamp.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/test_propagation.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/tests/test_results_parameters.py +0 -0
- {openscvx-0.5.3.dev43 → openscvx-0.5.3.dev45}/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.dev45
|
|
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
|
|
@@ -10,7 +10,7 @@ Classifier: License :: OSI Approved :: Apache Software License
|
|
|
10
10
|
Requires-Python: >=3.11
|
|
11
11
|
Description-Content-Type: text/markdown
|
|
12
12
|
License-File: LICENSE
|
|
13
|
-
Requires-Dist: cvxpy
|
|
13
|
+
Requires-Dist: cvxpy>=1.8.1
|
|
14
14
|
Requires-Dist: qoco
|
|
15
15
|
Requires-Dist: numpy
|
|
16
16
|
Requires-Dist: jax
|
|
@@ -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.dev45'
|
|
22
|
+
__version_tuple__ = version_tuple = (0, 5, 3, 'dev45')
|
|
23
23
|
|
|
24
|
-
__commit_id__ = commit_id = '
|
|
24
|
+
__commit_id__ = commit_id = 'g7ded3ab51'
|
|
@@ -210,7 +210,7 @@ class CVXPyPTRSolver(PTRSolver):
|
|
|
210
210
|
self.solver_args = (
|
|
211
211
|
solver_args
|
|
212
212
|
if solver_args is not None
|
|
213
|
-
else {"abstol": 1e-06, "reltol": 1e-09, "enforce_dpp": True}
|
|
213
|
+
else {"abstol": 1e-06, "reltol": 1e-09, "enforce_dpp": True, "warm_start": False}
|
|
214
214
|
)
|
|
215
215
|
self.cvxpygen = cvxpygen
|
|
216
216
|
self.cvxpygen_override = cvxpygen_override
|
|
@@ -1135,23 +1135,40 @@ _CINTERP_METHODS = {
|
|
|
1135
1135
|
|
|
1136
1136
|
|
|
1137
1137
|
class Cinterp(Expr):
|
|
1138
|
-
"""1D cubic
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1138
|
+
"""1D piecewise-cubic interpolation for symbolic expressions.
|
|
1139
|
+
|
|
1140
|
+
Evaluates a piecewise-cubic polynomial at query point ``x`` by a segment
|
|
1141
|
+
lookup on the fixed breakpoints ``xp`` followed by Horner evaluation. The
|
|
1142
|
+
polynomial table is held as ``coeffs`` of shape ``(4, n_segments)`` where
|
|
1143
|
+
``n_segments = len(xp) - 1``; row ``k`` holds the degree-``k`` coefficients,
|
|
1144
|
+
so the value in segment ``i`` at local coordinate ``t = x - xp[i]`` is
|
|
1145
|
+
``coeffs[0, i] + coeffs[1, i]*t + coeffs[2, i]*t**2 + coeffs[3, i]*t**3``.
|
|
1146
|
+
|
|
1147
|
+
The table can be supplied two ways, and exactly one must be chosen:
|
|
1148
|
+
|
|
1149
|
+
- **Fit from data (default).** Pass ``fp`` (values at the breakpoints) and
|
|
1150
|
+
an optional ``method``; scipy fits the spline once at construction and the
|
|
1151
|
+
coefficients are baked into the compiled function as constants.
|
|
1152
|
+
- **Coefficient override.** Pass ``coeffs`` directly — either a numeric
|
|
1153
|
+
``(4, n_segments)`` array or a symbolic :class:`~openscvx.Parameter` of
|
|
1154
|
+
that shape. A symbolic override is *not* baked in: the compiled function
|
|
1155
|
+
gathers the current parameter value at run time, so the interpolated
|
|
1156
|
+
function can be swapped **between solves** — with any host-side fitting
|
|
1157
|
+
method you like — without recompiling. ``method`` is meaningless with an
|
|
1158
|
+
override and passing it is an error.
|
|
1144
1159
|
|
|
1145
1160
|
Attributes:
|
|
1146
1161
|
x: Query point at which to evaluate the spline (symbolic expression).
|
|
1147
|
-
xp: 1D array of breakpoints (must be strictly increasing).
|
|
1148
|
-
|
|
1149
|
-
|
|
1162
|
+
xp: 1D array of breakpoints (must be strictly increasing). Fixed at
|
|
1163
|
+
construction; it drives the segment lookup and cannot be symbolic.
|
|
1164
|
+
fp: 1D array of values at the breakpoints (fit path only; ``None`` for a
|
|
1165
|
+
coefficient override).
|
|
1166
|
+
method: Spline method used to fit ``fp`` — ``"cubic"`` (not-a-knot, C2),
|
|
1150
1167
|
``"pchip"`` (monotonicity-preserving, C1), or ``"akima"`` (C1).
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1168
|
+
``None`` for a coefficient override.
|
|
1169
|
+
coeffs: The polynomial table. A numeric ``(4, n_segments)`` array for
|
|
1170
|
+
the fit and numeric-override paths, or the coefficient ``Expr`` for a
|
|
1171
|
+
symbolic override.
|
|
1155
1172
|
|
|
1156
1173
|
Example:
|
|
1157
1174
|
Interpolate a discrete reference path::
|
|
@@ -1173,34 +1190,101 @@ class Cinterp(Expr):
|
|
|
1173
1190
|
altitude = ox.State("altitude", shape=(1,))
|
|
1174
1191
|
rho = ox.Cinterp(altitude[0], alt_data, rho_data, method="pchip")
|
|
1175
1192
|
|
|
1193
|
+
Drive the table with a :class:`~openscvx.Parameter` so the interpolated
|
|
1194
|
+
function can be retuned between solves without recompiling. Fit the
|
|
1195
|
+
spline host-side with any scipy method and push its coefficients (scipy
|
|
1196
|
+
stores them highest-degree-first, so reverse to this class's
|
|
1197
|
+
ascending-degree layout)::
|
|
1198
|
+
|
|
1199
|
+
from scipy.interpolate import PchipInterpolator
|
|
1200
|
+
|
|
1201
|
+
xp = np.linspace(0, 1, 11)
|
|
1202
|
+
n_seg = len(xp) - 1
|
|
1203
|
+
|
|
1204
|
+
cs = PchipInterpolator(xp, fp_data)
|
|
1205
|
+
coeffs = ox.Parameter("spline_coeffs", shape=(4, n_seg),
|
|
1206
|
+
value=cs.c[::-1])
|
|
1207
|
+
|
|
1208
|
+
progress = ox.State("progress", shape=(1,))
|
|
1209
|
+
ref = ox.Cinterp(progress[0], xp, coeffs=coeffs)
|
|
1210
|
+
|
|
1211
|
+
# ... build and solve the problem, then before the next solve:
|
|
1212
|
+
cs = PchipInterpolator(xp, new_fp_data)
|
|
1213
|
+
problem.parameters["spline_coeffs"] = cs.c[::-1]
|
|
1214
|
+
|
|
1176
1215
|
!!! note
|
|
1177
1216
|
`xp` must be strictly increasing.
|
|
1178
1217
|
|
|
1179
1218
|
!!! warning "Extrapolation behavior"
|
|
1180
1219
|
For query points outside `[xp[0], xp[-1]]`, boundary segment
|
|
1181
1220
|
polynomials are extrapolated (consistent with scipy defaults).
|
|
1221
|
+
|
|
1222
|
+
!!! warning "Continuity is the caller's responsibility"
|
|
1223
|
+
With a coefficient override the library no longer guarantees that the
|
|
1224
|
+
table describes a continuous function — that is now the caller's job.
|
|
1225
|
+
A table whose segment polynomials disagree at a breakpoint yields a
|
|
1226
|
+
discontinuous dynamics function, which the discretizer will linearize
|
|
1227
|
+
and integrate without complaint, silently degrading accuracy.
|
|
1182
1228
|
"""
|
|
1183
1229
|
|
|
1184
1230
|
def __init__(
|
|
1185
1231
|
self,
|
|
1186
1232
|
x: Union[Expr, float, int, np.ndarray],
|
|
1187
1233
|
xp: Union[np.ndarray, list],
|
|
1188
|
-
fp: Union[np.ndarray, list],
|
|
1234
|
+
fp: Union[np.ndarray, list, None] = None,
|
|
1189
1235
|
*,
|
|
1190
|
-
|
|
1236
|
+
coeffs: Union[Expr, np.ndarray, list, None] = None,
|
|
1237
|
+
method: Union[str, None] = None,
|
|
1191
1238
|
_coeffs: Union[np.ndarray, None] = None,
|
|
1192
1239
|
):
|
|
1193
1240
|
self.x = to_expr(x)
|
|
1194
1241
|
xp = np.asarray(xp, dtype=float)
|
|
1195
|
-
|
|
1242
|
+
if xp.ndim != 1:
|
|
1243
|
+
raise ValueError(f"Cinterp xp must be 1D, got shape {xp.shape}")
|
|
1244
|
+
self.xp_np = xp
|
|
1245
|
+
n_seg = xp.shape[0] - 1
|
|
1246
|
+
|
|
1247
|
+
if (fp is None) == (coeffs is None):
|
|
1248
|
+
raise ValueError(
|
|
1249
|
+
"Cinterp requires exactly one of fp or coeffs: pass fp to fit a "
|
|
1250
|
+
"spline through breakpoint values, or coeffs to supply the "
|
|
1251
|
+
"polynomial table directly."
|
|
1252
|
+
)
|
|
1196
1253
|
|
|
1254
|
+
if coeffs is not None:
|
|
1255
|
+
# --- Coefficient-override path (numeric array or symbolic Expr). ---
|
|
1256
|
+
if method is not None:
|
|
1257
|
+
raise ValueError(
|
|
1258
|
+
"Cinterp method is meaningless with a coeffs override "
|
|
1259
|
+
"(the table is supplied, not fit); drop the method argument."
|
|
1260
|
+
)
|
|
1261
|
+
expected = (4, n_seg)
|
|
1262
|
+
if isinstance(coeffs, Expr):
|
|
1263
|
+
got = coeffs.check_shape()
|
|
1264
|
+
if got != expected:
|
|
1265
|
+
raise ValueError(
|
|
1266
|
+
f"Cinterp coeffs must have shape {expected} (4 by len(xp) - 1), got {got}"
|
|
1267
|
+
)
|
|
1268
|
+
self.coeffs = coeffs
|
|
1269
|
+
else:
|
|
1270
|
+
arr = np.asarray(coeffs, dtype=float)
|
|
1271
|
+
if arr.shape != expected:
|
|
1272
|
+
raise ValueError(
|
|
1273
|
+
f"Cinterp coeffs must have shape {expected} "
|
|
1274
|
+
f"(4 by len(xp) - 1), got {arr.shape}"
|
|
1275
|
+
)
|
|
1276
|
+
self.coeffs = arr
|
|
1277
|
+
self.fp_np = None
|
|
1278
|
+
self.method = None
|
|
1279
|
+
return
|
|
1280
|
+
|
|
1281
|
+
# --- Fit path: precompute spline coefficients via scipy. ---
|
|
1282
|
+
method = "cubic" if method is None else method
|
|
1197
1283
|
if method not in _CINTERP_METHODS:
|
|
1198
1284
|
raise ValueError(
|
|
1199
1285
|
f"Cinterp method must be one of {set(_CINTERP_METHODS)}, got {method!r}"
|
|
1200
1286
|
)
|
|
1201
|
-
|
|
1202
|
-
if xp.ndim != 1:
|
|
1203
|
-
raise ValueError(f"Cinterp xp must be 1D, got shape {xp.shape}")
|
|
1287
|
+
fp = np.asarray(fp, dtype=float)
|
|
1204
1288
|
if fp.ndim != 1:
|
|
1205
1289
|
raise ValueError(f"Cinterp fp must be 1D, got shape {fp.shape}")
|
|
1206
1290
|
if xp.shape != fp.shape:
|
|
@@ -1208,38 +1292,53 @@ class Cinterp(Expr):
|
|
|
1208
1292
|
f"Cinterp xp and fp must have same length, got {xp.shape} vs {fp.shape}"
|
|
1209
1293
|
)
|
|
1210
1294
|
|
|
1211
|
-
self.xp_np = xp
|
|
1212
1295
|
self.fp_np = fp
|
|
1213
1296
|
self.method = method
|
|
1214
1297
|
|
|
1215
1298
|
if _coeffs is not None:
|
|
1216
1299
|
self.coeffs = _coeffs
|
|
1217
1300
|
else:
|
|
1218
|
-
# Precompute spline coefficients via scipy.
|
|
1219
1301
|
# scipy returns shape (4, n_seg) with c[0]=cubic, c[1]=quadratic, ...
|
|
1220
1302
|
# We reorder to ascending-degree layout for Horner evaluation.
|
|
1221
1303
|
cs = _CINTERP_METHODS[method](xp, fp)
|
|
1222
1304
|
self.coeffs = cs.c[::-1].copy() # row 0 = const, row 3 = cubic
|
|
1223
1305
|
|
|
1224
1306
|
def children(self):
|
|
1307
|
+
if isinstance(self.coeffs, Expr):
|
|
1308
|
+
return [self.x, self.coeffs]
|
|
1225
1309
|
return [self.x]
|
|
1226
1310
|
|
|
1227
1311
|
def canonicalize(self) -> "Expr":
|
|
1228
1312
|
x = self.x.canonicalize()
|
|
1229
|
-
|
|
1313
|
+
if isinstance(self.coeffs, Expr):
|
|
1314
|
+
return Cinterp(x, self.xp_np, coeffs=self.coeffs.canonicalize())
|
|
1315
|
+
if self.fp_np is not None:
|
|
1316
|
+
return Cinterp(x, self.xp_np, self.fp_np, method=self.method, _coeffs=self.coeffs)
|
|
1317
|
+
return Cinterp(x, self.xp_np, coeffs=self.coeffs)
|
|
1230
1318
|
|
|
1231
1319
|
def check_shape(self) -> Tuple[int, ...]:
|
|
1232
1320
|
return self.x.check_shape()
|
|
1233
1321
|
|
|
1234
1322
|
def _hash_into(self, hasher: "hashlib._Hash") -> None:
|
|
1235
1323
|
hasher.update(b"Cinterp")
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1324
|
+
if isinstance(self.coeffs, Expr):
|
|
1325
|
+
hasher.update(b"coeffs_expr")
|
|
1326
|
+
hasher.update(self.xp_np.tobytes())
|
|
1327
|
+
self.coeffs._hash_into(hasher)
|
|
1328
|
+
elif self.fp_np is not None:
|
|
1329
|
+
hasher.update(self.method.encode())
|
|
1330
|
+
hasher.update(self.xp_np.tobytes())
|
|
1331
|
+
hasher.update(self.fp_np.tobytes())
|
|
1332
|
+
else:
|
|
1333
|
+
hasher.update(b"coeffs_num")
|
|
1334
|
+
hasher.update(self.xp_np.tobytes())
|
|
1335
|
+
hasher.update(np.asarray(self.coeffs).tobytes())
|
|
1239
1336
|
self.x._hash_into(hasher)
|
|
1240
1337
|
|
|
1241
1338
|
def __repr__(self) -> str:
|
|
1242
|
-
if self.
|
|
1339
|
+
if isinstance(self.coeffs, Expr):
|
|
1340
|
+
return f"cinterp({self.x!r}, coeffs={self.coeffs!r})"
|
|
1341
|
+
if self.method == "cubic" or self.method is None:
|
|
1243
1342
|
return f"cinterp({self.x!r})"
|
|
1244
1343
|
return f"cinterp({self.x!r}, method={self.method!r})"
|
|
1245
1344
|
|
|
@@ -17,6 +17,8 @@ import jax
|
|
|
17
17
|
import jax.numpy as jnp
|
|
18
18
|
from jax.scipy.special import logsumexp
|
|
19
19
|
|
|
20
|
+
from openscvx.symbolic.expr.expr import Expr
|
|
21
|
+
|
|
20
22
|
# Expression types to handle — uncomment as you paste visitors:
|
|
21
23
|
from openscvx.symbolic.expr.math import (
|
|
22
24
|
Abs,
|
|
@@ -285,33 +287,46 @@ def _visit_linterp(lowerer, node: Linterp):
|
|
|
285
287
|
|
|
286
288
|
@visitor(Cinterp)
|
|
287
289
|
def _visit_cinterp(lowerer, node: Cinterp):
|
|
288
|
-
"""Lower 1D cubic
|
|
290
|
+
"""Lower 1D piecewise-cubic interpolation to a JAX function.
|
|
289
291
|
|
|
290
|
-
Evaluates
|
|
291
|
-
method.
|
|
292
|
-
is symbolic
|
|
293
|
-
|
|
292
|
+
Evaluates the polynomial table via segment lookup on the fixed breakpoints
|
|
293
|
+
and Horner's method. When ``node.coeffs`` is a numeric array it is baked in
|
|
294
|
+
as a constant; when it is a symbolic ``Expr`` (e.g. a ``Parameter``) it is
|
|
295
|
+
lowered too and gathered at run time, so the table can change between solves
|
|
296
|
+
without recompiling. Either way only ``xp`` is fixed. For queries outside
|
|
297
|
+
the data range the boundary segment polynomial is extrapolated.
|
|
294
298
|
|
|
295
299
|
Args:
|
|
296
|
-
node: Cinterp expression node with
|
|
300
|
+
node: Cinterp expression node with xp_np and numeric-or-symbolic coeffs.
|
|
297
301
|
|
|
298
302
|
Returns:
|
|
299
303
|
Function (x, u, node_idx, params) -> interpolated value(s)
|
|
300
304
|
"""
|
|
301
305
|
f_x = lowerer.lower(node.x)
|
|
302
306
|
xp = jnp.asarray(node.xp_np)
|
|
303
|
-
coeffs = jnp.asarray(node.coeffs) # (4, n_seg)
|
|
304
307
|
|
|
305
|
-
def
|
|
306
|
-
|
|
307
|
-
# Segment index (clamp to valid range)
|
|
308
|
+
def evaluate(x_val, coeffs):
|
|
309
|
+
# Segment index (clamp to valid range), then Horner: c0 + t*(c1 + t*(c2 + t*c3)).
|
|
308
310
|
idx = jnp.searchsorted(xp, x_val, side="right") - 1
|
|
309
311
|
idx = jnp.clip(idx, 0, xp.shape[0] - 2)
|
|
310
312
|
t = x_val - xp[idx]
|
|
311
|
-
# Horner evaluation: c0 + t*(c1 + t*(c2 + t*c3))
|
|
312
313
|
c = coeffs[:, idx]
|
|
313
314
|
return c[0] + t * (c[1] + t * (c[2] + t * c[3]))
|
|
314
315
|
|
|
316
|
+
if isinstance(node.coeffs, Expr):
|
|
317
|
+
f_coeffs = lowerer.lower(node.coeffs)
|
|
318
|
+
|
|
319
|
+
def cinterp_fn(x, u, node_idx, params):
|
|
320
|
+
coeffs = f_coeffs(x, u, node_idx, params) # (4, n_seg)
|
|
321
|
+
return evaluate(f_x(x, u, node_idx, params), coeffs)
|
|
322
|
+
|
|
323
|
+
return cinterp_fn
|
|
324
|
+
|
|
325
|
+
coeffs = jnp.asarray(node.coeffs) # (4, n_seg)
|
|
326
|
+
|
|
327
|
+
def cinterp_fn(x, u, node_idx, params):
|
|
328
|
+
return evaluate(f_x(x, u, node_idx, params), coeffs)
|
|
329
|
+
|
|
315
330
|
return cinterp_fn
|
|
316
331
|
|
|
317
332
|
|
|
@@ -171,14 +171,13 @@ def _visit_linterp(lowerer, node: Linterp):
|
|
|
171
171
|
|
|
172
172
|
@visitor(Cinterp)
|
|
173
173
|
def _visit_cinterp(lowerer, node: Cinterp):
|
|
174
|
-
"""Render 1-D cubic
|
|
174
|
+
"""Render 1-D piecewise-cubic interpolation as ``\\operatorname{cinterp}(x)``.
|
|
175
175
|
|
|
176
|
-
Only the query point is
|
|
177
|
-
|
|
178
|
-
|
|
176
|
+
Only the query point is rendered; the breakpoints and the polynomial table
|
|
177
|
+
(whether baked-in coefficients or a symbolic override) are structural and
|
|
178
|
+
stay implicit.
|
|
179
179
|
"""
|
|
180
|
-
|
|
181
|
-
return _call(r"\operatorname{cinterp}", args)
|
|
180
|
+
return _call(r"\operatorname{cinterp}", lowerer.lower(node.x))
|
|
182
181
|
|
|
183
182
|
|
|
184
183
|
@visitor(Bilerp)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: openscvx
|
|
3
|
-
Version: 0.5.3.
|
|
3
|
+
Version: 0.5.3.dev45
|
|
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
|
|
@@ -10,7 +10,7 @@ Classifier: License :: OSI Approved :: Apache Software License
|
|
|
10
10
|
Requires-Python: >=3.11
|
|
11
11
|
Description-Content-Type: text/markdown
|
|
12
12
|
License-File: LICENSE
|
|
13
|
-
Requires-Dist: cvxpy
|
|
13
|
+
Requires-Dist: cvxpy>=1.8.1
|
|
14
14
|
Requires-Dist: qoco
|
|
15
15
|
Requires-Dist: numpy
|
|
16
16
|
Requires-Dist: jax
|
|
@@ -270,7 +270,7 @@ def test_monolithic():
|
|
|
270
270
|
)
|
|
271
271
|
|
|
272
272
|
problem.settings.prp.dt = 0.01
|
|
273
|
-
problem.solver.solver_args = {"abstol": 1e-6, "reltol": 1e-9}
|
|
273
|
+
problem.solver.solver_args = {"abstol": 1e-6, "reltol": 1e-9, "warm_start": False}
|
|
274
274
|
problem.settings.sim.save_compiled = False
|
|
275
275
|
|
|
276
276
|
# Disable printing for cleaner test output
|
|
@@ -398,7 +398,7 @@ def test_backend(backend, constraint_type, with_parameters):
|
|
|
398
398
|
|
|
399
399
|
problem.settings.prp.dt = 0.01
|
|
400
400
|
if backend == "cvxpy":
|
|
401
|
-
problem.solver.solver_args = {"abstol": 1e-6, "reltol": 1e-9}
|
|
401
|
+
problem.solver.solver_args = {"abstol": 1e-6, "reltol": 1e-9, "warm_start": False}
|
|
402
402
|
problem.settings.sim.save_compiled = False
|
|
403
403
|
if hasattr(problem.settings, "dev"):
|
|
404
404
|
problem.settings.dev.printing = False
|
|
@@ -687,7 +687,7 @@ def test_constraint_types(constraint_type):
|
|
|
687
687
|
)
|
|
688
688
|
|
|
689
689
|
problem.settings.prp.dt = 0.01
|
|
690
|
-
problem.solver.solver_args = {"abstol": 1e-6, "reltol": 1e-9}
|
|
690
|
+
problem.solver.solver_args = {"abstol": 1e-6, "reltol": 1e-9, "warm_start": False}
|
|
691
691
|
problem.settings.sim.save_compiled = False
|
|
692
692
|
|
|
693
693
|
# Disable printing for cleaner test output
|
|
@@ -827,7 +827,7 @@ def test_autotuning(autotuner_spec):
|
|
|
827
827
|
)
|
|
828
828
|
|
|
829
829
|
problem.settings.prp.dt = 0.01
|
|
830
|
-
problem.solver.solver_args = {"abstol": 1e-6, "reltol": 1e-9}
|
|
830
|
+
problem.solver.solver_args = {"abstol": 1e-6, "reltol": 1e-9, "warm_start": False}
|
|
831
831
|
problem.settings.sim.save_compiled = False
|
|
832
832
|
|
|
833
833
|
# Disable printing for cleaner test output
|
|
@@ -969,7 +969,7 @@ def test_cross_nodal(test_case):
|
|
|
969
969
|
)
|
|
970
970
|
|
|
971
971
|
problem.settings.prp.dt = 0.01
|
|
972
|
-
problem.solver.solver_args = {"abstol": 1e-6, "reltol": 1e-9}
|
|
972
|
+
problem.solver.solver_args = {"abstol": 1e-6, "reltol": 1e-9, "warm_start": False}
|
|
973
973
|
problem.settings.sim.save_compiled = False
|
|
974
974
|
|
|
975
975
|
# Disable printing for cleaner test output
|
|
@@ -1107,7 +1107,7 @@ def test_parameters():
|
|
|
1107
1107
|
},
|
|
1108
1108
|
)
|
|
1109
1109
|
|
|
1110
|
-
problem.solver.solver_args = {"abstol": 1e-6, "reltol": 1e-9}
|
|
1110
|
+
problem.solver.solver_args = {"abstol": 1e-6, "reltol": 1e-9, "warm_start": False}
|
|
1111
1111
|
problem.settings.sim.save_compiled = False
|
|
1112
1112
|
|
|
1113
1113
|
# Disable printing for cleaner test output
|
|
@@ -1304,7 +1304,7 @@ def test_propagation():
|
|
|
1304
1304
|
)
|
|
1305
1305
|
|
|
1306
1306
|
problem.settings.prp.dt = 0.01
|
|
1307
|
-
problem.solver.solver_args = {"abstol": 1e-6, "reltol": 1e-9}
|
|
1307
|
+
problem.solver.solver_args = {"abstol": 1e-6, "reltol": 1e-9, "warm_start": False}
|
|
1308
1308
|
problem.settings.sim.save_compiled = False
|
|
1309
1309
|
|
|
1310
1310
|
# Disable printing for cleaner test output
|
|
@@ -1701,7 +1701,7 @@ def test_byof(byof_mode):
|
|
|
1701
1701
|
)
|
|
1702
1702
|
|
|
1703
1703
|
problem.settings.prp.dt = 0.01
|
|
1704
|
-
problem.solver.solver_args = {"abstol": 1e-6, "reltol": 1e-9}
|
|
1704
|
+
problem.solver.solver_args = {"abstol": 1e-6, "reltol": 1e-9, "warm_start": False}
|
|
1705
1705
|
problem.settings.sim.save_compiled = False
|
|
1706
1706
|
|
|
1707
1707
|
# Disable printing for cleaner test output
|
|
@@ -3533,6 +3533,172 @@ def test_cvxpy_cinterp_not_implemented():
|
|
|
3533
3533
|
lowerer.lower(expr)
|
|
3534
3534
|
|
|
3535
3535
|
|
|
3536
|
+
# --- Cinterp: Coefficient Override ---
|
|
3537
|
+
|
|
3538
|
+
|
|
3539
|
+
def _reverse_coeffs(cs):
|
|
3540
|
+
"""scipy stores coefficients highest-degree-first; Cinterp uses ascending."""
|
|
3541
|
+
return np.asarray(cs.c[::-1], dtype=float)
|
|
3542
|
+
|
|
3543
|
+
|
|
3544
|
+
def test_cinterp_numeric_coeffs_override_matches_fit():
|
|
3545
|
+
"""A numeric coeffs override reproduces the fitted spline exactly."""
|
|
3546
|
+
import jax.numpy as jnp
|
|
3547
|
+
from scipy.interpolate import CubicSpline
|
|
3548
|
+
|
|
3549
|
+
from openscvx.symbolic.expr import Cinterp, Constant
|
|
3550
|
+
from openscvx.symbolic.lower import lower_to_jax
|
|
3551
|
+
|
|
3552
|
+
xp = np.array([0.0, 1.0, 2.0, 3.0])
|
|
3553
|
+
fp = np.array([0.0, 2.0, 1.0, 3.0])
|
|
3554
|
+
query = np.linspace(0.0, 3.0, 50)
|
|
3555
|
+
|
|
3556
|
+
coeffs = _reverse_coeffs(CubicSpline(xp, fp))
|
|
3557
|
+
|
|
3558
|
+
fitted = lower_to_jax(Cinterp(Constant(query), xp, fp))(None, None, None, None)
|
|
3559
|
+
override = lower_to_jax(Cinterp(Constant(query), xp, coeffs=coeffs))(None, None, None, None)
|
|
3560
|
+
|
|
3561
|
+
assert jnp.allclose(fitted, override)
|
|
3562
|
+
|
|
3563
|
+
|
|
3564
|
+
def test_cinterp_symbolic_coeffs_matches_scipy():
|
|
3565
|
+
"""Symbolic coeffs (via a Parameter) evaluate to the host-side scipy spline.
|
|
3566
|
+
|
|
3567
|
+
Covers each host-side fitting method: cubic, pchip, akima.
|
|
3568
|
+
"""
|
|
3569
|
+
import jax.numpy as jnp
|
|
3570
|
+
from scipy.interpolate import Akima1DInterpolator, CubicSpline, PchipInterpolator
|
|
3571
|
+
|
|
3572
|
+
from openscvx.symbolic.expr import Cinterp, Constant, Parameter
|
|
3573
|
+
from openscvx.symbolic.lower import lower_to_jax
|
|
3574
|
+
|
|
3575
|
+
xp = np.linspace(0.0, 5.0, 8)
|
|
3576
|
+
fp = np.array([0.0, 1.5, 1.0, 2.0, 0.5, 2.5, 1.0, 3.0])
|
|
3577
|
+
n_seg = len(xp) - 1
|
|
3578
|
+
query = np.linspace(0.0, 5.0, 120)
|
|
3579
|
+
|
|
3580
|
+
for fitter in (CubicSpline, PchipInterpolator, Akima1DInterpolator):
|
|
3581
|
+
cs = fitter(xp, fp)
|
|
3582
|
+
coeffs = _reverse_coeffs(cs)
|
|
3583
|
+
param = Parameter("spline_coeffs", shape=(4, n_seg), value=coeffs)
|
|
3584
|
+
|
|
3585
|
+
fn = lower_to_jax(Cinterp(Constant(query), xp, coeffs=param))
|
|
3586
|
+
result = fn(None, None, None, {"spline_coeffs": coeffs})
|
|
3587
|
+
|
|
3588
|
+
assert jnp.allclose(result, cs(query)), fitter.__name__
|
|
3589
|
+
|
|
3590
|
+
|
|
3591
|
+
def test_cinterp_symbolic_coeffs_update_between_evals_no_recompile():
|
|
3592
|
+
"""Updating the parameter value changes the SAME lowered function's output."""
|
|
3593
|
+
import jax.numpy as jnp
|
|
3594
|
+
from scipy.interpolate import PchipInterpolator
|
|
3595
|
+
|
|
3596
|
+
from openscvx.symbolic.expr import Cinterp, Constant, Parameter
|
|
3597
|
+
from openscvx.symbolic.lower import lower_to_jax
|
|
3598
|
+
|
|
3599
|
+
xp = np.linspace(0.0, 1.0, 6)
|
|
3600
|
+
n_seg = len(xp) - 1
|
|
3601
|
+
query = np.linspace(0.0, 1.0, 40)
|
|
3602
|
+
|
|
3603
|
+
fp_a = np.array([0.0, 0.4, 0.2, 0.9, 0.3, 1.0])
|
|
3604
|
+
fp_b = np.array([1.0, 0.2, 0.7, 0.1, 0.8, 0.0])
|
|
3605
|
+
cs_a = PchipInterpolator(xp, fp_a)
|
|
3606
|
+
cs_b = PchipInterpolator(xp, fp_b)
|
|
3607
|
+
|
|
3608
|
+
param = Parameter("c", shape=(4, n_seg), value=_reverse_coeffs(cs_a))
|
|
3609
|
+
fn = lower_to_jax(Cinterp(Constant(query), xp, coeffs=param))
|
|
3610
|
+
|
|
3611
|
+
result_a = fn(None, None, None, {"c": _reverse_coeffs(cs_a)})
|
|
3612
|
+
result_b = fn(None, None, None, {"c": _reverse_coeffs(cs_b)})
|
|
3613
|
+
|
|
3614
|
+
assert jnp.allclose(result_a, cs_a(query))
|
|
3615
|
+
assert jnp.allclose(result_b, cs_b(query))
|
|
3616
|
+
assert not jnp.allclose(result_a, result_b)
|
|
3617
|
+
|
|
3618
|
+
|
|
3619
|
+
def test_cinterp_symbolic_coeffs_children_and_canonicalize():
|
|
3620
|
+
"""Symbolic coeffs appear as a child (so the Parameter binds) and survive canonicalize."""
|
|
3621
|
+
from openscvx.symbolic.expr import Cinterp, Parameter, State
|
|
3622
|
+
|
|
3623
|
+
xp = np.array([0.0, 1.0, 2.0, 3.0])
|
|
3624
|
+
n_seg = len(xp) - 1
|
|
3625
|
+
param = Parameter("c", shape=(4, n_seg), value=np.ones((4, n_seg)))
|
|
3626
|
+
|
|
3627
|
+
state = State("s", shape=(1,))
|
|
3628
|
+
interp = Cinterp(state[0], xp, coeffs=param)
|
|
3629
|
+
|
|
3630
|
+
children = interp.children()
|
|
3631
|
+
assert len(children) == 2
|
|
3632
|
+
assert param in children
|
|
3633
|
+
|
|
3634
|
+
canonical = interp.canonicalize()
|
|
3635
|
+
assert isinstance(canonical, Cinterp)
|
|
3636
|
+
assert isinstance(canonical.coeffs, Parameter)
|
|
3637
|
+
assert canonical.coeffs.name == "c"
|
|
3638
|
+
assert canonical.fp_np is None
|
|
3639
|
+
assert canonical.method is None
|
|
3640
|
+
|
|
3641
|
+
|
|
3642
|
+
# --- Cinterp: Coefficient-Override Validation ---
|
|
3643
|
+
|
|
3644
|
+
|
|
3645
|
+
def test_cinterp_coeffs_wrong_shape():
|
|
3646
|
+
"""A coeffs table that is not (4, len(xp) - 1) raises, stating the expected shape."""
|
|
3647
|
+
from openscvx.symbolic.expr import Cinterp, State
|
|
3648
|
+
|
|
3649
|
+
xp = np.array([0.0, 1.0, 2.0, 3.0]) # n_seg = 3, expected (4, 3)
|
|
3650
|
+
x = State("s", shape=(1,))[0]
|
|
3651
|
+
|
|
3652
|
+
with pytest.raises(ValueError, match=r"Cinterp coeffs must have shape \(4, 3\)"):
|
|
3653
|
+
Cinterp(x, xp, coeffs=np.ones((4, 5)))
|
|
3654
|
+
|
|
3655
|
+
|
|
3656
|
+
def test_cinterp_symbolic_coeffs_wrong_shape():
|
|
3657
|
+
"""A Parameter of the wrong shape raises, stating the expected shape."""
|
|
3658
|
+
from openscvx.symbolic.expr import Cinterp, Parameter, State
|
|
3659
|
+
|
|
3660
|
+
xp = np.array([0.0, 1.0, 2.0, 3.0]) # expected (4, 3)
|
|
3661
|
+
x = State("s", shape=(1,))[0]
|
|
3662
|
+
param = Parameter("c", shape=(3, 3), value=np.ones((3, 3)))
|
|
3663
|
+
|
|
3664
|
+
with pytest.raises(ValueError, match=r"Cinterp coeffs must have shape \(4, 3\)"):
|
|
3665
|
+
Cinterp(x, xp, coeffs=param)
|
|
3666
|
+
|
|
3667
|
+
|
|
3668
|
+
def test_cinterp_both_fp_and_coeffs():
|
|
3669
|
+
"""Passing both fp and coeffs is ambiguous and raises."""
|
|
3670
|
+
from openscvx.symbolic.expr import Cinterp, State
|
|
3671
|
+
|
|
3672
|
+
xp = np.array([0.0, 1.0, 2.0, 3.0])
|
|
3673
|
+
fp = np.array([0.0, 1.0, 2.0, 3.0])
|
|
3674
|
+
x = State("s", shape=(1,))[0]
|
|
3675
|
+
|
|
3676
|
+
with pytest.raises(ValueError, match="exactly one of fp or coeffs"):
|
|
3677
|
+
Cinterp(x, xp, fp, coeffs=np.ones((4, 3)))
|
|
3678
|
+
|
|
3679
|
+
|
|
3680
|
+
def test_cinterp_neither_fp_nor_coeffs():
|
|
3681
|
+
"""Passing neither fp nor coeffs raises."""
|
|
3682
|
+
from openscvx.symbolic.expr import Cinterp, State
|
|
3683
|
+
|
|
3684
|
+
xp = np.array([0.0, 1.0, 2.0, 3.0])
|
|
3685
|
+
x = State("s", shape=(1,))[0]
|
|
3686
|
+
|
|
3687
|
+
with pytest.raises(ValueError, match="exactly one of fp or coeffs"):
|
|
3688
|
+
Cinterp(x, xp)
|
|
3689
|
+
|
|
3690
|
+
|
|
3691
|
+
def test_cinterp_method_with_coeffs_rejected():
|
|
3692
|
+
"""method is meaningless with a coeffs override and is rejected."""
|
|
3693
|
+
from openscvx.symbolic.expr import Cinterp, State
|
|
3694
|
+
|
|
3695
|
+
xp = np.array([0.0, 1.0, 2.0, 3.0])
|
|
3696
|
+
x = State("s", shape=(1,))[0]
|
|
3697
|
+
|
|
3698
|
+
with pytest.raises(ValueError, match="method is meaningless with a coeffs override"):
|
|
3699
|
+
Cinterp(x, xp, coeffs=np.ones((4, 3)), method="pchip")
|
|
3700
|
+
|
|
3701
|
+
|
|
3536
3702
|
# =============================================================================
|
|
3537
3703
|
# Bilerp (2D Bilinear Interpolation)
|
|
3538
3704
|
# =============================================================================
|
|
@@ -44,7 +44,7 @@ G = 9.81
|
|
|
44
44
|
def _configure_and_solve(problem):
|
|
45
45
|
"""Apply standard solver settings, solve, and post-process."""
|
|
46
46
|
problem.settings.prp.dt = 0.01
|
|
47
|
-
problem.solver.solver_args = {"abstol": 1e-6, "reltol": 1e-9}
|
|
47
|
+
problem.solver.solver_args = {"abstol": 1e-6, "reltol": 1e-9, "warm_start": False}
|
|
48
48
|
problem.settings.sim.save_compiled = False
|
|
49
49
|
problem.settings.dev.printing = False
|
|
50
50
|
|
|
@@ -354,7 +354,7 @@ def test_cross_nodal(feasible):
|
|
|
354
354
|
)
|
|
355
355
|
|
|
356
356
|
problem.settings.prp.dt = 0.01
|
|
357
|
-
problem.solver.solver_args = {"abstol": 1e-6, "reltol": 1e-9}
|
|
357
|
+
problem.solver.solver_args = {"abstol": 1e-6, "reltol": 1e-9, "warm_start": False}
|
|
358
358
|
problem.settings.sim.save_compiled = False
|
|
359
359
|
problem.settings.dev.printing = False
|
|
360
360
|
|