openscvx 0.4.1.dev144__tar.gz → 0.4.1.dev146__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.
Files changed (312) hide show
  1. {openscvx-0.4.1.dev144/openscvx.egg-info → openscvx-0.4.1.dev146}/PKG-INFO +1 -1
  2. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/_version.py +3 -3
  3. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/algorithms/__init__.py +11 -3
  4. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/algorithms/augmented_lagrangian.py +7 -5
  5. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/algorithms/base.py +312 -13
  6. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/algorithms/optimization_results.py +1 -1
  7. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/algorithms/penalized_trust_region.py +50 -20
  8. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/algorithms/ramp_proximal_weight.py +4 -2
  9. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/lowered/cvxpy_variables.py +1 -1
  10. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/plotting/scp_iteration.py +3 -2
  11. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/problem.py +7 -3
  12. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/solvers/ptr_solver.py +5 -4
  13. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/symbolic/lower.py +1 -1
  14. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146/openscvx.egg-info}/PKG-INFO +1 -1
  15. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/tests/test_autotuning.py +35 -36
  16. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/tests/test_optimization_results.py +1 -1
  17. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/.github/assets/logo.svg +0 -0
  18. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/.github/release-drafter.yml +0 -0
  19. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/.github/workflows/_docs.yml +0 -0
  20. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/.github/workflows/branch-name.yml +0 -0
  21. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/.github/workflows/docs.yml +0 -0
  22. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/.github/workflows/lint.yml +0 -0
  23. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/.github/workflows/nightly.yml +0 -0
  24. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/.github/workflows/release-drafter.yml +0 -0
  25. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/.github/workflows/release.yml +0 -0
  26. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/.github/workflows/tests-integration.yml +0 -0
  27. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/.github/workflows/tests-unit.yml +0 -0
  28. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/.gitignore +0 -0
  29. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/CONTRIBUTING.md +0 -0
  30. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/LICENSE +0 -0
  31. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/README.md +0 -0
  32. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/docs/Foundations/constraint_reformulation.md +0 -0
  33. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/docs/Foundations/control_parameterization.md +0 -0
  34. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/docs/Foundations/discretization.md +0 -0
  35. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/docs/Foundations/ocp.md +0 -0
  36. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/docs/Foundations/scvx.md +0 -0
  37. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/docs/Foundations/time_dilation.md +0 -0
  38. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/docs/UnderTheHood/lowering_architecture.md +0 -0
  39. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/docs/UnderTheHood/vectorization_and_vmapping.md +0 -0
  40. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/docs/UsersGuide/00_introduction.md +0 -0
  41. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/docs/UsersGuide/01_hello_world_brachistochrone.md +0 -0
  42. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/docs/UsersGuide/02_drone_racing_constraints.md +0 -0
  43. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/docs/UsersGuide/03_obstacle_avoidance_vmap.md +0 -0
  44. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/docs/UsersGuide/04_viewpoint_constraints.md +0 -0
  45. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/docs/UsersGuide/05_visualization.md +0 -0
  46. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/docs/UsersGuide/06_logic.md +0 -0
  47. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/docs/UsersGuide/07_lie.md +0 -0
  48. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/docs/assets/favicon.png +0 -0
  49. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/docs/assets/images/ct-scvx_dark.png +0 -0
  50. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/docs/assets/images/ct-scvx_light.png +0 -0
  51. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/docs/assets/images/ctcs_dark.png +0 -0
  52. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/docs/assets/images/ctcs_light.png +0 -0
  53. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/docs/assets/images/problem_class_dark.png +0 -0
  54. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/docs/assets/images/problem_class_light.png +0 -0
  55. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/docs/assets/logo.svg +0 -0
  56. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/docs/citation.md +0 -0
  57. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/docs/examples.md +0 -0
  58. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/docs/getting-started.md +0 -0
  59. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/docs/index.md +0 -0
  60. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/docs/javascripts/mathjax.js +0 -0
  61. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/examples/abstract/brachistochrone.py +0 -0
  62. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/examples/abstract/impulsive.py +0 -0
  63. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/examples/arm/three_link_arm.py +0 -0
  64. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/examples/car/dubins_car.py +0 -0
  65. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/examples/car/dubins_car_conditional.py +0 -0
  66. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/examples/car/dubins_car_disjoint.py +0 -0
  67. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/examples/car/dubins_car_stljax.py +0 -0
  68. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/examples/drone/cinema_vp.py +0 -0
  69. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/examples/drone/dr_double_integrator.py +0 -0
  70. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/examples/drone/dr_vp.py +0 -0
  71. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/examples/drone/dr_vp_nodal.py +0 -0
  72. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/examples/drone/dr_vp_polytope.py +0 -0
  73. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/examples/drone/drone_racing.py +0 -0
  74. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/examples/drone/logo.py +0 -0
  75. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/examples/drone/logo_utils/acl_logo.svg +0 -0
  76. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/examples/drone/logo_utils/svg_path_utils.py +0 -0
  77. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/examples/drone/obstacle_avoidance.py +0 -0
  78. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/examples/drone/obstacle_avoidance_nodal.py +0 -0
  79. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/examples/drone/obstacle_avoidance_vmap.py +0 -0
  80. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/examples/plotting.py +0 -0
  81. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/examples/plotting_viser.py +0 -0
  82. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/examples/realtime/base_problems/cinema_vp_realtime_base.py +0 -0
  83. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/examples/realtime/base_problems/drone_racing_realtime_base.py +0 -0
  84. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/examples/realtime/base_problems/obstacle_avoidance_realtime_base.py +0 -0
  85. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/examples/realtime/cinema_vp_realtime.py +0 -0
  86. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/examples/realtime/drone_racing_realtime.py +0 -0
  87. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/examples/realtime/dubins_car_realtime.py +0 -0
  88. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/examples/realtime/obstacle_avoidance_realtime.py +0 -0
  89. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/examples/rocket/3DoF_pdg.py +0 -0
  90. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/examples/spacecraft/hohmann_transfer.py +0 -0
  91. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/examples/spacecraft/proxops_cw.py +0 -0
  92. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/figures/ctlos_cine.gif +0 -0
  93. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/figures/ctlos_dr.gif +0 -0
  94. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/figures/dtlos_cine.gif +0 -0
  95. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/figures/dtlos_dr.gif +0 -0
  96. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/figures/openscvx_logo.svg +0 -0
  97. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/figures/openscvx_logo_square.png +0 -0
  98. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/figures/oscvx_structure_full_dark.svg +0 -0
  99. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/figures/video_preview.png +0 -0
  100. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/material/__init__.py +0 -0
  101. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/material/overrides/assets/images/layers/1-background.avif +0 -0
  102. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/material/overrides/assets/images/layers/1-background@1x.avif +0 -0
  103. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/material/overrides/assets/images/layers/1-background@2x.avif +0 -0
  104. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/material/overrides/assets/images/layers/1-background@3x.avif +0 -0
  105. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/material/overrides/assets/images/layers/1-background@4x.avif +0 -0
  106. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/material/overrides/assets/images/layers/2-mars.avif +0 -0
  107. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/material/overrides/assets/images/layers/2-mars@1x.avif +0 -0
  108. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/material/overrides/assets/images/layers/2-mars@2x.avif +0 -0
  109. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/material/overrides/assets/images/layers/2-mars@3x.avif +0 -0
  110. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/material/overrides/assets/images/layers/2-mars@4x.avif +0 -0
  111. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/material/overrides/assets/images/layers/3-moon.avif +0 -0
  112. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/material/overrides/assets/images/layers/3-moon@1x.avif +0 -0
  113. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/material/overrides/assets/images/layers/3-moon@2x.avif +0 -0
  114. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/material/overrides/assets/images/layers/3-moon@3x.avif +0 -0
  115. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/material/overrides/assets/images/layers/3-moon@4x.avif +0 -0
  116. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/material/overrides/assets/images/layers/4-sat1.avif +0 -0
  117. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/material/overrides/assets/images/layers/4-sat1@1x.avif +0 -0
  118. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/material/overrides/assets/images/layers/4-sat1@2x.avif +0 -0
  119. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/material/overrides/assets/images/layers/4-sat1@3x.avif +0 -0
  120. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/material/overrides/assets/images/layers/4-sat1@4x.avif +0 -0
  121. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/material/overrides/assets/images/layers/5-space.avif +0 -0
  122. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/material/overrides/assets/images/layers/5-space@1x.avif +0 -0
  123. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/material/overrides/assets/images/layers/5-space@2x.avif +0 -0
  124. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/material/overrides/assets/images/layers/5-space@3x.avif +0 -0
  125. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/material/overrides/assets/images/layers/5-space@4x.avif +0 -0
  126. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/material/overrides/assets/images/layers/6-earth.avif +0 -0
  127. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/material/overrides/assets/images/layers/6-earth@1x.avif +0 -0
  128. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/material/overrides/assets/images/layers/6-earth@2x.avif +0 -0
  129. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/material/overrides/assets/images/layers/6-earth@3x.avif +0 -0
  130. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/material/overrides/assets/images/layers/6-earth@4x.avif +0 -0
  131. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/material/overrides/assets/javascripts/parallax.js +0 -0
  132. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/material/overrides/assets/logo.svg +0 -0
  133. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/material/overrides/assets/stylesheets/custom.css +0 -0
  134. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/material/overrides/assets/stylesheets/parallax.css +0 -0
  135. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/material/overrides/home.html +0 -0
  136. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/material/overrides/main.html +0 -0
  137. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/material/overrides/partials/parallax/hero.html +0 -0
  138. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/material/overrides/partials/parallax.html +0 -0
  139. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/mkdocs.yml +0 -0
  140. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/__init__.py +0 -0
  141. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/__main__.py +0 -0
  142. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/algorithms/constant_proximal_weight.py +0 -0
  143. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/config.py +0 -0
  144. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/discretization/__init__.py +0 -0
  145. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/discretization/base.py +0 -0
  146. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/discretization/linearize_discretize.py +0 -0
  147. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/expert/__init__.py +0 -0
  148. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/expert/byof.py +0 -0
  149. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/expert/lowering.py +0 -0
  150. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/expert/validation.py +0 -0
  151. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/init/__init__.py +0 -0
  152. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/init/interpolation.py +0 -0
  153. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/integrators/__init__.py +0 -0
  154. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/integrators/runge_kutta.py +0 -0
  155. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/loader.py +0 -0
  156. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/lowered/__init__.py +0 -0
  157. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/lowered/cvxpy_constraints.py +0 -0
  158. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/lowered/dynamics.py +0 -0
  159. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/lowered/jax_constraints.py +0 -0
  160. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/lowered/parameters.py +0 -0
  161. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/lowered/problem.py +0 -0
  162. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/lowered/unified.py +0 -0
  163. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/plotting/__init__.py +0 -0
  164. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/plotting/plotting.py +0 -0
  165. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/plotting/viser/__init__.py +0 -0
  166. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/plotting/viser/animated.py +0 -0
  167. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/plotting/viser/orbits.py +0 -0
  168. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/plotting/viser/plotly_integration.py +0 -0
  169. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/plotting/viser/primitives.py +0 -0
  170. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/plotting/viser/scp.py +0 -0
  171. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/plotting/viser/server.py +0 -0
  172. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/propagation/__init__.py +0 -0
  173. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/propagation/post_processing.py +0 -0
  174. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/propagation/propagation.py +0 -0
  175. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/solvers/__init__.py +0 -0
  176. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/solvers/base.py +0 -0
  177. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/symbolic/__init__.py +0 -0
  178. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/symbolic/augmentation.py +0 -0
  179. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/symbolic/builder.py +0 -0
  180. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/symbolic/constraint_set.py +0 -0
  181. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/symbolic/expr/__init__.py +0 -0
  182. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/symbolic/expr/arithmetic.py +0 -0
  183. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/symbolic/expr/array.py +0 -0
  184. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/symbolic/expr/constraint.py +0 -0
  185. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/symbolic/expr/control.py +0 -0
  186. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/symbolic/expr/expr.py +0 -0
  187. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/symbolic/expr/lie/__init__.py +0 -0
  188. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/symbolic/expr/lie/adjoint.py +0 -0
  189. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/symbolic/expr/lie/se3.py +0 -0
  190. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/symbolic/expr/lie/so3.py +0 -0
  191. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/symbolic/expr/linalg.py +0 -0
  192. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/symbolic/expr/logic.py +0 -0
  193. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/symbolic/expr/math.py +0 -0
  194. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/symbolic/expr/spatial.py +0 -0
  195. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/symbolic/expr/state.py +0 -0
  196. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/symbolic/expr/stl.py +0 -0
  197. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/symbolic/expr/time.py +0 -0
  198. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/symbolic/expr/variable.py +0 -0
  199. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/symbolic/expr/vmap.py +0 -0
  200. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/symbolic/hashing.py +0 -0
  201. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/symbolic/lowerers/__init__.py +0 -0
  202. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/symbolic/lowerers/cvxpy/__init__.py +0 -0
  203. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/symbolic/lowerers/cvxpy/_lowerer.py +0 -0
  204. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/symbolic/lowerers/cvxpy/_registry.py +0 -0
  205. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/symbolic/lowerers/cvxpy/arithmetic.py +0 -0
  206. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/symbolic/lowerers/cvxpy/array.py +0 -0
  207. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/symbolic/lowerers/cvxpy/constraint.py +0 -0
  208. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/symbolic/lowerers/cvxpy/control.py +0 -0
  209. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/symbolic/lowerers/cvxpy/expr.py +0 -0
  210. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/symbolic/lowerers/cvxpy/linalg.py +0 -0
  211. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/symbolic/lowerers/cvxpy/logic.py +0 -0
  212. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/symbolic/lowerers/cvxpy/math.py +0 -0
  213. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/symbolic/lowerers/cvxpy/state.py +0 -0
  214. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/symbolic/lowerers/jax/__init__.py +0 -0
  215. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/symbolic/lowerers/jax/_lowerer.py +0 -0
  216. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/symbolic/lowerers/jax/_registry.py +0 -0
  217. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/symbolic/lowerers/jax/arithmetic.py +0 -0
  218. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/symbolic/lowerers/jax/array.py +0 -0
  219. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/symbolic/lowerers/jax/constraint.py +0 -0
  220. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/symbolic/lowerers/jax/control.py +0 -0
  221. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/symbolic/lowerers/jax/expr.py +0 -0
  222. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/symbolic/lowerers/jax/lie.py +0 -0
  223. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/symbolic/lowerers/jax/linalg.py +0 -0
  224. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/symbolic/lowerers/jax/logic.py +0 -0
  225. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/symbolic/lowerers/jax/math.py +0 -0
  226. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/symbolic/lowerers/jax/spatial.py +0 -0
  227. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/symbolic/lowerers/jax/state.py +0 -0
  228. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/symbolic/lowerers/jax/stl.py +0 -0
  229. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/symbolic/lowerers/jax/vmap.py +0 -0
  230. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/symbolic/parser/__init__.py +0 -0
  231. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/symbolic/parser/_registry.py +0 -0
  232. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/symbolic/parser/array.py +0 -0
  233. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/symbolic/parser/constraint.py +0 -0
  234. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/symbolic/parser/lie.py +0 -0
  235. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/symbolic/parser/linalg.py +0 -0
  236. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/symbolic/parser/logic.py +0 -0
  237. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/symbolic/parser/math.py +0 -0
  238. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/symbolic/parser/parser.py +0 -0
  239. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/symbolic/parser/spatial.py +0 -0
  240. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/symbolic/parser/stl.py +0 -0
  241. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/symbolic/parser/tokenizer.py +0 -0
  242. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/symbolic/preprocessing.py +0 -0
  243. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/symbolic/problem.py +0 -0
  244. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/symbolic/sparsity.py +0 -0
  245. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/symbolic/unified.py +0 -0
  246. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/utils/__init__.py +0 -0
  247. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/utils/cache.py +0 -0
  248. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/utils/caching.py +0 -0
  249. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/utils/printing.py +0 -0
  250. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/utils/profiling.py +0 -0
  251. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx/utils/utils.py +0 -0
  252. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx.egg-info/SOURCES.txt +0 -0
  253. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx.egg-info/dependency_links.txt +0 -0
  254. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx.egg-info/entry_points.txt +0 -0
  255. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx.egg-info/requires.txt +0 -0
  256. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/openscvx.egg-info/top_level.txt +0 -0
  257. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/pyproject.toml +0 -0
  258. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/scripts/gen_example_pages.py +0 -0
  259. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/scripts/gen_ref_pages.py +0 -0
  260. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/setup.cfg +0 -0
  261. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/tests/__init__.py +0 -0
  262. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/tests/brachistochrone_analytical.py +0 -0
  263. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/tests/fixtures/brachistochrone.json +0 -0
  264. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/tests/fixtures/brachistochrone.yaml +0 -0
  265. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/tests/hohmann_analytical.py +0 -0
  266. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/tests/symbolic/__init__.py +0 -0
  267. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/tests/symbolic/expr/__init__.py +0 -0
  268. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/tests/symbolic/expr/test_arithmetic.py +0 -0
  269. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/tests/symbolic/expr/test_array.py +0 -0
  270. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/tests/symbolic/expr/test_constraint.py +0 -0
  271. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/tests/symbolic/expr/test_expr.py +0 -0
  272. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/tests/symbolic/expr/test_lie.py +0 -0
  273. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/tests/symbolic/expr/test_linalg.py +0 -0
  274. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/tests/symbolic/expr/test_logic.py +0 -0
  275. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/tests/symbolic/expr/test_math.py +0 -0
  276. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/tests/symbolic/expr/test_node_reference.py +0 -0
  277. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/tests/symbolic/expr/test_parameters.py +0 -0
  278. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/tests/symbolic/expr/test_scaling.py +0 -0
  279. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/tests/symbolic/expr/test_spatial.py +0 -0
  280. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/tests/symbolic/expr/test_variable.py +0 -0
  281. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/tests/symbolic/expr/test_vmap.py +0 -0
  282. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/tests/symbolic/parser/__init__.py +0 -0
  283. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/tests/symbolic/parser/test_array.py +0 -0
  284. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/tests/symbolic/parser/test_constraint.py +0 -0
  285. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/tests/symbolic/parser/test_lie.py +0 -0
  286. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/tests/symbolic/parser/test_linalg.py +0 -0
  287. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/tests/symbolic/parser/test_load.py +0 -0
  288. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/tests/symbolic/parser/test_logic.py +0 -0
  289. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/tests/symbolic/parser/test_math.py +0 -0
  290. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/tests/symbolic/parser/test_parser.py +0 -0
  291. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/tests/symbolic/parser/test_spatial.py +0 -0
  292. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/tests/symbolic/parser/test_stl.py +0 -0
  293. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/tests/symbolic/parser/test_tokenizer.py +0 -0
  294. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/tests/symbolic/parser/test_vmap.py +0 -0
  295. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/tests/symbolic/test_augmentation.py +0 -0
  296. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/tests/symbolic/test_hashing.py +0 -0
  297. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/tests/symbolic/test_lower_cvxpy.py +0 -0
  298. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/tests/symbolic/test_lower_jax.py +0 -0
  299. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/tests/symbolic/test_preprocessing.py +0 -0
  300. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/tests/symbolic/test_sparsity.py +0 -0
  301. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/tests/symbolic/test_unified.py +0 -0
  302. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/tests/test_brachistochrone.py +0 -0
  303. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/tests/test_cvxpygen_optional.py +0 -0
  304. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/tests/test_discretization.py +0 -0
  305. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/tests/test_examples.py +0 -0
  306. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/tests/test_expert.py +0 -0
  307. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/tests/test_impulsive.py +0 -0
  308. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/tests/test_init.py +0 -0
  309. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/tests/test_integrators.py +0 -0
  310. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/tests/test_loader.py +0 -0
  311. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/tests/test_plotting.py +0 -0
  312. {openscvx-0.4.1.dev144 → openscvx-0.4.1.dev146}/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.dev144
