openscvx 0.5.3.dev15__tar.gz → 0.5.3.dev17__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 (388) hide show
  1. {openscvx-0.5.3.dev15/openscvx.egg-info → openscvx-0.5.3.dev17}/PKG-INFO +1 -1
  2. openscvx-0.5.3.dev17/docs/UnderTheHood/batching_jit_grad.md +134 -0
  3. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/docs/UnderTheHood/lowering_architecture.md +23 -8
  4. openscvx-0.5.3.dev17/examples/abstract/brachistochrone_batched.py +126 -0
  5. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/mkdocs.yml +2 -1
  6. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/_version.py +3 -3
  7. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/algorithms/base.py +39 -7
  8. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/algorithms/optimization_results.py +233 -1
  9. openscvx-0.5.3.dev17/openscvx/algorithms/scvx/iteration.py +386 -0
  10. openscvx-0.5.3.dev17/openscvx/algorithms/scvx/penalized_trust_region.py +330 -0
  11. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/problem.py +191 -96
  12. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/solvers/cvxpy_ptr_solver.py +33 -2
  13. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/solvers/moreau_ptr_solver.py +16 -3
  14. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/solvers/qpax_ptr_solver.py +37 -26
  15. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/utils/caching.py +25 -17
  16. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17/openscvx.egg-info}/PKG-INFO +1 -1
  17. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx.egg-info/SOURCES.txt +11 -0
  18. openscvx-0.5.3.dev17/tests/algorithms/_iteration_helpers.py +27 -0
  19. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/tests/algorithms/autotuner/test_update_weights_jit.py +1 -0
  20. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/tests/algorithms/test_algorithm_state_pytree.py +1 -0
  21. openscvx-0.5.3.dev17/tests/algorithms/test_iteration_fn_jit.py +47 -0
  22. openscvx-0.5.3.dev17/tests/algorithms/test_iteration_fn_parity.py +64 -0
  23. openscvx-0.5.3.dev17/tests/algorithms/test_make_solve_loop.py +41 -0
  24. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/tests/solvers/_iteration_callback_helpers.py +86 -0
  25. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/tests/solvers/test_iteration_callback_moreau.py +5 -4
  26. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/tests/solvers/test_iteration_callback_qpax.py +12 -11
  27. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/tests/solvers/test_iteration_callback_vmap.py +3 -2
  28. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/tests/solvers/test_moreau_ptr_solver.py +3 -1
  29. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/tests/solvers/test_qpax_ptr_solver.py +9 -3
  30. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/tests/test_autotuning.py +1 -0
  31. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/tests/test_brachistochrone.py +11 -22
  32. openscvx-0.5.3.dev17/tests/test_solve_jax_bare_brachistochrone.py +70 -0
  33. openscvx-0.5.3.dev17/tests/test_solve_jax_jit_brachistochrone.py +36 -0
  34. openscvx-0.5.3.dev17/tests/test_solve_jax_vmap_brachistochrone.py +51 -0
  35. openscvx-0.5.3.dev17/tests/test_solve_jax_vmap_converged_no_drift.py +128 -0
  36. openscvx-0.5.3.dev15/openscvx/algorithms/scvx/penalized_trust_region.py +0 -794
  37. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/.github/assets/logo.svg +0 -0
  38. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/.github/release-drafter.yml +0 -0
  39. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/.github/workflows/_docs.yml +0 -0
  40. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/.github/workflows/branch-name.yml +0 -0
  41. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/.github/workflows/docs.yml +0 -0
  42. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/.github/workflows/lint.yml +0 -0
  43. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/.github/workflows/nightly.yml +0 -0
  44. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/.github/workflows/release-drafter.yml +0 -0
  45. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/.github/workflows/release.yml +0 -0
  46. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/.github/workflows/tests-integration.yml +0 -0
  47. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/.github/workflows/tests-unit.yml +0 -0
  48. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/.gitignore +0 -0
  49. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/.gitmodules +0 -0
  50. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/CONTRIBUTING.md +0 -0
  51. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/LICENSE +0 -0
  52. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/README.md +0 -0
  53. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/docs/Foundations/constraint_reformulation.md +0 -0
  54. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/docs/Foundations/control_parameterization.md +0 -0
  55. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/docs/Foundations/discretization.md +0 -0
  56. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/docs/Foundations/ocp.md +0 -0
  57. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/docs/Foundations/scvx.md +0 -0
  58. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/docs/Foundations/time_dilation.md +0 -0
  59. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/docs/UnderTheHood/vectorization_and_vmapping.md +0 -0
  60. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/docs/UsersGuide/00_introduction.md +0 -0
  61. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/docs/UsersGuide/01_hello_world_brachistochrone.md +0 -0
  62. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/docs/UsersGuide/02_drone_racing_constraints.md +0 -0
  63. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/docs/UsersGuide/03_obstacle_avoidance_vmap.md +0 -0
  64. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/docs/UsersGuide/04_viewpoint_constraints.md +0 -0
  65. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/docs/UsersGuide/05_visualization.md +0 -0
  66. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/docs/UsersGuide/06_logic.md +0 -0
  67. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/docs/UsersGuide/07_lie.md +0 -0
  68. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/docs/UsersGuide/08_mpcc.md +0 -0
  69. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/docs/UsersGuide/09_mjx_dynamics.md +0 -0
  70. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/docs/assets/favicon.png +0 -0
  71. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/docs/assets/images/ct-scvx_dark.png +0 -0
  72. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/docs/assets/images/ct-scvx_light.png +0 -0
  73. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/docs/assets/images/ctcs_dark.png +0 -0
  74. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/docs/assets/images/ctcs_light.png +0 -0
  75. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/docs/assets/images/problem_class_dark.png +0 -0
  76. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/docs/assets/images/problem_class_light.png +0 -0
  77. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/docs/assets/logo.svg +0 -0
  78. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/docs/assets/openscvx_logo_square.png +0 -0
  79. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/docs/assets/viser-client/index.html +0 -0
  80. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/docs/assets/viser-recordings/drone_racing.viser +0 -0
  81. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/docs/assets/viser-recordings/franka_fr3v2_pick_place.viser +0 -0
  82. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/docs/citation.md +0 -0
  83. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/docs/examples.md +0 -0
  84. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/docs/index.md +0 -0
  85. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/docs/javascripts/mathjax.js +0 -0
  86. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/docs/versions.json +0 -0
  87. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/examples/_viser_embed_export.py +0 -0
  88. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/examples/abstract/brachistochrone.py +0 -0
  89. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/examples/abstract/hypersensitive.py +0 -0
  90. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/examples/abstract/impulsive.py +0 -0
  91. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/examples/abstract/stl_integer_variable.py +0 -0
  92. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/examples/abstract/stl_or.py +0 -0
  93. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/examples/animations/7_dof_arm.py +0 -0
  94. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/examples/animations/_camera.py +0 -0
  95. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/examples/animations/_render.py +0 -0
  96. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/examples/animations/_sensor_view.py +0 -0
  97. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/examples/animations/dr_vp_polytope.py +0 -0
  98. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/examples/animations/franka_fr3v2_pick_place.py +0 -0
  99. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/examples/animations/logo.py +0 -0
  100. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/examples/animations/obstacle_avoidance_vmap.py +0 -0
  101. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/examples/arm/3_dof_arm.py +0 -0
  102. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/examples/arm/7_dof_arm.py +0 -0
  103. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/examples/arm/7_dof_arm_collision.py +0 -0
  104. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/examples/arm/7_dof_arm_vp.py +0 -0
  105. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/examples/arm/franka_fr3v2_pick_place.py +0 -0
  106. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/examples/arm/franka_fr3v2_viewplanning.py +0 -0
  107. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/examples/car/dubins_car.py +0 -0
  108. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/examples/car/dubins_car_disjoint.py +0 -0
  109. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/examples/car/dubins_car_obstacle_conditional.py +0 -0
  110. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/examples/car/dubins_car_obstacle_stl.py +0 -0
  111. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/examples/car/dubins_car_stl_or.py +0 -0
  112. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/examples/car/dubins_car_waypoint_stl.py +0 -0
  113. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/examples/drone/cinema_vp.py +0 -0
  114. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/examples/drone/dr_double_integrator.py +0 -0
  115. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/examples/drone/dr_vp.py +0 -0
  116. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/examples/drone/dr_vp_nodal.py +0 -0
  117. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/examples/drone/dr_vp_polytope.py +0 -0
  118. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/examples/drone/drone_racing.py +0 -0
  119. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/examples/drone/logo.py +0 -0
  120. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/examples/drone/logo_utils/acl_logo.svg +0 -0
  121. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/examples/drone/logo_utils/svg_path_utils.py +0 -0
  122. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/examples/drone/obstacle_avoidance.py +0 -0
  123. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/examples/drone/obstacle_avoidance_nodal.py +0 -0
  124. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/examples/drone/obstacle_avoidance_vmap.py +0 -0
  125. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/examples/mjx/cartpole_mjx.py +0 -0
  126. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/examples/mjx/double_cartpole_mjx.py +0 -0
  127. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/examples/mjx/skydio_x2_mjx.py +0 -0
  128. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/examples/mjx/triple_cartpole_3d_mjx.py +0 -0
  129. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/examples/mjx/triple_cartpole_game.py +0 -0
  130. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/examples/mjx/triple_cartpole_mjx.py +0 -0
  131. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/examples/mpc/double_integrator_discrete.py +0 -0
  132. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/examples/mpc/double_integrator_drone_racing.py +0 -0
  133. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/examples/mpc/dubins_car_circle_analytical.py +0 -0
  134. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/examples/mpc/dubins_car_circle_discrete.py +0 -0
  135. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/examples/mpc/realtime_double_integrator_drone_racing.py +0 -0
  136. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/examples/plotting.py +0 -0
  137. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/examples/plotting_viser.py +0 -0
  138. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/examples/realtime/3DoF_pdg_realtime.py +0 -0
  139. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/examples/realtime/6DoF_pdg_realtime.py +0 -0
  140. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/examples/realtime/base_problems/3DoF_pdg_realtime_base.py +0 -0
  141. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/examples/realtime/base_problems/6DoF_pdg_realtime_base.py +0 -0
  142. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/examples/realtime/base_problems/cinema_vp_realtime_base.py +0 -0
  143. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/examples/realtime/base_problems/drone_racing_realtime_base.py +0 -0
  144. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/examples/realtime/base_problems/dubins_car_realtime_base.py +0 -0
  145. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/examples/realtime/base_problems/obstacle_avoidance_realtime_base.py +0 -0
  146. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/examples/realtime/cinema_vp_realtime.py +0 -0
  147. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/examples/realtime/drone_racing_realtime.py +0 -0
  148. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/examples/realtime/dubins_car_realtime.py +0 -0
  149. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/examples/realtime/obstacle_avoidance_realtime.py +0 -0
  150. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/examples/rocket/3DoF_pdg.py +0 -0
  151. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/examples/rocket/6DoF_pdg.py +0 -0
  152. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/examples/spacecraft/halo_orbit.py +0 -0
  153. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/examples/spacecraft/hohmann_transfer.py +0 -0
  154. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/examples/spacecraft/let_transfer.py +0 -0
  155. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/examples/spacecraft/proxops_cw.py +0 -0
  156. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/examples/spacecraft/relative_loitering.py +0 -0
  157. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/figures/ctlos_cine.gif +0 -0
  158. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/figures/ctlos_dr.gif +0 -0
  159. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/figures/dtlos_cine.gif +0 -0
  160. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/figures/dtlos_dr.gif +0 -0
  161. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/figures/openscvx_logo.svg +0 -0
  162. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/figures/openscvx_logo_square.png +0 -0
  163. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/figures/oscvx_structure_full_dark.svg +0 -0
  164. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/figures/video_preview.png +0 -0
  165. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/material/__init__.py +0 -0
  166. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/material/overrides/assets/stylesheets/custom.css +0 -0
  167. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/material/overrides/assets/stylesheets/home-dropin.css +0 -0
  168. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/material/overrides/assets/stylesheets/home-hero.css +0 -0
  169. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/material/overrides/assets/stylesheets/home-viser.css +0 -0
  170. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/material/overrides/home.html +0 -0
  171. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/material/overrides/main.html +0 -0
  172. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/material/overrides/partials/home-diagram.html +0 -0
  173. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/material/overrides/partials/home-dropin-banner.html +0 -0
  174. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/material/overrides/partials/home-hero.html +0 -0
  175. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/material/overrides/partials/home-pipeline.html +0 -0
  176. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/material/overrides/partials/home-viser-strip.html +0 -0
  177. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/__init__.py +0 -0
  178. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/__main__.py +0 -0
  179. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/algorithms/__init__.py +0 -0
  180. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/algorithms/autotuner/__init__.py +0 -0
  181. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/algorithms/autotuner/adaptive_proximal_weight.py +0 -0
  182. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/algorithms/autotuner/augmented_lagrangian.py +0 -0
  183. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/algorithms/autotuner/constant_proximal_weight.py +0 -0
  184. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/algorithms/autotuner/ramp_proximal_weight.py +0 -0
  185. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/algorithms/scvx/__init__.py +0 -0
  186. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/algorithms/weights.py +0 -0
  187. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/config.py +0 -0
  188. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/discretization/__init__.py +0 -0
  189. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/discretization/base.py +0 -0
  190. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/discretization/discretize_linearize.py +0 -0
  191. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/discretization/linearize_discretize.py +0 -0
  192. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/discretization/linearize_discretize_sparse.py +0 -0
  193. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/discretization/sparse_utils/__init__.py +0 -0
  194. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/discretization/sparse_utils/bcoo_helpers.py +0 -0
  195. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/discretization/sparse_utils/sparse_jacobian.py +0 -0
  196. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/expert/__init__.py +0 -0
  197. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/expert/byof.py +0 -0
  198. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/expert/lowering.py +0 -0
  199. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/expert/validation.py +0 -0
  200. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/init/__init__.py +0 -0
  201. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/init/interpolation.py +0 -0
  202. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/init/inverse_kinematics.py +0 -0
  203. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/integrations/__init__.py +0 -0
  204. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/integrations/base.py +0 -0
  205. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/integrations/menagerie.py +0 -0
  206. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/integrations/mjx.py +0 -0
  207. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/integrators/__init__.py +0 -0
  208. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/integrators/diffrax.py +0 -0
  209. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/integrators/runge_kutta.py +0 -0
  210. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/loader.py +0 -0
  211. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/lowered/__init__.py +0 -0
  212. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/lowered/cvxpy_constraints.py +0 -0
  213. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/lowered/cvxpy_variables.py +0 -0
  214. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/lowered/dynamics.py +0 -0
  215. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/lowered/jax_constraints.py +0 -0
  216. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/lowered/parameters.py +0 -0
  217. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/lowered/problem.py +0 -0
  218. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/lowered/unified.py +0 -0
  219. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/plotting/__init__.py +0 -0
  220. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/plotting/plotting.py +0 -0
  221. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/plotting/scp_iteration.py +0 -0
  222. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/plotting/viser/__init__.py +0 -0
  223. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/plotting/viser/animated.py +0 -0
  224. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/plotting/viser/orbits.py +0 -0
  225. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/plotting/viser/plotly_integration.py +0 -0
  226. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/plotting/viser/primitives.py +0 -0
  227. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/plotting/viser/scp.py +0 -0
  228. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/plotting/viser/server.py +0 -0
  229. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/propagation/__init__.py +0 -0
  230. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/propagation/post_processing.py +0 -0
  231. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/propagation/propagation.py +0 -0
  232. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/solvers/__init__.py +0 -0
  233. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/solvers/base.py +0 -0
  234. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/solvers/ptr_solver.py +0 -0
  235. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/symbolic/__init__.py +0 -0
  236. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/symbolic/augmentation.py +0 -0
  237. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/symbolic/builder.py +0 -0
  238. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/symbolic/constraint_set.py +0 -0
  239. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/symbolic/expr/__init__.py +0 -0
  240. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/symbolic/expr/arithmetic.py +0 -0
  241. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/symbolic/expr/array.py +0 -0
  242. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/symbolic/expr/constraint.py +0 -0
  243. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/symbolic/expr/control.py +0 -0
  244. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/symbolic/expr/expr.py +0 -0
  245. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/symbolic/expr/lie/__init__.py +0 -0
  246. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/symbolic/expr/lie/adjoint.py +0 -0
  247. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/symbolic/expr/lie/se3.py +0 -0
  248. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/symbolic/expr/lie/so3.py +0 -0
  249. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/symbolic/expr/linalg.py +0 -0
  250. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/symbolic/expr/logic.py +0 -0
  251. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/symbolic/expr/math.py +0 -0
  252. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/symbolic/expr/parameter.py +0 -0
  253. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/symbolic/expr/spatial.py +0 -0
  254. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/symbolic/expr/state.py +0 -0
  255. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/symbolic/expr/stl.py +0 -0
  256. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/symbolic/expr/stljax.py +0 -0
  257. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/symbolic/expr/time.py +0 -0
  258. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/symbolic/expr/variable.py +0 -0
  259. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/symbolic/expr/vmap.py +0 -0
  260. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/symbolic/hashing.py +0 -0
  261. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/symbolic/lower.py +0 -0
  262. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/symbolic/lowerers/__init__.py +0 -0
  263. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/symbolic/lowerers/cvxpy/__init__.py +0 -0
  264. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/symbolic/lowerers/cvxpy/_lowerer.py +0 -0
  265. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/symbolic/lowerers/cvxpy/_registry.py +0 -0
  266. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/symbolic/lowerers/cvxpy/arithmetic.py +0 -0
  267. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/symbolic/lowerers/cvxpy/array.py +0 -0
  268. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/symbolic/lowerers/cvxpy/constraint.py +0 -0
  269. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/symbolic/lowerers/cvxpy/control.py +0 -0
  270. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/symbolic/lowerers/cvxpy/expr.py +0 -0
  271. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/symbolic/lowerers/cvxpy/linalg.py +0 -0
  272. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/symbolic/lowerers/cvxpy/logic.py +0 -0
  273. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/symbolic/lowerers/cvxpy/math.py +0 -0
  274. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/symbolic/lowerers/cvxpy/state.py +0 -0
  275. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/symbolic/lowerers/jax/__init__.py +0 -0
  276. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/symbolic/lowerers/jax/_lowerer.py +0 -0
  277. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/symbolic/lowerers/jax/_registry.py +0 -0
  278. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/symbolic/lowerers/jax/arithmetic.py +0 -0
  279. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/symbolic/lowerers/jax/array.py +0 -0
  280. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/symbolic/lowerers/jax/constraint.py +0 -0
  281. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/symbolic/lowerers/jax/control.py +0 -0
  282. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/symbolic/lowerers/jax/expr.py +0 -0
  283. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/symbolic/lowerers/jax/lie.py +0 -0
  284. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/symbolic/lowerers/jax/linalg.py +0 -0
  285. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/symbolic/lowerers/jax/logic.py +0 -0
  286. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/symbolic/lowerers/jax/math.py +0 -0
  287. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/symbolic/lowerers/jax/spatial.py +0 -0
  288. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/symbolic/lowerers/jax/state.py +0 -0
  289. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/symbolic/lowerers/jax/stl.py +0 -0
  290. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/symbolic/lowerers/jax/stljax.py +0 -0
  291. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/symbolic/lowerers/jax/vmap.py +0 -0
  292. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/symbolic/parser/__init__.py +0 -0
  293. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/symbolic/parser/_registry.py +0 -0
  294. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/symbolic/parser/array.py +0 -0
  295. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/symbolic/parser/constraint.py +0 -0
  296. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/symbolic/parser/lie.py +0 -0
  297. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/symbolic/parser/linalg.py +0 -0
  298. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/symbolic/parser/logic.py +0 -0
  299. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/symbolic/parser/math.py +0 -0
  300. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/symbolic/parser/parser.py +0 -0
  301. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/symbolic/parser/spatial.py +0 -0
  302. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/symbolic/parser/stl.py +0 -0
  303. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/symbolic/parser/stljax.py +0 -0
  304. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/symbolic/parser/tokenizer.py +0 -0
  305. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/symbolic/preprocessing.py +0 -0
  306. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/symbolic/problem.py +0 -0
  307. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/symbolic/sparsity.py +0 -0
  308. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/symbolic/unified.py +0 -0
  309. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/utils/__init__.py +0 -0
  310. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/utils/cache.py +0 -0
  311. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/utils/printing.py +0 -0
  312. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/utils/profiling.py +0 -0
  313. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx/utils/utils.py +0 -0
  314. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx.egg-info/dependency_links.txt +0 -0
  315. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx.egg-info/entry_points.txt +0 -0
  316. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx.egg-info/requires.txt +0 -0
  317. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/openscvx.egg-info/top_level.txt +0 -0
  318. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/pyproject.toml +0 -0
  319. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/scripts/gen_example_pages.py +0 -0
  320. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/scripts/gen_ref_pages.py +0 -0
  321. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/scripts/mkdocs_copy_viser_client_hook.py +0 -0
  322. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/setup.cfg +0 -0
  323. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/tests/__init__.py +0 -0
  324. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/tests/_marks.py +0 -0
  325. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/tests/algorithms/__init__.py +0 -0
  326. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/tests/algorithms/autotuner/__init__.py +0 -0
  327. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/tests/brachistochrone_analytical.py +0 -0
  328. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/tests/conftest.py +0 -0
  329. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/tests/expr/__init__.py +0 -0
  330. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/tests/expr/test_gmsr.py +0 -0
  331. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/tests/fixtures/brachistochrone.json +0 -0
  332. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/tests/fixtures/brachistochrone.yaml +0 -0
  333. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/tests/hohmann_analytical.py +0 -0
  334. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/tests/integrations/__init__.py +0 -0
  335. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/tests/integrations/test_mjx.py +0 -0
  336. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/tests/integrations/test_mjx_dynamics.py +0 -0
  337. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/tests/solvers/__init__.py +0 -0
  338. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/tests/solvers/test_cvxpy_callback_jit_spike.py +0 -0
  339. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/tests/solvers/test_iteration_callback_cvxpy.py +0 -0
  340. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/tests/solvers/test_subproblem_pytree.py +0 -0
  341. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/tests/symbolic/__init__.py +0 -0
  342. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/tests/symbolic/expr/__init__.py +0 -0
  343. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/tests/symbolic/expr/test_arithmetic.py +0 -0
  344. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/tests/symbolic/expr/test_array.py +0 -0
  345. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/tests/symbolic/expr/test_constraint.py +0 -0
  346. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/tests/symbolic/expr/test_expr.py +0 -0
  347. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/tests/symbolic/expr/test_lie.py +0 -0
  348. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/tests/symbolic/expr/test_linalg.py +0 -0
  349. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/tests/symbolic/expr/test_logic.py +0 -0
  350. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/tests/symbolic/expr/test_math.py +0 -0
  351. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/tests/symbolic/expr/test_node_reference.py +0 -0
  352. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/tests/symbolic/expr/test_parameters.py +0 -0
  353. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/tests/symbolic/expr/test_scaling.py +0 -0
  354. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/tests/symbolic/expr/test_spatial.py +0 -0
  355. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/tests/symbolic/expr/test_stl.py +0 -0
  356. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/tests/symbolic/expr/test_variable.py +0 -0
  357. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/tests/symbolic/expr/test_vmap.py +0 -0
  358. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/tests/symbolic/parser/__init__.py +0 -0
  359. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/tests/symbolic/parser/test_array.py +0 -0
  360. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/tests/symbolic/parser/test_constraint.py +0 -0
  361. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/tests/symbolic/parser/test_lie.py +0 -0
  362. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/tests/symbolic/parser/test_linalg.py +0 -0
  363. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/tests/symbolic/parser/test_load.py +0 -0
  364. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/tests/symbolic/parser/test_logic.py +0 -0
  365. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/tests/symbolic/parser/test_math.py +0 -0
  366. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/tests/symbolic/parser/test_parser.py +0 -0
  367. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/tests/symbolic/parser/test_spatial.py +0 -0
  368. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/tests/symbolic/parser/test_stl.py +0 -0
  369. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/tests/symbolic/parser/test_tokenizer.py +0 -0
  370. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/tests/symbolic/parser/test_vmap.py +0 -0
  371. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/tests/symbolic/test_augmentation.py +0 -0
  372. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/tests/symbolic/test_hashing.py +0 -0
  373. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/tests/symbolic/test_lower_cvxpy.py +0 -0
  374. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/tests/symbolic/test_lower_jax.py +0 -0
  375. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/tests/symbolic/test_preprocessing.py +0 -0
  376. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/tests/symbolic/test_sparsity.py +0 -0
  377. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/tests/symbolic/test_unified.py +0 -0
  378. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/tests/test_cvxpygen_optional.py +0 -0
  379. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/tests/test_discretization.py +0 -0
  380. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/tests/test_examples.py +0 -0
  381. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/tests/test_expert.py +0 -0
  382. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/tests/test_impulsive.py +0 -0
  383. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/tests/test_init.py +0 -0
  384. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/tests/test_integrators.py +0 -0
  385. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/tests/test_loader.py +0 -0
  386. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/tests/test_optimization_results.py +0 -0
  387. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/tests/test_plotting.py +0 -0
  388. {openscvx-0.5.3.dev15 → openscvx-0.5.3.dev17}/tests/test_propagation.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: openscvx
