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