3
+ Version: 0.4.1.dev146
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.dev144'
32
- __version_tuple__ = version_tuple = (0, 4, 1, 'dev144')
31
+ __version__ = version = '0.4.1.dev146'
32
+ __version_tuple__ = version_tuple = (0, 4, 1, 'dev146')
33
33
 
34
- __commit_id__ = commit_id = 'g137ef78b8'
34
+ __commit_id__ = commit_id = 'g66b4191a1'
@@ -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(kwargs: dict, states: list = None) -> "PenalizedTrustRegion":
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 immediately.
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 lam_cost can be expanded eagerly
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: float,
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
- scale = self.eta_lambda * (1 / (2 * lam_prox))
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 = min(self.lam_prox_max, self.gamma_1 * lam_prox_k)
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 = min(self.lam_prox_max, self.gamma_1 * lam_prox_k)
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 = max(self.lam_prox_min, self.gamma_2 * lam_prox_k)
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
 
@@ -101,6 +102,207 @@ def _expand_lam_cost_dict(
101
102
  return lam_arr
102
103
 
103
104
 
105
+ def _expand_lam_vc_dict(
106
+ lam_vc_dict: Dict[str, Union[float, list, np.ndarray]],
107
+ states: List["State"],
108
+ ) -> np.ndarray:
109
+ """Expand a ``{state_name: weight}`` dict to a per-state VC weight array.
110
+
111
+ Maps user-provided per-state virtual control weights to a dense array
112
+ using each state's ``_slice``. States not present in the dict default
113
+ to ``1.0`` (neutral weight — dynamics violations are still penalised at
114
+ the base rate).
115
+
116
+ Per-state values may be:
117
+
118
+ * **scalar** — broadcast to every component and every node.
119
+ * **1-D array** of length ``n_components`` — per-component weight,
120
+ same for every node.
121
+ * **2-D array** of shape ``(K, n_components)`` — per-node-per-component.
122
+ When any state supplies a 2-D value the output is 2-D with first
123
+ dimension *K* (all 2-D entries must agree on *K*).
124
+
125
+ Args:
126
+ lam_vc_dict: Mapping from state names to VC weights.
127
+ states: List of State objects (must already have ``_slice`` assigned).
128
+
129
+ Returns:
130
+ np.ndarray of shape ``(n_states,)`` when all entries are scalar/1-D,
131
+ or ``(K, n_states)`` when any entry is 2-D.
132
+
133
+ Raises:
134
+ ValueError: If the dict contains unknown state names or 2-D entries
135
+ disagree on the number of nodes.
136
+ """
137
+ n_states = sum(s.shape[0] if len(s.shape) > 0 else 1 for s in states)
138
+
139
+ valid_names = {s.name for s in states}
140
+ unknown = set(lam_vc_dict.keys()) - valid_names
141
+ if unknown:
142
+ raise ValueError(
143
+ f"lam_vc dict contains unknown state name(s): {unknown}. "
144
+ f"Valid state names: {sorted(valid_names)}"
145
+ )
146
+
147
+ # First pass: determine if any entry is 2-D and infer K.
148
+ n_nodes: Optional[int] = None
149
+ for state in states:
150
+ if state.name not in lam_vc_dict:
151
+ continue
152
+ val = np.asarray(lam_vc_dict[state.name], dtype=float)
153
+ if val.ndim == 2:
154
+ if n_nodes is None:
155
+ n_nodes = val.shape[0]
156
+ elif val.shape[0] != n_nodes:
157
+ raise ValueError(
158
+ f"lam_vc['{state.name}'] has {val.shape[0]} rows, but a "
159
+ f"previous entry had {n_nodes} rows. All 2-D entries "
160
+ f"must have the same number of rows (n_nodes-1)."
161
+ )
162
+
163
+ # Build the output array.
164
+ if n_nodes is not None:
165
+ lam_arr = np.ones((n_nodes, n_states))
166
+ else:
167
+ lam_arr = np.ones(n_states)
168
+
169
+ for state in states:
170
+ if state.name not in lam_vc_dict:
171
+ continue
172
+ val = np.asarray(lam_vc_dict[state.name], dtype=float)
173
+ n_components = state.shape[0] if len(state.shape) > 0 else 1
174
+
175
+ if val.ndim == 0:
176
+ # Scalar — broadcast to all components (and all nodes if 2-D).
177
+ lam_arr[..., state._slice] = float(val)
178
+ elif val.ndim == 1:
179
+ if val.shape[0] != n_components:
180
+ raise ValueError(
181
+ f"lam_vc['{state.name}'] has length {val.shape[0]}, "
182
+ f"expected scalar or length {n_components}"
183
+ )
184
+ lam_arr[..., state._slice] = val
185
+ elif val.ndim == 2:
186
+ if val.shape[1] != n_components:
187
+ raise ValueError(
188
+ f"lam_vc['{state.name}'] has {val.shape[1]} columns, expected {n_components}"
189
+ )
190
+ lam_arr[:, state._slice] = val
191
+ else:
192
+ raise ValueError(
193
+ f"lam_vc['{state.name}'] has {val.ndim} dimensions, expected scalar, 1-D, or 2-D"
194
+ )
195
+
196
+ return lam_arr
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
+
104
306
  @dataclass
105
307
  class Weights:
106
308
  """Normalized SCP weights used internally by the algorithm and autotuner.
@@ -120,8 +322,13 @@ class Weights:
120
322
  drift.
121
323
 
122
324
  Attributes:
123
- lam_prox: Trust region (proximal) weight (normalized).
124
- lam_vc: Virtual control penalty 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.
329
+ lam_vc: Virtual control penalty weight (normalized). Scalar or
330
+ array of shape ``(n_states,)`` or ``(n_nodes-1, n_states)``
331
+ for per-state / per-node weighting.
125
332
  lam_cost: Cost weight per state (normalized). Scalar or array of
126
333
  shape ``(n_states,)`` for per-state weighting.
127
334
  lam_vb: Global virtual buffer penalty weight (normalized). Scalar
@@ -135,8 +342,8 @@ class Weights:
135
342
  :meth:`set_vb_arrays`.
136
343
  """
137
344
 
138
- lam_prox: float = 1e0
139
- lam_vc: float = 1e1
345
+ lam_prox: Union[float, np.ndarray] = 1e0
346
+ lam_vc: Union[float, np.ndarray] = 1e1
140
347
  lam_cost: Union[float, np.ndarray] = 1e-1
141
348
  lam_vb: float = 0.0
142
349
  lam_vb_nodal: Optional[np.ndarray] = None
@@ -144,12 +351,20 @@ class Weights:
144
351
 
145
352
  def __post_init__(self):
146
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)
356
+ if isinstance(self.lam_vc, (list, tuple)):
357
+ self.lam_vc = np.asarray(self.lam_vc, dtype=float)
147
358
  if isinstance(self.lam_cost, (list, tuple)):