3
- Version: 0.5.3.dev15
3
+ Version: 0.5.3.dev17
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
@@ -0,0 +1,134 @@
1
+ # Batching, JIT, and Grad with `Problem.solve_jax()`
2
+
3
+ `Problem` exposes two solve entry points. `solve()` is the familiar
4
+ Python-loop driver — real-time prints, wall-clock `time_limit`, `continuous`
5
+ mode, populated per-iteration history. `solve_jax()` is its JAX-pure
6
+ sibling: it drives the same fused `iteration_fn` body inside a
7
+ `lax.while_loop` and returns an `OptimizationResults`
8
+ (`openscvx/algorithms/optimization_results.py`) pytree, so it composes with
9
+ `jax.vmap`, `jax.jit`, and `jax.grad`.
10
+
11
+ ```python
12
+ problem = ox.Problem(..., solver={"backend": "qpax"})
13
+ problem.initialize()
14
+
15
+ # Familiar interactive solve — unchanged: prints, history, time limit.
16
+ result = problem.solve()
17
+
18
+ # JAX-pure single solve — silent, no per-iteration history, batchable.
19
+ result = problem.solve_jax()
20
+
21
+ # Batched — standard jax.vmap, no library-specific API.
22
+ batched = jax.vmap(problem.solve_jax, in_axes=(0, 0, None))(
23
+ x_initial_stack, x_final_stack, params
24
+ )
25
+
26
+ # JIT-compile once, solve forever (e.g. MPC inner loop).
27
+ fast_solve = jax.jit(problem.solve_jax)
28
+ ```
29
+
30
+ A worked example lives at `examples/abstract/brachistochrone_batched.py`
31
+ — four brachistochrone problems with shifted starting x-coordinates,
32
+ solved in parallel via `jax.vmap(problem.solve_jax)`.
33
+
34
+ ## When to choose `solve()` vs. `solve_jax()`
35
+
36
+ | Use case | Entry point |
37
+ |---|---|
38
+ | Interactive use, real-time prints, plotting per iteration | `solve()` |
39
+ | Wall-clock `time_limit` or `continuous=True` | `solve()` |
40
+ | Per-iteration trajectories / weights / diagnostics | `solve()` |
41
+ | Batched solve over many initial conditions or parameters | `solve_jax()` |
42
+ | JIT-compile once, solve forever (MPC inner loop, scenario sweeps) | `solve_jax()` |
43
+ | `jax.grad` through the solver (best-effort, untested) | `solve_jax()` |
44
+
45
+ The split exists to make user intent explicit — a single dispatched
46
+ `solve()` would have to infer from arguments which path the caller wants,
47
+ and silent routing failures (like `continuous=True` quietly skipping the
48
+ Python loop) are exactly the failure class the two-method design exists to
49
+ prevent. See `plans/jax-pure-solve.md`'s Decision Log for the longer
50
+ discussion.
51
+
52
+ ## What `solve_jax()` returns
53
+
54
+ `solve_jax()` returns the same `OptimizationResults` type as `solve()`,
55
+ but built via
56
+ `OptimizationResults.from_final_state(state, problem=...)` instead of
57
+ `from_history(history, final_state, ...)`. The differences:
58
+
59
+ * **Per-iteration history is empty.** `X = [state.x]` and `U = [state.u]`
60
+ are single-element lists so `result.x` / `result.u` continue to return
61
+ the final iterate; every `*_history` field is `[]`. List growth doesn't
62
+ fit inside `lax.while_loop`. If you need per-iteration trajectories, use
63
+ `solve()` or wrap `solve_jax()` in `lax.scan` manually.
64
+ * **Post-process fields stay `None`.** `t_full`, `x_full`, `u_full`,
65
+ `cost`, `ctcs_violation` are populated only by `post_process()`. They're
66
+ outside the JAX pytree's children surface, so a batched `solve_jax`
67
+ result doesn't force every consumer to handle `None` leaves. If you want
68
+ to post-process, call `post_process()` per batch element after the
69
+ batched solve.
70
+ * **`converged` is a `jnp.bool_`** under the JAX-pure path (a `(B,)` array
71
+ under vmap), not a Python `bool` like `solve()` returns. Most uses
72
+ (`if result.converged: ...`) work either way.
73
+
74
+ ## `solve_jax()` arguments
75
+
76
+ ```python
77
+ problem.solve_jax(
78
+ x_initial=None, # boundary-condition pin (full unified state vector,
79
+ # ``jnp.nan`` at non-Fix entries — see
80
+ # ``AlgorithmState.from_settings``); falls back
81
+ # to the default from settings
82
+ x_final=None, # terminal pin, same conventions
83
+ parameters=None, # parameters dict for this solve; falls back to
84
+ # ``self._parameters``
85
+ *,
86
+ max_iters=None, # SCP iteration cap; non-default rebuilds the
87
+ # cached ``lax.while_loop`` closure (one extra
88
+ # trace; subsequent calls at the same cap hit
89
+ # the cache)
90
+ )
91
+ ```
92
+
93
+ Positional kwargs (rather than a single `inputs` pytree) keep
94
+ `jax.vmap(problem.solve_jax, in_axes=(0, 0, None))` ergonomic;
95
+ multi-argument gradient uses `jax.grad(..., argnums=(0, 1))`.
96
+
97
+ ## Caveats
98
+
99
+ ### CVXPy under `vmap` is sequential
100
+
101
+ The CVXPy backend's `iteration_callback`
102
+ (`openscvx/solvers/cvxpy_ptr_solver.py`) host-calls CVXPy through
103
+ `jax.pure_callback` with `vmap_method="sequential"`. Host
104
+ CVXPy is not thread-safe, so a `jax.vmap(problem.solve_jax)` over the
105
+ CVXPy backend runs `B` sequential CVXPy solves. The QPAX and Moreau
106
+ backends are pure JAX end-to-end and run in parallel under vmap.
107
+
108
+ ### Moreau warm-start is bypassed
109
+
110
+ The Moreau backend's `_warm_start` carry is host-side mutable state that
111
+ `lax.while_loop` doesn't thread. Both `solve()` and `solve_jax()` cold-start
112
+ the inner Moreau solve every SCP iteration (see the Moreau module
113
+ docstring and `plans/jax-pure-solve.md`'s Decision Log 2026-05-27).
114
+ Restoring warm-start to the SCP loop requires threading `(x, z, s)`
115
+ through an `AlgorithmState.moreau_carry` field — a Future Extension.
116
+
117
+ ### `jax.grad` is best-effort, untested
118
+
119
+ The QPAX backend's `solve_qp` is not differentiable (its convergence flag
120
+ costs reverse-mode autodiff). The CVXPy backend's `pure_callback` is
121
+ non-differentiable by default. End-to-end gradient validation through
122
+ `solve_jax` is a follow-up — `jax.grad(loss_fn)(x0)` will run without
123
+ erroring under QPAX (`solve_qp_primal` would be `custom_vjp`, but the
124
+ backend currently uses `solve_qp`), but the gradient's correctness is not
125
+ yet pinned down by a test against finite differences.
126
+
127
+ ### Convergence under `vmap` with mixed-rate elements
128
+
129
+ `lax.while_loop` continues while *any* batch element still needs
130
+ iterations — converged elements would otherwise keep receiving body calls
131
+ while their peers iterate. `make_solve_loop`'s body selects the unchanged
132
+ state for converged elements (`jax.tree.map(jnp.where, ...)`), so a
133
+ batched solve agrees with the single-problem `solve_jax` on each element.
134
+ The cost is per-iteration work × slowest-element iteration count.
@@ -168,18 +168,33 @@ of the abstract `PTRSolver` base. Three backends ship today:
168
168
  | Backend | Class | Selector | Notes |
