openscvx 0.3.2.dev333__tar.gz → 0.3.2.dev342__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.3.2.dev333/openscvx.egg-info → openscvx-0.3.2.dev342}/PKG-INFO +1 -1
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/_version.py +3 -3
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/problem.py +1 -2
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/symbolic/builder.py +13 -7
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/symbolic/lowerers/jax/constraint.py +14 -35
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/symbolic/lowerers/jax/logic.py +4 -2
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/symbolic/preprocessing.py +136 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342/openscvx.egg-info}/PKG-INFO +1 -1
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/tests/symbolic/test_preprocessing.py +175 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/.github/assets/logo.svg +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/.github/release-drafter.yml +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/.github/workflows/_docs.yml +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/.github/workflows/branch-name.yml +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/.github/workflows/docs.yml +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/.github/workflows/lint.yml +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/.github/workflows/nightly.yml +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/.github/workflows/release-drafter.yml +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/.github/workflows/release.yml +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/.github/workflows/tests-integration.yml +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/.github/workflows/tests-unit.yml +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/.gitignore +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/CONTRIBUTING.md +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/LICENSE +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/README.md +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/docs/Foundations/constraint_reformulation.md +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/docs/Foundations/control_parameterization.md +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/docs/Foundations/discretization.md +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/docs/Foundations/ocp.md +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/docs/Foundations/scvx.md +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/docs/Foundations/time_dilation.md +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/docs/UnderTheHood/lowering_architecture.md +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/docs/UnderTheHood/vectorization_and_vmapping.md +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/docs/UsersGuide/00_introduction.md +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/docs/UsersGuide/01_hello_world_brachistochrone.md +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/docs/UsersGuide/02_drone_racing_constraints.md +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/docs/UsersGuide/03_obstacle_avoidance_vmap.md +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/docs/UsersGuide/04_viewpoint_constraints.md +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/docs/UsersGuide/05_visualization.md +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/docs/UsersGuide/06_logic.md +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/docs/UsersGuide/07_lie.md +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/docs/assets/favicon.png +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/docs/assets/images/ct-scvx_dark.png +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/docs/assets/images/ct-scvx_light.png +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/docs/assets/images/ctcs_dark.png +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/docs/assets/images/ctcs_light.png +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/docs/assets/images/problem_class_dark.png +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/docs/assets/images/problem_class_light.png +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/docs/assets/logo.svg +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/docs/citation.md +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/docs/examples.md +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/docs/getting-started.md +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/docs/index.md +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/docs/javascripts/mathjax.js +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/examples/abstract/brachistochrone.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/examples/arm/three_link_arm.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/examples/car/dubins_car.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/examples/car/dubins_car_conditional.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/examples/car/dubins_car_disjoint.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/examples/car/dubins_car_stljax.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/examples/drone/cinema_vp.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/examples/drone/cinema_vp_realtime_base.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/examples/drone/dr_double_integrator.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/examples/drone/dr_vp.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/examples/drone/dr_vp_nodal.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/examples/drone/dr_vp_polytope.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/examples/drone/drone_racing.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/examples/drone/obstacle_avoidance.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/examples/drone/obstacle_avoidance_nodal.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/examples/drone/obstacle_avoidance_realtime_base.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/examples/drone/obstacle_avoidance_vmap.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/examples/plotting.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/examples/plotting_viser.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/examples/realtime/cinema_vp_realtime.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/examples/realtime/drone_racing_realtime.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/examples/realtime/dubins_car_realtime.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/examples/realtime/obstacle_avoidance_realtime.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/examples/rocket/3DoF_pdg.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/examples/spacecraft/proxops_cw.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/figures/ctlos_cine.gif +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/figures/ctlos_dr.gif +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/figures/dtlos_cine.gif +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/figures/dtlos_dr.gif +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/figures/openscvx_logo.svg +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/figures/openscvx_logo_square.png +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/figures/oscvx_structure_full_dark.svg +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/figures/video_preview.png +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/material/__init__.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/material/overrides/assets/images/layers/1-background.avif +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/material/overrides/assets/images/layers/1-background@1x.avif +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/material/overrides/assets/images/layers/1-background@2x.avif +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/material/overrides/assets/images/layers/1-background@3x.avif +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/material/overrides/assets/images/layers/1-background@4x.avif +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/material/overrides/assets/images/layers/2-mars.avif +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/material/overrides/assets/images/layers/2-mars@1x.avif +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/material/overrides/assets/images/layers/2-mars@2x.avif +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/material/overrides/assets/images/layers/2-mars@3x.avif +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/material/overrides/assets/images/layers/2-mars@4x.avif +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/material/overrides/assets/images/layers/3-moon.avif +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/material/overrides/assets/images/layers/3-moon@1x.avif +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/material/overrides/assets/images/layers/3-moon@2x.avif +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/material/overrides/assets/images/layers/3-moon@3x.avif +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/material/overrides/assets/images/layers/3-moon@4x.avif +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/material/overrides/assets/images/layers/4-sat1.avif +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/material/overrides/assets/images/layers/4-sat1@1x.avif +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/material/overrides/assets/images/layers/4-sat1@2x.avif +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/material/overrides/assets/images/layers/4-sat1@3x.avif +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/material/overrides/assets/images/layers/4-sat1@4x.avif +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/material/overrides/assets/images/layers/5-space.avif +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/material/overrides/assets/images/layers/5-space@1x.avif +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/material/overrides/assets/images/layers/5-space@2x.avif +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/material/overrides/assets/images/layers/5-space@3x.avif +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/material/overrides/assets/images/layers/5-space@4x.avif +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/material/overrides/assets/images/layers/6-earth.avif +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/material/overrides/assets/images/layers/6-earth@1x.avif +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/material/overrides/assets/images/layers/6-earth@2x.avif +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/material/overrides/assets/images/layers/6-earth@3x.avif +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/material/overrides/assets/images/layers/6-earth@4x.avif +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/material/overrides/assets/javascripts/parallax.js +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/material/overrides/assets/logo.svg +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/material/overrides/assets/stylesheets/custom.css +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/material/overrides/assets/stylesheets/parallax.css +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/material/overrides/home.html +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/material/overrides/main.html +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/material/overrides/partials/parallax/hero.html +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/material/overrides/partials/parallax.html +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/mkdocs.yml +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/__init__.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/algorithms/__init__.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/algorithms/autotuning.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/algorithms/base.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/algorithms/optimization_results.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/algorithms/penalized_trust_region.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/config.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/discretization/__init__.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/discretization/discretization.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/expert/__init__.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/expert/byof.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/expert/lowering.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/expert/validation.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/init/__init__.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/init/interpolation.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/integrators/__init__.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/integrators/runge_kutta.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/lowered/__init__.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/lowered/cvxpy_constraints.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/lowered/cvxpy_variables.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/lowered/dynamics.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/lowered/jax_constraints.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/lowered/parameters.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/lowered/problem.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/lowered/unified.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/plotting/__init__.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/plotting/plotting.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/plotting/scp_iteration.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/plotting/viser/__init__.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/plotting/viser/animated.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/plotting/viser/plotly_integration.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/plotting/viser/primitives.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/plotting/viser/scp.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/plotting/viser/server.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/propagation/__init__.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/propagation/post_processing.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/propagation/propagation.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/solvers/__init__.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/solvers/base.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/solvers/ptr_solver.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/symbolic/__init__.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/symbolic/augmentation.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/symbolic/constraint_set.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/symbolic/expr/__init__.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/symbolic/expr/arithmetic.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/symbolic/expr/array.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/symbolic/expr/constraint.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/symbolic/expr/control.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/symbolic/expr/expr.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/symbolic/expr/lie/__init__.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/symbolic/expr/lie/adjoint.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/symbolic/expr/lie/se3.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/symbolic/expr/lie/so3.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/symbolic/expr/linalg.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/symbolic/expr/logic.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/symbolic/expr/math.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/symbolic/expr/spatial.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/symbolic/expr/state.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/symbolic/expr/stl.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/symbolic/expr/variable.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/symbolic/expr/vmap.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/symbolic/hashing.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/symbolic/lower.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/symbolic/lowerers/__init__.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/symbolic/lowerers/cvxpy/__init__.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/symbolic/lowerers/cvxpy/_lowerer.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/symbolic/lowerers/cvxpy/_registry.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/symbolic/lowerers/cvxpy/arithmetic.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/symbolic/lowerers/cvxpy/array.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/symbolic/lowerers/cvxpy/constraint.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/symbolic/lowerers/cvxpy/control.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/symbolic/lowerers/cvxpy/expr.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/symbolic/lowerers/cvxpy/linalg.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/symbolic/lowerers/cvxpy/logic.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/symbolic/lowerers/cvxpy/math.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/symbolic/lowerers/cvxpy/state.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/symbolic/lowerers/jax/__init__.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/symbolic/lowerers/jax/_lowerer.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/symbolic/lowerers/jax/_registry.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/symbolic/lowerers/jax/arithmetic.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/symbolic/lowerers/jax/array.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/symbolic/lowerers/jax/control.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/symbolic/lowerers/jax/expr.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/symbolic/lowerers/jax/lie.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/symbolic/lowerers/jax/linalg.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/symbolic/lowerers/jax/math.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/symbolic/lowerers/jax/spatial.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/symbolic/lowerers/jax/state.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/symbolic/lowerers/jax/stl.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/symbolic/lowerers/jax/vmap.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/symbolic/problem.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/symbolic/time.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/symbolic/unified.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/utils/__init__.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/utils/cache.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/utils/caching.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/utils/printing.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/utils/profiling.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/utils/utils.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx.egg-info/SOURCES.txt +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx.egg-info/dependency_links.txt +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx.egg-info/requires.txt +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx.egg-info/top_level.txt +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/pyproject.toml +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/scripts/gen_example_pages.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/scripts/gen_ref_pages.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/setup.cfg +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/tests/__init__.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/tests/brachistochrone_analytical.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/tests/symbolic/__init__.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/tests/symbolic/expr/__init__.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/tests/symbolic/expr/test_arithmetic.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/tests/symbolic/expr/test_array.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/tests/symbolic/expr/test_constraint.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/tests/symbolic/expr/test_expr.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/tests/symbolic/expr/test_lie.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/tests/symbolic/expr/test_linalg.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/tests/symbolic/expr/test_logic.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/tests/symbolic/expr/test_math.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/tests/symbolic/expr/test_node_reference.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/tests/symbolic/expr/test_parameters.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/tests/symbolic/expr/test_scaling.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/tests/symbolic/expr/test_spatial.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/tests/symbolic/expr/test_variable.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/tests/symbolic/expr/test_vmap.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/tests/symbolic/test_augmentation.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/tests/symbolic/test_hashing.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/tests/symbolic/test_lower_cvxpy.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/tests/symbolic/test_lower_jax.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/tests/symbolic/test_unified.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/tests/test_brachistochrone.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/tests/test_cvxpygen_optional.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/tests/test_discretization.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/tests/test_examples.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/tests/test_expert.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/tests/test_init.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/tests/test_integrators.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/tests/test_plotting.py +0 -0
- {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/tests/test_propagation.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: openscvx
|
|
3
|
-
Version: 0.3.2.
|
|
3
|
+
Version: 0.3.2.dev342
|
|
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
|
|
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
|
|
|
28
28
|
commit_id: COMMIT_ID
|
|
29
29
|
__commit_id__: COMMIT_ID
|
|
30
30
|
|
|
31
|
-
__version__ = version = '0.3.2.
|
|
32
|
-
__version_tuple__ = version_tuple = (0, 3, 2, '
|
|
31
|
+
__version__ = version = '0.3.2.dev342'
|
|
32
|
+
__version_tuple__ = version_tuple = (0, 3, 2, 'dev342')
|
|
33
33
|
|
|
34
|
-
__commit_id__ = commit_id = '
|
|
34
|
+
__commit_id__ = commit_id = 'gd4121da9a'
|
|
@@ -50,7 +50,6 @@ from openscvx.lowered.jax_constraints import (
|
|
|
50
50
|
from openscvx.propagation import get_propagation_solver, propagate_trajectory_results
|
|
51
51
|
from openscvx.solvers import PTRSolver
|
|
52
52
|
from openscvx.symbolic.builder import preprocess_symbolic_problem
|
|
53
|
-
from openscvx.symbolic.constraint_set import ConstraintSet
|
|
54
53
|
from openscvx.symbolic.expr import CTCS, Constraint
|
|
55
54
|
from openscvx.symbolic.expr.control import Control
|
|
56
55
|
from openscvx.symbolic.expr.state import State
|
|
@@ -128,7 +127,7 @@ class Problem:
|
|
|
128
127
|
# Symbolic Preprocessing & Augmentation
|
|
129
128
|
self.symbolic: SymbolicProblem = preprocess_symbolic_problem(
|
|
130
129
|
dynamics=dynamics,
|
|
131
|
-
constraints=
|
|
130
|
+
constraints=constraints,
|
|
132
131
|
states=states,
|
|
133
132
|
controls=controls,
|
|
134
133
|
N=N,
|
|
@@ -55,6 +55,8 @@ from openscvx.symbolic.preprocessing import (
|
|
|
55
55
|
validate_dynamics_dict_dimensions,
|
|
56
56
|
validate_dynamics_dimension,
|
|
57
57
|
validate_guesses,
|
|
58
|
+
validate_input_types,
|
|
59
|
+
validate_propagation_input_types,
|
|
58
60
|
validate_shapes,
|
|
59
61
|
validate_variable_names,
|
|
60
62
|
)
|
|
@@ -64,7 +66,7 @@ from openscvx.symbolic.time import Time
|
|
|
64
66
|
|
|
65
67
|
def preprocess_symbolic_problem(
|
|
66
68
|
dynamics: dict,
|
|
67
|
-
constraints:
|
|
69
|
+
constraints: list,
|
|
68
70
|
states: List[State],
|
|
69
71
|
controls: List[Control],
|
|
70
72
|
N: int,
|
|
@@ -99,8 +101,8 @@ def preprocess_symbolic_problem(
|
|
|
99
101
|
Args:
|
|
100
102
|
dynamics: Dictionary mapping state names to dynamics expressions.
|
|
101
103
|
Example: {"x": v, "v": u}
|
|
102
|
-
constraints:
|
|
103
|
-
|
|
104
|
+
constraints: List of constraint objects (Constraint, NodalConstraint,
|
|
105
|
+
CrossNodeConstraint, or CTCS).
|
|
104
106
|
states: List of user-defined State objects (should NOT include time or CTCS states)
|
|
105
107
|
controls: List of user-defined Control objects (should NOT include time dilation)
|
|
106
108
|
N: Number of discretization nodes in the trajectory
|
|
@@ -140,16 +142,13 @@ def preprocess_symbolic_problem(
|
|
|
140
142
|
Basic usage with CTCS constraint::
|
|
141
143
|
|
|
142
144
|
import openscvx as ox
|
|
143
|
-
from openscvx.symbolic.constraint_set import ConstraintSet
|
|
144
145
|
|
|
145
146
|
x = ox.State("x", shape=(2,))
|
|
146
147
|
v = ox.State("v", shape=(2,))
|
|
147
148
|
u = ox.Control("u", shape=(2,))
|
|
148
149
|
|
|
149
150
|
dynamics = {"x": v, "v": u}
|
|
150
|
-
constraints =
|
|
151
|
-
(ox.Norm(x) <= 5.0).over((0, 50))
|
|
152
|
-
])
|
|
151
|
+
constraints = [(ox.Norm(x) <= 5.0).over((0, 50))]
|
|
153
152
|
|
|
154
153
|
problem = preprocess_symbolic_problem(
|
|
155
154
|
dynamics=dynamics,
|
|
@@ -187,6 +186,13 @@ def preprocess_symbolic_problem(
|
|
|
187
186
|
print([s.name for s in problem.states_prop])
|
|
188
187
|
"""
|
|
189
188
|
|
|
189
|
+
# Validate input types before anything else
|
|
190
|
+
validate_input_types(dynamics, states, controls, constraints, N, time)
|
|
191
|
+
validate_propagation_input_types(dynamics_prop_extra, states_prop_extra)
|
|
192
|
+
|
|
193
|
+
# Wrap validated constraints into a ConstraintSet
|
|
194
|
+
constraints = ConstraintSet(unsorted=list(constraints))
|
|
195
|
+
|
|
190
196
|
# Validate user-provided variables have required attributes
|
|
191
197
|
validate_boundary_conditions(states)
|
|
192
198
|
validate_bounds(states + controls)
|
{openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/openscvx/symbolic/lowerers/jax/constraint.py
RENAMED
|
@@ -3,9 +3,6 @@
|
|
|
3
3
|
Visitors: Equality, Inequality, NodalConstraint, CrossNodeConstraint, CTCS
|
|
4
4
|
"""
|
|
5
5
|
|
|
6
|
-
import jax.numpy as jnp
|
|
7
|
-
from jax.lax import cond
|
|
8
|
-
|
|
9
6
|
# Expression types to handle — uncomment as you paste visitors:
|
|
10
7
|
from openscvx.symbolic.expr.constraint import (
|
|
11
8
|
CTCS,
|
|
@@ -15,6 +12,7 @@ from openscvx.symbolic.expr.constraint import (
|
|
|
15
12
|
Inequality,
|
|
16
13
|
NodalConstraint,
|
|
17
14
|
)
|
|
15
|
+
from openscvx.symbolic.expr.logic import Cond
|
|
18
16
|
from openscvx.symbolic.lowerers.jax._registry import visitor # noqa: F401
|
|
19
17
|
|
|
20
18
|
|
|
@@ -106,17 +104,13 @@ def _visit_cross_node_constraint(lowerer, node: CrossNodeConstraint):
|
|
|
106
104
|
return trajectory_constraint
|
|
107
105
|
|
|
108
106
|
|
|
109
|
-
# TODO: (norrisg) CTCS is playing 2 roles here: both as a constraint wrapper and as the penalty
|
|
110
|
-
# expression w/ conditional logic. Consider adding conditional logic as separate AST nodes.
|
|
111
|
-
# Then, CTCS remains a wrapper and we just wrap the penalty expression with the conditional
|
|
112
|
-
# logic when we lower it.
|
|
113
107
|
@visitor(CTCS)
|
|
114
108
|
def _visit_ctcs(lowerer, node: CTCS):
|
|
115
109
|
"""Lower CTCS (Continuous-Time Constraint Satisfaction) to JAX function.
|
|
116
110
|
|
|
117
111
|
CTCS constraints use penalty methods to enforce constraints over continuous
|
|
118
|
-
time intervals.
|
|
119
|
-
|
|
112
|
+
time intervals. When a node range is specified, the penalty expression is
|
|
113
|
+
wrapped in a Cond node to activate it only within that interval.
|
|
120
114
|
|
|
121
115
|
Args:
|
|
122
116
|
node: CTCS constraint node with penalty expression and optional node range
|
|
@@ -125,35 +119,20 @@ def _visit_ctcs(lowerer, node: CTCS):
|
|
|
125
119
|
Function (x, u, current_node, params) -> penalty value or 0
|
|
126
120
|
|
|
127
121
|
Note:
|
|
128
|
-
|
|
129
|
-
is active only when current_node is in [start_node, end_node).
|
|
122
|
+
The penalty is active only when current_node is in [start_node, end_node).
|
|
130
123
|
If no node range is specified, the penalty is always active.
|
|
124
|
+
Conditional node-range logic is delegated to the Cond AST node.
|
|
131
125
|
|
|
132
126
|
See Also:
|
|
133
127
|
- CTCS: The symbolic CTCS constraint class
|
|
128
|
+
- Cond: Conditional AST node used for node-range gating
|
|
134
129
|
- penalty functions: PositivePart, Huber, SmoothReLU
|
|
135
130
|
"""
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
# Keep as JAX array for tracing compatibility
|
|
145
|
-
node_scalar = jnp.atleast_1d(current_node)[0]
|
|
146
|
-
is_active = (start_node <= node_scalar) & (node_scalar < end_node)
|
|
147
|
-
|
|
148
|
-
# Use jax.lax.cond for conditional evaluation
|
|
149
|
-
return cond(
|
|
150
|
-
is_active,
|
|
151
|
-
lambda _: penalty_expr_fn(x, u, current_node, params),
|
|
152
|
-
lambda _: 0.0,
|
|
153
|
-
operand=None,
|
|
154
|
-
)
|
|
155
|
-
else:
|
|
156
|
-
# Always active if no node range specified
|
|
157
|
-
return penalty_expr_fn(x, u, current_node, params)
|
|
158
|
-
|
|
159
|
-
return ctcs_fn
|
|
131
|
+
penalty_expr = node.penalty_expr()
|
|
132
|
+
|
|
133
|
+
if node.nodes is not None:
|
|
134
|
+
# Wrap penalty in a Cond node that gates on the node range
|
|
135
|
+
gated_expr = Cond(None, penalty_expr, 0.0, node_ranges=[node.nodes])
|
|
136
|
+
return lowerer.lower(gated_expr)
|
|
137
|
+
else:
|
|
138
|
+
return lowerer.lower(penalty_expr)
|
|
@@ -143,10 +143,12 @@ def _visit_cond(lowerer, node: Cond):
|
|
|
143
143
|
|
|
144
144
|
# If node_ranges is specified, check if current node is in range
|
|
145
145
|
if node_ranges is not None:
|
|
146
|
-
#
|
|
146
|
+
# Extract scalar from node_arg (which may be array or scalar from vmap)
|
|
147
|
+
node_scalar = jnp.atleast_1d(node_arg)[0]
|
|
148
|
+
# Check if node_scalar is within any of the specified ranges [start, end)
|
|
147
149
|
in_range = jnp.array(False)
|
|
148
150
|
for start, end in node_ranges:
|
|
149
|
-
in_range = in_range | ((
|
|
151
|
+
in_range = in_range | ((node_scalar >= start) & (node_scalar < end))
|
|
150
152
|
# Combined predicate: must be in range AND predicate satisfied
|
|
151
153
|
pred_bool = in_range & pred_bool
|
|
152
154
|
|
|
@@ -748,6 +748,142 @@ def validate_bounds(variables: List[Variable]) -> None:
|
|
|
748
748
|
)
|
|
749
749
|
|
|
750
750
|
|
|
751
|
+
def validate_input_types(
|
|
752
|
+
dynamics: any,
|
|
753
|
+
states: any,
|
|
754
|
+
controls: any,
|
|
755
|
+
constraints: any,
|
|
756
|
+
N: any,
|
|
757
|
+
time: any,
|
|
758
|
+
) -> None:
|
|
759
|
+
"""Validate that all user-facing inputs have correct types.
|
|
760
|
+
|
|
761
|
+
This catches common user errors like passing a single State or Control
|
|
762
|
+
instead of a list, or passing wrong types for dynamics, N, or time.
|
|
763
|
+
Should be called before any other validation in the preprocessing pipeline.
|
|
764
|
+
|
|
765
|
+
Raises:
|
|
766
|
+
TypeError: If any input has the wrong type
|
|
767
|
+
ValueError: If N is not positive
|
|
768
|
+
"""
|
|
769
|
+
from openscvx.symbolic.expr import CTCS, Constraint, CrossNodeConstraint, NodalConstraint
|
|
770
|
+
from openscvx.symbolic.time import Time
|
|
771
|
+
|
|
772
|
+
if not isinstance(dynamics, dict):
|
|
773
|
+
raise TypeError(
|
|
774
|
+
f"'dynamics' must be a dict mapping state names to expressions, "
|
|
775
|
+
f"got {type(dynamics).__name__}"
|
|
776
|
+
)
|
|
777
|
+
|
|
778
|
+
if not isinstance(states, list):
|
|
779
|
+
hint = ""
|
|
780
|
+
if isinstance(states, State):
|
|
781
|
+
hint = f" Hint: use states=[{states.name}] instead of states={states.name}"
|
|
782
|
+
raise TypeError(
|
|
783
|
+
f"'states' must be a list of State objects, got {type(states).__name__}.{hint}"
|
|
784
|
+
)
|
|
785
|
+
|
|
786
|
+
for i, s in enumerate(states):
|
|
787
|
+
if not isinstance(s, State):
|
|
788
|
+
raise TypeError(f"states[{i}] must be a State, got {type(s).__name__}")
|
|
789
|
+
|
|
790
|
+
if not isinstance(controls, list):
|
|
791
|
+
hint = ""
|
|
792
|
+
if isinstance(controls, Control):
|
|
793
|
+
hint = f" Hint: use controls=[{controls.name}] instead of controls={controls.name}"
|
|
794
|
+
raise TypeError(
|
|
795
|
+
f"'controls' must be a list of Control objects, got {type(controls).__name__}.{hint}"
|
|
796
|
+
)
|
|
797
|
+
|
|
798
|
+
for i, c in enumerate(controls):
|
|
799
|
+
if not isinstance(c, Control):
|
|
800
|
+
raise TypeError(f"controls[{i}] must be a Control, got {type(c).__name__}")
|
|
801
|
+
|
|
802
|
+
if not isinstance(constraints, list):
|
|
803
|
+
raise TypeError(
|
|
804
|
+
f"'constraints' must be a list of Constraint objects, got {type(constraints).__name__}"
|
|
805
|
+
)
|
|
806
|
+
|
|
807
|
+
valid_constraint_types = (Constraint, NodalConstraint, CrossNodeConstraint, CTCS)
|
|
808
|
+
for i, c in enumerate(constraints):
|
|
809
|
+
if not isinstance(c, valid_constraint_types):
|
|
810
|
+
raise TypeError(
|
|
811
|
+
f"constraints[{i}] must be a Constraint, NodalConstraint, "
|
|
812
|
+
f"CrossNodeConstraint, or CTCS, got {type(c).__name__}"
|
|
813
|
+
)
|
|
814
|
+
|
|
815
|
+
if not isinstance(N, int):
|
|
816
|
+
raise TypeError(f"'N' must be an integer, got {type(N).__name__}")
|
|
817
|
+
|
|
818
|
+
if N < 1:
|
|
819
|
+
raise ValueError(f"'N' must be positive, got {N}")
|
|
820
|
+
|
|
821
|
+
if not isinstance(time, Time):
|
|
822
|
+
raise TypeError(f"'time' must be a Time object, got {type(time).__name__}")
|
|
823
|
+
|
|
824
|
+
|
|
825
|
+
def validate_propagation_input_types(
|
|
826
|
+
dynamics_prop_extra: any,
|
|
827
|
+
states_prop_extra: any,
|
|
828
|
+
) -> None:
|
|
829
|
+
"""Validate types for optional propagation inputs.
|
|
830
|
+
|
|
831
|
+
These parameters must either both be None or both be provided.
|
|
832
|
+
When provided, dynamics_prop_extra must be a dict and states_prop_extra
|
|
833
|
+
must be a list of State objects.
|
|
834
|
+
|
|
835
|
+
Args:
|
|
836
|
+
dynamics_prop_extra: Should be None or a dict mapping state names to expressions
|
|
837
|
+
states_prop_extra: Should be None or a list of State objects
|
|
838
|
+
|
|
839
|
+
Raises:
|
|
840
|
+
TypeError: If either input has the wrong type
|
|
841
|
+
ValueError: If only one of the two is provided
|
|
842
|
+
|
|
843
|
+
Example:
|
|
844
|
+
distance = ox.State("distance", shape=(1,))
|
|
845
|
+
|
|
846
|
+
# Wrong: passing bare State instead of list
|
|
847
|
+
validate_propagation_input_types({"distance": expr}, distance)
|
|
848
|
+
# Raises TypeError: 'states_prop_extra' must be a list ...
|
|
849
|
+
"""
|
|
850
|
+
both_none = dynamics_prop_extra is None and states_prop_extra is None
|
|
851
|
+
both_set = dynamics_prop_extra is not None and states_prop_extra is not None
|
|
852
|
+
|
|
853
|
+
if not both_none and not both_set:
|
|
854
|
+
provided = "dynamics_prop" if dynamics_prop_extra is not None else "states_prop"
|
|
855
|
+
missing = "states_prop" if dynamics_prop_extra is not None else "dynamics_prop"
|
|
856
|
+
raise ValueError(
|
|
857
|
+
f"'{provided}' was provided but '{missing}' was not. "
|
|
858
|
+
f"Both must be provided together, or both omitted."
|
|
859
|
+
)
|
|
860
|
+
|
|
861
|
+
if both_none:
|
|
862
|
+
return
|
|
863
|
+
|
|
864
|
+
if not isinstance(dynamics_prop_extra, dict):
|
|
865
|
+
raise TypeError(
|
|
866
|
+
f"'dynamics_prop' must be a dict mapping state names to expressions, "
|
|
867
|
+
f"got {type(dynamics_prop_extra).__name__}"
|
|
868
|
+
)
|
|
869
|
+
|
|
870
|
+
if not isinstance(states_prop_extra, list):
|
|
871
|
+
hint = ""
|
|
872
|
+
if isinstance(states_prop_extra, State):
|
|
873
|
+
hint = (
|
|
874
|
+
f" Hint: use states_prop=[{states_prop_extra.name}]"
|
|
875
|
+
f" instead of states_prop={states_prop_extra.name}"
|
|
876
|
+
)
|
|
877
|
+
raise TypeError(
|
|
878
|
+
f"'states_prop' must be a list of State objects, "
|
|
879
|
+
f"got {type(states_prop_extra).__name__}.{hint}"
|
|
880
|
+
)
|
|
881
|
+
|
|
882
|
+
for i, s in enumerate(states_prop_extra):
|
|
883
|
+
if not isinstance(s, State):
|
|
884
|
+
raise TypeError(f"states_prop[{i}] must be a State, got {type(s).__name__}")
|
|
885
|
+
|
|
886
|
+
|
|
751
887
|
def validate_guesses(variables: List[Variable]) -> None:
|
|
752
888
|
"""Validate that all variables have initial guesses set.
|
|
753
889
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: openscvx
|
|
3
|
-
Version: 0.3.2.
|
|
3
|
+
Version: 0.3.2.dev342
|
|
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
|
|
@@ -15,6 +15,8 @@ from openscvx.symbolic.preprocessing import (
|
|
|
15
15
|
validate_dynamics_dict_dimensions,
|
|
16
16
|
validate_dynamics_dimension,
|
|
17
17
|
validate_guesses,
|
|
18
|
+
validate_input_types,
|
|
19
|
+
validate_propagation_input_types,
|
|
18
20
|
validate_variable_names,
|
|
19
21
|
)
|
|
20
22
|
|
|
@@ -976,3 +978,176 @@ def test_validate_guesses_raises_missing():
|
|
|
976
978
|
match="Control 'thrust' is missing initial guess.*controls require explicit guesses",
|
|
977
979
|
):
|
|
978
980
|
validate_guesses([u])
|
|
981
|
+
|
|
982
|
+
|
|
983
|
+
# =============================================================================
|
|
984
|
+
# validate_input_types Tests
|
|
985
|
+
# =============================================================================
|
|
986
|
+
|
|
987
|
+
|
|
988
|
+
@pytest.fixture
|
|
989
|
+
def valid_inputs():
|
|
990
|
+
"""Provide a minimal set of valid inputs for validate_input_types."""
|
|
991
|
+
from openscvx.symbolic.time import Time
|
|
992
|
+
|
|
993
|
+
x = State("x", shape=(3,))
|
|
994
|
+
u = Control("u", shape=(2,))
|
|
995
|
+
dynamics = {"x": x}
|
|
996
|
+
constraints = [x <= 5]
|
|
997
|
+
time = Time(initial=0.0, final=10.0, min=0.0, max=20.0)
|
|
998
|
+
return dynamics, [x], [u], constraints, 50, time
|
|
999
|
+
|
|
1000
|
+
|
|
1001
|
+
def test_validate_input_types_passes(valid_inputs):
|
|
1002
|
+
"""Test that valid inputs pass validation."""
|
|
1003
|
+
dynamics, states, controls, constraints, N, time = valid_inputs
|
|
1004
|
+
validate_input_types(dynamics, states, controls, constraints, N, time)
|
|
1005
|
+
|
|
1006
|
+
|
|
1007
|
+
def test_validate_input_types_bare_control(valid_inputs):
|
|
1008
|
+
"""Test that passing a bare Control instead of a list raises TypeError with hint."""
|
|
1009
|
+
dynamics, states, _, constraints, N, time = valid_inputs
|
|
1010
|
+
u = Control("thrust", shape=(2,))
|
|
1011
|
+
|
|
1012
|
+
with pytest.raises(
|
|
1013
|
+
TypeError, match=r"'controls' must be a list.*Control.*Hint.*controls=\[thrust\]"
|
|
1014
|
+
):
|
|
1015
|
+
validate_input_types(dynamics, states, u, constraints, N, time)
|
|
1016
|
+
|
|
1017
|
+
|
|
1018
|
+
def test_validate_input_types_bare_state(valid_inputs):
|
|
1019
|
+
"""Test that passing a bare State instead of a list raises TypeError with hint."""
|
|
1020
|
+
dynamics, _, controls, constraints, N, time = valid_inputs
|
|
1021
|
+
x = State("position", shape=(3,))
|
|
1022
|
+
|
|
1023
|
+
with pytest.raises(
|
|
1024
|
+
TypeError, match=r"'states' must be a list.*State.*Hint.*states=\[position\]"
|
|
1025
|
+
):
|
|
1026
|
+
validate_input_types(dynamics, x, controls, constraints, N, time)
|
|
1027
|
+
|
|
1028
|
+
|
|
1029
|
+
def test_validate_input_types_wrong_element_in_states(valid_inputs):
|
|
1030
|
+
"""Test that a non-State element in the states list raises TypeError."""
|
|
1031
|
+
dynamics, _, controls, constraints, N, time = valid_inputs
|
|
1032
|
+
|
|
1033
|
+
with pytest.raises(TypeError, match=r"states\[0\] must be a State, got str"):
|
|
1034
|
+
validate_input_types(dynamics, ["not_a_state"], controls, constraints, N, time)
|
|
1035
|
+
|
|
1036
|
+
|
|
1037
|
+
def test_validate_input_types_wrong_element_in_controls(valid_inputs):
|
|
1038
|
+
"""Test that a non-Control element in the controls list raises TypeError."""
|
|
1039
|
+
dynamics, states, _, constraints, N, time = valid_inputs
|
|
1040
|
+
|
|
1041
|
+
with pytest.raises(TypeError, match=r"controls\[0\] must be a Control, got int"):
|
|
1042
|
+
validate_input_types(dynamics, states, [42], constraints, N, time)
|
|
1043
|
+
|
|
1044
|
+
|
|
1045
|
+
def test_validate_input_types_dynamics_not_dict(valid_inputs):
|
|
1046
|
+
"""Test that passing non-dict dynamics raises TypeError."""
|
|
1047
|
+
_, states, controls, constraints, N, time = valid_inputs
|
|
1048
|
+
|
|
1049
|
+
with pytest.raises(TypeError, match="'dynamics' must be a dict"):
|
|
1050
|
+
validate_input_types([1, 2, 3], states, controls, constraints, N, time)
|
|
1051
|
+
|
|
1052
|
+
|
|
1053
|
+
def test_validate_input_types_constraints_not_list(valid_inputs):
|
|
1054
|
+
"""Test that passing a non-list constraints raises TypeError."""
|
|
1055
|
+
dynamics, states, controls, _, N, time = valid_inputs
|
|
1056
|
+
|
|
1057
|
+
with pytest.raises(TypeError, match="'constraints' must be a list"):
|
|
1058
|
+
validate_input_types(dynamics, states, controls, "not_a_list", N, time)
|
|
1059
|
+
|
|
1060
|
+
|
|
1061
|
+
def test_validate_input_types_constraints_invalid_element(valid_inputs):
|
|
1062
|
+
"""Test that non-constraint elements raise TypeError."""
|
|
1063
|
+
dynamics, states, controls, _, N, time = valid_inputs
|
|
1064
|
+
|
|
1065
|
+
with pytest.raises(TypeError, match=r"constraints\[0\] must be a Constraint.*got int"):
|
|
1066
|
+
validate_input_types(dynamics, states, controls, [42], N, time)
|
|
1067
|
+
|
|
1068
|
+
|
|
1069
|
+
def test_validate_input_types_constraints_mixed_valid_and_invalid(valid_inputs):
|
|
1070
|
+
"""Test that invalid element is caught even after valid ones."""
|
|
1071
|
+
dynamics, states, controls, _, N, time = valid_inputs
|
|
1072
|
+
x = State("x", shape=(3,))
|
|
1073
|
+
|
|
1074
|
+
with pytest.raises(TypeError, match=r"constraints\[1\] must be a Constraint.*got str"):
|
|
1075
|
+
validate_input_types(dynamics, states, controls, [x <= 5, "bad"], N, time)
|
|
1076
|
+
|
|
1077
|
+
|
|
1078
|
+
def test_validate_input_types_N_not_int(valid_inputs):
|
|
1079
|
+
"""Test that passing non-int N raises TypeError."""
|
|
1080
|
+
dynamics, states, controls, constraints, _, time = valid_inputs
|
|
1081
|
+
|
|
1082
|
+
with pytest.raises(TypeError, match="'N' must be an integer, got float"):
|
|
1083
|
+
validate_input_types(dynamics, states, controls, constraints, 50.0, time)
|
|
1084
|
+
|
|
1085
|
+
|
|
1086
|
+
def test_validate_input_types_N_not_positive(valid_inputs):
|
|
1087
|
+
"""Test that passing non-positive N raises ValueError."""
|
|
1088
|
+
dynamics, states, controls, constraints, _, time = valid_inputs
|
|
1089
|
+
|
|
1090
|
+
with pytest.raises(ValueError, match="'N' must be positive, got 0"):
|
|
1091
|
+
validate_input_types(dynamics, states, controls, constraints, 0, time)
|
|
1092
|
+
|
|
1093
|
+
with pytest.raises(ValueError, match="'N' must be positive, got -5"):
|
|
1094
|
+
validate_input_types(dynamics, states, controls, constraints, -5, time)
|
|
1095
|
+
|
|
1096
|
+
|
|
1097
|
+
def test_validate_input_types_time_not_time(valid_inputs):
|
|
1098
|
+
"""Test that passing non-Time object raises TypeError."""
|
|
1099
|
+
dynamics, states, controls, constraints, N, _ = valid_inputs
|
|
1100
|
+
|
|
1101
|
+
with pytest.raises(TypeError, match="'time' must be a Time object, got float"):
|
|
1102
|
+
validate_input_types(dynamics, states, controls, constraints, N, 10.0)
|
|
1103
|
+
|
|
1104
|
+
|
|
1105
|
+
# =============================================================================
|
|
1106
|
+
# validate_propagation_input_types Tests
|
|
1107
|
+
# =============================================================================
|
|
1108
|
+
|
|
1109
|
+
|
|
1110
|
+
def test_validate_propagation_input_types_both_none():
|
|
1111
|
+
"""Test that both None passes validation."""
|
|
1112
|
+
validate_propagation_input_types(None, None)
|
|
1113
|
+
|
|
1114
|
+
|
|
1115
|
+
def test_validate_propagation_input_types_both_valid():
|
|
1116
|
+
"""Test that valid dict + list passes validation."""
|
|
1117
|
+
distance = State("distance", shape=(1,))
|
|
1118
|
+
validate_propagation_input_types({"distance": distance}, [distance])
|
|
1119
|
+
|
|
1120
|
+
|
|
1121
|
+
def test_validate_propagation_input_types_only_dynamics():
|
|
1122
|
+
"""Test that providing dynamics_prop without states_prop raises ValueError."""
|
|
1123
|
+
with pytest.raises(ValueError, match="'dynamics_prop' was provided but 'states_prop' was not"):
|
|
1124
|
+
validate_propagation_input_types({"distance": 1.0}, None)
|
|
1125
|
+
|
|
1126
|
+
|
|
1127
|
+
def test_validate_propagation_input_types_only_states():
|
|
1128
|
+
"""Test that providing states_prop without dynamics_prop raises ValueError."""
|
|
1129
|
+
distance = State("distance", shape=(1,))
|
|
1130
|
+
with pytest.raises(ValueError, match="'states_prop' was provided but 'dynamics_prop' was not"):
|
|
1131
|
+
validate_propagation_input_types(None, [distance])
|
|
1132
|
+
|
|
1133
|
+
|
|
1134
|
+
def test_validate_propagation_input_types_bare_state():
|
|
1135
|
+
"""Test that passing a bare State instead of a list raises TypeError with hint."""
|
|
1136
|
+
distance = State("distance", shape=(1,))
|
|
1137
|
+
with pytest.raises(
|
|
1138
|
+
TypeError, match=r"'states_prop' must be a list.*Hint.*states_prop=\[distance\]"
|
|
1139
|
+
):
|
|
1140
|
+
validate_propagation_input_types({"distance": distance}, distance)
|
|
1141
|
+
|
|
1142
|
+
|
|
1143
|
+
def test_validate_propagation_input_types_dynamics_not_dict():
|
|
1144
|
+
"""Test that passing non-dict dynamics_prop raises TypeError."""
|
|
1145
|
+
distance = State("distance", shape=(1,))
|
|
1146
|
+
with pytest.raises(TypeError, match="'dynamics_prop' must be a dict"):
|
|
1147
|
+
validate_propagation_input_types([distance], [distance])
|
|
1148
|
+
|
|
1149
|
+
|
|
1150
|
+
def test_validate_propagation_input_types_wrong_element_in_states():
|
|
1151
|
+
"""Test that a non-State element in states_prop raises TypeError."""
|
|
1152
|
+
with pytest.raises(TypeError, match=r"states_prop\[0\] must be a State, got str"):
|
|
1153
|
+
validate_propagation_input_types({"x": 1.0}, ["not_a_state"])
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/docs/Foundations/constraint_reformulation.md
RENAMED
|
File without changes
|
{openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/docs/Foundations/control_parameterization.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/docs/UnderTheHood/vectorization_and_vmapping.md
RENAMED
|
File without changes
|
|
File without changes
|
{openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/docs/UsersGuide/01_hello_world_brachistochrone.md
RENAMED
|
File without changes
|
{openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/docs/UsersGuide/02_drone_racing_constraints.md
RENAMED
|
File without changes
|
{openscvx-0.3.2.dev333 → openscvx-0.3.2.dev342}/docs/UsersGuide/03_obstacle_avoidance_vmap.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|