openscvx 2.dev4__tar.gz → 2.dev6__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-2.dev4/openscvx.egg-info → openscvx-2.dev6}/PKG-INFO +1 -1
- {openscvx-2.dev4 → openscvx-2.dev6}/examples/mjx/cartpole_mjx.py +13 -19
- {openscvx-2.dev4 → openscvx-2.dev6}/examples/mjx/double_cartpole_mjx.py +9 -18
- {openscvx-2.dev4 → openscvx-2.dev6}/examples/mjx/skydio_x2_mjx.py +14 -21
- {openscvx-2.dev4 → openscvx-2.dev6}/examples/mjx/triple_cartpole_3d_mjx.py +9 -18
- {openscvx-2.dev4 → openscvx-2.dev6}/examples/mjx/triple_cartpole_mjx.py +10 -19
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/__init__.py +6 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/_version.py +3 -3
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/algorithms/__init__.py +13 -4
- openscvx-2.dev6/openscvx/algorithms/autotuner/__init__.py +17 -0
- openscvx-2.dev6/openscvx/algorithms/autotuner/adaptive_proximal_weight.py +190 -0
- {openscvx-2.dev4/openscvx/algorithms → openscvx-2.dev6/openscvx/algorithms/autotuner}/augmented_lagrangian.py +9 -5
- {openscvx-2.dev4/openscvx/algorithms → openscvx-2.dev6/openscvx/algorithms/autotuner}/constant_proximal_weight.py +3 -3
- {openscvx-2.dev4/openscvx/algorithms → openscvx-2.dev6/openscvx/algorithms/autotuner}/ramp_proximal_weight.py +3 -3
- openscvx-2.dev6/openscvx/algorithms/scvx/__init__.py +5 -0
- {openscvx-2.dev4/openscvx/algorithms → openscvx-2.dev6/openscvx/algorithms/scvx}/penalized_trust_region.py +6 -6
- openscvx-2.dev6/openscvx/integrations/__init__.py +66 -0
- openscvx-2.dev6/openscvx/integrations/base.py +89 -0
- openscvx-2.dev6/openscvx/integrations/mjx.py +496 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/problem.py +13 -4
- {openscvx-2.dev4 → openscvx-2.dev6/openscvx.egg-info}/PKG-INFO +1 -1
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx.egg-info/SOURCES.txt +9 -4
- {openscvx-2.dev4 → openscvx-2.dev6}/tests/integrations/test_mjx.py +2 -69
- openscvx-2.dev6/tests/integrations/test_mjx_dynamics.py +542 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/tests/test_autotuning.py +196 -4
- {openscvx-2.dev4 → openscvx-2.dev6}/tests/test_brachistochrone.py +3 -0
- openscvx-2.dev4/openscvx/integrations/__init__.py +0 -62
- openscvx-2.dev4/openscvx/integrations/mjx.py +0 -323
- {openscvx-2.dev4 → openscvx-2.dev6}/.github/assets/logo.svg +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/.github/release-drafter.yml +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/.github/workflows/_docs.yml +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/.github/workflows/branch-name.yml +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/.github/workflows/docs.yml +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/.github/workflows/lint.yml +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/.github/workflows/nightly.yml +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/.github/workflows/release-drafter.yml +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/.github/workflows/release.yml +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/.github/workflows/tests-integration.yml +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/.github/workflows/tests-unit.yml +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/.gitignore +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/.gitmodules +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/CONTRIBUTING.md +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/LICENSE +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/README.md +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/docs/Foundations/constraint_reformulation.md +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/docs/Foundations/control_parameterization.md +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/docs/Foundations/discretization.md +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/docs/Foundations/ocp.md +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/docs/Foundations/scvx.md +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/docs/Foundations/time_dilation.md +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/docs/UnderTheHood/lowering_architecture.md +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/docs/UnderTheHood/vectorization_and_vmapping.md +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/docs/UsersGuide/00_introduction.md +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/docs/UsersGuide/01_hello_world_brachistochrone.md +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/docs/UsersGuide/02_drone_racing_constraints.md +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/docs/UsersGuide/03_obstacle_avoidance_vmap.md +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/docs/UsersGuide/04_viewpoint_constraints.md +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/docs/UsersGuide/05_visualization.md +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/docs/UsersGuide/06_logic.md +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/docs/UsersGuide/07_lie.md +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/docs/UsersGuide/08_mpcc.md +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/docs/assets/favicon.png +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/docs/assets/images/ct-scvx_dark.png +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/docs/assets/images/ct-scvx_light.png +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/docs/assets/images/ctcs_dark.png +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/docs/assets/images/ctcs_light.png +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/docs/assets/images/problem_class_dark.png +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/docs/assets/images/problem_class_light.png +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/docs/assets/logo.svg +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/docs/assets/openscvx_logo_square.png +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/docs/assets/viser-client/index.html +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/docs/assets/viser-recordings/drone_racing.viser +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/docs/assets/viser-recordings/franka_fr3v2_pick_place.viser +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/docs/citation.md +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/docs/examples.md +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/docs/index.md +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/docs/javascripts/mathjax.js +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/docs/versions.json +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/examples/_viser_embed_export.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/examples/abstract/brachistochrone.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/examples/abstract/hypersensitive.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/examples/abstract/impulsive.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/examples/abstract/stl_integer_variable.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/examples/abstract/stl_or.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/examples/animations/7_dof_arm.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/examples/animations/_camera.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/examples/animations/_render.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/examples/animations/_sensor_view.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/examples/animations/dr_vp_polytope.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/examples/animations/franka_fr3v2_pick_place.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/examples/animations/logo.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/examples/animations/obstacle_avoidance_vmap.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/examples/arm/3_dof_arm.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/examples/arm/7_dof_arm.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/examples/arm/7_dof_arm_collision.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/examples/arm/7_dof_arm_vp.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/examples/arm/franka_fr3v2_pick_place.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/examples/arm/franka_fr3v2_viewplanning.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/examples/car/dubins_car.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/examples/car/dubins_car_disjoint.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/examples/car/dubins_car_obstacle_conditional.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/examples/car/dubins_car_obstacle_stl.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/examples/car/dubins_car_stl_or.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/examples/car/dubins_car_waypoint_stl.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/examples/drone/cinema_vp.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/examples/drone/dr_double_integrator.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/examples/drone/dr_vp.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/examples/drone/dr_vp_nodal.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/examples/drone/dr_vp_polytope.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/examples/drone/drone_racing.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/examples/drone/logo.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/examples/drone/logo_utils/acl_logo.svg +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/examples/drone/logo_utils/svg_path_utils.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/examples/drone/obstacle_avoidance.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/examples/drone/obstacle_avoidance_nodal.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/examples/drone/obstacle_avoidance_vmap.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/examples/mjx/triple_cartpole_game.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/examples/mpc/double_integrator_discrete.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/examples/mpc/double_integrator_drone_racing.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/examples/mpc/dubins_car_circle_analytical.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/examples/mpc/dubins_car_circle_discrete.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/examples/mpc/realtime_double_integrator_drone_racing.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/examples/plotting.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/examples/plotting_viser.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/examples/realtime/3DoF_pdg_realtime.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/examples/realtime/6DoF_pdg_realtime.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/examples/realtime/base_problems/3DoF_pdg_realtime_base.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/examples/realtime/base_problems/6DoF_pdg_realtime_base.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/examples/realtime/base_problems/cinema_vp_realtime_base.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/examples/realtime/base_problems/drone_racing_realtime_base.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/examples/realtime/base_problems/dubins_car_realtime_base.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/examples/realtime/base_problems/obstacle_avoidance_realtime_base.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/examples/realtime/cinema_vp_realtime.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/examples/realtime/drone_racing_realtime.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/examples/realtime/dubins_car_realtime.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/examples/realtime/obstacle_avoidance_realtime.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/examples/rocket/3DoF_pdg.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/examples/rocket/6DoF_pdg.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/examples/spacecraft/halo_orbit.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/examples/spacecraft/hohmann_transfer.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/examples/spacecraft/let_transfer.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/examples/spacecraft/proxops_cw.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/figures/ctlos_cine.gif +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/figures/ctlos_dr.gif +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/figures/dtlos_cine.gif +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/figures/dtlos_dr.gif +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/figures/openscvx_logo.svg +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/figures/openscvx_logo_square.png +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/figures/oscvx_structure_full_dark.svg +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/figures/video_preview.png +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/material/__init__.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/material/overrides/assets/stylesheets/custom.css +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/material/overrides/assets/stylesheets/home-dropin.css +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/material/overrides/assets/stylesheets/home-hero.css +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/material/overrides/assets/stylesheets/home-viser.css +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/material/overrides/home.html +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/material/overrides/main.html +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/material/overrides/partials/home-diagram.html +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/material/overrides/partials/home-dropin-banner.html +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/material/overrides/partials/home-hero.html +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/material/overrides/partials/home-pipeline.html +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/material/overrides/partials/home-viser-strip.html +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/mkdocs.yml +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/__main__.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/algorithms/base.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/algorithms/optimization_results.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/algorithms/weights.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/config.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/discretization/__init__.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/discretization/base.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/discretization/discretize_linearize.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/discretization/linearize_discretize.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/discretization/linearize_discretize_sparse.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/discretization/sparse_utils/__init__.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/discretization/sparse_utils/bcoo_helpers.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/discretization/sparse_utils/sparse_jacobian.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/expert/__init__.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/expert/byof.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/expert/lowering.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/expert/validation.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/init/__init__.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/init/interpolation.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/init/inverse_kinematics.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/integrations/menagerie.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/integrators/__init__.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/integrators/diffrax.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/integrators/runge_kutta.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/loader.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/lowered/__init__.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/lowered/cvxpy_constraints.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/lowered/cvxpy_variables.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/lowered/dynamics.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/lowered/jax_constraints.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/lowered/parameters.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/lowered/problem.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/lowered/unified.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/plotting/__init__.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/plotting/plotting.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/plotting/scp_iteration.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/plotting/viser/__init__.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/plotting/viser/animated.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/plotting/viser/orbits.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/plotting/viser/plotly_integration.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/plotting/viser/primitives.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/plotting/viser/scp.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/plotting/viser/server.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/propagation/__init__.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/propagation/post_processing.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/propagation/propagation.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/solvers/__init__.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/solvers/base.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/solvers/ptr_solver.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/symbolic/__init__.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/symbolic/augmentation.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/symbolic/builder.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/symbolic/constraint_set.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/symbolic/expr/__init__.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/symbolic/expr/arithmetic.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/symbolic/expr/array.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/symbolic/expr/constraint.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/symbolic/expr/control.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/symbolic/expr/expr.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/symbolic/expr/lie/__init__.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/symbolic/expr/lie/adjoint.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/symbolic/expr/lie/se3.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/symbolic/expr/lie/so3.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/symbolic/expr/linalg.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/symbolic/expr/logic.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/symbolic/expr/math.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/symbolic/expr/parameter.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/symbolic/expr/spatial.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/symbolic/expr/state.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/symbolic/expr/stl.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/symbolic/expr/stljax.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/symbolic/expr/time.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/symbolic/expr/variable.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/symbolic/expr/vmap.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/symbolic/hashing.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/symbolic/lower.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/symbolic/lowerers/__init__.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/symbolic/lowerers/cvxpy/__init__.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/symbolic/lowerers/cvxpy/_lowerer.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/symbolic/lowerers/cvxpy/_registry.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/symbolic/lowerers/cvxpy/arithmetic.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/symbolic/lowerers/cvxpy/array.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/symbolic/lowerers/cvxpy/constraint.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/symbolic/lowerers/cvxpy/control.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/symbolic/lowerers/cvxpy/expr.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/symbolic/lowerers/cvxpy/linalg.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/symbolic/lowerers/cvxpy/logic.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/symbolic/lowerers/cvxpy/math.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/symbolic/lowerers/cvxpy/state.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/symbolic/lowerers/jax/__init__.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/symbolic/lowerers/jax/_lowerer.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/symbolic/lowerers/jax/_registry.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/symbolic/lowerers/jax/arithmetic.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/symbolic/lowerers/jax/array.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/symbolic/lowerers/jax/constraint.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/symbolic/lowerers/jax/control.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/symbolic/lowerers/jax/expr.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/symbolic/lowerers/jax/lie.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/symbolic/lowerers/jax/linalg.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/symbolic/lowerers/jax/logic.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/symbolic/lowerers/jax/math.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/symbolic/lowerers/jax/spatial.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/symbolic/lowerers/jax/state.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/symbolic/lowerers/jax/stl.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/symbolic/lowerers/jax/stljax.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/symbolic/lowerers/jax/vmap.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/symbolic/parser/__init__.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/symbolic/parser/_registry.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/symbolic/parser/array.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/symbolic/parser/constraint.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/symbolic/parser/lie.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/symbolic/parser/linalg.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/symbolic/parser/logic.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/symbolic/parser/math.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/symbolic/parser/parser.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/symbolic/parser/spatial.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/symbolic/parser/stl.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/symbolic/parser/stljax.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/symbolic/parser/tokenizer.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/symbolic/preprocessing.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/symbolic/problem.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/symbolic/sparsity.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/symbolic/unified.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/utils/__init__.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/utils/cache.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/utils/caching.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/utils/printing.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/utils/profiling.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx/utils/utils.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx.egg-info/dependency_links.txt +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx.egg-info/entry_points.txt +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx.egg-info/requires.txt +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/openscvx.egg-info/top_level.txt +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/pyproject.toml +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/scripts/gen_example_pages.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/scripts/gen_ref_pages.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/scripts/mkdocs_copy_viser_client_hook.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/setup.cfg +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/tests/__init__.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/tests/brachistochrone_analytical.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/tests/expr/__init__.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/tests/expr/test_gmsr.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/tests/fixtures/brachistochrone.json +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/tests/fixtures/brachistochrone.yaml +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/tests/hohmann_analytical.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/tests/integrations/__init__.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/tests/symbolic/__init__.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/tests/symbolic/expr/__init__.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/tests/symbolic/expr/test_arithmetic.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/tests/symbolic/expr/test_array.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/tests/symbolic/expr/test_constraint.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/tests/symbolic/expr/test_expr.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/tests/symbolic/expr/test_lie.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/tests/symbolic/expr/test_linalg.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/tests/symbolic/expr/test_logic.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/tests/symbolic/expr/test_math.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/tests/symbolic/expr/test_node_reference.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/tests/symbolic/expr/test_parameters.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/tests/symbolic/expr/test_scaling.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/tests/symbolic/expr/test_spatial.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/tests/symbolic/expr/test_stl.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/tests/symbolic/expr/test_variable.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/tests/symbolic/expr/test_vmap.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/tests/symbolic/parser/__init__.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/tests/symbolic/parser/test_array.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/tests/symbolic/parser/test_constraint.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/tests/symbolic/parser/test_lie.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/tests/symbolic/parser/test_linalg.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/tests/symbolic/parser/test_load.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/tests/symbolic/parser/test_logic.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/tests/symbolic/parser/test_math.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/tests/symbolic/parser/test_parser.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/tests/symbolic/parser/test_spatial.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/tests/symbolic/parser/test_stl.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/tests/symbolic/parser/test_tokenizer.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/tests/symbolic/parser/test_vmap.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/tests/symbolic/test_augmentation.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/tests/symbolic/test_hashing.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/tests/symbolic/test_lower_cvxpy.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/tests/symbolic/test_lower_jax.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/tests/symbolic/test_preprocessing.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/tests/symbolic/test_sparsity.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/tests/symbolic/test_unified.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/tests/test_cvxpygen_optional.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/tests/test_discretization.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/tests/test_examples.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/tests/test_expert.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/tests/test_impulsive.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/tests/test_init.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/tests/test_integrators.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/tests/test_loader.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/tests/test_optimization_results.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/tests/test_plotting.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev6}/tests/test_propagation.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: openscvx
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.dev6
|
|
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
|
|
@@ -34,7 +34,6 @@ except ImportError:
|
|
|
34
34
|
sys.exit(1)
|
|
35
35
|
|
|
36
36
|
import openscvx as ox
|
|
37
|
-
from openscvx.integrations import mjx_byof
|
|
38
37
|
|
|
39
38
|
CARTPOLE_XML = """
|
|
40
39
|
<mujoco model="cartpole">
|
|
@@ -69,36 +68,32 @@ n_u = int(mjx_model.nu)
|
|
|
69
68
|
n = 60
|
|
70
69
|
total_time = 3.0
|
|
71
70
|
|
|
72
|
-
|
|
71
|
+
# ── MJX dynamics as a first-class adapter ─────────────────────────────────────
|
|
72
|
+
# `MjxDynamics` builds default qpos / qvel / ctrl State and Control objects
|
|
73
|
+
# matching the model's nq / nv / nu and routes the MJX forward dynamics into
|
|
74
|
+
# the BYOF channel internally — no separate `byof=` plumbing required.
|
|
75
|
+
dyn = ox.MjxDynamics(mjx_model)
|
|
76
|
+
qpos, qvel = dyn.states
|
|
77
|
+
(ctrl,) = dyn.controls
|
|
78
|
+
|
|
73
79
|
qpos.min = np.array([-3.0, -2.0 * np.pi])
|
|
74
80
|
qpos.max = np.array([3.0, 2.0 * np.pi])
|
|
75
81
|
qpos.initial = np.array([0.0, np.pi])
|
|
76
82
|
qpos.final = np.array([0.0, 0.0])
|
|
77
83
|
|
|
78
|
-
qvel = ox.State("qvel", shape=(n_v,))
|
|
79
84
|
qvel.min = np.array([-10.0, -15.0])
|
|
80
85
|
qvel.max = np.array([10.0, 15.0])
|
|
81
86
|
qvel.initial = np.array([0.0, 0.0])
|
|
82
87
|
qvel.final = np.array([0.0, 0.0])
|
|
83
88
|
|
|
84
|
-
ctrl = ox.Control("ctrl", shape=(n_u,))
|
|
85
89
|
ctrl.min = np.array([-1.0])
|
|
86
90
|
ctrl.max = np.array([1.0])
|
|
87
91
|
ctrl.guess = np.zeros((n, n_u))
|
|
88
92
|
|
|
89
|
-
states = [qpos, qvel]
|
|
90
|
-
controls = [ctrl]
|
|
91
|
-
|
|
92
|
-
dynamics = {
|
|
93
|
-
"qpos": qvel,
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
byof: ox.ByofSpec = {"dynamics": mjx_byof(mjx_model, qpos=qpos, qvel=qvel, ctrl=ctrl)}
|
|
97
|
-
|
|
98
93
|
constraints = []
|
|
99
|
-
for state in states:
|
|
94
|
+
for state in dyn.states:
|
|
100
95
|
constraints.extend([ox.ctcs(state <= state.max), ox.ctcs(state.min <= state)])
|
|
101
|
-
for control in controls:
|
|
96
|
+
for control in dyn.controls:
|
|
102
97
|
constraints.extend([ox.ctcs(control <= control.max), ox.ctcs(control.min <= control)])
|
|
103
98
|
|
|
104
99
|
theta_guess = np.linspace(np.pi, 0.0, n)
|
|
@@ -115,13 +110,12 @@ time = ox.Time(
|
|
|
115
110
|
)
|
|
116
111
|
|
|
117
112
|
problem = ox.Problem(
|
|
118
|
-
dynamics=
|
|
119
|
-
states=states,
|
|
120
|
-
controls=controls,
|
|
113
|
+
dynamics=dyn,
|
|
114
|
+
states=dyn.states,
|
|
115
|
+
controls=dyn.controls,
|
|
121
116
|
time=time,
|
|
122
117
|
constraints=constraints,
|
|
123
118
|
N=n,
|
|
124
|
-
byof=byof,
|
|
125
119
|
algorithm={
|
|
126
120
|
"lam_prox": 1e-1,
|
|
127
121
|
"lam_cost": 1e-2,
|
|
@@ -34,8 +34,6 @@ except ImportError:
|
|
|
34
34
|
sys.exit(1)
|
|
35
35
|
|
|
36
36
|
import openscvx as ox
|
|
37
|
-
from openscvx import ByofSpec
|
|
38
|
-
from openscvx.integrations import mjx_byof
|
|
39
37
|
|
|
40
38
|
L1, L2 = 0.5, 0.4 # link lengths (m)
|
|
41
39
|
|
|
@@ -81,32 +79,26 @@ n_u = int(mjx_model.nu) # 1: cart force
|
|
|
81
79
|
n = 400
|
|
82
80
|
total_time = 2.5
|
|
83
81
|
|
|
84
|
-
# ──
|
|
85
|
-
|
|
82
|
+
# ── MJX dynamics adapter ──────────────────────────────────────────────────────
|
|
83
|
+
dyn = ox.MjxDynamics(mjx_model)
|
|
84
|
+
qpos, qvel = dyn.states
|
|
85
|
+
(ctrl,) = dyn.controls
|
|
86
|
+
ctrl.parameterization = "ZOH"
|
|
87
|
+
|
|
86
88
|
qpos.min = np.array([-8.0, -2 * np.pi, -2 * np.pi])
|
|
87
89
|
qpos.max = np.array([8.0, 2 * np.pi, 2 * np.pi])
|
|
88
90
|
qpos.initial = np.array([0.0, np.pi, 0.0]) # cart at origin, link1 hanging down
|
|
89
91
|
qpos.final = [ox.Free(0.0), 0.0, 0.0] # cart free, both links upright
|
|
90
92
|
|
|
91
|
-
qvel = ox.State("qvel", shape=(n_v,))
|
|
92
93
|
qvel.min = np.array([-12.0, -12.0, -12.0])
|
|
93
94
|
qvel.max = np.array([12.0, 12.0, 12.0])
|
|
94
95
|
qvel.initial = np.zeros(n_v)
|
|
95
96
|
qvel.final = [0.0, 0.0, 0.0]
|
|
96
97
|
|
|
97
|
-
ctrl = ox.Control("ctrl", shape=(n_u,), parameterization="ZOH")
|
|
98
98
|
ctrl.min = np.array([-2.0])
|
|
99
99
|
ctrl.max = np.array([2.0])
|
|
100
100
|
ctrl.guess = np.zeros((n, n_u))
|
|
101
101
|
|
|
102
|
-
states = [qpos, qvel]
|
|
103
|
-
controls = [ctrl]
|
|
104
|
-
|
|
105
|
-
# ── Dynamics: position kinematics symbolically, velocity via MJX ──────────────
|
|
106
|
-
dynamics: dict = {"qpos": qvel} # nq == nv, valid for all-revolute/prismatic joints
|
|
107
|
-
|
|
108
|
-
byof: ByofSpec = {"dynamics": mjx_byof(mjx_model, qpos=qpos, qvel=qvel, ctrl=ctrl)}
|
|
109
|
-
|
|
110
102
|
# ── Constraints (CTCS on state / control bounds) ───────────────────────────────
|
|
111
103
|
constraints = []
|
|
112
104
|
|
|
@@ -123,13 +115,12 @@ time = ox.Time(
|
|
|
123
115
|
)
|
|
124
116
|
|
|
125
117
|
problem = ox.Problem(
|
|
126
|
-
dynamics=
|
|
127
|
-
states=states,
|
|
128
|
-
controls=controls,
|
|
118
|
+
dynamics=dyn,
|
|
119
|
+
states=dyn.states,
|
|
120
|
+
controls=dyn.controls,
|
|
129
121
|
time=time,
|
|
130
122
|
constraints=constraints,
|
|
131
123
|
N=n,
|
|
132
|
-
byof=byof,
|
|
133
124
|
algorithm={
|
|
134
125
|
"lam_prox": 1e-1,
|
|
135
126
|
"lam_cost": 0e0,
|
|
@@ -51,8 +51,7 @@ from examples.plotting_viser import (
|
|
|
51
51
|
create_animated_plotting_server,
|
|
52
52
|
create_scp_animated_plotting_server,
|
|
53
53
|
)
|
|
54
|
-
from openscvx import
|
|
55
|
-
from openscvx.integrations import mjx_byof
|
|
54
|
+
from openscvx import Problem
|
|
56
55
|
from openscvx.utils import gen_vertices, rot
|
|
57
56
|
|
|
58
57
|
HOVER_CTRL = 3.2495625 # N per motor for level hover (from menagerie keyframe)
|
|
@@ -78,33 +77,28 @@ n_u = int(mjx_model.nu) # 4 — rotor thrusts
|
|
|
78
77
|
n = 22
|
|
79
78
|
total_time = 24.0
|
|
80
79
|
|
|
81
|
-
# ──
|
|
82
|
-
|
|
80
|
+
# ── MJX dynamics adapter ──────────────────────────────────────────────────────
|
|
81
|
+
# The free joint has nq=7 but nv=6 (quaternion adds one extra position DOF).
|
|
82
|
+
# MjxDynamics detects nq > nv and automatically routes quaternion kinematics
|
|
83
|
+
# for "qpos" alongside the MJX "qvel" dynamics through the BYOF channel.
|
|
84
|
+
dyn = ox.MjxDynamics(mjx_model)
|
|
85
|
+
qpos, qvel = dyn.states
|
|
86
|
+
(ctrl,) = dyn.controls
|
|
87
|
+
|
|
83
88
|
qpos.min = np.array([-200.0, -100.0, 15.0, -1.0, -1.0, -1.0, -1.0])
|
|
84
89
|
qpos.max = np.array([200.0, 100.0, 200.0, 1.0, 1.0, 1.0, 1.0])
|
|
85
90
|
qpos.initial = np.concatenate([START_POS, HOVER_QUAT])
|
|
86
91
|
qpos.final = [10.0, 0.0, 20.0, ("free", 1.0), ("free", 0.0), ("free", 0.0), ("free", 0.0)]
|
|
87
92
|
|
|
88
|
-
qvel = ox.State("qvel", shape=(n_v,))
|
|
89
93
|
qvel.min = np.array([-100.0, -100.0, -100.0, -10.0, -10.0, -10.0])
|
|
90
94
|
qvel.max = np.array([100.0, 100.0, 100.0, 10.0, 10.0, 10.0])
|
|
91
95
|
qvel.initial = np.zeros(n_v)
|
|
92
96
|
qvel.final = [("free", 0.0)] * n_v
|
|
93
97
|
|
|
94
|
-
ctrl = ox.Control("ctrl", shape=(n_u,))
|
|
95
98
|
ctrl.min = np.zeros(n_u)
|
|
96
99
|
ctrl.max = 13.0 * np.ones(n_u)
|
|
97
100
|
ctrl.guess = HOVER_CTRL * np.ones((n, n_u))
|
|
98
101
|
|
|
99
|
-
states = [qpos, qvel]
|
|
100
|
-
controls = [ctrl]
|
|
101
|
-
|
|
102
|
-
# ── Dynamics via BYOF ─────────────────────────────────────────────────────────
|
|
103
|
-
# The free joint has nq=7 but nv=6 (quaternion adds one extra position DOF).
|
|
104
|
-
# nq=7, nv=6 (free joint): mjx_byof detects nq > nv and automatically
|
|
105
|
-
# includes quaternion kinematics for "qpos" alongside the MJX "qvel" dynamics.
|
|
106
|
-
byof: ByofSpec = {"dynamics": mjx_byof(mjx_model, qpos=qpos, qvel=qvel, ctrl=ctrl)}
|
|
107
|
-
|
|
108
102
|
# ── Gate parameters (matching examples/drone/drone_racing.py) ───────────────
|
|
109
103
|
n_gates = 10
|
|
110
104
|
initial_gate_centers = [
|
|
@@ -135,9 +129,9 @@ gate_centers = np.array(modified_centers)
|
|
|
135
129
|
|
|
136
130
|
# ── Constraints ───────────────────────────────────────────────────────────────
|
|
137
131
|
constraints = []
|
|
138
|
-
for state in states:
|
|
132
|
+
for state in dyn.states:
|
|
139
133
|
constraints.extend([ox.ctcs(state <= state.max), ox.ctcs(state.min <= state)])
|
|
140
|
-
for control in controls:
|
|
134
|
+
for control in dyn.controls:
|
|
141
135
|
constraints.extend([ox.ctcs(control <= control.max), ox.ctcs(control.min <= control)])
|
|
142
136
|
|
|
143
137
|
# Enforce sequential gate traversal using nodal constraints on qpos position.
|
|
@@ -172,13 +166,12 @@ time = ox.Time(
|
|
|
172
166
|
)
|
|
173
167
|
|
|
174
168
|
problem = Problem(
|
|
175
|
-
dynamics=
|
|
176
|
-
states=states,
|
|
177
|
-
controls=controls,
|
|
169
|
+
dynamics=dyn,
|
|
170
|
+
states=dyn.states,
|
|
171
|
+
controls=dyn.controls,
|
|
178
172
|
time=time,
|
|
179
173
|
constraints=constraints,
|
|
180
174
|
N=n,
|
|
181
|
-
byof=byof,
|
|
182
175
|
algorithm={
|
|
183
176
|
"lam_prox": 1e-1,
|
|
184
177
|
"lam_cost": 1e-2,
|
|
@@ -57,8 +57,7 @@ except ImportError:
|
|
|
57
57
|
sys.exit(1)
|
|
58
58
|
|
|
59
59
|
import openscvx as ox
|
|
60
|
-
from openscvx import
|
|
61
|
-
from openscvx.integrations import mjx_byof
|
|
60
|
+
from openscvx import Problem
|
|
62
61
|
|
|
63
62
|
L1, L2, L3 = 0.5, 0.4, 0.3 # link lengths (m)
|
|
64
63
|
|
|
@@ -122,8 +121,11 @@ IDX_A1, IDX_B1 = 2, 3
|
|
|
122
121
|
IDX_A2, IDX_B2 = 4, 5
|
|
123
122
|
IDX_A3, IDX_B3 = 6, 7
|
|
124
123
|
|
|
125
|
-
# ──
|
|
126
|
-
|
|
124
|
+
# ── MJX dynamics adapter ──────────────────────────────────────────────────────
|
|
125
|
+
dyn = ox.MjxDynamics(mjx_model)
|
|
126
|
+
qpos, qvel = dyn.states
|
|
127
|
+
(ctrl,) = dyn.controls
|
|
128
|
+
|
|
127
129
|
qpos.min = np.array(
|
|
128
130
|
[-8.0, -8.0, -2 * np.pi, -2 * np.pi, -2 * np.pi, -2 * np.pi, -2 * np.pi, -2 * np.pi]
|
|
129
131
|
)
|
|
@@ -142,25 +144,15 @@ qpos.final = [
|
|
|
142
144
|
0.0, # link 3 upright
|
|
143
145
|
]
|
|
144
146
|
|
|
145
|
-
qvel = ox.State("qvel", shape=(n_v,))
|
|
146
147
|
qvel.min = np.full(n_v, -12.0)
|
|
147
148
|
qvel.max = np.full(n_v, 12.0)
|
|
148
149
|
qvel.initial = np.zeros(n_v)
|
|
149
150
|
qvel.final = [0.0] * n_v
|
|
150
151
|
|
|
151
|
-
ctrl = ox.Control("ctrl", shape=(n_u,))
|
|
152
152
|
ctrl.min = np.array([-2.0, -2.0])
|
|
153
153
|
ctrl.max = np.array([2.0, 2.0])
|
|
154
154
|
ctrl.guess = np.zeros((n, n_u))
|
|
155
155
|
|
|
156
|
-
states = [qpos, qvel]
|
|
157
|
-
controls = [ctrl]
|
|
158
|
-
|
|
159
|
-
# ── Dynamics: position kinematics symbolically, velocity via MJX ──────────────
|
|
160
|
-
dynamics: dict = {"qpos": qvel} # nq == nv
|
|
161
|
-
|
|
162
|
-
byof: ByofSpec = {"dynamics": mjx_byof(mjx_model, qpos=qpos, qvel=qvel, ctrl=ctrl)}
|
|
163
|
-
|
|
164
156
|
# ── Constraints (CTCS on state / control bounds) ─────────────────────────────
|
|
165
157
|
constraints = []
|
|
166
158
|
|
|
@@ -179,13 +171,12 @@ time = ox.Time(
|
|
|
179
171
|
)
|
|
180
172
|
|
|
181
173
|
problem = Problem(
|
|
182
|
-
dynamics=
|
|
183
|
-
states=states,
|
|
184
|
-
controls=controls,
|
|
174
|
+
dynamics=dyn,
|
|
175
|
+
states=dyn.states,
|
|
176
|
+
controls=dyn.controls,
|
|
185
177
|
time=time,
|
|
186
178
|
constraints=constraints,
|
|
187
179
|
N=n,
|
|
188
|
-
byof=byof,
|
|
189
180
|
algorithm={
|
|
190
181
|
"lam_prox": 1e-1,
|
|
191
182
|
"lam_cost": 0e0,
|
|
@@ -35,8 +35,7 @@ except ImportError:
|
|
|
35
35
|
sys.exit(1)
|
|
36
36
|
|
|
37
37
|
import openscvx as ox
|
|
38
|
-
from openscvx import
|
|
39
|
-
from openscvx.integrations import mjx_byof
|
|
38
|
+
from openscvx import Problem
|
|
40
39
|
|
|
41
40
|
L1, L2, L3 = 0.5, 0.4, 0.3 # link lengths (m)
|
|
42
41
|
|
|
@@ -88,35 +87,28 @@ n_u = int(mjx_model.nu) # 1: cart force
|
|
|
88
87
|
n = 60 # more nodes → finer resolution near the unstable upright equilibrium
|
|
89
88
|
total_time = 2.5
|
|
90
89
|
|
|
91
|
-
# ──
|
|
92
|
-
|
|
90
|
+
# ── MJX dynamics adapter ──────────────────────────────────────────────────────
|
|
91
|
+
dyn = ox.MjxDynamics(mjx_model)
|
|
92
|
+
qpos, qvel = dyn.states
|
|
93
|
+
(ctrl,) = dyn.controls
|
|
94
|
+
|
|
93
95
|
qpos.min = np.array([-100.0, -2 * np.pi, -2 * np.pi, -2 * np.pi])
|
|
94
96
|
qpos.max = np.array([100.0, 2 * np.pi, 2 * np.pi, 2 * np.pi])
|
|
95
97
|
qpos.initial = np.array([0.0, np.pi, 0.0, 0.0]) # all links hanging down
|
|
96
98
|
qpos.final = [ox.Free(0.0), 0.0, 0.0, 0.0] # all links upright
|
|
97
99
|
|
|
98
|
-
qvel = ox.State("qvel", shape=(n_v,))
|
|
99
100
|
qvel.min = np.array([-12.0, -12.0, -12.0, -12.0])
|
|
100
101
|
qvel.max = np.array([12.0, 12.0, 12.0, 12.0])
|
|
101
102
|
qvel.initial = np.zeros(n_v)
|
|
102
103
|
qvel.final = [0.0, 0.0, 0.0, 0.0]
|
|
103
104
|
|
|
104
|
-
ctrl = ox.Control("ctrl", shape=(n_u,))
|
|
105
105
|
ctrl.min = np.array([-3.0])
|
|
106
106
|
ctrl.max = np.array([3.0])
|
|
107
107
|
ctrl.guess = np.zeros((n, n_u))
|
|
108
108
|
|
|
109
|
-
states = [qpos, qvel]
|
|
110
|
-
controls = [ctrl]
|
|
111
|
-
|
|
112
|
-
# ── Dynamics: position kinematics symbolically, velocity via MJX ──────────────
|
|
113
|
-
dynamics: dict = {"qpos": qvel} # nq==nv so this is always valid
|
|
114
|
-
|
|
115
|
-
byof: ByofSpec = {"dynamics": mjx_byof(mjx_model, qpos=qpos, qvel=qvel, ctrl=ctrl)}
|
|
116
|
-
|
|
117
109
|
# ── Constraints (CTCS on state / control bounds) ───────────────────────────────
|
|
118
110
|
constraints = []
|
|
119
|
-
for state in states:
|
|
111
|
+
for state in dyn.states:
|
|
120
112
|
constraints.extend([ox.ctcs(state <= state.max), ox.ctcs(state.min <= state)])
|
|
121
113
|
|
|
122
114
|
# ── Initial guess: linearly swing θ₁ from π → 0, others stay 0 ───────────────
|
|
@@ -132,13 +124,12 @@ time = ox.Time(
|
|
|
132
124
|
)
|
|
133
125
|
|
|
134
126
|
problem = Problem(
|
|
135
|
-
dynamics=
|
|
136
|
-
states=states,
|
|
137
|
-
controls=controls,
|
|
127
|
+
dynamics=dyn,
|
|
128
|
+
states=dyn.states,
|
|
129
|
+
controls=dyn.controls,
|
|
138
130
|
time=time,
|
|
139
131
|
constraints=constraints,
|
|
140
132
|
N=n,
|
|
141
|
-
byof=byof,
|
|
142
133
|
algorithm={
|
|
143
134
|
"lam_prox": 1e0,
|
|
144
135
|
"lam_cost": 0e0,
|
|
@@ -12,6 +12,7 @@ import openscvx.symbolic.expr.spatial as spatial
|
|
|
12
12
|
import openscvx.symbolic.expr.stl as stl
|
|
13
13
|
import openscvx.symbolic.expr.stljax as stljax
|
|
14
14
|
from openscvx.algorithms import (
|
|
15
|
+
AdaptiveProximalWeight,
|
|
15
16
|
AugmentedLagrangian,
|
|
16
17
|
ConstantProximalWeight,
|
|
17
18
|
PenalizedTrustRegion,
|
|
@@ -25,6 +26,7 @@ from openscvx.discretization import (
|
|
|
25
26
|
VectorizeDiscretizeLinearize,
|
|
26
27
|
)
|
|
27
28
|
from openscvx.expert import ByofSpec
|
|
29
|
+
from openscvx.integrations import DynamicsAdapter, MjxDynamics
|
|
28
30
|
from openscvx.loader import load_dict, load_json, load_yaml
|
|
29
31
|
from openscvx.problem import Problem
|
|
30
32
|
from openscvx.solvers import PTRSolver
|
|
@@ -176,6 +178,9 @@ __all__ = [
|
|
|
176
178
|
"lie",
|
|
177
179
|
# Expert mode types
|
|
178
180
|
"ByofSpec",
|
|
181
|
+
# External-backend dynamics adapters
|
|
182
|
+
"DynamicsAdapter",
|
|
183
|
+
"MjxDynamics",
|
|
179
184
|
# Discretization
|
|
180
185
|
"DiscretizeLinearizeVectorize",
|
|
181
186
|
"LinearizeDiscretize",
|
|
@@ -186,6 +191,7 @@ __all__ = [
|
|
|
186
191
|
# Algorithm & Autotuning
|
|
187
192
|
"PenalizedTrustRegion",
|
|
188
193
|
"AugmentedLagrangian",
|
|
194
|
+
"AdaptiveProximalWeight",
|
|
189
195
|
"ConstantProximalWeight",
|
|
190
196
|
"RampProximalWeight",
|
|
191
197
|
]
|
|
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
|
|
|
18
18
|
commit_id: str | None
|
|
19
19
|
__commit_id__: str | None
|
|
20
20
|
|
|
21
|
-
__version__ = version = '2.
|
|
22
|
-
__version_tuple__ = version_tuple = (2, '
|
|
21
|
+
__version__ = version = '2.dev6'
|
|
22
|
+
__version_tuple__ = version_tuple = (2, 'dev6')
|
|
23
23
|
|
|
24
|
-
__commit_id__ = commit_id = '
|
|
24
|
+
__commit_id__ = commit_id = 'gcabefce07'
|
|
@@ -82,12 +82,19 @@ from typing import Annotated, Any, Dict, List, Optional, Union
|
|
|
82
82
|
|
|
83
83
|
from pydantic import BaseModel, ConfigDict, Field, field_validator
|
|
84
84
|
|
|
85
|
-
from .
|
|
85
|
+
from .autotuner import (
|
|
86
|
+
AdaptiveProximalWeight,
|
|
87
|
+
AdaptiveProximalWeightSpec,
|
|
88
|
+
AugmentedLagrangian,
|
|
89
|
+
AugmentedLagrangianSpec,
|
|
90
|
+
ConstantProximalWeight,
|
|
91
|
+
ConstantProximalWeightSpec,
|
|
92
|
+
RampProximalWeight,
|
|
93
|
+
RampProximalWeightSpec,
|
|
94
|
+
)
|
|
86
95
|
from .base import Algorithm, AlgorithmState, AutotuningBase, DiscretizationResult
|
|
87
|
-
from .constant_proximal_weight import ConstantProximalWeight, ConstantProximalWeightSpec
|
|
88
96
|
from .optimization_results import OptimizationResults
|
|
89
|
-
from .
|
|
90
|
-
from .ramp_proximal_weight import RampProximalWeight, RampProximalWeightSpec
|
|
97
|
+
from .scvx import PenalizedTrustRegion
|
|
91
98
|
from .weights import Weights
|
|
92
99
|
|
|
93
100
|
# ---------------------------------------------------------------------------
|
|
@@ -97,6 +104,7 @@ from .weights import Weights
|
|
|
97
104
|
AutotunerConfig = Annotated[
|
|
98
105
|
Union[
|
|
99
106
|
AugmentedLagrangianSpec,
|
|
107
|
+
AdaptiveProximalWeightSpec,
|
|
100
108
|
RampProximalWeightSpec,
|
|
101
109
|
ConstantProximalWeightSpec,
|
|
102
110
|
],
|
|
@@ -173,6 +181,7 @@ __all__ = [
|
|
|
173
181
|
"PenalizedTrustRegion",
|
|
174
182
|
"AutotuningBase",
|
|
175
183
|
"AugmentedLagrangian",
|
|
184
|
+
"AdaptiveProximalWeight",
|
|
176
185
|
"ConstantProximalWeight",
|
|
177
186
|
"RampProximalWeight",
|
|
178
187
|
# Config models
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"""SCP weight autotuning strategies."""
|
|
2
|
+
|
|
3
|
+
from .adaptive_proximal_weight import AdaptiveProximalWeight, AdaptiveProximalWeightSpec
|
|
4
|
+
from .augmented_lagrangian import AugmentedLagrangian, AugmentedLagrangianSpec
|
|
5
|
+
from .constant_proximal_weight import ConstantProximalWeight, ConstantProximalWeightSpec
|
|
6
|
+
from .ramp_proximal_weight import RampProximalWeight, RampProximalWeightSpec
|
|
7
|
+
|
|
8
|
+
__all__ = [
|
|
9
|
+
"AdaptiveProximalWeight",
|
|
10
|
+
"AdaptiveProximalWeightSpec",
|
|
11
|
+
"AugmentedLagrangian",
|
|
12
|
+
"AugmentedLagrangianSpec",
|
|
13
|
+
"ConstantProximalWeight",
|
|
14
|
+
"ConstantProximalWeightSpec",
|
|
15
|
+
"RampProximalWeight",
|
|
16
|
+
"RampProximalWeightSpec",
|
|
17
|
+
]
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
"""Autotuning functions for SCP (Successive Convex Programming) parameters."""
|
|
2
|
+
|
|
3
|
+
from copy import deepcopy
|
|
4
|
+
from typing import TYPE_CHECKING, Literal
|
|
5
|
+
|
|
6
|
+
import numpy as np
|
|
7
|
+
from pydantic import BaseModel, ConfigDict
|
|
8
|
+
|
|
9
|
+
from openscvx.config import Config
|
|
10
|
+
|
|
11
|
+
from ..base import AutotuningBase
|
|
12
|
+
from .augmented_lagrangian import AugmentedLagrangian
|
|
13
|
+
|
|
14
|
+
if TYPE_CHECKING:
|
|
15
|
+
from openscvx.lowered import LoweredJaxConstraints
|
|
16
|
+
|
|
17
|
+
from ..base import AlgorithmState, CandidateIterate
|
|
18
|
+
from ..weights import Weights
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class AdaptiveProximalWeight(AutotuningBase):
|
|
22
|
+
"""PTR-style proximal adaptation with fixed virtual penalty weights.
|
|
23
|
+
|
|
24
|
+
Same acceptance-ratio logic as :class:`AugmentedLagrangian` for ``lam_prox``,
|
|
25
|
+
but ``lam_vc`` and ``lam_vb_*`` are held constant at their current state values.
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
COLUMNS = AugmentedLagrangian.COLUMNS
|
|
29
|
+
|
|
30
|
+
def __init__(
|
|
31
|
+
self,
|
|
32
|
+
gamma_1: float = 2.0,
|
|
33
|
+
gamma_2: float = 0.5,
|
|
34
|
+
eta_0: float = 1e-2,
|
|
35
|
+
eta_1: float = 1e-1,
|
|
36
|
+
eta_2: float = 0.8,
|
|
37
|
+
lam_prox_min: float = 1e-3,
|
|
38
|
+
lam_prox_max: float = 1e4,
|
|
39
|
+
lam_cost_drop: int = -1,
|
|
40
|
+
lam_cost_relax: float = 1.0,
|
|
41
|
+
):
|
|
42
|
+
self.gamma_1 = gamma_1
|
|
43
|
+
self.gamma_2 = gamma_2
|
|
44
|
+
self.eta_0 = eta_0
|
|
45
|
+
self.eta_1 = eta_1
|
|
46
|
+
self.eta_2 = eta_2
|
|
47
|
+
self.lam_prox_min = lam_prox_min
|
|
48
|
+
self.lam_prox_max = lam_prox_max
|
|
49
|
+
self.lam_cost_drop = lam_cost_drop
|
|
50
|
+
self.lam_cost_relax = lam_cost_relax
|
|
51
|
+
|
|
52
|
+
@staticmethod
|
|
53
|
+
def _copy_virtual_weights(
|
|
54
|
+
candidate: "CandidateIterate",
|
|
55
|
+
state: "AlgorithmState",
|
|
56
|
+
) -> None:
|
|
57
|
+
candidate.lam_vc = state.lam_vc
|
|
58
|
+
candidate.lam_vb_nodal = state.lam_vb_nodal
|
|
59
|
+
candidate.lam_vb_cross = state.lam_vb_cross
|
|
60
|
+
|
|
61
|
+
def update_weights(
|
|
62
|
+
self,
|
|
63
|
+
state: "AlgorithmState",
|
|
64
|
+
candidate: "CandidateIterate",
|
|
65
|
+
nodal_constraints: "LoweredJaxConstraints",
|
|
66
|
+
settings: Config,
|
|
67
|
+
params: dict,
|
|
68
|
+
weights: "Weights",
|
|
69
|
+
) -> str:
|
|
70
|
+
"""Update SCP proximal weight based on acceptance ratio; keep VC/VB fixed."""
|
|
71
|
+
candidate_x_prop = (
|
|
72
|
+
candidate.x_prop_plus[1:] if candidate.x_prop_plus is not None else candidate.x_prop
|
|
73
|
+
)
|
|
74
|
+
(
|
|
75
|
+
nonlinear_cost,
|
|
76
|
+
nonlinear_penalty,
|
|
77
|
+
nodal_penalty,
|
|
78
|
+
) = self.calculate_nonlinear_penalty(
|
|
79
|
+
candidate_x_prop,
|
|
80
|
+
candidate.x,
|
|
81
|
+
candidate.u,
|
|
82
|
+
state.lam_vc,
|
|
83
|
+
state.lam_vb_nodal,
|
|
84
|
+
state.lam_vb_cross,
|
|
85
|
+
state.lam_cost,
|
|
86
|
+
nodal_constraints,
|
|
87
|
+
params,
|
|
88
|
+
settings,
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
candidate.J_nonlin = nonlinear_cost + nonlinear_penalty + nodal_penalty
|
|
92
|
+
|
|
93
|
+
if state.k > self.lam_cost_drop:
|
|
94
|
+
candidate.lam_cost = state.lam_cost * self.lam_cost_relax
|
|
95
|
+
else:
|
|
96
|
+
candidate.lam_cost = weights.lam_cost
|
|
97
|
+
|
|
98
|
+
lam_prox_k = deepcopy(state.lam_prox)
|
|
99
|
+
|
|
100
|
+
if state.k > 1:
|
|
101
|
+
state_x_prop_plus = state.x_prop_plus()
|
|
102
|
+
state_x_prop = (
|
|
103
|
+
state_x_prop_plus[1:] if state_x_prop_plus is not None else state.x_prop()
|
|
104
|
+
)
|
|
105
|
+
(
|
|
106
|
+
prev_nonlinear_cost,
|
|
107
|
+
prev_nonlinear_penalty,
|
|
108
|
+
prev_nodal_penalty,
|
|
109
|
+
) = self.calculate_nonlinear_penalty(
|
|
110
|
+
state_x_prop,
|
|
111
|
+
state.x,
|
|
112
|
+
state.u,
|
|
113
|
+
state.lam_vc,
|
|
114
|
+
state.lam_vb_nodal,
|
|
115
|
+
state.lam_vb_cross,
|
|
116
|
+
state.lam_cost,
|
|
117
|
+
nodal_constraints,
|
|
118
|
+
params,
|
|
119
|
+
settings,
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
J_nonlin_prev = prev_nonlinear_cost + prev_nonlinear_penalty + prev_nodal_penalty
|
|
123
|
+
|
|
124
|
+
actual_reduction = J_nonlin_prev - candidate.J_nonlin
|
|
125
|
+
predicted_reduction = J_nonlin_prev - candidate.J_lin
|
|
126
|
+
|
|
127
|
+
if predicted_reduction == 0:
|
|
128
|
+
raise ValueError("Predicted reduction is 0.")
|
|
129
|
+
|
|
130
|
+
rho = actual_reduction / predicted_reduction
|
|
131
|
+
|
|
132
|
+
state.pred_reduction_history.append(predicted_reduction)
|
|
133
|
+
state.actual_reduction_history.append(actual_reduction)
|
|
134
|
+
state.acceptance_ratio_history.append(rho)
|
|
135
|
+
|
|
136
|
+
if rho < self.eta_0:
|
|
137
|
+
lam_prox_k1 = np.minimum(self.lam_prox_max, self.gamma_1 * lam_prox_k)
|
|
138
|
+
candidate.lam_prox = lam_prox_k1
|
|
139
|
+
state.reject_solution(candidate)
|
|
140
|
+
adaptive_state = "Reject Higher"
|
|
141
|
+
elif rho >= self.eta_0 and rho < self.eta_1:
|
|
142
|
+
lam_prox_k1 = np.minimum(self.lam_prox_max, self.gamma_1 * lam_prox_k)
|
|
143
|
+
candidate.lam_prox = lam_prox_k1
|
|
144
|
+
self._copy_virtual_weights(candidate, state)
|
|
145
|
+
state.accept_solution(candidate)
|
|
146
|
+
adaptive_state = "Accept Higher"
|
|
147
|
+
elif rho >= self.eta_1 and rho < self.eta_2:
|
|
148
|
+
candidate.lam_prox = lam_prox_k
|
|
149
|
+
self._copy_virtual_weights(candidate, state)
|
|
150
|
+
state.accept_solution(candidate)
|
|
151
|
+
adaptive_state = "Accept Constant"
|
|
152
|
+
else:
|
|
153
|
+
lam_prox_k1 = np.maximum(self.lam_prox_min, self.gamma_2 * lam_prox_k)
|
|
154
|
+
candidate.lam_prox = lam_prox_k1
|
|
155
|
+
self._copy_virtual_weights(candidate, state)
|
|
156
|
+
state.accept_solution(candidate)
|
|
157
|
+
adaptive_state = "Accept Lower"
|
|
158
|
+
|
|
159
|
+
else:
|
|
160
|
+
candidate.lam_prox = lam_prox_k
|
|
161
|
+
self._copy_virtual_weights(candidate, state)
|
|
162
|
+
state.accept_solution(candidate)
|
|
163
|
+
adaptive_state = "Initial"
|
|
164
|
+
|
|
165
|
+
return adaptive_state
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
# =============================================================================
|
|
169
|
+
# Pydantic spec for dict / YAML validation
|
|
170
|
+
# =============================================================================
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
class AdaptiveProximalWeightSpec(BaseModel):
|
|
174
|
+
"""Validates AdaptiveProximalWeight configuration from dict/YAML input."""
|
|
175
|
+
|
|
176
|
+
type: Literal["AdaptiveProximalWeight"] = "AdaptiveProximalWeight"
|
|
177
|
+
gamma_1: float = 2.0
|
|
178
|
+
gamma_2: float = 0.5
|
|
179
|
+
eta_0: float = 1e-2
|
|
180
|
+
eta_1: float = 1e-1
|
|
181
|
+
eta_2: float = 0.8
|
|
182
|
+
lam_prox_min: float = 1e-3
|
|
183
|
+
lam_prox_max: float = 1e4
|
|
184
|
+
lam_cost_drop: int = -1
|
|
185
|
+
lam_cost_relax: float = 1.0
|
|
186
|
+
|
|
187
|
+
model_config = ConfigDict(extra="forbid")
|
|
188
|
+
|
|
189
|
+
def build(self) -> AdaptiveProximalWeight:
|
|
190
|
+
return AdaptiveProximalWeight(**self.model_dump(exclude={"type"}, exclude_unset=True))
|