169
169
  |---------|-------|----------|-------|
170
170
  | CVXPy (default) | `CVXPyPTRSolver` | `solver={"backend": "cvxpy"}` (default) | DCP graph via CVXPy, dispatched to QOCO / CLARABEL / etc. Supports user `.convex()` constraints, cross-node constraints, CTCS, and impulsive controls. Optional cvxpygen code generation. |
171
- | QPAX | `QPAXPTRSolver` | `solver={"backend": "qpax"}` | JAX-native QP via `qpax.solve_qp`. Flat `(Q, q, A, b, G, h)` assembly. Supports box / dynamics (continuous and impulsive) / CTCS / boundary-Fix; **rejects** user `.convex()` and cross-node at `initialize()` with a clear "use `CVXPyPTRSolver`" message. Enables a path toward an end-to-end JAX-differentiable SCP loop in follow-up work. |
171
+ | QPAX | `QPAXPTRSolver` | `solver={"backend": "qpax"}` | JAX-native QP via `qpax.solve_qp`. Flat `(Q, q, A, b, G, h)` assembly. Supports box / dynamics (continuous and impulsive) / CTCS / boundary-Fix; **rejects** user `.convex()` and cross-node at `initialize()` with a clear "use `CVXPyPTRSolver`" message. The `iteration_callback` uses `qpax.solve_qp`, whose convergence flag maps to a `status_code` so a diverged solve fails loudly (chosen over the differentiable `solve_qp_primal`, which exposes no such flag). |
172
172
  | Moreau | `MoreauPTRSolver` | `solver={"backend": "moreau"}` | JAX-native conic solver (`moreau.jax.Solver`). Sparse CSR assembly; SOC epigraphs for the L1 / pos PTR penalties (fewer variables and rows than QPAX). Warm-starts between SCP iterations. Same supported subset as QPAX (continuous and impulsive dynamics). Paves the way for user `.convex()` SOC support in a follow-up. |