148
359
  self.lam_cost = np.asarray(self.lam_cost, dtype=float)
149
360
 
150
361
  # Snapshot the user-specified values so normalize() is idempotent.
151
- self._raw_lam_prox = self.lam_prox
152
- self._raw_lam_vc = self.lam_vc
362
+ self._raw_lam_prox = (
363
+ self.lam_prox.copy() if isinstance(self.lam_prox, np.ndarray) else self.lam_prox
364
+ )
365
+ self._raw_lam_vc = (
366
+ self.lam_vc.copy() if isinstance(self.lam_vc, np.ndarray) else self.lam_vc
367
+ )
153
368
  self._raw_lam_cost = (
154
369
  self.lam_cost.copy() if isinstance(self.lam_cost, np.ndarray) else self.lam_cost
155
370
  )
@@ -164,6 +379,16 @@ class Weights:
164
379
  making this method idempotent and safe to call after updating
165
380
  any individual raw weight.
166
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
+ )
387
+ raw_vc_max = (
388
+ float(np.max(self._raw_lam_vc))
389
+ if isinstance(self._raw_lam_vc, np.ndarray)
390
+ else self._raw_lam_vc
391
+ )
167
392
  raw_cost_max = (
168
393
  float(np.max(self._raw_lam_cost))
169
394
  if isinstance(self._raw_lam_cost, np.ndarray)
@@ -176,7 +401,7 @@ class Weights:
176
401
  )
