openscvx 0.4.1.dev145__tar.gz → 0.4.1.dev147__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.4.1.dev145/openscvx.egg-info → openscvx-0.4.1.dev147}/PKG-INFO +1 -1
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/_version.py +3 -3
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/algorithms/__init__.py +11 -3
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/algorithms/augmented_lagrangian.py +7 -5
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/algorithms/base.py +168 -8
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/algorithms/optimization_results.py +1 -1
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/algorithms/penalized_trust_region.py +32 -13
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/algorithms/ramp_proximal_weight.py +4 -2
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/lowered/cvxpy_variables.py +1 -1
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/plotting/scp_iteration.py +3 -2
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/problem.py +16 -8
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/solvers/ptr_solver.py +5 -4
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/symbolic/augmentation.py +36 -10
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/symbolic/builder.py +9 -5
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/symbolic/lower.py +1 -1
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147/openscvx.egg-info}/PKG-INFO +1 -1
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/tests/symbolic/test_augmentation.py +99 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/tests/test_autotuning.py +35 -36
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/tests/test_optimization_results.py +1 -1
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/.github/assets/logo.svg +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/.github/release-drafter.yml +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/.github/workflows/_docs.yml +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/.github/workflows/branch-name.yml +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/.github/workflows/docs.yml +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/.github/workflows/lint.yml +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/.github/workflows/nightly.yml +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/.github/workflows/release-drafter.yml +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/.github/workflows/release.yml +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/.github/workflows/tests-integration.yml +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/.github/workflows/tests-unit.yml +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/.gitignore +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/CONTRIBUTING.md +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/LICENSE +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/README.md +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/docs/Foundations/constraint_reformulation.md +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/docs/Foundations/control_parameterization.md +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/docs/Foundations/discretization.md +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/docs/Foundations/ocp.md +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/docs/Foundations/scvx.md +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/docs/Foundations/time_dilation.md +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/docs/UnderTheHood/lowering_architecture.md +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/docs/UnderTheHood/vectorization_and_vmapping.md +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/docs/UsersGuide/00_introduction.md +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/docs/UsersGuide/01_hello_world_brachistochrone.md +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/docs/UsersGuide/02_drone_racing_constraints.md +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/docs/UsersGuide/03_obstacle_avoidance_vmap.md +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/docs/UsersGuide/04_viewpoint_constraints.md +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/docs/UsersGuide/05_visualization.md +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/docs/UsersGuide/06_logic.md +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/docs/UsersGuide/07_lie.md +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/docs/assets/favicon.png +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/docs/assets/images/ct-scvx_dark.png +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/docs/assets/images/ct-scvx_light.png +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/docs/assets/images/ctcs_dark.png +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/docs/assets/images/ctcs_light.png +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/docs/assets/images/problem_class_dark.png +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/docs/assets/images/problem_class_light.png +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/docs/assets/logo.svg +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/docs/citation.md +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/docs/examples.md +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/docs/getting-started.md +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/docs/index.md +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/docs/javascripts/mathjax.js +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/examples/abstract/brachistochrone.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/examples/abstract/impulsive.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/examples/arm/three_link_arm.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/examples/car/dubins_car.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/examples/car/dubins_car_conditional.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/examples/car/dubins_car_disjoint.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/examples/car/dubins_car_stljax.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/examples/drone/cinema_vp.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/examples/drone/dr_double_integrator.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/examples/drone/dr_vp.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/examples/drone/dr_vp_nodal.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/examples/drone/dr_vp_polytope.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/examples/drone/drone_racing.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/examples/drone/logo.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/examples/drone/logo_utils/acl_logo.svg +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/examples/drone/logo_utils/svg_path_utils.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/examples/drone/obstacle_avoidance.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/examples/drone/obstacle_avoidance_nodal.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/examples/drone/obstacle_avoidance_vmap.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/examples/plotting.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/examples/plotting_viser.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/examples/realtime/base_problems/cinema_vp_realtime_base.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/examples/realtime/base_problems/drone_racing_realtime_base.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/examples/realtime/base_problems/obstacle_avoidance_realtime_base.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/examples/realtime/cinema_vp_realtime.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/examples/realtime/drone_racing_realtime.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/examples/realtime/dubins_car_realtime.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/examples/realtime/obstacle_avoidance_realtime.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/examples/rocket/3DoF_pdg.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/examples/spacecraft/hohmann_transfer.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/examples/spacecraft/proxops_cw.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/figures/ctlos_cine.gif +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/figures/ctlos_dr.gif +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/figures/dtlos_cine.gif +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/figures/dtlos_dr.gif +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/figures/openscvx_logo.svg +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/figures/openscvx_logo_square.png +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/figures/oscvx_structure_full_dark.svg +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/figures/video_preview.png +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/material/__init__.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/material/overrides/assets/images/layers/1-background.avif +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/material/overrides/assets/images/layers/1-background@1x.avif +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/material/overrides/assets/images/layers/1-background@2x.avif +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/material/overrides/assets/images/layers/1-background@3x.avif +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/material/overrides/assets/images/layers/1-background@4x.avif +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/material/overrides/assets/images/layers/2-mars.avif +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/material/overrides/assets/images/layers/2-mars@1x.avif +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/material/overrides/assets/images/layers/2-mars@2x.avif +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/material/overrides/assets/images/layers/2-mars@3x.avif +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/material/overrides/assets/images/layers/2-mars@4x.avif +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/material/overrides/assets/images/layers/3-moon.avif +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/material/overrides/assets/images/layers/3-moon@1x.avif +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/material/overrides/assets/images/layers/3-moon@2x.avif +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/material/overrides/assets/images/layers/3-moon@3x.avif +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/material/overrides/assets/images/layers/3-moon@4x.avif +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/material/overrides/assets/images/layers/4-sat1.avif +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/material/overrides/assets/images/layers/4-sat1@1x.avif +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/material/overrides/assets/images/layers/4-sat1@2x.avif +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/material/overrides/assets/images/layers/4-sat1@3x.avif +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/material/overrides/assets/images/layers/4-sat1@4x.avif +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/material/overrides/assets/images/layers/5-space.avif +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/material/overrides/assets/images/layers/5-space@1x.avif +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/material/overrides/assets/images/layers/5-space@2x.avif +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/material/overrides/assets/images/layers/5-space@3x.avif +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/material/overrides/assets/images/layers/5-space@4x.avif +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/material/overrides/assets/images/layers/6-earth.avif +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/material/overrides/assets/images/layers/6-earth@1x.avif +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/material/overrides/assets/images/layers/6-earth@2x.avif +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/material/overrides/assets/images/layers/6-earth@3x.avif +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/material/overrides/assets/images/layers/6-earth@4x.avif +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/material/overrides/assets/javascripts/parallax.js +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/material/overrides/assets/logo.svg +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/material/overrides/assets/stylesheets/custom.css +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/material/overrides/assets/stylesheets/parallax.css +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/material/overrides/home.html +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/material/overrides/main.html +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/material/overrides/partials/parallax/hero.html +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/material/overrides/partials/parallax.html +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/mkdocs.yml +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/__init__.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/__main__.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/algorithms/constant_proximal_weight.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/config.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/discretization/__init__.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/discretization/base.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/discretization/linearize_discretize.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/expert/__init__.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/expert/byof.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/expert/lowering.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/expert/validation.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/init/__init__.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/init/interpolation.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/integrators/__init__.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/integrators/runge_kutta.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/loader.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/lowered/__init__.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/lowered/cvxpy_constraints.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/lowered/dynamics.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/lowered/jax_constraints.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/lowered/parameters.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/lowered/problem.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/lowered/unified.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/plotting/__init__.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/plotting/plotting.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/plotting/viser/__init__.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/plotting/viser/animated.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/plotting/viser/orbits.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/plotting/viser/plotly_integration.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/plotting/viser/primitives.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/plotting/viser/scp.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/plotting/viser/server.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/propagation/__init__.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/propagation/post_processing.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/propagation/propagation.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/solvers/__init__.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/solvers/base.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/symbolic/__init__.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/symbolic/constraint_set.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/symbolic/expr/__init__.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/symbolic/expr/arithmetic.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/symbolic/expr/array.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/symbolic/expr/constraint.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/symbolic/expr/control.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/symbolic/expr/expr.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/symbolic/expr/lie/__init__.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/symbolic/expr/lie/adjoint.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/symbolic/expr/lie/se3.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/symbolic/expr/lie/so3.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/symbolic/expr/linalg.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/symbolic/expr/logic.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/symbolic/expr/math.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/symbolic/expr/spatial.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/symbolic/expr/state.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/symbolic/expr/stl.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/symbolic/expr/time.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/symbolic/expr/variable.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/symbolic/expr/vmap.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/symbolic/hashing.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/symbolic/lowerers/__init__.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/symbolic/lowerers/cvxpy/__init__.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/symbolic/lowerers/cvxpy/_lowerer.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/symbolic/lowerers/cvxpy/_registry.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/symbolic/lowerers/cvxpy/arithmetic.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/symbolic/lowerers/cvxpy/array.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/symbolic/lowerers/cvxpy/constraint.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/symbolic/lowerers/cvxpy/control.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/symbolic/lowerers/cvxpy/expr.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/symbolic/lowerers/cvxpy/linalg.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/symbolic/lowerers/cvxpy/logic.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/symbolic/lowerers/cvxpy/math.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/symbolic/lowerers/cvxpy/state.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/symbolic/lowerers/jax/__init__.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/symbolic/lowerers/jax/_lowerer.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/symbolic/lowerers/jax/_registry.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/symbolic/lowerers/jax/arithmetic.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/symbolic/lowerers/jax/array.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/symbolic/lowerers/jax/constraint.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/symbolic/lowerers/jax/control.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/symbolic/lowerers/jax/expr.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/symbolic/lowerers/jax/lie.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/symbolic/lowerers/jax/linalg.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/symbolic/lowerers/jax/logic.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/symbolic/lowerers/jax/math.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/symbolic/lowerers/jax/spatial.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/symbolic/lowerers/jax/state.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/symbolic/lowerers/jax/stl.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/symbolic/lowerers/jax/vmap.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/symbolic/parser/__init__.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/symbolic/parser/_registry.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/symbolic/parser/array.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/symbolic/parser/constraint.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/symbolic/parser/lie.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/symbolic/parser/linalg.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/symbolic/parser/logic.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/symbolic/parser/math.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/symbolic/parser/parser.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/symbolic/parser/spatial.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/symbolic/parser/stl.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/symbolic/parser/tokenizer.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/symbolic/preprocessing.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/symbolic/problem.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/symbolic/sparsity.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/symbolic/unified.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/utils/__init__.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/utils/cache.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/utils/caching.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/utils/printing.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/utils/profiling.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/utils/utils.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx.egg-info/SOURCES.txt +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx.egg-info/dependency_links.txt +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx.egg-info/entry_points.txt +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx.egg-info/requires.txt +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx.egg-info/top_level.txt +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/pyproject.toml +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/scripts/gen_example_pages.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/scripts/gen_ref_pages.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/setup.cfg +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/tests/__init__.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/tests/brachistochrone_analytical.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/tests/fixtures/brachistochrone.json +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/tests/fixtures/brachistochrone.yaml +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/tests/hohmann_analytical.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/tests/symbolic/__init__.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/tests/symbolic/expr/__init__.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/tests/symbolic/expr/test_arithmetic.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/tests/symbolic/expr/test_array.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/tests/symbolic/expr/test_constraint.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/tests/symbolic/expr/test_expr.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/tests/symbolic/expr/test_lie.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/tests/symbolic/expr/test_linalg.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/tests/symbolic/expr/test_logic.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/tests/symbolic/expr/test_math.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/tests/symbolic/expr/test_node_reference.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/tests/symbolic/expr/test_parameters.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/tests/symbolic/expr/test_scaling.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/tests/symbolic/expr/test_spatial.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/tests/symbolic/expr/test_variable.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/tests/symbolic/expr/test_vmap.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/tests/symbolic/parser/__init__.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/tests/symbolic/parser/test_array.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/tests/symbolic/parser/test_constraint.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/tests/symbolic/parser/test_lie.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/tests/symbolic/parser/test_linalg.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/tests/symbolic/parser/test_load.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/tests/symbolic/parser/test_logic.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/tests/symbolic/parser/test_math.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/tests/symbolic/parser/test_parser.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/tests/symbolic/parser/test_spatial.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/tests/symbolic/parser/test_stl.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/tests/symbolic/parser/test_tokenizer.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/tests/symbolic/parser/test_vmap.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/tests/symbolic/test_hashing.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/tests/symbolic/test_lower_cvxpy.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/tests/symbolic/test_lower_jax.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/tests/symbolic/test_preprocessing.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/tests/symbolic/test_sparsity.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/tests/symbolic/test_unified.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/tests/test_brachistochrone.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/tests/test_cvxpygen_optional.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/tests/test_discretization.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/tests/test_examples.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/tests/test_expert.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/tests/test_impulsive.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/tests/test_init.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/tests/test_integrators.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/tests/test_loader.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/tests/test_plotting.py +0 -0
- {openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/tests/test_propagation.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: openscvx
|
|
3
|
-
Version: 0.4.1.
|
|
3
|
+
Version: 0.4.1.dev147
|
|
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.4.1.
|
|
32
|
-
__version_tuple__ = version_tuple = (0, 4, 1, '
|
|
31
|
+
__version__ = version = '0.4.1.dev147'
|
|
32
|
+
__version_tuple__ = version_tuple = (0, 4, 1, 'dev147')
|
|
33
33
|
|
|
34
|
-
__commit_id__ = commit_id = '
|
|
34
|
+
__commit_id__ = commit_id = 'g50fc80214'
|
|
@@ -140,7 +140,9 @@ def _resolve_autotuner(val: Any) -> Any:
|
|
|
140
140
|
raise TypeError(f"Invalid autotuner keyword argument: {e}. Valid keys: {valid}") from None
|
|
141
141
|
|
|
142
142
|
|
|
143
|
-
def _resolve_algorithm(
|
|
143
|
+
def _resolve_algorithm(
|
|
144
|
+
kwargs: dict, states: list = None, controls: list = None
|
|
145
|
+
) -> "PenalizedTrustRegion":
|
|
144
146
|
"""Build a :class:`PenalizedTrustRegion` from a user-supplied dict.
|
|
145
147
|
|
|
146
148
|
Supports a nested ``autotuner`` key that is resolved via
|
|
@@ -149,7 +151,11 @@ def _resolve_algorithm(kwargs: dict, states: list = None) -> "PenalizedTrustRegi
|
|
|
149
151
|
Args:
|
|
150
152
|
kwargs: Algorithm keyword arguments (e.g. ``lam_cost``, ``autotuner``).
|
|
151
153
|
states: Symbolic State objects, forwarded to the algorithm constructor
|
|
152
|
-
so that dict-valued ``lam_cost`` can be expanded
|
|
154
|
+
so that dict-valued ``lam_cost`` / ``lam_prox`` can be expanded
|
|
155
|
+
immediately.
|
|
156
|
+
controls: Symbolic Control objects, forwarded to the algorithm
|
|
157
|
+
constructor so that dict-valued ``lam_prox`` can be expanded
|
|
158
|
+
immediately.
|
|
153
159
|
"""
|
|
154
160
|
kwargs = dict(kwargs) # copy to avoid mutating the caller's dict
|
|
155
161
|
|
|
@@ -157,9 +163,11 @@ def _resolve_algorithm(kwargs: dict, states: list = None) -> "PenalizedTrustRegi
|
|
|
157
163
|
if "autotuner" in kwargs:
|
|
158
164
|
kwargs["autotuner"] = _resolve_autotuner(kwargs["autotuner"])
|
|
159
165
|
|
|
160
|
-
# Forward states so dict
|
|
166
|
+
# Forward states/controls so dict weights can be expanded eagerly
|
|
161
167
|
if states is not None:
|
|
162
168
|
kwargs.setdefault("states", states)
|
|
169
|
+
if controls is not None:
|
|
170
|
+
kwargs.setdefault("controls", controls)
|
|
163
171
|
|
|
164
172
|
try:
|
|
165
173
|
return PenalizedTrustRegion(**kwargs)
|
|
@@ -116,7 +116,7 @@ class AugmentedLagrangian(AutotuningBase):
|
|
|
116
116
|
candidate_x_prop: np.ndarray,
|
|
117
117
|
settings: Config,
|
|
118
118
|
lam_vc: np.ndarray,
|
|
119
|
-
lam_prox:
|
|
119
|
+
lam_prox: np.ndarray,
|
|
120
120
|
) -> np.ndarray:
|
|
121
121
|
"""Update virtual control penalty weights from state violation.
|
|
122
122
|
|
|
@@ -126,7 +126,9 @@ class AugmentedLagrangian(AutotuningBase):
|
|
|
126
126
|
"""
|
|
127
127
|
nu = (settings.sim.inv_S_x @ abs(candidate.x[1:] - candidate_x_prop).T).T
|
|
128
128
|
mask = nu > self.ep
|
|
129
|
-
|
|
129
|
+
# TODO: (haynec) use per-variable lam_prox to scale VC updates proportionally
|
|
130
|
+
lam_prox_scalar = float(np.max(lam_prox))
|
|
131
|
+
scale = self.eta_lambda * (1 / (2 * lam_prox_scalar))
|
|
130
132
|
case1 = lam_vc + nu * scale
|
|
131
133
|
case2 = lam_vc + (nu**2) / self.ep * scale
|
|
132
134
|
vc_new = np.where(mask, case1, case2)
|
|
@@ -222,12 +224,12 @@ class AugmentedLagrangian(AutotuningBase):
|
|
|
222
224
|
|
|
223
225
|
if rho < self.eta_0:
|
|
224
226
|
# Reject Solution and higher weight
|
|
225
|
-
lam_prox_k1 =
|
|
227
|
+
lam_prox_k1 = np.minimum(self.lam_prox_max, self.gamma_1 * lam_prox_k)
|
|
226
228
|
state.lam_prox_history.append(lam_prox_k1)
|
|
227
229
|
adaptive_state = "Reject Higher"
|
|
228
230
|
elif rho >= self.eta_0 and rho < self.eta_1:
|
|
229
231
|
# Accept Solution with heigher weight
|
|
230
|
-
lam_prox_k1 =
|
|
232
|
+
lam_prox_k1 = np.minimum(self.lam_prox_max, self.gamma_1 * lam_prox_k)
|
|
231
233
|
state.lam_prox_history.append(lam_prox_k1)
|
|
232
234
|
|
|
233
235
|
# Update virtual control weight matrix
|
|
@@ -255,7 +257,7 @@ class AugmentedLagrangian(AutotuningBase):
|
|
|
255
257
|
adaptive_state = "Accept Constant"
|
|
256
258
|
else:
|
|
257
259
|
# Accept Solution with lower weight
|
|
258
|
-
lam_prox_k1 =
|
|
260
|
+
lam_prox_k1 = np.maximum(self.lam_prox_min, self.gamma_2 * lam_prox_k)
|
|
259
261
|
state.lam_prox_history.append(lam_prox_k1)
|
|
260
262
|
# Update virtual control weight matrix
|
|
261
263
|
candidate.lam_vc = self._update_virtual_control_weights(
|
|
@@ -17,6 +17,7 @@ if TYPE_CHECKING:
|
|
|
17
17
|
from openscvx.config import Config
|
|
18
18
|
from openscvx.lowered.jax_constraints import LoweredJaxConstraints
|
|
19
19
|
from openscvx.solvers import ConvexSolver
|
|
20
|
+
from openscvx.symbolic.expr.control import Control
|
|
20
21
|
from openscvx.symbolic.expr.state import State
|
|
21
22
|
|
|
22
23
|
|
|
@@ -195,6 +196,113 @@ def _expand_lam_vc_dict(
|
|
|
195
196
|
return lam_arr
|
|
196
197
|
|
|
197
198
|
|
|
199
|
+
def _expand_lam_prox_dict(
|
|
200
|
+
lam_prox_dict: Dict[str, Union[float, list, np.ndarray]],
|
|
201
|
+
states: List["State"],
|
|
202
|
+
controls: List["Control"],
|
|
203
|
+
) -> np.ndarray:
|
|
204
|
+
"""Expand a ``{name: weight}`` dict to a per-variable proximal weight array.
|
|
205
|
+
|
|
206
|
+
Maps user-provided per-state/per-control trust region weights to a dense
|
|
207
|
+
array using each variable's ``_slice``. Variables not present in the dict
|
|
208
|
+
default to ``1.0``.
|
|
209
|
+
|
|
210
|
+
Per-variable values may be:
|
|
211
|
+
|
|
212
|
+
* **scalar** — broadcast to every component and every node.
|
|
213
|
+
* **1-D array** of length ``n_components`` — per-component weight,
|
|
214
|
+
same for every node.
|
|
215
|
+
* **2-D array** of shape ``(K, n_components)`` — per-node-per-component.
|
|
216
|
+
When any variable supplies a 2-D value the output is 2-D with first
|
|
217
|
+
dimension *K* (all 2-D entries must agree on *K*).
|
|
218
|
+
|
|
219
|
+
Args:
|
|
220
|
+
lam_prox_dict: Mapping from state/control names to proximal weights.
|
|
221
|
+
states: List of State objects (must already have ``_slice`` assigned).
|
|
222
|
+
controls: List of Control objects (must already have ``_slice`` assigned).
|
|
223
|
+
|
|
224
|
+
Returns:
|
|
225
|
+
np.ndarray of shape ``(n_states + n_controls,)`` when all entries are
|
|
226
|
+
scalar/1-D, or ``(K, n_states + n_controls)`` when any entry is 2-D.
|
|
227
|
+
|
|
228
|
+
Raises:
|
|
229
|
+
ValueError: If the dict contains unknown names or 2-D entries disagree
|
|
230
|
+
on the number of nodes.
|
|
231
|
+
"""
|
|
232
|
+
n_states = sum(s.shape[0] if len(s.shape) > 0 else 1 for s in states)
|
|
233
|
+
n_controls = sum(c.shape[0] if len(c.shape) > 0 else 1 for c in controls)
|
|
234
|
+
n_total = n_states + n_controls
|
|
235
|
+
|
|
236
|
+
valid_state_names = {s.name for s in states}
|
|
237
|
+
valid_control_names = {c.name for c in controls}
|
|
238
|
+
valid_names = valid_state_names | valid_control_names
|
|
239
|
+
unknown = set(lam_prox_dict.keys()) - valid_names
|
|
240
|
+
if unknown:
|
|
241
|
+
raise ValueError(
|
|
242
|
+
f"lam_prox dict contains unknown name(s): {unknown}. Valid names: {sorted(valid_names)}"
|
|
243
|
+
)
|
|
244
|
+
|
|
245
|
+
# Build a unified list of (name, n_components, slice_in_output).
|
|
246
|
+
# States occupy columns [0, n_states), controls occupy [n_states, n_total).
|
|
247
|
+
variables: list = []
|
|
248
|
+
for s in states:
|
|
249
|
+
nc = s.shape[0] if len(s.shape) > 0 else 1
|
|
250
|
+
variables.append((s.name, nc, s._slice))
|
|
251
|
+
for c in controls:
|
|
252
|
+
nc = c.shape[0] if len(c.shape) > 0 else 1
|
|
253
|
+
out_slice = slice(n_states + c._slice.start, n_states + c._slice.stop)
|
|
254
|
+
variables.append((c.name, nc, out_slice))
|
|
255
|
+
|
|
256
|
+
# First pass: determine if any entry is 2-D and infer K.
|
|
257
|
+
n_nodes: Optional[int] = None
|
|
258
|
+
for name, n_comp, _ in variables:
|
|
259
|
+
if name not in lam_prox_dict:
|
|
260
|
+
continue
|
|
261
|
+
val = np.asarray(lam_prox_dict[name], dtype=float)
|
|
262
|
+
if val.ndim == 2:
|
|
263
|
+
if n_nodes is None:
|
|
264
|
+
n_nodes = val.shape[0]
|
|
265
|
+
elif val.shape[0] != n_nodes:
|
|
266
|
+
raise ValueError(
|
|
267
|
+
f"lam_prox['{name}'] has {val.shape[0]} rows, but a "
|
|
268
|
+
f"previous entry had {n_nodes} rows. All 2-D entries "
|
|
269
|
+
f"must have the same number of rows (n_nodes)."
|
|
270
|
+
)
|
|
271
|
+
|
|
272
|
+
# Build the output array.
|
|
273
|
+
if n_nodes is not None:
|
|
274
|
+
lam_arr = np.ones((n_nodes, n_total))
|
|
275
|
+
else:
|
|
276
|
+
lam_arr = np.ones(n_total)
|
|
277
|
+
|
|
278
|
+
for name, n_comp, out_slice in variables:
|
|
279
|
+
if name not in lam_prox_dict:
|
|
280
|
+
continue
|
|
281
|
+
val = np.asarray(lam_prox_dict[name], dtype=float)
|
|
282
|
+
|
|
283
|
+
if val.ndim == 0:
|
|
284
|
+
lam_arr[..., out_slice] = float(val)
|
|
285
|
+
elif val.ndim == 1:
|
|
286
|
+
if val.shape[0] != n_comp:
|
|
287
|
+
raise ValueError(
|
|
288
|
+
f"lam_prox['{name}'] has length {val.shape[0]}, "
|
|
289
|
+
f"expected scalar or length {n_comp}"
|
|
290
|
+
)
|
|
291
|
+
lam_arr[..., out_slice] = val
|
|
292
|
+
elif val.ndim == 2:
|
|
293
|
+
if val.shape[1] != n_comp:
|
|
294
|
+
raise ValueError(
|
|
295
|
+
f"lam_prox['{name}'] has {val.shape[1]} columns, expected {n_comp}"
|
|
296
|
+
)
|
|
297
|
+
lam_arr[:, out_slice] = val
|
|
298
|
+
else:
|
|
299
|
+
raise ValueError(
|
|
300
|
+
f"lam_prox['{name}'] has {val.ndim} dimensions, expected scalar, 1-D, or 2-D"
|
|
301
|
+
)
|
|
302
|
+
|
|
303
|
+
return lam_arr
|
|
304
|
+
|
|
305
|
+
|
|
198
306
|
@dataclass
|
|
199
307
|
class Weights:
|
|
200
308
|
"""Normalized SCP weights used internally by the algorithm and autotuner.
|
|
@@ -214,7 +322,10 @@ class Weights:
|
|
|
214
322
|
drift.
|
|
215
323
|
|
|
216
324
|
Attributes:
|
|
217
|
-
lam_prox: Trust region (proximal) weight (normalized).
|
|
325
|
+
lam_prox: Trust region (proximal) weight (normalized). Scalar or
|
|
326
|
+
array of shape ``(n_states + n_controls,)`` or
|
|
327
|
+
``(N, n_states + n_controls)`` for per-variable / per-node
|
|
328
|
+
weighting.
|
|
218
329
|
lam_vc: Virtual control penalty weight (normalized). Scalar or
|
|
219
330
|
array of shape ``(n_states,)`` or ``(n_nodes-1, n_states)``
|
|
220
331
|
for per-state / per-node weighting.
|
|
@@ -231,7 +342,7 @@ class Weights:
|
|
|
231
342
|
:meth:`set_vb_arrays`.
|
|
232
343
|
"""
|
|
233
344
|
|
|
234
|
-
lam_prox: float = 1e0
|
|
345
|
+
lam_prox: Union[float, np.ndarray] = 1e0
|
|
235
346
|
lam_vc: Union[float, np.ndarray] = 1e1
|
|
236
347
|
lam_cost: Union[float, np.ndarray] = 1e-1
|
|
237
348
|
lam_vb: float = 0.0
|
|
@@ -240,13 +351,17 @@ class Weights:
|
|
|
240
351
|
|
|
241
352
|
def __post_init__(self):
|
|
242
353
|
# Coerce lists/lists-of-lists to numpy arrays.
|
|
354
|
+
if isinstance(self.lam_prox, (list, tuple)):
|
|
355
|
+
self.lam_prox = np.asarray(self.lam_prox, dtype=float)
|
|
243
356
|
if isinstance(self.lam_vc, (list, tuple)):
|
|
244
357
|
self.lam_vc = np.asarray(self.lam_vc, dtype=float)
|
|
245
358
|
if isinstance(self.lam_cost, (list, tuple)):
|
|
246
359
|
self.lam_cost = np.asarray(self.lam_cost, dtype=float)
|
|
247
360
|
|
|
248
361
|
# Snapshot the user-specified values so normalize() is idempotent.
|
|
249
|
-
self._raw_lam_prox =
|
|
362
|
+
self._raw_lam_prox = (
|
|
363
|
+
self.lam_prox.copy() if isinstance(self.lam_prox, np.ndarray) else self.lam_prox
|
|
364
|
+
)
|
|
250
365
|
self._raw_lam_vc = (
|
|
251
366
|
self.lam_vc.copy() if isinstance(self.lam_vc, np.ndarray) else self.lam_vc
|
|
252
367
|
)
|
|
@@ -264,6 +379,11 @@ class Weights:
|
|
|
264
379
|
making this method idempotent and safe to call after updating
|
|
265
380
|
any individual raw weight.
|
|
266
381
|
"""
|
|
382
|
+
raw_prox_max = (
|
|
383
|
+
float(np.max(self._raw_lam_prox))
|
|
384
|
+
if isinstance(self._raw_lam_prox, np.ndarray)
|
|
385
|
+
else self._raw_lam_prox
|
|
386
|
+
)
|
|
267
387
|
raw_vc_max = (
|
|
268
388
|
float(np.max(self._raw_lam_vc))
|
|
269
389
|
if isinstance(self._raw_lam_vc, np.ndarray)
|
|
@@ -281,7 +401,7 @@ class Weights:
|
|
|
281
401
|
)
|
|
282
402
|
else:
|
|
283
403
|
raw_vb_max = self._raw_lam_vb
|
|
284
|
-
scale = max(
|
|
404
|
+
scale = max(raw_prox_max, raw_vc_max, raw_cost_max, raw_vb_max)
|
|
285
405
|
if scale > 0:
|
|
286
406
|
self.lam_prox = self._raw_lam_prox / scale
|
|
287
407
|
self.lam_vc = self._raw_lam_vc / scale
|
|
@@ -614,7 +734,7 @@ class AlgorithmState:
|
|
|
614
734
|
lam_cost_history: List[Union[float, np.ndarray]] = field(default_factory=list)
|
|
615
735
|
lam_vb_nodal_history: List[np.ndarray] = field(default_factory=list)
|
|
616
736
|
lam_vb_cross_history: List[np.ndarray] = field(default_factory=list)
|
|
617
|
-
lam_prox_history: List[
|
|
737
|
+
lam_prox_history: List[np.ndarray] = field(default_factory=list)
|
|
618
738
|
x_full: List[np.ndarray] = field(default_factory=list)
|
|
619
739
|
x_prop_full: List[np.ndarray] = field(default_factory=list)
|
|
620
740
|
|
|
@@ -820,11 +940,11 @@ class AlgorithmState:
|
|
|
820
940
|
return self.discretizations[index].E_d
|
|
821
941
|
|
|
822
942
|
@property
|
|
823
|
-
def lam_prox(self) ->
|
|
943
|
+
def lam_prox(self) -> np.ndarray:
|
|
824
944
|
"""Get current trust region weight.
|
|
825
945
|
|
|
826
946
|
Returns:
|
|
827
|
-
|
|
947
|
+
Array of shape ``(N, n_states + n_controls)``.
|
|
828
948
|
"""
|
|
829
949
|
if not self.lam_prox_history:
|
|
830
950
|
raise ValueError("lam_prox_history is empty. Initialize state using from_settings().")
|
|
@@ -901,8 +1021,13 @@ class AlgorithmState:
|
|
|
901
1021
|
"""
|
|
902
1022
|
n = settings.sim.n
|
|
903
1023
|
n_states = settings.sim.n_states
|
|
1024
|
+
n_controls = settings.sim.n_controls
|
|
1025
|
+
n_total = n_states + n_controls
|
|
904
1026
|
lam_vc_array = np.ones((n - 1, n_states)) * weights.lam_vc
|
|
905
1027
|
|
|
1028
|
+
# Expand lam_prox to (N, n_states + n_controls) array
|
|
1029
|
+
lam_prox_array = np.ones((n, n_total)) * weights.lam_prox
|
|
1030
|
+
|
|
906
1031
|
# Expand scalar lam_cost to per-state array
|
|
907
1032
|
if isinstance(weights.lam_cost, np.ndarray):
|
|
908
1033
|
lam_cost_init = weights.lam_cost.copy()
|
|
@@ -931,7 +1056,7 @@ class AlgorithmState:
|
|
|
931
1056
|
lam_cost_history=[lam_cost_init],
|
|
932
1057
|
lam_vb_nodal_history=[weights.lam_vb_nodal.copy()],
|
|
933
1058
|
lam_vb_cross_history=[weights.lam_vb_cross.copy()],
|
|
934
|
-
lam_prox_history=[
|
|
1059
|
+
lam_prox_history=[lam_prox_array],
|
|
935
1060
|
)
|
|
936
1061
|
|
|
937
1062
|
|
|
@@ -989,6 +1114,41 @@ class Algorithm(ABC):
|
|
|
989
1114
|
#: Maximum number of SCP iterations. Subclasses must set this in ``__init__``.
|
|
990
1115
|
k_max: int
|
|
991
1116
|
|
|
1117
|
+
@staticmethod
|
|
1118
|
+
def _resolve_lam_prox(
|
|
1119
|
+
lam_prox: Union[float, Dict[str, Union[float, list, np.ndarray]]],
|
|
1120
|
+
states: Optional[List["State"]] = None,
|
|
1121
|
+
controls: Optional[List["Control"]] = None,
|
|
1122
|
+
) -> Union[float, np.ndarray]:
|
|
1123
|
+
"""Resolve a ``lam_prox`` spec to a numeric value.
|
|
1124
|
+
|
|
1125
|
+
If *lam_prox* is a float it is returned as-is. If it is a dict
|
|
1126
|
+
mapping state/control names to weights, *states* and *controls*
|
|
1127
|
+
must be provided so the dict can be expanded to a per-variable
|
|
1128
|
+
array via :func:`_expand_lam_prox_dict`.
|
|
1129
|
+
|
|
1130
|
+
Args:
|
|
1131
|
+
lam_prox: Scalar weight or ``{name: weight}`` dict.
|
|
1132
|
+
states: Symbolic State objects (required when *lam_prox* is a dict).
|
|
1133
|
+
controls: Symbolic Control objects (required when *lam_prox* is a dict).
|
|
1134
|
+
|
|
1135
|
+
Returns:
|
|
1136
|
+
float or np.ndarray of shape ``(n_states + n_controls,)`` or
|
|
1137
|
+
``(K, n_states + n_controls)``.
|
|
1138
|
+
|
|
1139
|
+
Raises:
|
|
1140
|
+
ValueError: If *lam_prox* is a dict and *states*/*controls* is ``None``.
|
|
1141
|
+
"""
|
|
1142
|
+
if isinstance(lam_prox, dict):
|
|
1143
|
+
if states is None or controls is None:
|
|
1144
|
+
raise ValueError(
|
|
1145
|
+
"lam_prox was specified as a dict but states and/or "
|
|
1146
|
+
"controls were not provided. Pass both so the dict can "
|
|
1147
|
+
"be expanded to a per-variable weight array."
|
|
1148
|
+
)
|
|
1149
|
+
return _expand_lam_prox_dict(lam_prox, states, controls)
|
|
1150
|
+
return lam_prox
|
|
1151
|
+
|
|
992
1152
|
@staticmethod
|
|
993
1153
|
def _resolve_lam_cost(
|
|
994
1154
|
lam_cost: Union[float, Dict[str, float]],
|
|
@@ -91,7 +91,7 @@ class OptimizationResults:
|
|
|
91
91
|
VC_history: list[np.ndarray] = field(default_factory=list, metadata={"npz": "array_list"})
|
|
92
92
|
|
|
93
93
|
# Convergence histories
|
|
94
|
-
lam_prox_history: list[
|
|
94
|
+
lam_prox_history: list[np.ndarray] = field(default_factory=list, metadata={"npz": "array_list"})
|
|
95
95
|
actual_reduction_history: list[float] = field(
|
|
96
96
|
default_factory=list, metadata={"npz": "float_list"}
|
|
97
97
|
)
|
{openscvx-0.4.1.dev145 → openscvx-0.4.1.dev147}/openscvx/algorithms/penalized_trust_region.py
RENAMED
|
@@ -29,6 +29,7 @@ from .ramp_proximal_weight import RampProximalWeight
|
|
|
29
29
|
if TYPE_CHECKING:
|
|
30
30
|
from openscvx.lowered import LoweredJaxConstraints
|
|
31
31
|
from openscvx.solvers import ConvexSolver
|
|
32
|
+
from openscvx.symbolic.expr.control import Control
|
|
32
33
|
from openscvx.symbolic.expr.state import State
|
|
33
34
|
|
|
34
35
|
from .base import AutotuningBase
|
|
@@ -85,7 +86,7 @@ class PenalizedTrustRegion(Algorithm):
|
|
|
85
86
|
self,
|
|
86
87
|
autotuner: "AutotuningBase" = None,
|
|
87
88
|
k_max: int = 200,
|
|
88
|
-
lam_prox: float = 1e0,
|
|
89
|
+
lam_prox: Union[float, Dict[str, Union[float, list]]] = 1e0,
|
|
89
90
|
lam_vc: Union[float, Dict[str, Union[float, list]]] = 1e1,
|
|
90
91
|
lam_cost: Union[float, Dict[str, float]] = 1e-1,
|
|
91
92
|
lam_vb: float = 0.0,
|
|
@@ -93,6 +94,7 @@ class PenalizedTrustRegion(Algorithm):
|
|
|
93
94
|
ep_vb: float = 1e-4,
|
|
94
95
|
ep_vc: float = 1e-8,
|
|
95
96
|
states: List["State"] = None,
|
|
97
|
+
controls: List["Control"] = None,
|
|
96
98
|
):
|
|
97
99
|
"""Initialize PTR with algorithm parameters and optional autotuner.
|
|
98
100
|
|
|
@@ -100,7 +102,14 @@ class PenalizedTrustRegion(Algorithm):
|
|
|
100
102
|
autotuner: Weight adaptation strategy. Defaults to
|
|
101
103
|
:class:`AugmentedLagrangian` when ``None``.
|
|
102
104
|
k_max: Maximum SCP iterations. Defaults to 200.
|
|
103
|
-
lam_prox: Trust region (proximal) weight.
|
|
105
|
+
lam_prox: Trust region (proximal) weight. Either a float
|
|
106
|
+
(applied uniformly to all states and controls) or a dict
|
|
107
|
+
mapping state/control names to weights, e.g.
|
|
108
|
+
``{"velocity": 1e0, "thrust": 5e-1}``. Dict values may
|
|
109
|
+
be scalars, 1-D arrays for per-component weighting, or
|
|
110
|
+
2-D arrays of shape ``(n_nodes, n_components)`` for
|
|
111
|
+
per-node-per-component weighting. Variables not in the
|
|
112
|
+
dict default to ``1.0``. Defaults to 1.0.
|
|
104
113
|
lam_vc: Virtual control penalty weight. Either a float
|
|
105
114
|
(applied uniformly to all states) or a dict mapping state
|
|
106
115
|
names to per-state weights, e.g.
|
|
@@ -119,8 +128,12 @@ class PenalizedTrustRegion(Algorithm):
|
|
|
119
128
|
ep_tr: Trust region convergence tolerance. Defaults to 1e-4.
|
|
120
129
|
ep_vb: Virtual buffer convergence tolerance. Defaults to 1e-4.
|
|
121
130
|
ep_vc: Virtual control convergence tolerance. Defaults to 1e-8.
|
|
122
|
-
states: Symbolic State objects (required when *lam_cost*
|
|
123
|
-
dict). Normally provided automatically by
|
|
131
|
+
states: Symbolic State objects (required when *lam_cost* or
|
|
132
|
+
*lam_prox* is a dict). Normally provided automatically by
|
|
133
|
+
:class:`Problem`.
|
|
134
|
+
controls: Symbolic Control objects (required when *lam_prox*
|
|
135
|
+
is a dict). Normally provided automatically by
|
|
136
|
+
:class:`Problem`.
|
|
124
137
|
"""
|
|
125
138
|
# Compiled infrastructure (set by initialize())
|
|
126
139
|
self._solver: "ConvexSolver" = None
|
|
@@ -134,17 +147,20 @@ class PenalizedTrustRegion(Algorithm):
|
|
|
134
147
|
autotuner if autotuner is not None else AugmentedLagrangian()
|
|
135
148
|
)
|
|
136
149
|
|
|
137
|
-
# Store states for later re-resolution (e.g. user sets
|
|
138
|
-
# new dict via the property setter after
|
|
150
|
+
# Store states/controls for later re-resolution (e.g. user sets
|
|
151
|
+
# lam_cost or lam_prox to a new dict via the property setter after
|
|
152
|
+
# construction).
|
|
139
153
|
self._states: List["State"] = states
|
|
154
|
+
self._controls: List["Control"] = controls
|
|
140
155
|
|
|
141
|
-
# Resolve dict lam_vc / lam_cost → ndarray (requires states)
|
|
156
|
+
# Resolve dict lam_prox / lam_vc / lam_cost → ndarray (requires states/controls)
|
|
157
|
+
resolved_lam_prox = self._resolve_lam_prox(lam_prox, states, controls)
|
|
142
158
|
resolved_lam_vc = self._resolve_lam_vc(lam_vc, states)
|
|
143
159
|
resolved_lam_cost = self._resolve_lam_cost(lam_cost, states)
|
|
144
160
|
|
|
145
161
|
# SCP weights (grouped dataclass, normalized for numerical conditioning)
|
|
146
162
|
self.weights = Weights(
|
|
147
|
-
lam_prox=
|
|
163
|
+
lam_prox=resolved_lam_prox,
|
|
148
164
|
lam_vc=resolved_lam_vc,
|
|
149
165
|
lam_cost=resolved_lam_cost,
|
|
150
166
|
lam_vb=lam_vb,
|
|
@@ -187,11 +203,12 @@ class PenalizedTrustRegion(Algorithm):
|
|
|
187
203
|
return x0_prior.reshape(1, -1)
|
|
188
204
|
|
|
189
205
|
@property
|
|
190
|
-
def lam_prox(self) -> float:
|
|
206
|
+
def lam_prox(self) -> Union[float, np.ndarray]:
|
|
191
207
|
"""Trust region (proximal) weight.
|
|
192
208
|
|
|
193
209
|
This is the user-specified value before normalization. Setting this
|
|
194
|
-
property triggers automatic re-normalization of all weights.
|
|
210
|
+
property triggers automatic re-normalization of all weights. May be
|
|
211
|
+
a scalar or array for per-variable / per-node weighting.
|
|
195
212
|
|
|
196
213
|
!!! note
|
|
197
214
|
The autotuner may modify the normalized weight in
|
|
@@ -201,8 +218,9 @@ class PenalizedTrustRegion(Algorithm):
|
|
|
201
218
|
return self.weights._raw_lam_prox
|
|
202
219
|
|
|
203
220
|
@lam_prox.setter
|
|
204
|
-
def lam_prox(self, value: float) -> None:
|
|
205
|
-
self.
|
|
221
|
+
def lam_prox(self, value: Union[float, Dict[str, Union[float, list]]]) -> None:
|
|
222
|
+
resolved = self._resolve_lam_prox(value, self._states, self._controls)
|
|
223
|
+
self.weights._raw_lam_prox = resolved
|
|
206
224
|
self.weights.normalize()
|
|
207
225
|
|
|
208
226
|
@property
|
|
@@ -465,7 +483,8 @@ class PenalizedTrustRegion(Algorithm):
|
|
|
465
483
|
"J_vb": state.J_vb,
|
|
466
484
|
"J_vc": state.J_vc,
|
|
467
485
|
"cost": cost[-1],
|
|
468
|
-
|
|
486
|
+
# TODO: (haynec) log per-variable lam_prox detail (e.g. min/max range)
|
|
487
|
+
"lam_prox": float(np.max(state.lam_prox)),
|
|
469
488
|
"prob_stat": prob_stat,
|
|
470
489
|
"adaptive_state": adaptive_state,
|
|
471
490
|
"ep_tr": self.ep_tr,
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
from typing import TYPE_CHECKING
|
|
4
4
|
|
|
5
|
+
import numpy as np
|
|
6
|
+
|
|
5
7
|
from openscvx.config import Config
|
|
6
8
|
|
|
7
9
|
from .base import AutotuningBase
|
|
@@ -61,10 +63,10 @@ class RampProximalWeight(AutotuningBase):
|
|
|
61
63
|
candidate.lam_cost = weights.lam_cost
|
|
62
64
|
|
|
63
65
|
# Check if we're already at max before updating
|
|
64
|
-
was_at_max = state.lam_prox >= self.lam_prox_max
|
|
66
|
+
was_at_max = np.all(state.lam_prox >= self.lam_prox_max)
|
|
65
67
|
|
|
66
68
|
# Calculate and append new value
|
|
67
|
-
new_lam_prox =
|
|
69
|
+
new_lam_prox = np.minimum(state.lam_prox * self.ramp_factor, self.lam_prox_max)
|
|
68
70
|
state.lam_prox_history.append(new_lam_prox)
|
|
69
71
|
|
|
70
72
|
# If we were already at max, or if we just reached it and it's staying constant
|
|
@@ -28,7 +28,7 @@ class CVXPyVariables:
|
|
|
28
28
|
- Scaled expressions: CVXPy expressions for scaled state/control at each node
|
|
29
29
|
|
|
30
30
|
Attributes:
|
|
31
|
-
lam_prox: Trust region weight parameter (
|
|
31
|
+
lam_prox: Trust region weight parameter (N x (n_states+n_controls), nonneg)
|
|
32
32
|
lam_cost: Cost function weight parameter (n_states, nonneg)
|
|
33
33
|
lam_vc: Virtual control penalty weights (N-1 x n_states, nonneg)
|
|
34
34
|
lam_vb_nodal: Virtual buffer penalty weights for nodal constraints (N x n_nodal, nonneg)
|
|
@@ -339,12 +339,13 @@ def plot_scp_convergence_histories(result: OptimizationResults) -> go.Figure:
|
|
|
339
339
|
iterations_reduction = np.arange(len(result.actual_reduction_history))
|
|
340
340
|
iterations_ratio = np.arange(len(result.acceptance_ratio_history))
|
|
341
341
|
|
|
342
|
-
# Plot 1: Trust region weight history
|
|
342
|
+
# Plot 1: Trust region weight history (plot max across all variables)
|
|
343
343
|
if len(result.lam_prox_history) > 0:
|
|
344
|
+
lam_prox_max_per_iter = [float(np.max(lp)) for lp in result.lam_prox_history]
|
|
344
345
|
fig.add_trace(
|
|
345
346
|
go.Scatter(
|
|
346
347
|
x=iterations_lam_prox,
|
|
347
|
-
y=
|
|
348
|
+
y=lam_prox_max_per_iter,
|
|
348
349
|
mode="lines+markers",
|
|
349
350
|
name="lam_prox",
|
|
350
351
|
line={"color": "cyan", "width": 2},
|
|
@@ -18,7 +18,7 @@ import os
|
|
|
18
18
|
import queue
|
|
19
19
|
import threading
|
|
20
20
|
import time
|
|
21
|
-
from typing import List, Optional, Union
|
|
21
|
+
from typing import Dict, List, Optional, Union
|
|
22
22
|
|
|
23
23
|
import jax
|
|
24
24
|
|
|
@@ -83,8 +83,8 @@ class Problem:
|
|
|
83
83
|
dynamics_prop: Optional[dict] = None,
|
|
84
84
|
states_prop: Optional[List[State]] = None,
|
|
85
85
|
algebraic_prop: Optional[dict] = None,
|
|
86
|
-
licq_min: float = 0.0,
|
|
87
|
-
licq_max: float = 1e-4,
|
|
86
|
+
licq_min: Union[float, Dict[int, float]] = 0.0,
|
|
87
|
+
licq_max: Union[float, Dict[int, float]] = 1e-4,
|
|
88
88
|
algorithm: Optional[Union[Algorithm, dict]] = None,
|
|
89
89
|
discretizer: Optional[Union[Discretizer, dict]] = None,
|
|
90
90
|
solver: Optional[Union[ConvexSolver, dict]] = None,
|
|
@@ -114,8 +114,12 @@ class Problem:
|
|
|
114
114
|
Only specify additional states beyond optimization states. Used with dynamics_prop.
|
|
115
115
|
algebraic_prop (dict, optional): Dictionary mapping names to symbolic expressions
|
|
116
116
|
for outputs evaluated (not integrated) during propagation.
|
|
117
|
-
licq_min
|
|
118
|
-
|
|
117
|
+
licq_min: Minimum LICQ constraint value. Defaults to 0.0.
|
|
118
|
+
Either a scalar (applied to all CTCS groups) or a dict
|
|
119
|
+
mapping CTCS group ``idx`` to per-group bounds.
|
|
120
|
+
licq_max: Maximum LICQ constraint value. Defaults to 1e-4.
|
|
121
|
+
Either a scalar (applied to all CTCS groups) or a dict
|
|
122
|
+
mapping CTCS group ``idx`` to per-group bounds.
|
|
119
123
|
algorithm: SCP algorithm configuration. Accepts:
|
|
120
124
|
|
|
121
125
|
- ``None`` — uses ``PenalizedTrustRegion()`` with defaults.
|
|
@@ -272,11 +276,15 @@ class Problem:
|
|
|
272
276
|
self._byof = byof
|
|
273
277
|
|
|
274
278
|
# Resolve algorithm: None → default PTR, dict → PTR(**dict), instance → use directly
|
|
275
|
-
# Pass symbolic states so dict-valued
|
|
279
|
+
# Pass symbolic states/controls so dict-valued weights can be expanded eagerly.
|
|
276
280
|
if algorithm is None:
|
|
277
|
-
self._algorithm = PenalizedTrustRegion(
|
|
281
|
+
self._algorithm = PenalizedTrustRegion(
|
|
282
|
+
states=self.symbolic.states, controls=self.symbolic.controls
|
|
283
|
+
)
|
|
278
284
|
elif isinstance(algorithm, dict):
|
|
279
|
-
self._algorithm = _resolve_algorithm(
|
|
285
|
+
self._algorithm = _resolve_algorithm(
|
|
286
|
+
algorithm, states=self.symbolic.states, controls=self.symbolic.controls
|
|
287
|
+
)
|
|
280
288
|
else:
|
|
281
289
|
if not isinstance(algorithm, Algorithm):
|
|
282
290
|
raise TypeError(
|
|
@@ -375,9 +375,10 @@ class PTRSolver(ConvexSolver):
|
|
|
375
375
|
if settings.sim.x.final_type[i] == "Maximize":
|
|
376
376
|
cost -= lam_cost[i] * x[-1][i]
|
|
377
377
|
|
|
378
|
-
# Trust Region Cost
|
|
378
|
+
# Trust Region Cost (per-variable weighting)
|
|
379
379
|
cost += sum(
|
|
380
|
-
lam_prox
|
|
380
|
+
cp.sum(cp.multiply(lam_prox[i], cp.square(cp.hstack((dx[i], du[i])))))
|
|
381
|
+
for i in range(settings.sim.n)
|
|
381
382
|
)
|
|
382
383
|
|
|
383
384
|
# Virtual Control Slack
|
|
@@ -724,7 +725,7 @@ class PTRSolver(ConvexSolver):
|
|
|
724
725
|
|
|
725
726
|
def update_penalties(
|
|
726
727
|
self,
|
|
727
|
-
lam_prox:
|
|
728
|
+
lam_prox: np.ndarray,
|
|
728
729
|
lam_cost: Union[float, np.ndarray],
|
|
729
730
|
lam_vc: np.ndarray,
|
|
730
731
|
lam_vb_nodal: np.ndarray,
|
|
@@ -736,7 +737,7 @@ class PTRSolver(ConvexSolver):
|
|
|
736
737
|
PTR convex subproblem.
|
|
737
738
|
|
|
738
739
|
Args:
|
|
739
|
-
lam_prox: Trust region
|
|
740
|
+
lam_prox: Trust region weights, shape ``(N, n_states + n_controls)``.
|
|
740
741
|
lam_cost: Cost function weight. Scalar or array of shape
|
|
741
742
|
``(n_states,)`` for per-state weighting.
|
|
742
743
|
lam_vc: Virtual control penalty weights, shape (N-1, n_states)
|