173
173
 
174
174
  Each backend exposes two per-iteration entry points: the historical NumPy
175
- `update_*` + `solve()` stages used by today's Python-side SCP loop, and a
175
+ `update_*` + `solve()` stages (kept for direct / interactive solver use), and a
176
176
  JAX-pure `iteration_callback()` built once at `initialize()`. The callback
177
- returns a `(state, SubproblemData) -> SubproblemSolution` callable; all
178
- three backends emit the same input/output pytree shape so the callable
179
- composes with `jax.jit` and `jax.vmap` (CVXPy via `jax.pure_callback` with
180
- `vmap_method="sequential"` — its batched solves are serial). The downstream
181
- batchable-`Problem.solve()` work wraps this callback in `lax.while_loop` to
182
- keep the entire SCP iteration on the JAX boundary.
177
+ returns a `(state, SubproblemData) -> SubproblemSolution` callable; all three
178
+ backends emit the same input/output pytree shape (CVXPy host-calls via
179
+ `jax.pure_callback`).
180
+
181
+ `Problem.initialize()` fuses that callback with discretization, constraint
182
+ linearization, the SCP metrics, and the autotuner into one JAX function —
183
+ `iteration_fn`, built by `make_scp_iteration`
184
+ (`openscvx/algorithms/scvx/iteration.py`). A single JIT'd `iteration_fn` call
185
+ per iteration replaces the former per-step NumPy↔JAX stitching, and the Python
186
+ SCP loop now drives that one fused body. Forward propagation stays a separate
187
+ JAX export, used only by `post_process()` — so a compiled problem holds **one
188
+ `iteration_fn` plus one propagation export**, not three discretization /
189
+ propagation exports stitched together in Python. Because `iteration_fn` is a
190
+ registered pytree in and out, it also composes with `jax.jit`; `make_solve_loop`
191
+ wraps it in `lax.while_loop` to drive the **JAX-pure** `Problem.solve_jax()`
192
+ entry point, which composes with `jax.vmap`, `jax.jit`, and `jax.grad` (see
193
+ `docs/UnderTheHood/batching_jit_grad.md`). The familiar
194
+ `Problem.solve()` keeps its Python-loop shape — real-time prints, wall-clock
195
+ `time_limit`, populated per-iteration history — and is the right entry
196
+ point for interactive use. `solve_jax()` is the right entry point for
197
+ batched / JIT'd / differentiable workflows.
183
198
 