177
402
  else:
178
403
  raw_vb_max = self._raw_lam_vb
179
- scale = max(self._raw_lam_prox, self._raw_lam_vc, raw_cost_max, raw_vb_max)
404
+ scale = max(raw_prox_max, raw_vc_max, raw_cost_max, raw_vb_max)
180
405
  if scale > 0:
181
406
  self.lam_prox = self._raw_lam_prox / scale
182
407
  self.lam_vc = self._raw_lam_vc / scale
@@ -509,7 +734,7 @@ class AlgorithmState:
509
734
  lam_cost_history: List[Union[float, np.ndarray]] = field(default_factory=list)
510
735
  lam_vb_nodal_history: List[np.ndarray] = field(default_factory=list)
511
736
  lam_vb_cross_history: List[np.ndarray] = field(default_factory=list)
512
- lam_prox_history: List[float] = field(default_factory=list)
737
+ lam_prox_history: List[np.ndarray] = field(default_factory=list)
513
738
  x_full: List[np.ndarray] = field(default_factory=list)
514
739
  x_prop_full: List[np.ndarray] = field(default_factory=list)
515
740
 
@@ -715,11 +940,11 @@ class AlgorithmState:
715
940
  return self.discretizations[index].E_d
716
941
 
717
942
  @property
718
- def lam_prox(self) -> float:
943
+ def lam_prox(self) -> np.ndarray:
719
944
  """Get current trust region weight.
720
945
 
721
946
  Returns:
722
- Current trust region weight (latest entry in lam_prox_history)
947
+ Array of shape ``(N, n_states + n_controls)``.
723
948
  """
