openscvx 0.5.3.dev35__tar.gz → 0.5.3.dev37__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.dev37/.github/workflows/_extra.yml +41 -0
- openscvx-0.5.3.dev37/.github/workflows/tests-cvxpygen.yml +18 -0
- openscvx-0.5.3.dev35/.github/workflows/tests-integration.yml → openscvx-0.5.3.dev37/.github/workflows/tests-examples.yml +12 -9
- openscvx-0.5.3.dev37/.github/workflows/tests-lie.yml +18 -0
- openscvx-0.5.3.dev37/.github/workflows/tests-mjx.yml +18 -0
- openscvx-0.5.3.dev37/.github/workflows/tests-qpax.yml +16 -0
- openscvx-0.5.3.dev37/.github/workflows/tests.yml +140 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/CONTRIBUTING.md +7 -6
- {openscvx-0.5.3.dev35/openscvx.egg-info → openscvx-0.5.3.dev37}/PKG-INFO +20 -7
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/README.md +18 -2
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/docs/UsersGuide/01_hello_world_brachistochrone.md +1 -1
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/_version.py +3 -3
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/symbolic/expr/expr.py +43 -0
- openscvx-0.5.3.dev37/openscvx/symbolic/lowerers/jax/_lowerer.py +122 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/symbolic/lowerers/jax/logic.py +16 -6
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/symbolic/lowerers/jax/vmap.py +14 -4
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37/openscvx.egg-info}/PKG-INFO +20 -7
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx.egg-info/SOURCES.txt +19 -15
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx.egg-info/requires.txt +1 -4
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx.egg-info/scm_file_list.json +19 -15
- openscvx-0.5.3.dev37/openscvx.egg-info/scm_version.json +8 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/pyproject.toml +9 -5
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/tests/algorithms/test_iteration_fn_jit.py +2 -2
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/tests/algorithms/test_iteration_fn_parity.py +10 -6
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/tests/algorithms/test_make_solve_loop.py +2 -2
- openscvx-0.5.3.dev37/tests/conftest.py +80 -0
- {openscvx-0.5.3.dev35/tests → openscvx-0.5.3.dev37/tests/e2e}/test_brachistochrone.py +14 -29
- {openscvx-0.5.3.dev35/tests → openscvx-0.5.3.dev37/tests/e2e}/test_impulsive.py +8 -7
- {openscvx-0.5.3.dev35/tests → openscvx-0.5.3.dev37/tests/e2e}/test_multishot_propagation.py +6 -6
- {openscvx-0.5.3.dev35/tests → openscvx-0.5.3.dev37/tests/e2e}/test_solve_batched_brachistochrone.py +11 -22
- {openscvx-0.5.3.dev35/tests → openscvx-0.5.3.dev37/tests/e2e}/test_solve_batched_export_roundtrip.py +2 -3
- {openscvx-0.5.3.dev35/tests → openscvx-0.5.3.dev37/tests/e2e}/test_solve_jax_bare_brachistochrone.py +2 -5
- {openscvx-0.5.3.dev35/tests → openscvx-0.5.3.dev37/tests/e2e}/test_solve_jax_jit_brachistochrone.py +1 -4
- {openscvx-0.5.3.dev35/tests → openscvx-0.5.3.dev37/tests/e2e}/test_solve_jax_vmap_brachistochrone.py +1 -4
- {openscvx-0.5.3.dev35/tests → openscvx-0.5.3.dev37/tests/e2e}/test_solve_jax_vmap_converged_no_drift.py +1 -4
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/tests/integrations/test_mjx.py +1 -16
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/tests/integrations/test_mjx_dynamics.py +18 -34
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/tests/solvers/test_cvxpy_callback_jit_spike.py +3 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/tests/solvers/test_iteration_callback_cvxpy.py +3 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/tests/solvers/test_iteration_callback_moreau.py +11 -14
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/tests/solvers/test_iteration_callback_qpax.py +2 -2
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/tests/solvers/test_iteration_callback_vmap.py +4 -5
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/tests/solvers/test_moreau_ptr_solver.py +2 -4
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/tests/solvers/test_qpax_ptr_solver.py +4 -5
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/tests/symbolic/expr/test_lie.py +23 -28
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/tests/symbolic/parser/test_lie.py +12 -20
- openscvx-0.5.3.dev37/tests/test_examples.py +189 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/tests/test_loader.py +5 -1
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/tests/test_results_parameters.py +3 -5
- openscvx-0.5.3.dev35/.github/workflows/tests-unit.yml +0 -55
- openscvx-0.5.3.dev35/openscvx/symbolic/lowerers/jax/_lowerer.py +0 -56
- openscvx-0.5.3.dev35/openscvx.egg-info/scm_version.json +0 -8
- openscvx-0.5.3.dev35/tests/_marks.py +0 -59
- openscvx-0.5.3.dev35/tests/conftest.py +0 -12
- openscvx-0.5.3.dev35/tests/test_examples.py +0 -223
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/.github/assets/logo.svg +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/.github/release-drafter.yml +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/.github/workflows/_docs.yml +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/.github/workflows/branch-name.yml +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/.github/workflows/docs.yml +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/.github/workflows/lint.yml +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/.github/workflows/nightly.yml +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/.github/workflows/release-drafter.yml +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/.github/workflows/release.yml +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/.gitignore +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/.gitmodules +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/LICENSE +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/docs/Foundations/constraint_reformulation.md +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/docs/Foundations/control_parameterization.md +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/docs/Foundations/discretization.md +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/docs/Foundations/ocp.md +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/docs/Foundations/scvx.md +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/docs/Foundations/time_dilation.md +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/docs/UnderTheHood/batching_jit_grad.md +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/docs/UnderTheHood/custom_algorithms_autotuners.md +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/docs/UnderTheHood/lowering_architecture.md +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/docs/UnderTheHood/vectorization_and_vmapping.md +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/docs/UsersGuide/00_introduction.md +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/docs/UsersGuide/02_drone_racing_constraints.md +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/docs/UsersGuide/03_obstacle_avoidance_vmap.md +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/docs/UsersGuide/04_viewpoint_constraints.md +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/docs/UsersGuide/05_visualization.md +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/docs/UsersGuide/06_logic.md +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/docs/UsersGuide/07_lie.md +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/docs/UsersGuide/08_mpcc.md +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/docs/UsersGuide/09_mjx_dynamics.md +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/docs/assets/favicon.png +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/docs/assets/images/ct-scvx_dark.png +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/docs/assets/images/ct-scvx_light.png +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/docs/assets/images/ctcs_dark.png +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/docs/assets/images/ctcs_light.png +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/docs/assets/images/problem_class_dark.png +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/docs/assets/images/problem_class_light.png +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/docs/assets/logo.svg +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/docs/assets/openscvx_logo_square.png +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/docs/assets/viser-client/index.html +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/docs/assets/viser-recordings/drone_racing.viser +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/docs/assets/viser-recordings/franka_fr3v2_pick_place.viser +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/docs/citation.md +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/docs/examples.md +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/docs/index.md +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/docs/javascripts/mathjax.js +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/docs/versions.json +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/_viser_embed_export.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/abstract/brachistochrone.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/abstract/brachistochrone_batched.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/abstract/flappy_bird.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/abstract/hypersensitive.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/abstract/impulsive.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/abstract/stl_integer_variable.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/abstract/stl_or.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/aircraft/dynamic_soaring.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/aircraft/supersonic_time_to_climb.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/animations/7_dof_arm.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/animations/_camera.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/animations/_render.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/animations/_sensor_view.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/animations/dr_vp_polytope.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/animations/franka_fr3v2_pick_place.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/animations/logo.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/animations/obstacle_avoidance_vmap.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/arm/3_dof_arm.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/arm/7_dof_arm.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/arm/7_dof_arm_collision.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/arm/7_dof_arm_vp.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/arm/franka_fr3v2_pick_place.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/arm/franka_fr3v2_viewplanning.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/arm/franka_fr3v2_viewplanning_nodal.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/car/dubins_car.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/car/dubins_car_disjoint.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/car/dubins_car_obstacle_conditional.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/car/dubins_car_obstacle_stl.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/car/dubins_car_stl_or.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/car/dubins_car_waypoint_stl.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/double_integrator/_plotting.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/double_integrator/moving_safe_zones.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/drone/2d_obstacle_avoidance_batched_ic.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/drone/cinema_vp.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/drone/cinema_vp_nodal.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/drone/dr_double_integrator.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/drone/dr_vp.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/drone/dr_vp_nodal.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/drone/dr_vp_polytope.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/drone/drone_racing.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/drone/drone_racing_batched_gates.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/drone/logo.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/drone/logo_utils/acl_logo.svg +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/drone/logo_utils/openscvx_logo_single.svg +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/drone/logo_utils/quadrotor_mesh.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/drone/logo_utils/svg_path_utils.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/drone/multi_agent_circle_swap.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/drone/obstacle_avoidance.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/drone/obstacle_avoidance_nodal.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/drone/obstacle_avoidance_vmap.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/drone/obstacle_avoidance_vmap_2d.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/drone/openscvx_logo.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/frax/panda_frax.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/frax/panda_frax_pick_place.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/frax/panda_frax_viewplanning.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/frax/panda_frax_waypoint.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/mjx/cartpole_mjx.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/mjx/double_cartpole_mjx.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/mjx/skydio_x2_mjx.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/mjx/triple_cartpole_3d_mjx.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/mjx/triple_cartpole_game.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/mjx/triple_cartpole_mjx.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/mpc/double_integrator_discrete.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/mpc/double_integrator_drone_racing.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/mpc/dubins_car_circle_analytical.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/mpc/dubins_car_circle_discrete.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/mpc/realtime_double_integrator_drone_racing.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/plotting.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/plotting_viser.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/realtime/3DoF_pdg_realtime.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/realtime/6DoF_pdg_realtime.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/realtime/base_problems/3DoF_pdg_realtime_base.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/realtime/base_problems/6DoF_pdg_realtime_base.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/realtime/base_problems/cinema_vp_realtime_base.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/realtime/base_problems/drone_racing_realtime_base.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/realtime/base_problems/dubins_car_realtime_base.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/realtime/base_problems/obstacle_avoidance_realtime_base.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/realtime/cinema_vp_realtime.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/realtime/drone_racing_realtime.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/realtime/dubins_car_realtime.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/realtime/obstacle_avoidance_realtime.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/rocket/3DoF_pdg.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/rocket/6DoF_pdg.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/rocket/6DoF_pdg_batched_ic.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/rocket/ascent_launch_vehicle.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/spacecraft/halo_orbit.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/spacecraft/hohmann_transfer.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/spacecraft/let_transfer.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/spacecraft/proxops_cw.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/examples/spacecraft/relative_loitering.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/figures/ctlos_cine.gif +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/figures/ctlos_dr.gif +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/figures/dtlos_cine.gif +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/figures/dtlos_dr.gif +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/figures/openscvx_logo.svg +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/figures/openscvx_logo_square.png +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/figures/oscvx_structure_full_dark.svg +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/figures/video_preview.png +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/material/__init__.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/material/overrides/assets/stylesheets/custom.css +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/material/overrides/assets/stylesheets/home-dropin.css +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/material/overrides/assets/stylesheets/home-hero.css +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/material/overrides/assets/stylesheets/home-viser.css +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/material/overrides/home.html +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/material/overrides/main.html +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/material/overrides/partials/home-diagram.html +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/material/overrides/partials/home-dropin-banner.html +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/material/overrides/partials/home-hero.html +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/material/overrides/partials/home-pipeline.html +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/material/overrides/partials/home-viser-strip.html +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/mkdocs.yml +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/__init__.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/__main__.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/algorithms/__init__.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/algorithms/autotuner/__init__.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/algorithms/autotuner/acceptance_ratio.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/algorithms/autotuner/adaptive_proximal_weight.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/algorithms/autotuner/augmented_lagrangian.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/algorithms/autotuner/base.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/algorithms/autotuner/constant_proximal_weight.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/algorithms/autotuner/ramp_proximal_weight.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/algorithms/base.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/algorithms/history.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/algorithms/hyperparams.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/algorithms/loop.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/algorithms/optimization_results.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/algorithms/penalty.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/algorithms/scvx/__init__.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/algorithms/scvx/iteration.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/algorithms/scvx/penalized_trust_region.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/algorithms/state.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/algorithms/weights.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/config.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/discretization/__init__.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/discretization/base.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/discretization/discretize_linearize.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/discretization/linearize_discretize.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/discretization/linearize_discretize_sparse.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/discretization/sparse_utils/__init__.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/discretization/sparse_utils/bcoo_helpers.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/discretization/sparse_utils/sparse_jacobian.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/expert/__init__.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/expert/byof.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/expert/lowering.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/expert/validation.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/init/__init__.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/init/interpolation.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/init/inverse_kinematics.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/integrations/__init__.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/integrations/_utils.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/integrations/base.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/integrations/frax.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/integrations/menagerie.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/integrations/mjx.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/integrators/__init__.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/integrators/diffrax.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/integrators/runge_kutta.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/loader.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/lowered/__init__.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/lowered/cvxpy_constraints.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/lowered/cvxpy_variables.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/lowered/dynamics.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/lowered/jax_constraints.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/lowered/parameters.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/lowered/problem.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/lowered/unified.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/plotting/__init__.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/plotting/plotting.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/plotting/publication.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/plotting/scp_iteration.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/plotting/viser/__init__.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/plotting/viser/animated.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/plotting/viser/coordinates.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/plotting/viser/orbits.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/plotting/viser/plotly_integration.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/plotting/viser/primitives.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/plotting/viser/scp.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/plotting/viser/server.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/problem.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/propagation/__init__.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/propagation/post_processing.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/propagation/propagation.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/solvers/__init__.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/solvers/base.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/solvers/cones.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/solvers/cvxpy_ptr_solver.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/solvers/moreau_ptr_solver.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/solvers/ptr_solver.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/solvers/qpax_ptr_solver.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/symbolic/__init__.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/symbolic/affine.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/symbolic/augmentation.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/symbolic/builder.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/symbolic/canonicalize.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/symbolic/constraint_set.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/symbolic/expr/__init__.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/symbolic/expr/arithmetic.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/symbolic/expr/array.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/symbolic/expr/constraint.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/symbolic/expr/control.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/symbolic/expr/lie/__init__.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/symbolic/expr/lie/adjoint.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/symbolic/expr/lie/se3.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/symbolic/expr/lie/so3.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/symbolic/expr/linalg.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/symbolic/expr/logic.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/symbolic/expr/math.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/symbolic/expr/parameter.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/symbolic/expr/spatial.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/symbolic/expr/state.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/symbolic/expr/stl.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/symbolic/expr/stljax.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/symbolic/expr/time.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/symbolic/expr/variable.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/symbolic/expr/vmap.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/symbolic/hashing.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/symbolic/lower.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/symbolic/lowerers/__init__.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/symbolic/lowerers/cvxpy/__init__.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/symbolic/lowerers/cvxpy/_lowerer.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/symbolic/lowerers/cvxpy/_registry.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/symbolic/lowerers/cvxpy/arithmetic.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/symbolic/lowerers/cvxpy/array.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/symbolic/lowerers/cvxpy/constraint.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/symbolic/lowerers/cvxpy/control.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/symbolic/lowerers/cvxpy/expr.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/symbolic/lowerers/cvxpy/linalg.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/symbolic/lowerers/cvxpy/logic.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/symbolic/lowerers/cvxpy/math.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/symbolic/lowerers/cvxpy/state.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/symbolic/lowerers/jax/__init__.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/symbolic/lowerers/jax/_registry.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/symbolic/lowerers/jax/arithmetic.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/symbolic/lowerers/jax/array.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/symbolic/lowerers/jax/constraint.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/symbolic/lowerers/jax/control.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/symbolic/lowerers/jax/expr.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/symbolic/lowerers/jax/lie.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/symbolic/lowerers/jax/linalg.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/symbolic/lowerers/jax/math.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/symbolic/lowerers/jax/spatial.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/symbolic/lowerers/jax/state.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/symbolic/lowerers/jax/stl.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/symbolic/lowerers/jax/stljax.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/symbolic/parser/__init__.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/symbolic/parser/_registry.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/symbolic/parser/array.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/symbolic/parser/constraint.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/symbolic/parser/lie.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/symbolic/parser/linalg.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/symbolic/parser/logic.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/symbolic/parser/math.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/symbolic/parser/parser.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/symbolic/parser/spatial.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/symbolic/parser/stl.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/symbolic/parser/stljax.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/symbolic/parser/tokenizer.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/symbolic/preprocessing.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/symbolic/problem.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/symbolic/sparsity.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/symbolic/unified.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/utils/__init__.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/utils/cache.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/utils/caching.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/utils/printing.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/utils/profiling.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx/utils/utils.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx.egg-info/dependency_links.txt +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx.egg-info/entry_points.txt +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/openscvx.egg-info/top_level.txt +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/scripts/gen_example_pages.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/scripts/gen_ref_pages.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/scripts/mkdocs_copy_viser_client_hook.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/setup.cfg +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/tests/__init__.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/tests/algorithms/__init__.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/tests/algorithms/_iteration_helpers.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/tests/algorithms/autotuner/__init__.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/tests/algorithms/autotuner/test_defaults_agreement.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/tests/algorithms/autotuner/test_hyper_overrides.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/tests/algorithms/autotuner/test_update_weights_jit.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/tests/algorithms/test_algorithm_state_pytree.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/tests/brachistochrone_analytical.py +0 -0
- {openscvx-0.5.3.dev35/tests/expr → openscvx-0.5.3.dev37/tests/e2e}/__init__.py +0 -0
- {openscvx-0.5.3.dev35/tests → openscvx-0.5.3.dev37/tests/e2e}/test_solve_batched_cvxpy_export_errors.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/tests/fixtures/brachistochrone.json +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/tests/fixtures/brachistochrone.yaml +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/tests/hohmann_analytical.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/tests/integrations/__init__.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/tests/solvers/__init__.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/tests/solvers/_iteration_callback_helpers.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/tests/solvers/test_subproblem_pytree.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/tests/symbolic/__init__.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/tests/symbolic/expr/__init__.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/tests/symbolic/expr/test_arithmetic.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/tests/symbolic/expr/test_array.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/tests/symbolic/expr/test_constraint.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/tests/symbolic/expr/test_expr.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/tests/symbolic/expr/test_linalg.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/tests/symbolic/expr/test_logic.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/tests/symbolic/expr/test_math.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/tests/symbolic/expr/test_node_reference.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/tests/symbolic/expr/test_parameters.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/tests/symbolic/expr/test_scaling.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/tests/symbolic/expr/test_spatial.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/tests/symbolic/expr/test_stl.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/tests/symbolic/expr/test_variable.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/tests/symbolic/expr/test_vmap.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/tests/symbolic/parser/__init__.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/tests/symbolic/parser/test_array.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/tests/symbolic/parser/test_constraint.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/tests/symbolic/parser/test_linalg.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/tests/symbolic/parser/test_load.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/tests/symbolic/parser/test_logic.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/tests/symbolic/parser/test_math.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/tests/symbolic/parser/test_parser.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/tests/symbolic/parser/test_spatial.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/tests/symbolic/parser/test_stl.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/tests/symbolic/parser/test_tokenizer.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/tests/symbolic/parser/test_vmap.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/tests/symbolic/test_augmentation.py +0 -0
- {openscvx-0.5.3.dev35/tests/expr → openscvx-0.5.3.dev37/tests/symbolic}/test_gmsr.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/tests/symbolic/test_hashing.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/tests/symbolic/test_lower_cvxpy.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/tests/symbolic/test_lower_jax.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/tests/symbolic/test_preprocessing.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/tests/symbolic/test_sparsity.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/tests/symbolic/test_unified.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/tests/test_autotuning.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/tests/test_cvxpygen_optional.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/tests/test_discretization.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/tests/test_expert.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/tests/test_init.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/tests/test_integrators.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/tests/test_optimization_results.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/tests/test_plotting.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/tests/test_post_process_batched_tau_clamp.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/tests/test_propagation.py +0 -0
- {openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/tests/test_solve_batched_inference.py +0 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
name: 🔌 Third-Party Extra
|
|
2
|
+
|
|
3
|
+
# Reusable workflow behind the per-integration badge workflows (tests-mjx.yml,
|
|
4
|
+
# tests-lie.yml, ...). Installs one optional extra and runs exactly the tests
|
|
5
|
+
# carrying its marker — marker name == extra name, so one input drives both.
|
|
6
|
+
|
|
7
|
+
on:
|
|
8
|
+
workflow_call:
|
|
9
|
+
inputs:
|
|
10
|
+
extra:
|
|
11
|
+
description: 'pyproject optional extra to install; also the pytest marker to select'
|
|
12
|
+
required: true
|
|
13
|
+
type: string
|
|
14
|
+
|
|
15
|
+
jobs:
|
|
16
|
+
test:
|
|
17
|
+
name: ${{ inputs.extra }} (Python 3.13, ubuntu-latest)
|
|
18
|
+
runs-on: ubuntu-latest
|
|
19
|
+
timeout-minutes: 15
|
|
20
|
+
|
|
21
|
+
steps:
|
|
22
|
+
- name: Checkout repository
|
|
23
|
+
uses: actions/checkout@v4
|
|
24
|
+
|
|
25
|
+
- name: Set up Python
|
|
26
|
+
uses: actions/setup-python@v5
|
|
27
|
+
with:
|
|
28
|
+
python-version: '3.13'
|
|
29
|
+
|
|
30
|
+
- name: Install uv
|
|
31
|
+
uses: astral-sh/setup-uv@v7
|
|
32
|
+
with:
|
|
33
|
+
enable-cache: true
|
|
34
|
+
|
|
35
|
+
- name: Install dependencies
|
|
36
|
+
run: |
|
|
37
|
+
uv pip install --system -e ".[test,${{ inputs.extra }}]"
|
|
38
|
+
|
|
39
|
+
- name: Run ${{ inputs.extra }} tests
|
|
40
|
+
run: |
|
|
41
|
+
pytest -v -m "${{ inputs.extra }} and not examples" --durations=10 --tb=short -n auto
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
name: cvxpygen
|
|
2
|
+
|
|
3
|
+
# Badge workflow: health of the cvxpygen integration. Currently failing at
|
|
4
|
+
# install (#551: cvxpygen>=1.0.0 needs cvxpy>=1.9, conflicting with the <1.9
|
|
5
|
+
# pin) — cron + dispatch only while broken, so merges to main don't carry a
|
|
6
|
+
# guaranteed red check; add a push trigger alongside the extras-job install
|
|
7
|
+
# once the pins reconcile.
|
|
8
|
+
|
|
9
|
+
on:
|
|
10
|
+
schedule:
|
|
11
|
+
- cron: '0 6 * * 1' # Weekly on Monday, offset from the Sunday examples sweep
|
|
12
|
+
workflow_dispatch:
|
|
13
|
+
|
|
14
|
+
jobs:
|
|
15
|
+
cvxpygen:
|
|
16
|
+
uses: ./.github/workflows/_extra.yml
|
|
17
|
+
with:
|
|
18
|
+
extra: cvxpygen
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
name: 🧪
|
|
1
|
+
name: 🧪 Examples Sweep
|
|
2
2
|
|
|
3
3
|
on:
|
|
4
4
|
release:
|
|
@@ -8,10 +8,10 @@ on:
|
|
|
8
8
|
- cron: '0 0 * * 0' # Weekly on Sunday at midnight UTC
|
|
9
9
|
|
|
10
10
|
jobs:
|
|
11
|
-
|
|
12
|
-
name:
|
|
11
|
+
examples:
|
|
12
|
+
name: Examples Sweep
|
|
13
13
|
runs-on: ${{ matrix.os }}
|
|
14
|
-
timeout-minutes: 30 #
|
|
14
|
+
timeout-minutes: 30 # Solving every example is slow
|
|
15
15
|
|
|
16
16
|
strategy:
|
|
17
17
|
fail-fast: false # Continue testing other examples even if one fails
|
|
@@ -35,18 +35,21 @@ jobs:
|
|
|
35
35
|
|
|
36
36
|
- name: Install dependencies
|
|
37
37
|
run: |
|
|
38
|
-
# Install package with
|
|
39
|
-
|
|
38
|
+
# Install the package with every extra the examples exercise.
|
|
39
|
+
# cvxpygen omitted: its extra is unsatisfiable while cvxpy is pinned <1.9
|
|
40
|
+
# (cvxpygen>=1.0.0 needs cvxpy>=1.9, #551); its tests skip until that resolves.
|
|
41
|
+
# qpax omitted until its solves are stable on Linux runners (#550).
|
|
42
|
+
uv pip install --system -e ".[test,mjx,lie,frax,stl]"
|
|
40
43
|
|
|
41
|
-
- name: Run
|
|
44
|
+
- name: Run examples sweep
|
|
42
45
|
run: |
|
|
43
|
-
pytest -v -m
|
|
46
|
+
pytest -v -m examples --durations=10 -n auto
|
|
44
47
|
|
|
45
48
|
- name: Upload test results on failure
|
|
46
49
|
if: failure()
|
|
47
50
|
uses: actions/upload-artifact@v4
|
|
48
51
|
with:
|
|
49
|
-
name:
|
|
52
|
+
name: examples-test-results-py${{ matrix.python-version }}-${{ matrix.os }}
|
|
50
53
|
path: |
|
|
51
54
|
.pytest_cache/
|
|
52
55
|
test-results/
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
name: jaxlie
|
|
2
|
+
|
|
3
|
+
# Badge workflow: health of the jaxlie (Lie group) integration on main.
|
|
4
|
+
# The weekly cron catches breakage from upstream releases between commits.
|
|
5
|
+
|
|
6
|
+
on:
|
|
7
|
+
push:
|
|
8
|
+
branches:
|
|
9
|
+
- main
|
|
10
|
+
schedule:
|
|
11
|
+
- cron: '0 6 * * 1' # Weekly on Monday, offset from the Sunday examples sweep
|
|
12
|
+
workflow_dispatch:
|
|
13
|
+
|
|
14
|
+
jobs:
|
|
15
|
+
lie:
|
|
16
|
+
uses: ./.github/workflows/_extra.yml
|
|
17
|
+
with:
|
|
18
|
+
extra: lie
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
name: mjx
|
|
2
|
+
|
|
3
|
+
# Badge workflow: health of the MuJoCo MJX integration on main.
|
|
4
|
+
# The weekly cron catches breakage from upstream releases between commits.
|
|
5
|
+
|
|
6
|
+
on:
|
|
7
|
+
push:
|
|
8
|
+
branches:
|
|
9
|
+
- main
|
|
10
|
+
schedule:
|
|
11
|
+
- cron: '0 6 * * 1' # Weekly on Monday, offset from the Sunday examples sweep
|
|
12
|
+
workflow_dispatch:
|
|
13
|
+
|
|
14
|
+
jobs:
|
|
15
|
+
mjx:
|
|
16
|
+
uses: ./.github/workflows/_extra.yml
|
|
17
|
+
with:
|
|
18
|
+
extra: mjx
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
name: qpax
|
|
2
|
+
|
|
3
|
+
# Badge workflow: health of the qpax integration. Currently failing (#550) —
|
|
4
|
+
# cron + dispatch only while broken, so merges to main don't carry a guaranteed
|
|
5
|
+
# red check; add a push trigger alongside the extras-job install once fixed.
|
|
6
|
+
|
|
7
|
+
on:
|
|
8
|
+
schedule:
|
|
9
|
+
- cron: '0 6 * * 1' # Weekly on Monday, offset from the Sunday examples sweep
|
|
10
|
+
workflow_dispatch:
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
qpax:
|
|
14
|
+
uses: ./.github/workflows/_extra.yml
|
|
15
|
+
with:
|
|
16
|
+
extra: qpax
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
name: 🧪 Tests
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- main
|
|
7
|
+
pull_request:
|
|
8
|
+
branches:
|
|
9
|
+
- main
|
|
10
|
+
types: [opened, synchronize, reopened, ready_for_review]
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
unit:
|
|
14
|
+
if: ${{ !github.event.pull_request.draft }}
|
|
15
|
+
name: Unit Tests (Python ${{ matrix.python-version }}, ${{ matrix.os }})
|
|
16
|
+
runs-on: ${{ matrix.os }}
|
|
17
|
+
timeout-minutes: 15 # Unit tests should be fast
|
|
18
|
+
|
|
19
|
+
strategy:
|
|
20
|
+
fail-fast: false # Continue testing other versions even if one fails
|
|
21
|
+
matrix:
|
|
22
|
+
os: [ubuntu-latest, macos-latest]
|
|
23
|
+
python-version: ['3.11', '3.12', '3.13', '3.14']
|
|
24
|
+
|
|
25
|
+
steps:
|
|
26
|
+
- name: Checkout repository
|
|
27
|
+
uses: actions/checkout@v4
|
|
28
|
+
|
|
29
|
+
- name: Set up Python
|
|
30
|
+
uses: actions/setup-python@v5
|
|
31
|
+
with:
|
|
32
|
+
python-version: ${{ matrix.python-version }}
|
|
33
|
+
|
|
34
|
+
- name: Install uv
|
|
35
|
+
uses: astral-sh/setup-uv@v7
|
|
36
|
+
with:
|
|
37
|
+
enable-cache: true
|
|
38
|
+
|
|
39
|
+
- name: Install dependencies
|
|
40
|
+
run: |
|
|
41
|
+
uv pip install --system -e ".[test]"
|
|
42
|
+
|
|
43
|
+
- name: Run unit tests
|
|
44
|
+
run: |
|
|
45
|
+
pytest -v -m "not e2e and not examples and not extras" --durations=10 --tb=short -n auto
|
|
46
|
+
|
|
47
|
+
- name: Upload test results on failure
|
|
48
|
+
if: failure()
|
|
49
|
+
uses: actions/upload-artifact@v4
|
|
50
|
+
with:
|
|
51
|
+
name: unit-test-results-py${{ matrix.python-version }}-${{ matrix.os }}
|
|
52
|
+
path: |
|
|
53
|
+
.pytest_cache/
|
|
54
|
+
test-results/
|
|
55
|
+
retention-days: 7
|
|
56
|
+
|
|
57
|
+
e2e:
|
|
58
|
+
needs: unit
|
|
59
|
+
name: E2E Tests (Python ${{ matrix.python-version }}, ${{ matrix.os }})
|
|
60
|
+
runs-on: ${{ matrix.os }}
|
|
61
|
+
timeout-minutes: 15
|
|
62
|
+
|
|
63
|
+
strategy:
|
|
64
|
+
fail-fast: false # Continue testing other versions even if one fails
|
|
65
|
+
matrix:
|
|
66
|
+
os: [ubuntu-latest, macos-latest]
|
|
67
|
+
python-version: ['3.11', '3.12', '3.13', '3.14']
|
|
68
|
+
|
|
69
|
+
steps:
|
|
70
|
+
- name: Checkout repository
|
|
71
|
+
uses: actions/checkout@v4
|
|
72
|
+
|
|
73
|
+
- name: Set up Python
|
|
74
|
+
uses: actions/setup-python@v5
|
|
75
|
+
with:
|
|
76
|
+
python-version: ${{ matrix.python-version }}
|
|
77
|
+
|
|
78
|
+
- name: Install uv
|
|
79
|
+
uses: astral-sh/setup-uv@v7
|
|
80
|
+
with:
|
|
81
|
+
enable-cache: true
|
|
82
|
+
|
|
83
|
+
- name: Install dependencies
|
|
84
|
+
run: |
|
|
85
|
+
uv pip install --system -e ".[test]"
|
|
86
|
+
|
|
87
|
+
- name: Run e2e tests
|
|
88
|
+
run: |
|
|
89
|
+
pytest -v -m "e2e and not extras" --durations=10 --tb=short -n auto
|
|
90
|
+
|
|
91
|
+
- name: Upload test results on failure
|
|
92
|
+
if: failure()
|
|
93
|
+
uses: actions/upload-artifact@v4
|
|
94
|
+
with:
|
|
95
|
+
name: e2e-test-results-py${{ matrix.python-version }}-${{ matrix.os }}
|
|
96
|
+
path: |
|
|
97
|
+
.pytest_cache/
|
|
98
|
+
test-results/
|
|
99
|
+
retention-days: 7
|
|
100
|
+
|
|
101
|
+
extras:
|
|
102
|
+
needs: unit
|
|
103
|
+
name: Extras Tests (Python 3.13, ubuntu-latest)
|
|
104
|
+
runs-on: ubuntu-latest
|
|
105
|
+
timeout-minutes: 15
|
|
106
|
+
|
|
107
|
+
steps:
|
|
108
|
+
- name: Checkout repository
|
|
109
|
+
uses: actions/checkout@v4
|
|
110
|
+
|
|
111
|
+
- name: Set up Python
|
|
112
|
+
uses: actions/setup-python@v5
|
|
113
|
+
with:
|
|
114
|
+
python-version: '3.13'
|
|
115
|
+
|
|
116
|
+
- name: Install uv
|
|
117
|
+
uses: astral-sh/setup-uv@v7
|
|
118
|
+
with:
|
|
119
|
+
enable-cache: true
|
|
120
|
+
|
|
121
|
+
- name: Install dependencies
|
|
122
|
+
run: |
|
|
123
|
+
# cvxpygen omitted: its extra is unsatisfiable while cvxpy is pinned <1.9
|
|
124
|
+
# (cvxpygen>=1.0.0 needs cvxpy>=1.9, #551); its tests skip until that resolves.
|
|
125
|
+
# qpax omitted until its solves are stable on Linux runners (#550).
|
|
126
|
+
uv pip install --system -e ".[test,mjx,lie]"
|
|
127
|
+
|
|
128
|
+
- name: Run extras tests
|
|
129
|
+
run: |
|
|
130
|
+
pytest -v -m "extras and not examples" --durations=10 --tb=short -n auto
|
|
131
|
+
|
|
132
|
+
- name: Upload test results on failure
|
|
133
|
+
if: failure()
|
|
134
|
+
uses: actions/upload-artifact@v4
|
|
135
|
+
with:
|
|
136
|
+
name: extras-test-results
|
|
137
|
+
path: |
|
|
138
|
+
.pytest_cache/
|
|
139
|
+
test-results/
|
|
140
|
+
retention-days: 7
|
|
@@ -149,18 +149,19 @@ See the `[tool.ruff]` section in `pyproject.toml` for our configuration.
|
|
|
149
149
|
|
|
150
150
|
OpenSCvx uses `pytest` for automated testing. Tests run automatically via GitHub Actions:
|
|
151
151
|
|
|
152
|
-
- **[tests
|
|
153
|
-
- **[tests-
|
|
152
|
+
- **[tests.yml](.github/workflows/tests.yml)**: Runs on every PR - a fast `unit` job, then gated `e2e` (full SCP solves) and `extras` (optional-dependency tests) jobs
|
|
153
|
+
- **[tests-examples.yml](.github/workflows/tests-examples.yml)**: Runs weekly - solves every example problem as a smoke test
|
|
154
154
|
|
|
155
155
|
##### Running Tests Locally
|
|
156
156
|
|
|
157
157
|
For faster feedback during development, run tests locally:
|
|
158
158
|
|
|
159
159
|
```bash
|
|
160
|
-
pytest
|
|
161
|
-
pytest
|
|
162
|
-
pytest -
|
|
163
|
-
pytest -
|
|
160
|
+
pytest -m "not e2e and not examples and not extras" # Fast unit tests
|
|
161
|
+
pytest -m "e2e and not extras" # Full SCP-solve tests
|
|
162
|
+
pytest -m extras # Optional-dependency tests
|
|
163
|
+
pytest -m examples # Solve every example (slow)
|
|
164
|
+
pytest tests/e2e/test_brachistochrone.py -v # Just the brachistochrone benchmark
|
|
164
165
|
```
|
|
165
166
|
|
|
166
167
|
##### Brachistochrone Problem
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: openscvx
|
|
3
|
-
Version: 0.5.3.
|
|
3
|
+
Version: 0.5.3.dev37
|
|
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
|
|
@@ -41,11 +41,8 @@ Provides-Extra: frax
|
|
|
41
41
|
Requires-Dist: frax>=0.0.4; extra == "frax"
|
|
42
42
|
Provides-Extra: test
|
|
43
43
|
Requires-Dist: pytest; extra == "test"
|
|
44
|
-
Requires-Dist: scipy; extra == "test"
|
|
45
|
-
Requires-Dist: jaxlie; extra == "test"
|
|
46
|
-
Requires-Dist: svgpathtools; extra == "test"
|
|
47
44
|
Requires-Dist: pytest-xdist; extra == "test"
|
|
48
|
-
Requires-Dist:
|
|
45
|
+
Requires-Dist: scipy; extra == "test"
|
|
49
46
|
Dynamic: license-file
|
|
50
47
|
|
|
51
48
|
<a id="readme-top"></a>
|
|
@@ -53,8 +50,8 @@ Dynamic: license-file
|
|
|
53
50
|
<img src="figures/openscvx_logo.svg" width="1200"/>
|
|
54
51
|
<p align="center">
|
|
55
52
|
<a href="https://github.com/OpenSCvx/OpenSCvx/actions/workflows/lint.yml"><img src="https://github.com/OpenSCvx/OpenSCvx/actions/workflows/lint.yml/badge.svg"/></a>
|
|
56
|
-
<a href="https://github.com/OpenSCvx/OpenSCvx/actions/workflows/tests
|
|
57
|
-
<a href="https://github.com/OpenSCvx/OpenSCvx/actions/workflows/tests-
|
|
53
|
+
<a href="https://github.com/OpenSCvx/OpenSCvx/actions/workflows/tests.yml"><img src="https://github.com/OpenSCvx/OpenSCvx/actions/workflows/tests.yml/badge.svg"/></a>
|
|
54
|
+
<a href="https://github.com/OpenSCvx/OpenSCvx/actions/workflows/tests-examples.yml"><img src="https://github.com/OpenSCvx/OpenSCvx/actions/workflows/tests-examples.yml/badge.svg"/></a>
|
|
58
55
|
<a href="https://github.com/OpenSCvx/OpenSCvx/actions/workflows/nightly.yml"><img src="https://github.com/OpenSCvx/OpenSCvx/actions/workflows/nightly.yml/badge.svg"/></a>
|
|
59
56
|
<a href="https://github.com/OpenSCvx/OpenSCvx/actions/workflows/release.yml"><img src="https://github.com/OpenSCvx/OpenSCvx/actions/workflows/release.yml/badge.svg?event=release"/></a>
|
|
60
57
|
</p>
|
|
@@ -253,6 +250,22 @@ This repo has the following features:
|
|
|
253
250
|
|
|
254
251
|
<p align="right">(<a href="#readme-top">back to top</a>)</p>
|
|
255
252
|
|
|
253
|
+
## Third-Party Integrations
|
|
254
|
+
|
|
255
|
+
OpenSCvx integrates with several optional third-party packages. Each installs as a pip extra (`pip install openscvx[<extra>]`); without it, the library and its tests degrade gracefully — the corresponding tests simply skip. Integrations with a badge are tested against `main` on every push and re-checked weekly against the latest upstream releases.
|
|
256
|
+
|
|
257
|
+
| Integration | Extra | Provides | Status |
|
|
258
|
+
| --- | --- | --- | --- |
|
|
259
|
+
| [MuJoCo MJX](https://mujoco.readthedocs.io/en/stable/mjx.html) | `mjx` | MJX dynamics adapter (`openscvx.integrations`) | [](https://github.com/OpenSCvx/OpenSCvx/actions/workflows/tests-mjx.yml) |
|
|
260
|
+
| [jaxlie](https://github.com/brentyi/jaxlie) | `lie` | SO(3)/SE(3) Lie-group operations and IK initialization | [](https://github.com/OpenSCvx/OpenSCvx/actions/workflows/tests-lie.yml) |
|
|
261
|
+
| [qpax](https://github.com/qpax-solver/qpax) | `qpax` | JAX-native QP solver backend | [](https://github.com/OpenSCvx/OpenSCvx/issues/550) |
|
|
262
|
+
| [CVXPYGen](https://github.com/cvxgrp/cvxpygen) | `cvxpygen` | Generated C solver code for the convex subproblem | [](https://github.com/OpenSCvx/OpenSCvx/issues/551) |
|
|
263
|
+
| [moreau](https://pypi.org/project/moreau/) | `moreau` | Licensed QP solver backend |  |
|
|
264
|
+
| [stljax](https://github.com/UW-CTRL/stljax) | `stl` | Signal Temporal Logic robustness bridge |  |
|
|
265
|
+
| [frax](https://github.com/danielpmorton/frax) | `frax` | Robot dynamics for the manipulator examples | [](https://github.com/OpenSCvx/OpenSCvx/actions/workflows/tests-examples.yml) |
|
|
266
|
+
|
|
267
|
+
<p align="right">(<a href="#readme-top">back to top</a>)</p>
|
|
268
|
+
|
|
256
269
|
## Acknowledgements
|
|
257
270
|
|
|
258
271
|
This work was supported by a NASA Space Technology Graduate Research Opportunity and the Office of Naval Research under grant N00014-17-1-2433. The authors would like to acknowledge Natalia Pavlasek, Fabio Spada, Samuel Buckner, Abhi Kamath, Govind Chari, and Purnanand Elango as well as the other Autonomous Controls Laboratory members, for their many helpful discussions and support throughout this work.
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
<img src="figures/openscvx_logo.svg" width="1200"/>
|
|
4
4
|
<p align="center">
|
|
5
5
|
<a href="https://github.com/OpenSCvx/OpenSCvx/actions/workflows/lint.yml"><img src="https://github.com/OpenSCvx/OpenSCvx/actions/workflows/lint.yml/badge.svg"/></a>
|
|
6
|
-
<a href="https://github.com/OpenSCvx/OpenSCvx/actions/workflows/tests
|
|
7
|
-
<a href="https://github.com/OpenSCvx/OpenSCvx/actions/workflows/tests-
|
|
6
|
+
<a href="https://github.com/OpenSCvx/OpenSCvx/actions/workflows/tests.yml"><img src="https://github.com/OpenSCvx/OpenSCvx/actions/workflows/tests.yml/badge.svg"/></a>
|
|
7
|
+
<a href="https://github.com/OpenSCvx/OpenSCvx/actions/workflows/tests-examples.yml"><img src="https://github.com/OpenSCvx/OpenSCvx/actions/workflows/tests-examples.yml/badge.svg"/></a>
|
|
8
8
|
<a href="https://github.com/OpenSCvx/OpenSCvx/actions/workflows/nightly.yml"><img src="https://github.com/OpenSCvx/OpenSCvx/actions/workflows/nightly.yml/badge.svg"/></a>
|
|
9
9
|
<a href="https://github.com/OpenSCvx/OpenSCvx/actions/workflows/release.yml"><img src="https://github.com/OpenSCvx/OpenSCvx/actions/workflows/release.yml/badge.svg?event=release"/></a>
|
|
10
10
|
</p>
|
|
@@ -203,6 +203,22 @@ This repo has the following features:
|
|
|
203
203
|
|
|
204
204
|
<p align="right">(<a href="#readme-top">back to top</a>)</p>
|
|
205
205
|
|
|
206
|
+
## Third-Party Integrations
|
|
207
|
+
|
|
208
|
+
OpenSCvx integrates with several optional third-party packages. Each installs as a pip extra (`pip install openscvx[<extra>]`); without it, the library and its tests degrade gracefully — the corresponding tests simply skip. Integrations with a badge are tested against `main` on every push and re-checked weekly against the latest upstream releases.
|
|
209
|
+
|
|
210
|
+
| Integration | Extra | Provides | Status |
|
|
211
|
+
| --- | --- | --- | --- |
|
|
212
|
+
| [MuJoCo MJX](https://mujoco.readthedocs.io/en/stable/mjx.html) | `mjx` | MJX dynamics adapter (`openscvx.integrations`) | [](https://github.com/OpenSCvx/OpenSCvx/actions/workflows/tests-mjx.yml) |
|
|
213
|
+
| [jaxlie](https://github.com/brentyi/jaxlie) | `lie` | SO(3)/SE(3) Lie-group operations and IK initialization | [](https://github.com/OpenSCvx/OpenSCvx/actions/workflows/tests-lie.yml) |
|
|
214
|
+
| [qpax](https://github.com/qpax-solver/qpax) | `qpax` | JAX-native QP solver backend | [](https://github.com/OpenSCvx/OpenSCvx/issues/550) |
|
|
215
|
+
| [CVXPYGen](https://github.com/cvxgrp/cvxpygen) | `cvxpygen` | Generated C solver code for the convex subproblem | [](https://github.com/OpenSCvx/OpenSCvx/issues/551) |
|
|
216
|
+
| [moreau](https://pypi.org/project/moreau/) | `moreau` | Licensed QP solver backend |  |
|
|
217
|
+
| [stljax](https://github.com/UW-CTRL/stljax) | `stl` | Signal Temporal Logic robustness bridge |  |
|
|
218
|
+
| [frax](https://github.com/danielpmorton/frax) | `frax` | Robot dynamics for the manipulator examples | [](https://github.com/OpenSCvx/OpenSCvx/actions/workflows/tests-examples.yml) |
|
|
219
|
+
|
|
220
|
+
<p align="right">(<a href="#readme-top">back to top</a>)</p>
|
|
221
|
+
|
|
206
222
|
## Acknowledgements
|
|
207
223
|
|
|
208
224
|
This work was supported by a NASA Space Technology Graduate Research Opportunity and the Office of Naval Research under grant N00014-17-1-2433. The authors would like to acknowledge Natalia Pavlasek, Fabio Spada, Samuel Buckner, Abhi Kamath, Govind Chari, and Purnanand Elango as well as the other Autonomous Controls Laboratory members, for their many helpful discussions and support throughout this work.
|
{openscvx-0.5.3.dev35 → openscvx-0.5.3.dev37}/docs/UsersGuide/01_hello_world_brachistochrone.md
RENAMED
|
@@ -58,7 +58,7 @@ $$
|
|
|
58
58
|
t_f^* = \sqrt{\frac{r}{g}} \phi_f
|
|
59
59
|
$$
|
|
60
60
|
|
|
61
|
-
Because of these advantageous properties the Brachistochrone problem is extensively leveraged as a [unit test](https://github.com/OpenSCvx/OpenSCvx/blob/main/tests/test_brachistochrone.py).
|
|
61
|
+
Because of these advantageous properties the Brachistochrone problem is extensively leveraged as a [unit test](https://github.com/OpenSCvx/OpenSCvx/blob/main/tests/e2e/test_brachistochrone.py).
|
|
62
62
|
We would highly recommend that anyone setting out to develop some kind of optimization software do the same.
|
|
63
63
|
It may not be necessary _nor_ sufficient, but a lot of things have to be working properly to solve Brachistochrone problem.
|
|
64
64
|
|
|
@@ -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.dev37'
|
|
22
|
+
__version_tuple__ = version_tuple = (0, 5, 3, 'dev37')
|
|
23
23
|
|
|
24
|
-
__commit_id__ = commit_id = '
|
|
24
|
+
__commit_id__ = commit_id = 'gdb86fef25'
|
|
@@ -63,8 +63,10 @@ Example:
|
|
|
63
63
|
canonical = expr.canonicalize() # Simplifies to: x + x
|
|
64
64
|
"""
|
|
65
65
|
|
|
66
|
+
import functools
|
|
66
67
|
import hashlib
|
|
67
68
|
import struct
|
|
69
|
+
import threading
|
|
68
70
|
from typing import TYPE_CHECKING, Callable, List, Tuple, Union
|
|
69
71
|
|
|
70
72
|
if TYPE_CHECKING:
|
|
@@ -72,6 +74,40 @@ if TYPE_CHECKING:
|
|
|
72
74
|
|
|
73
75
|
import numpy as np
|
|
74
76
|
|
|
77
|
+
# Per-thread memo for canonicalize(). The memo canonicalizes each node once and
|
|
78
|
+
# returns the same object to every parent, preserving sharing.
|
|
79
|
+
_canon_state = threading.local()
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def _memoized_canonicalize(fn: Callable) -> Callable:
|
|
83
|
+
"""Wrap a subclass ``canonicalize`` so shared subexpressions are reused.
|
|
84
|
+
|
|
85
|
+
Keyed by ``id(self)``; the node is held alive in the memo for the duration of
|
|
86
|
+
the pass so its id cannot be recycled, with an identity guard on lookup. The
|
|
87
|
+
top-level call owns the memo and clears it on exit, so each independent
|
|
88
|
+
canonicalize pass starts fresh.
|
|
89
|
+
"""
|
|
90
|
+
|
|
91
|
+
@functools.wraps(fn)
|
|
92
|
+
def wrapper(self):
|
|
93
|
+
memo = getattr(_canon_state, "memo", None)
|
|
94
|
+
owns = memo is None
|
|
95
|
+
if owns:
|
|
96
|
+
memo = {}
|
|
97
|
+
_canon_state.memo = memo
|
|
98
|
+
try:
|
|
99
|
+
entry = memo.get(id(self))
|
|
100
|
+
if entry is not None and entry[0] is self:
|
|
101
|
+
return entry[1]
|
|
102
|
+
result = fn(self)
|
|
103
|
+
memo[id(self)] = (self, result)
|
|
104
|
+
return result
|
|
105
|
+
finally:
|
|
106
|
+
if owns:
|
|
107
|
+
_canon_state.memo = None
|
|
108
|
+
|
|
109
|
+
return wrapper
|
|
110
|
+
|
|
75
111
|
|
|
76
112
|
class Expr:
|
|
77
113
|
"""Base class for symbolic expressions in optimization problems.
|
|
@@ -101,6 +137,13 @@ class Expr:
|
|
|
101
137
|
# Give Expr objects higher priority than numpy arrays in operations
|
|
102
138
|
__array_priority__ = 1000
|
|
103
139
|
|
|
140
|
+
def __init_subclass__(cls, **kwargs):
|
|
141
|
+
# Wrap each subclass's own canonicalize() with identity memoization so a
|
|
142
|
+
# shared DAG node is canonicalized once rather than re-expanded per parent.
|
|
143
|
+
super().__init_subclass__(**kwargs)
|
|
144
|
+
if "canonicalize" in cls.__dict__:
|
|
145
|
+
cls.canonicalize = _memoized_canonicalize(cls.__dict__["canonicalize"])
|
|
146
|
+
|
|
104
147
|
def __le__(self, other):
|
|
105
148
|
from .constraint import Inequality
|
|
106
149
|
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
"""JaxLowerer class definition.
|
|
2
|
+
|
|
3
|
+
The visitor methods that populate the registry live in sibling modules
|
|
4
|
+
(``arithmetic``, ``math``, ``linalg``, etc.) and are registered via
|
|
5
|
+
``@visitor`` at import time.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from typing import Callable
|
|
9
|
+
|
|
10
|
+
import jax
|
|
11
|
+
|
|
12
|
+
from openscvx.symbolic.expr import Expr
|
|
13
|
+
from openscvx.symbolic.lowerers.jax._registry import dispatch
|
|
14
|
+
|
|
15
|
+
_MISSING = object()
|
|
16
|
+
|
|
17
|
+
# Value-memoization is only valid within a single JAX trace. Visitors bracket
|
|
18
|
+
# their nested trace with :func:`pause_memo` / :func:`resume_memo` so the wrapped
|
|
19
|
+
# closures recompute instead of returning a cross-trace value.
|
|
20
|
+
_memo_paused = [0]
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def pause_memo() -> None:
|
|
24
|
+
"""Disable value-memoization for the duration of a nested sub-trace."""
|
|
25
|
+
_memo_paused[0] += 1
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def resume_memo() -> None:
|
|
29
|
+
"""Re-enable value-memoization after a nested sub-trace finishes tracing."""
|
|
30
|
+
_memo_paused[0] -= 1
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def _memoize_call(fn: Callable) -> Callable:
|
|
34
|
+
"""Cache a lowered closure's result so it emits its subgraph once per trace.
|
|
35
|
+
|
|
36
|
+
Within a trace every node receives the same argument objects, so caching on
|
|
37
|
+
argument identity (``is``) lets a shared subexpression emit its subgraph once
|
|
38
|
+
instead of once per consumer. The cache only applies while tracing (at least
|
|
39
|
+
one positional argument is a JAX tracer); eager calls, keyword-argument
|
|
40
|
+
calls, and paused sections (nested sub-traces, see module note) bypass it.
|
|
41
|
+
"""
|
|
42
|
+
last_args = None
|
|
43
|
+
last_val = _MISSING
|
|
44
|
+
|
|
45
|
+
def wrapped(*args, **kwargs):
|
|
46
|
+
nonlocal last_args, last_val
|
|
47
|
+
if kwargs or _memo_paused[0] or not any(isinstance(a, jax.core.Tracer) for a in args):
|
|
48
|
+
return fn(*args, **kwargs)
|
|
49
|
+
if (
|
|
50
|
+
last_val is not _MISSING
|
|
51
|
+
and last_args is not None
|
|
52
|
+
and len(last_args) == len(args)
|
|
53
|
+
and all(a is b for a, b in zip(last_args, args))
|
|
54
|
+
):
|
|
55
|
+
return last_val
|
|
56
|
+
last_val = fn(*args)
|
|
57
|
+
last_args = args
|
|
58
|
+
return last_val
|
|
59
|
+
|
|
60
|
+
return wrapped
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
class JaxLowerer:
|
|
64
|
+
"""JAX backend for lowering symbolic expressions to executable functions.
|
|
65
|
+
|
|
66
|
+
This class implements the visitor pattern for converting symbolic expression
|
|
67
|
+
AST nodes to JAX functions. Each expression type has a corresponding visitor
|
|
68
|
+
function decorated with @visitor that handles the lowering logic.
|
|
69
|
+
|
|
70
|
+
The lowering process is recursive: each visitor lowers its child expressions
|
|
71
|
+
first, then composes them into a JAX operation. All lowered functions have
|
|
72
|
+
a standardized signature (x, u, node, params) -> result.
|
|
73
|
+
|
|
74
|
+
Shared subexpressions are lowered once: :meth:`lower` caches the closure for
|
|
75
|
+
each AST node by object identity, and each closure is wrapped so it emits its
|
|
76
|
+
subgraph only once per trace (see :func:`_memoize_call`).
|
|
77
|
+
|
|
78
|
+
Example:
|
|
79
|
+
Set up the JaxLowerer and lower an expression to a JAX function::
|
|
80
|
+
|
|
81
|
+
lowerer = JaxLowerer()
|
|
82
|
+
expr = ox.Norm(x)**2 + 0.1 * ox.Norm(u)**2
|
|
83
|
+
f = lowerer.lower(expr)
|
|
84
|
+
result = f(x_val, u_val, node=0, params={})
|
|
85
|
+
|
|
86
|
+
Note:
|
|
87
|
+
A fresh lowerer is created per lowering pass; its node cache is keyed by
|
|
88
|
+
``id(expr)`` and is valid only while the expression tree is alive.
|
|
89
|
+
"""
|
|
90
|
+
|
|
91
|
+
def __init__(self) -> None:
|
|
92
|
+
# Maps id(expr) -> (expr, lowered closure) so each node is lowered once,
|
|
93
|
+
# no matter how many parents share it. Storing the expr itself keeps it
|
|
94
|
+
# alive: if it were garbage-collected, Python could reuse its id for a
|
|
95
|
+
# new node and the cache would return the wrong closure. The identity
|
|
96
|
+
# check on lookup guards against exactly that.
|
|
97
|
+
self._node_cache: dict[int, tuple[Expr, Callable]] = {}
|
|
98
|
+
|
|
99
|
+
def lower(self, expr: Expr) -> Callable:
|
|
100
|
+
"""Lower a symbolic expression to a JAX function.
|
|
101
|
+
|
|
102
|
+
Main entry point for lowering. Delegates to dispatch() which looks up
|
|
103
|
+
the appropriate visitor method based on the expression type. Results are
|
|
104
|
+
memoized by node identity so shared subexpressions are lowered once.
|
|
105
|
+
|
|
106
|
+
Args:
|
|
107
|
+
expr: Symbolic expression to lower (any Expr subclass)
|
|
108
|
+
|
|
109
|
+
Returns:
|
|
110
|
+
JAX function with signature (x, u, node, params) -> result
|
|
111
|
+
|
|
112
|
+
Raises:
|
|
113
|
+
NotImplementedError: If no visitor exists for the expression type
|
|
114
|
+
ValueError: If the expression is malformed (e.g., State without slice)
|
|
115
|
+
"""
|
|
116
|
+
eid = id(expr)
|
|
117
|
+
cached = self._node_cache.get(eid)
|
|
118
|
+
if cached is not None and cached[0] is expr:
|
|
119
|
+
return cached[1]
|
|
120
|
+
fn = _memoize_call(dispatch(self, expr))
|
|
121
|
+
self._node_cache[eid] = (expr, fn)
|
|
122
|
+
return fn
|