184
199
  Picking a backend at construction time:
185
200
 
@@ -0,0 +1,126 @@
1
+ """Batched brachistochrone via ``jax.vmap(problem.solve_jax)``.
2
+
3
+ Solves four brachistochrone problems in parallel — each with a different
4
+ starting x-coordinate — using the JAX-pure
5
+ :meth:`~openscvx.problem.Problem.solve_jax` entry point. ``solve_jax``
6
+ returns an :class:`~openscvx.algorithms.optimization_results.OptimizationResults`
7
+ pytree, so ``jax.vmap`` over the boundary-condition pins is the standard JAX
8
+ composition pattern; no library-specific batching API is needed.
9
+
10
+ Run with ``python examples/abstract/brachistochrone_batched.py``.
11
+
12
+ Notes:
13
+
14
+ * Under the QPAX backend used here, vmap'd subproblem solves run in
15
+ parallel (no host callback). The CVXPy backend is single-threaded under
16
+ vmap because :func:`jax.pure_callback` uses ``vmap_method="sequential"``
17
+ for thread safety — see :meth:`solve_jax`'s docstring.
18
+ * The Moreau warm-start is bypassed on the JAX-pure path (its carry is
19
+ host-side state that ``lax.while_loop`` doesn't thread). Use QPAX or
20
+ CVXPy when you want batched solves.
21
+ """
22
+
23
+ import os
24
+ import sys
25
+
26
+ import jax
27
+ import jax.numpy as jnp
28
+ import numpy as np
29
+
30
+ current_dir = os.path.dirname(os.path.abspath(__file__))
31
+ grandparent_dir = os.path.dirname(os.path.dirname(current_dir))
32
+ sys.path.append(grandparent_dir)
33
+
34
+ import openscvx as ox
35
+ from openscvx import Problem
36
+
37
+
38
+ def build_problem(n: int = 8):
39
+ g = 9.81
40
+
41
+ position = ox.State("position", shape=(2,))
42
+ position.max = np.array([10.0, 10.0])
43
+ position.min = np.array([0.0, 0.0])
44
+ position.initial = np.array([0.0, 10.0])
45
+ position.final = [10.0, 5.0]
46
+
47
+ velocity = ox.State("velocity", shape=(1,))
48
+ velocity.max = np.array([10.0])
49
+ velocity.min = np.array([0.0])
50
+ velocity.initial = np.array([0.0])
51
+ velocity.final = [("free", 10.0)]
52
+
53
+ theta = ox.Control("theta", shape=(1,))
54
+ theta.max = np.array([100.5 * jnp.pi / 180])
55
+ theta.min = np.array([0.0])
56
+ theta.guess = np.linspace(5 * jnp.pi / 180, 100.5 * jnp.pi / 180, n).reshape(-1, 1)
57
+
58
+ states = [position, velocity]
59
+ controls = [theta]
60
+
61
+ dynamics = {
62
+ "position": ox.Concat(
63
+ velocity[0] * ox.Sin(theta[0]),
64
+ -velocity[0] * ox.Cos(theta[0]),
65
+ ),
66
+ "velocity": g * ox.Cos(theta[0]),
67
+ }
68
+
69
+ constraint_exprs = []
70
+ for state in states:
71
+ constraint_exprs.extend([ox.ctcs(state <= state.max), ox.ctcs(state.min <= state)])
72
+
73
+ time = ox.Time(
74
+ initial=0.0,
75
+ final=("minimize", 2.0),
76
+ min=0.0,
77
+ max=2.0,
78
+ uniform_time_grid=True,
79
+ )
80
+
81
+ return Problem(
82
+ dynamics=dynamics,
83
+ states=states,
84
+ controls=controls,
85
+ time=time,
86
+ constraints=constraint_exprs,
87
+ N=n,
88
+ float_dtype="float64",
89
+ algorithm={
90
+ "autotuner": "ConstantProximalWeight",
91
+ "lam_prox": 1e0,
92
+ "lam_cost": 6e-1,
93
+ "ep_tr": 1e-5,
94
+ "ep_vb": 1e-5,
95
+ "ep_vc": 1e-9,
96
+ "k_max": 30,
97
+ },
98
+ solver={"backend": "qpax"},
99
+ )
100
+
101
+
102
+ if __name__ == "__main__":
103
+ problem = build_problem()
104
+ problem.initialize()
105
+
106
+ # The default boundary-condition pin (the full unified state vector with
107
+ # ``jnp.nan`` at non-Fix entries — see
108
+ # :meth:`AlgorithmState.from_settings`).
109
+ default_pin = problem.state.x_init_pin
110
+
111
+ # Stack four ICs by varying the starting x-coordinate (component 0 of
112
+ # the unified state vector is the x-position).
113
+ shifts = jnp.array([0.0, 0.3, 0.6, 0.9])
114
+ x_initial_stack = jnp.stack([default_pin.at[0].set(default_pin[0] + s) for s in shifts])
115
+
116
+ # Bare ``jax.vmap`` — the library exposes no batching wrapper of its own.
117
+ batched_solve = jax.vmap(problem.solve_jax, in_axes=(0, None, None))
118
+ results = batched_solve(x_initial_stack, None, None)
119
+
120
+ # ``results`` is a batched ``OptimizationResults`` pytree — every child
121
+ # (``X``, ``U``, ``t_final``, ``converged``, ...) has a leading batch axis.
122
+ print(f"Batched solve over {x_initial_stack.shape[0]} initial conditions:")
123
+ print(f" result.x.shape: {results.x.shape}")
124
+ print(f" result.u.shape: {results.u.shape}")
125
+ print(f" result.t_final: {np.asarray(results.t_final).reshape(-1)}")
126
+ print(f" result.converged: {np.asarray(results.converged)}")
@@ -197,4 +197,5 @@ nav:
197
197
  - 'Foundations/discretization.md'