724
949
  if not self.lam_prox_history:
725
950
  raise ValueError("lam_prox_history is empty. Initialize state using from_settings().")
@@ -787,16 +1012,22 @@ class AlgorithmState:
787
1012
 
788
1013
  Args:
789
1014
  settings: Configuration object containing initial guesses and SCP parameters
790
- weights: Normalized initial weights from the algorithm. The scalar
791
- ``lam_vc`` is expanded to an ``(N-1, n_states)`` array here.
1015
+ weights: Normalized initial weights from the algorithm.
1016
+ ``lam_vc`` is expanded to an ``(N-1, n_states)`` array here
1017
+ (scalar or per-state values are broadcast).
792
1018
 
793
1019
  Returns:
794
1020
  Fresh AlgorithmState initialized from settings with copied arrays
795
1021
  """
796
1022
  n = settings.sim.n
797
1023
  n_states = settings.sim.n_states
1024
+ n_controls = settings.sim.n_controls
1025
+ n_total = n_states + n_controls
798
1026
  lam_vc_array = np.ones((n - 1, n_states)) * weights.lam_vc
799
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
+
800
1031
  # Expand scalar lam_cost to per-state array
801
1032
  if isinstance(weights.lam_cost, np.ndarray):
802
1033
  lam_cost_init = weights.lam_cost.copy()
@@ -825,7 +1056,7 @@ class AlgorithmState:
825
1056
  lam_cost_history=[lam_cost_init],
826
1057
  lam_vb_nodal_history=[weights.lam_vb_nodal.copy()],
827
1058
  lam_vb_cross_history=[weights.lam_vb_cross.copy()],
828
- lam_prox_history=[weights.lam_prox],
1059
+ lam_prox_history=[lam_prox_array],
829
1060
  )
830
1061
 
831
1062
 
@@ -883,6 +1114,41 @@ class Algorithm(ABC):
883
1114
  #: Maximum number of SCP iterations. Subclasses must set this in ``__init__``.
884
1115
  k_max: int
885
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
+
886
1152
  @staticmethod
887
1153
  def _resolve_lam_cost(
888
1154
  lam_cost: Union[float, Dict[str, float]],
@@ -915,6 +1181,39 @@ class Algorithm(ABC):
915
1181
  return _expand_lam_cost_dict(lam_cost, states)
916
1182
  return lam_cost
917
1183
 
1184
+ @staticmethod
1185
+ def _resolve_lam_vc(
1186
+ lam_vc: Union[float, Dict[str, Union[float, list, np.ndarray]]],
1187
+ states: Optional[List["State"]] = None,
1188
+ ) -> Union[float, np.ndarray]:
1189
+ """Resolve a ``lam_vc`` spec to a numeric value.
1190
+
1191
+ If *lam_vc* is a float it is returned as-is. If it is a dict
1192
+ mapping state names to weights, *states* must be provided so the
1193
+ dict can be expanded to a per-state array via
1194
+ :func:`_expand_lam_vc_dict`.
1195
+
1196
+ Args:
1197
+ lam_vc: Scalar weight or ``{state_name: weight}`` dict.
1198
+ states: Symbolic State objects (required when *lam_vc* is a dict).
1199
+
1200
+ Returns:
1201
+ float or np.ndarray of shape ``(n_states,)`` or
1202
+ ``(K, n_states)``.
1203
+
1204
+ Raises:
1205
+ ValueError: If *lam_vc* is a dict and *states* is ``None``.
1206
+ """
1207
+ if isinstance(lam_vc, dict):
1208
+ if states is None:
1209
+ raise ValueError(
1210
+ "lam_vc was specified as a dict but no states were "
1211
+ "provided. Pass states so the dict can be expanded to "
1212
+ "a per-state weight array."
1213
+ )
1214
+ return _expand_lam_vc_dict(lam_vc, states)
1215
+ return lam_vc
1216
+
918
1217
  def _resolve_lam_vb(
919
1218
  self,
920
1219
  N: int,
@@ -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[float] = field(default_factory=list, metadata={"npz": "float_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
  )