198
198
  - Under the Hood:
199
199
  - 'UnderTheHood/vectorization_and_vmapping.md'
200
- - 'UnderTheHood/lowering_architecture.md'
200
+ - 'UnderTheHood/lowering_architecture.md'
201
+ - 'UnderTheHood/batching_jit_grad.md'
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
18
18
  commit_id: str | None
19
19
  __commit_id__: str | None
20
20
 
21
- __version__ = version = '0.5.3.dev15'
22
- __version_tuple__ = version_tuple = (0, 5, 3, 'dev15')
21
+ __version__ = version = '0.5.3.dev17'
22
+ __version_tuple__ = version_tuple = (0, 5, 3, 'dev17')
23
23
 
24
- __commit_id__ = commit_id = 'ge47b6d19c'
24
+ __commit_id__ = commit_id = 'gb2143958f'
@@ -29,7 +29,6 @@ from openscvx.utils.printing import Column
29
29
  if TYPE_CHECKING:
30
30
  from openscvx.config import Config
31
31
  from openscvx.lowered.jax_constraints import LoweredJaxConstraints
32
- from openscvx.solvers import ConvexSolver
33
32
 
34
33
  from .weights import Weights
35
34
 
@@ -373,6 +372,16 @@ class AlgorithmState:
373
372
  actual_reduction: Actual reduction in ``J_nonlin`` for this iter.
374
373
  acceptance_ratio: ``actual_reduction / predicted_reduction``.
375
374
  adaptive_state_code: :class:`AdaptiveStateCode` value as ``int32``.
375
+ x_init_pin: Initial-state boundary condition, shape ``(n_states,)``.
376
+ ``jnp.nan`` where the state is not pinned at t0 (``initial_type``
377
+ is not ``"Fix"``). Carried on the pytree — rather than read from
378
+ ``settings`` — so the fused SCP iteration body assembles the
379
+ subproblem's initial boundary rows as a pure function of state,
380
+ and a future ``jax.vmap`` over problems can batch boundary
381
+ conditions per element.
382
+ x_term_pin: Terminal-state boundary condition, shape ``(n_states,)``.
383
+ ``jnp.nan`` where the state is not pinned at tf (``final_type`` is
384
+ not ``"Fix"``).
376
385
  """
377
386
 
378
387
  x: jnp.ndarray
@@ -394,6 +403,8 @@ class AlgorithmState:
394
403
  actual_reduction: jnp.ndarray
395
404
  acceptance_ratio: jnp.ndarray
396
405
  adaptive_state_code: jnp.ndarray
406
+ x_init_pin: jnp.ndarray
407
+ x_term_pin: jnp.ndarray
397
408
 
398
409
  # Field order is the source of truth for tree_flatten / tree_unflatten;
399
410
  # keep _FIELDS in sync with the dataclass field declarations above.
@@ -417,6 +428,8 @@ class AlgorithmState:
417
428
  "actual_reduction",
418
429
  "acceptance_ratio",
419
430
  "adaptive_state_code",
431
+ "x_init_pin",
432
+ "x_term_pin",
420
433
  )
421
434
 
422
435
  def replace(self, **changes) -> "AlgorithmState":
@@ -475,6 +488,17 @@ class AlgorithmState:
475
488
  else:
476
489
  lam_cost_init = np.full(n_states, weights.lam_cost)
477
490
 
491
+ # Boundary-condition pins: the physical value where the state is fixed
492
+ # at t0 / tf, ``nan`` elsewhere. The subproblem only reads these at
493
+ # ``"Fix"`` entries, so the sentinel marks "unpinned" without poisoning
494
+ # any value the solver consumes.
495
+ x_initial = np.asarray(settings.sim.x.initial, dtype=float).reshape(-1)
496
+ x_final = np.asarray(settings.sim.x.final, dtype=float).reshape(-1)
497
+ init_fixed = np.asarray(settings.sim.x.initial_type) == "Fix"
498
+ final_fixed = np.asarray(settings.sim.x.final_type) == "Fix"
499
+ x_init_pin = np.where(init_fixed, x_initial, np.nan)
500
+ x_term_pin = np.where(final_fixed, x_final, np.nan)
501
+
478
502
  return cls(
479
503
  x=put(jnp.asarray(settings.sim.x.guess, dtype=f)),
480
504
  u=put(jnp.asarray(settings.sim.u.guess, dtype=f)),
@@ -495,6 +519,8 @@ class AlgorithmState:
495
519
  actual_reduction=put(jnp.asarray(0.0, dtype=f)),
496
520
  acceptance_ratio=put(jnp.asarray(0.0, dtype=f)),
497
521
  adaptive_state_code=put(jnp.asarray(int(AdaptiveStateCode.INITIAL), dtype=i)),
522
+ x_init_pin=put(jnp.asarray(x_init_pin, dtype=f)),
523
+ x_term_pin=put(jnp.asarray(x_term_pin, dtype=f)),
498
524
  )
499
525
 
500
526
 
@@ -798,15 +824,21 @@ class Algorithm(ABC):
798
824
  @abstractmethod
799
825
  def initialize(
800
826
  self,
801
- solver: "ConvexSolver",
802
- discretization_solver: callable,
803
- jax_constraints: "LoweredJaxConstraints",
827
+ iteration_fn: Callable,
804
828
  emitter: callable,
805
- params: dict,
829
+ jax_constraints: "LoweredJaxConstraints",
806
830
  settings: "Config",
807
- discretization_solver_impulsive: Optional[Callable] = None,
808
831
  ) -> None:
809
- """Initialize the algorithm and store compiled infrastructure."""
832
+ """Store the fused SCP iteration body and per-iteration infrastructure.
833
+
834
+ Args:
835
+ iteration_fn: The JAX-pure ``(state, params) -> (next_state,
836
+ diagnostics)`` body built by
837
+ :func:`~openscvx.algorithms.scvx.iteration.make_scp_iteration`.
838
+ emitter: Per-iteration diagnostics sink (printing queue / no-op).
839
+ jax_constraints: Lowered JAX constraints the body operates over.
840
+ settings: Problem configuration.
841
+ """
810
842
  raise NotImplementedError
811
843
 
812
844
  @abstractmethod