openscvx 0.5.3.dev50__tar.gz → 0.5.3.dev51__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 (474) hide show
  1. {openscvx-0.5.3.dev50/openscvx.egg-info → openscvx-0.5.3.dev51}/PKG-INFO +1 -1
  2. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/docs/Foundations/discretization.md +38 -1
  3. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/_version.py +3 -3
  4. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/expr/__init__.py +10 -0
  5. openscvx-0.5.3.dev51/openscvx/symbolic/expr/autodiff.py +159 -0
  6. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/expr/expr.py +41 -0
  7. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/expr/variable.py +6 -0
  8. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/lowerers/cvxpy/__init__.py +1 -0
  9. openscvx-0.5.3.dev51/openscvx/symbolic/lowerers/cvxpy/autodiff.py +36 -0
  10. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/lowerers/jax/__init__.py +1 -0
  11. openscvx-0.5.3.dev51/openscvx/symbolic/lowerers/jax/autodiff.py +82 -0
  12. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/lowerers/latex/__init__.py +1 -0
  13. openscvx-0.5.3.dev51/openscvx/symbolic/lowerers/latex/autodiff.py +17 -0
  14. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51/openscvx.egg-info}/PKG-INFO +1 -1
  15. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx.egg-info/SOURCES.txt +5 -0
  16. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx.egg-info/scm_file_list.json +5 -0
  17. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx.egg-info/scm_version.json +2 -2
  18. openscvx-0.5.3.dev51/tests/symbolic/expr/test_autodiff.py +450 -0
  19. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/.github/assets/logo.svg +0 -0
  20. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/.github/release-drafter.yml +0 -0
  21. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/.github/workflows/_docs.yml +0 -0
  22. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/.github/workflows/_extra.yml +0 -0
  23. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/.github/workflows/branch-name.yml +0 -0
  24. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/.github/workflows/docs.yml +0 -0
  25. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/.github/workflows/lint.yml +0 -0
  26. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/.github/workflows/nightly.yml +0 -0
  27. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/.github/workflows/release-drafter.yml +0 -0
  28. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/.github/workflows/release.yml +0 -0
  29. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/.github/workflows/tests-cvxpygen.yml +0 -0
  30. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/.github/workflows/tests-examples.yml +0 -0
  31. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/.github/workflows/tests-lie.yml +0 -0
  32. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/.github/workflows/tests-mjx.yml +0 -0
  33. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/.github/workflows/tests-qpax.yml +0 -0
  34. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/.github/workflows/tests.yml +0 -0
  35. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/.gitignore +0 -0
  36. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/.gitmodules +0 -0
  37. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/CITATION.cff +0 -0
  38. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/CONTRIBUTING.md +0 -0
  39. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/LICENSE +0 -0
  40. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/README.md +0 -0
  41. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/docs/Foundations/constraint_reformulation.md +0 -0
  42. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/docs/Foundations/control_parameterization.md +0 -0
  43. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/docs/Foundations/ocp.md +0 -0
  44. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/docs/Foundations/scvx.md +0 -0
  45. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/docs/Foundations/time_dilation.md +0 -0
  46. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/docs/UnderTheHood/batching_jit_grad.md +0 -0
  47. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/docs/UnderTheHood/custom_algorithms_autotuners.md +0 -0
  48. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/docs/UnderTheHood/lowering_architecture.md +0 -0
  49. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/docs/UnderTheHood/vectorization_and_vmapping.md +0 -0
  50. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/docs/UsersGuide/00_introduction.md +0 -0
  51. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/docs/UsersGuide/01_hello_world_brachistochrone.md +0 -0
  52. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/docs/UsersGuide/02_drone_racing_constraints.md +0 -0
  53. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/docs/UsersGuide/03_obstacle_avoidance_vmap.md +0 -0
  54. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/docs/UsersGuide/04_viewpoint_constraints.md +0 -0
  55. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/docs/UsersGuide/05_visualization.md +0 -0
  56. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/docs/UsersGuide/06_logic.md +0 -0
  57. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/docs/UsersGuide/07_lie.md +0 -0
  58. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/docs/UsersGuide/08_mpcc.md +0 -0
  59. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/docs/UsersGuide/09_mjx_dynamics.md +0 -0
  60. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/docs/assets/favicon.png +0 -0
  61. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/docs/assets/images/ct-scvx_dark.png +0 -0
  62. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/docs/assets/images/ct-scvx_light.png +0 -0
  63. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/docs/assets/images/ctcs_dark.png +0 -0
  64. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/docs/assets/images/ctcs_light.png +0 -0
  65. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/docs/assets/images/problem_class_dark.png +0 -0
  66. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/docs/assets/images/problem_class_light.png +0 -0
  67. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/docs/assets/logo.svg +0 -0
  68. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/docs/assets/openscvx_logo_square.png +0 -0
  69. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/docs/assets/viser-client/index.html +0 -0
  70. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/docs/assets/viser-recordings/drone_racing.viser +0 -0
  71. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/docs/assets/viser-recordings/franka_fr3v2_pick_place.viser +0 -0
  72. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/docs/changelog.md +0 -0
  73. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/docs/citation.md +0 -0
  74. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/docs/examples.md +0 -0
  75. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/docs/index.md +0 -0
  76. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/docs/installation.md +0 -0
  77. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/docs/javascripts/mathjax.js +0 -0
  78. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/docs/llms.txt +0 -0
  79. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/docs/versions.json +0 -0
  80. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/_viser_embed_export.py +0 -0
  81. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/abstract/brachistochrone.py +0 -0
  82. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/abstract/brachistochrone_batched.py +0 -0
  83. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/abstract/flappy_bird.py +0 -0
  84. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/abstract/hypersensitive.py +0 -0
  85. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/abstract/impulsive.py +0 -0
  86. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/abstract/stl_integer_variable.py +0 -0
  87. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/abstract/stl_or.py +0 -0
  88. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/aircraft/dynamic_soaring.py +0 -0
  89. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/aircraft/supersonic_time_to_climb.py +0 -0
  90. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/animations/7_dof_arm.py +0 -0
  91. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/animations/_camera.py +0 -0
  92. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/animations/_render.py +0 -0
  93. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/animations/_sensor_view.py +0 -0
  94. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/animations/dr_vp_polytope.py +0 -0
  95. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/animations/franka_fr3v2_pick_place.py +0 -0
  96. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/animations/logo.py +0 -0
  97. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/animations/obstacle_avoidance_vmap.py +0 -0
  98. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/arm/3_dof_arm.py +0 -0
  99. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/arm/7_dof_arm.py +0 -0
  100. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/arm/7_dof_arm_collision.py +0 -0
  101. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/arm/7_dof_arm_vp.py +0 -0
  102. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/arm/franka_fr3v2_pick_place.py +0 -0
  103. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/arm/franka_fr3v2_viewplanning.py +0 -0
  104. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/arm/franka_fr3v2_viewplanning_nodal.py +0 -0
  105. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/car/dubins_car.py +0 -0
  106. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/car/dubins_car_disjoint.py +0 -0
  107. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/car/dubins_car_obstacle_conditional.py +0 -0
  108. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/car/dubins_car_obstacle_stl.py +0 -0
  109. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/car/dubins_car_stl_or.py +0 -0
  110. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/car/dubins_car_waypoint_stl.py +0 -0
  111. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/double_integrator/_plotting.py +0 -0
  112. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/double_integrator/moving_safe_zones.py +0 -0
  113. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/drone/2d_obstacle_avoidance_batched_ic.py +0 -0
  114. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/drone/boresight_trace_mpcc.py +0 -0
  115. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/drone/cinema_vp.py +0 -0
  116. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/drone/cinema_vp_nodal.py +0 -0
  117. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/drone/dr_double_integrator.py +0 -0
  118. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/drone/dr_vp.py +0 -0
  119. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/drone/dr_vp_nodal.py +0 -0
  120. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/drone/dr_vp_polytope.py +0 -0
  121. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/drone/drone_racing.py +0 -0
  122. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/drone/drone_racing_batched_gates.py +0 -0
  123. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/drone/logo.py +0 -0
  124. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/drone/logo_utils/acl_logo.svg +0 -0
  125. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/drone/logo_utils/circle.svg +0 -0
  126. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/drone/logo_utils/openscvx_logo_single.svg +0 -0
  127. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/drone/logo_utils/quadrotor_mesh.py +0 -0
  128. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/drone/logo_utils/svg_path_utils.py +0 -0
  129. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/drone/multi_agent_circle_swap.py +0 -0
  130. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/drone/obstacle_avoidance.py +0 -0
  131. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/drone/obstacle_avoidance_nodal.py +0 -0
  132. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/drone/obstacle_avoidance_vmap.py +0 -0
  133. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/drone/obstacle_avoidance_vmap_2d.py +0 -0
  134. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/drone/openscvx_logo.py +0 -0
  135. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/frax/panda_frax.py +0 -0
  136. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/frax/panda_frax_pick_place.py +0 -0
  137. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/frax/panda_frax_viewplanning.py +0 -0
  138. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/frax/panda_frax_waypoint.py +0 -0
  139. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/frax/ur5e_assets/ur5e.urdf +0 -0
  140. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/frax/ur5e_pen_trace.py +0 -0
  141. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/frax/ur5e_pen_trace_mpcc.py +0 -0
  142. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/mjx/cartpole_mjx.py +0 -0
  143. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/mjx/double_cartpole_mjx.py +0 -0
  144. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/mjx/skydio_x2_mjx.py +0 -0
  145. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/mjx/triple_cartpole_3d_mjx.py +0 -0
  146. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/mjx/triple_cartpole_game.py +0 -0
  147. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/mjx/triple_cartpole_mjx.py +0 -0
  148. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/mpc/double_integrator_discrete.py +0 -0
  149. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/mpc/double_integrator_drone_racing.py +0 -0
  150. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/mpc/dubins_car_circle_analytical.py +0 -0
  151. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/mpc/dubins_car_circle_discrete.py +0 -0
  152. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/mpc/realtime_double_integrator_drone_racing.py +0 -0
  153. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/plotting.py +0 -0
  154. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/plotting_viser.py +0 -0
  155. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/realtime/3DoF_pdg_realtime.py +0 -0
  156. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/realtime/6DoF_pdg_realtime.py +0 -0
  157. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/realtime/base_problems/3DoF_pdg_realtime_base.py +0 -0
  158. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/realtime/base_problems/6DoF_pdg_realtime_base.py +0 -0
  159. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/realtime/base_problems/cinema_vp_realtime_base.py +0 -0
  160. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/realtime/base_problems/drone_racing_realtime_base.py +0 -0
  161. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/realtime/base_problems/dubins_car_realtime_base.py +0 -0
  162. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/realtime/base_problems/obstacle_avoidance_realtime_base.py +0 -0
  163. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/realtime/cinema_vp_realtime.py +0 -0
  164. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/realtime/drone_racing_realtime.py +0 -0
  165. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/realtime/dubins_car_realtime.py +0 -0
  166. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/realtime/obstacle_avoidance_realtime.py +0 -0
  167. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/rocket/3DoF_pdg.py +0 -0
  168. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/rocket/6DoF_pdg.py +0 -0
  169. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/rocket/6DoF_pdg_batched_ic.py +0 -0
  170. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/rocket/ascent_launch_vehicle.py +0 -0
  171. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/spacecraft/halo_orbit.py +0 -0
  172. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/spacecraft/hohmann_transfer.py +0 -0
  173. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/spacecraft/let_transfer.py +0 -0
  174. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/spacecraft/proxops_cw.py +0 -0
  175. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/examples/spacecraft/relative_loitering.py +0 -0
  176. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/figures/ctlos_cine.gif +0 -0
  177. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/figures/ctlos_dr.gif +0 -0
  178. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/figures/dtlos_cine.gif +0 -0
  179. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/figures/dtlos_dr.gif +0 -0
  180. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/figures/openscvx_logo.svg +0 -0
  181. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/figures/openscvx_logo_square.png +0 -0
  182. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/figures/oscvx_structure_full_dark.svg +0 -0
  183. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/figures/video_preview.png +0 -0
  184. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/material/__init__.py +0 -0
  185. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/material/overrides/assets/stylesheets/custom.css +0 -0
  186. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/material/overrides/assets/stylesheets/home-dropin.css +0 -0
  187. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/material/overrides/assets/stylesheets/home-hero.css +0 -0
  188. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/material/overrides/assets/stylesheets/home-viser.css +0 -0
  189. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/material/overrides/home.html +0 -0
  190. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/material/overrides/main.html +0 -0
  191. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/material/overrides/partials/home-diagram.html +0 -0
  192. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/material/overrides/partials/home-dropin-banner.html +0 -0
  193. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/material/overrides/partials/home-hero.html +0 -0
  194. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/material/overrides/partials/home-pipeline.html +0 -0
  195. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/material/overrides/partials/home-viser-strip.html +0 -0
  196. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/material/overrides/sitemap.xml +0 -0
  197. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/mkdocs.yml +0 -0
  198. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/__init__.py +0 -0
  199. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/__main__.py +0 -0
  200. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/algorithms/__init__.py +0 -0
  201. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/algorithms/autotuner/__init__.py +0 -0
  202. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/algorithms/autotuner/acceptance_ratio.py +0 -0
  203. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/algorithms/autotuner/adaptive_proximal_weight.py +0 -0
  204. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/algorithms/autotuner/augmented_lagrangian.py +0 -0
  205. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/algorithms/autotuner/base.py +0 -0
  206. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/algorithms/autotuner/constant_proximal_weight.py +0 -0
  207. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/algorithms/autotuner/ramp_proximal_weight.py +0 -0
  208. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/algorithms/base.py +0 -0
  209. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/algorithms/history.py +0 -0
  210. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/algorithms/hyperparams.py +0 -0
  211. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/algorithms/loop.py +0 -0
  212. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/algorithms/optimization_results.py +0 -0
  213. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/algorithms/penalty.py +0 -0
  214. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/algorithms/scvx/__init__.py +0 -0
  215. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/algorithms/scvx/iteration.py +0 -0
  216. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/algorithms/scvx/penalized_trust_region.py +0 -0
  217. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/algorithms/state.py +0 -0
  218. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/algorithms/weights.py +0 -0
  219. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/config.py +0 -0
  220. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/discretization/__init__.py +0 -0
  221. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/discretization/base.py +0 -0
  222. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/discretization/discretize_linearize.py +0 -0
  223. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/discretization/linearize_discretize.py +0 -0
  224. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/discretization/linearize_discretize_sparse.py +0 -0
  225. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/discretization/sparse_utils/__init__.py +0 -0
  226. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/discretization/sparse_utils/bcoo_helpers.py +0 -0
  227. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/discretization/sparse_utils/sparse_jacobian.py +0 -0
  228. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/expert/__init__.py +0 -0
  229. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/expert/byof.py +0 -0
  230. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/expert/lowering.py +0 -0
  231. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/expert/validation.py +0 -0
  232. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/init/__init__.py +0 -0
  233. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/init/interpolation.py +0 -0
  234. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/init/inverse_kinematics.py +0 -0
  235. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/integrations/__init__.py +0 -0
  236. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/integrations/_utils.py +0 -0
  237. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/integrations/base.py +0 -0
  238. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/integrations/frax.py +0 -0
  239. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/integrations/menagerie.py +0 -0
  240. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/integrations/mjx.py +0 -0
  241. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/integrators/__init__.py +0 -0
  242. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/integrators/diffrax.py +0 -0
  243. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/integrators/runge_kutta.py +0 -0
  244. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/loader.py +0 -0
  245. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/lowered/__init__.py +0 -0
  246. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/lowered/cvxpy_constraints.py +0 -0
  247. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/lowered/cvxpy_variables.py +0 -0
  248. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/lowered/dynamics.py +0 -0
  249. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/lowered/jax_constraints.py +0 -0
  250. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/lowered/parameters.py +0 -0
  251. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/lowered/problem.py +0 -0
  252. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/lowered/unified.py +0 -0
  253. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/plotting/__init__.py +0 -0
  254. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/plotting/plotting.py +0 -0
  255. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/plotting/publication.py +0 -0
  256. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/plotting/scp_iteration.py +0 -0
  257. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/plotting/viser/__init__.py +0 -0
  258. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/plotting/viser/animated.py +0 -0
  259. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/plotting/viser/coordinates.py +0 -0
  260. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/plotting/viser/orbits.py +0 -0
  261. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/plotting/viser/plotly_integration.py +0 -0
  262. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/plotting/viser/primitives.py +0 -0
  263. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/plotting/viser/scp.py +0 -0
  264. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/plotting/viser/server.py +0 -0
  265. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/problem.py +0 -0
  266. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/propagation/__init__.py +0 -0
  267. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/propagation/post_processing.py +0 -0
  268. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/propagation/propagation.py +0 -0
  269. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/solvers/__init__.py +0 -0
  270. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/solvers/base.py +0 -0
  271. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/solvers/cones.py +0 -0
  272. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/solvers/cvxpy_ptr_solver.py +0 -0
  273. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/solvers/moreau_ptr_solver.py +0 -0
  274. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/solvers/ptr_solver.py +0 -0
  275. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/solvers/qpax_ptr_solver.py +0 -0
  276. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/__init__.py +0 -0
  277. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/affine.py +0 -0
  278. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/augmentation.py +0 -0
  279. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/builder.py +0 -0
  280. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/canonicalize.py +0 -0
  281. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/constraint_set.py +0 -0
  282. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/expr/arithmetic.py +0 -0
  283. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/expr/array.py +0 -0
  284. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/expr/constraint.py +0 -0
  285. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/expr/control.py +0 -0
  286. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/expr/lie/__init__.py +0 -0
  287. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/expr/lie/adjoint.py +0 -0
  288. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/expr/lie/se3.py +0 -0
  289. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/expr/lie/so3.py +0 -0
  290. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/expr/linalg.py +0 -0
  291. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/expr/logic.py +0 -0
  292. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/expr/math.py +0 -0
  293. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/expr/parameter.py +0 -0
  294. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/expr/spatial.py +0 -0
  295. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/expr/state.py +0 -0
  296. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/expr/stl.py +0 -0
  297. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/expr/stljax.py +0 -0
  298. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/expr/time.py +0 -0
  299. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/expr/vmap.py +0 -0
  300. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/hashing.py +0 -0
  301. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/lower.py +0 -0
  302. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/lowerers/__init__.py +0 -0
  303. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/lowerers/cvxpy/_lowerer.py +0 -0
  304. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/lowerers/cvxpy/_registry.py +0 -0
  305. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/lowerers/cvxpy/arithmetic.py +0 -0
  306. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/lowerers/cvxpy/array.py +0 -0
  307. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/lowerers/cvxpy/constraint.py +0 -0
  308. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/lowerers/cvxpy/control.py +0 -0
  309. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/lowerers/cvxpy/expr.py +0 -0
  310. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/lowerers/cvxpy/linalg.py +0 -0
  311. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/lowerers/cvxpy/logic.py +0 -0
  312. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/lowerers/cvxpy/math.py +0 -0
  313. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/lowerers/cvxpy/state.py +0 -0
  314. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/lowerers/jax/_lowerer.py +0 -0
  315. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/lowerers/jax/_registry.py +0 -0
  316. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/lowerers/jax/arithmetic.py +0 -0
  317. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/lowerers/jax/array.py +0 -0
  318. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/lowerers/jax/constraint.py +0 -0
  319. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/lowerers/jax/control.py +0 -0
  320. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/lowerers/jax/expr.py +0 -0
  321. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/lowerers/jax/lie.py +0 -0
  322. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/lowerers/jax/linalg.py +0 -0
  323. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/lowerers/jax/logic.py +0 -0
  324. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/lowerers/jax/math.py +0 -0
  325. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/lowerers/jax/spatial.py +0 -0
  326. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/lowerers/jax/state.py +0 -0
  327. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/lowerers/jax/stl.py +0 -0
  328. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/lowerers/jax/stljax.py +0 -0
  329. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/lowerers/jax/vmap.py +0 -0
  330. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/lowerers/latex/_lowerer.py +0 -0
  331. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/lowerers/latex/_registry.py +0 -0
  332. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/lowerers/latex/arithmetic.py +0 -0
  333. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/lowerers/latex/array.py +0 -0
  334. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/lowerers/latex/constraint.py +0 -0
  335. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/lowerers/latex/control.py +0 -0
  336. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/lowerers/latex/expr.py +0 -0
  337. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/lowerers/latex/formulation.py +0 -0
  338. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/lowerers/latex/lie.py +0 -0
  339. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/lowerers/latex/linalg.py +0 -0
  340. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/lowerers/latex/logic.py +0 -0
  341. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/lowerers/latex/math.py +0 -0
  342. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/lowerers/latex/spatial.py +0 -0
  343. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/lowerers/latex/state.py +0 -0
  344. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/lowerers/latex/stl.py +0 -0
  345. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/lowerers/latex/vmap.py +0 -0
  346. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/parser/__init__.py +0 -0
  347. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/parser/_registry.py +0 -0
  348. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/parser/array.py +0 -0
  349. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/parser/constraint.py +0 -0
  350. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/parser/lie.py +0 -0
  351. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/parser/linalg.py +0 -0
  352. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/parser/logic.py +0 -0
  353. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/parser/math.py +0 -0
  354. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/parser/parser.py +0 -0
  355. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/parser/spatial.py +0 -0
  356. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/parser/stl.py +0 -0
  357. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/parser/stljax.py +0 -0
  358. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/parser/tokenizer.py +0 -0
  359. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/preprocessing.py +0 -0
  360. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/problem.py +0 -0
  361. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/sparsity.py +0 -0
  362. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/symbolic/unified.py +0 -0
  363. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/utils/__init__.py +0 -0
  364. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/utils/cache.py +0 -0
  365. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/utils/caching.py +0 -0
  366. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/utils/printing.py +0 -0
  367. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/utils/profiling.py +0 -0
  368. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx/utils/utils.py +0 -0
  369. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx.egg-info/dependency_links.txt +0 -0
  370. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx.egg-info/entry_points.txt +0 -0
  371. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx.egg-info/requires.txt +0 -0
  372. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/openscvx.egg-info/top_level.txt +0 -0
  373. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/pyproject.toml +0 -0
  374. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/scripts/gen_example_pages.py +0 -0
  375. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/scripts/gen_ref_pages.py +0 -0
  376. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/scripts/mkdocs_copy_viser_client_hook.py +0 -0
  377. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/scripts/mkdocs_seo_hook.py +0 -0
  378. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/setup.cfg +0 -0
  379. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/__init__.py +0 -0
  380. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/algorithms/__init__.py +0 -0
  381. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/algorithms/_iteration_helpers.py +0 -0
  382. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/algorithms/autotuner/__init__.py +0 -0
  383. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/algorithms/autotuner/test_defaults_agreement.py +0 -0
  384. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/algorithms/autotuner/test_hyper_overrides.py +0 -0
  385. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/algorithms/autotuner/test_update_weights_jit.py +0 -0
  386. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/algorithms/test_algorithm_state_pytree.py +0 -0
  387. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/algorithms/test_iteration_fn_jit.py +0 -0
  388. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/algorithms/test_iteration_fn_parity.py +0 -0
  389. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/algorithms/test_make_solve_loop.py +0 -0
  390. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/brachistochrone_analytical.py +0 -0
  391. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/conftest.py +0 -0
  392. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/e2e/__init__.py +0 -0
  393. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/e2e/test_brachistochrone.py +0 -0
  394. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/e2e/test_impulsive.py +0 -0
  395. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/e2e/test_multishot_propagation.py +0 -0
  396. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/e2e/test_solve_batched_brachistochrone.py +0 -0
  397. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/e2e/test_solve_batched_cvxpy_export_errors.py +0 -0
  398. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/e2e/test_solve_batched_export_roundtrip.py +0 -0
  399. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/e2e/test_solve_jax_bare_brachistochrone.py +0 -0
  400. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/e2e/test_solve_jax_jit_brachistochrone.py +0 -0
  401. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/e2e/test_solve_jax_vmap_brachistochrone.py +0 -0
  402. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/e2e/test_solve_jax_vmap_converged_no_drift.py +0 -0
  403. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/fixtures/brachistochrone.json +0 -0
  404. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/fixtures/brachistochrone.yaml +0 -0
  405. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/hohmann_analytical.py +0 -0
  406. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/integrations/__init__.py +0 -0
  407. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/integrations/test_mjx.py +0 -0
  408. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/integrations/test_mjx_dynamics.py +0 -0
  409. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/solvers/__init__.py +0 -0
  410. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/solvers/_iteration_callback_helpers.py +0 -0
  411. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/solvers/test_cvxpy_callback_jit_spike.py +0 -0
  412. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/solvers/test_iteration_callback_cvxpy.py +0 -0
  413. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/solvers/test_iteration_callback_moreau.py +0 -0
  414. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/solvers/test_iteration_callback_qpax.py +0 -0
  415. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/solvers/test_iteration_callback_vmap.py +0 -0
  416. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/solvers/test_moreau_ptr_solver.py +0 -0
  417. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/solvers/test_qpax_ptr_solver.py +0 -0
  418. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/solvers/test_subproblem_pytree.py +0 -0
  419. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/symbolic/__init__.py +0 -0
  420. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/symbolic/expr/__init__.py +0 -0
  421. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/symbolic/expr/test_arithmetic.py +0 -0
  422. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/symbolic/expr/test_array.py +0 -0
  423. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/symbolic/expr/test_constraint.py +0 -0
  424. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/symbolic/expr/test_expr.py +0 -0
  425. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/symbolic/expr/test_guess_expr.py +0 -0
  426. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/symbolic/expr/test_lie.py +0 -0
  427. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/symbolic/expr/test_linalg.py +0 -0
  428. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/symbolic/expr/test_logic.py +0 -0
  429. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/symbolic/expr/test_math.py +0 -0
  430. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/symbolic/expr/test_node_reference.py +0 -0
  431. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/symbolic/expr/test_parameters.py +0 -0
  432. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/symbolic/expr/test_scaling.py +0 -0
  433. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/symbolic/expr/test_spatial.py +0 -0
  434. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/symbolic/expr/test_stl.py +0 -0
  435. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/symbolic/expr/test_variable.py +0 -0
  436. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/symbolic/expr/test_vmap.py +0 -0
  437. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/symbolic/parser/__init__.py +0 -0
  438. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/symbolic/parser/test_array.py +0 -0
  439. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/symbolic/parser/test_constraint.py +0 -0
  440. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/symbolic/parser/test_lie.py +0 -0
  441. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/symbolic/parser/test_linalg.py +0 -0
  442. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/symbolic/parser/test_load.py +0 -0
  443. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/symbolic/parser/test_logic.py +0 -0
  444. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/symbolic/parser/test_math.py +0 -0
  445. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/symbolic/parser/test_parser.py +0 -0
  446. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/symbolic/parser/test_spatial.py +0 -0
  447. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/symbolic/parser/test_stl.py +0 -0
  448. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/symbolic/parser/test_tokenizer.py +0 -0
  449. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/symbolic/parser/test_vmap.py +0 -0
  450. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/symbolic/test_augmentation.py +0 -0
  451. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/symbolic/test_gmsr.py +0 -0
  452. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/symbolic/test_hashing.py +0 -0
  453. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/symbolic/test_latex_formulation.py +0 -0
  454. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/symbolic/test_lower_cvxpy.py +0 -0
  455. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/symbolic/test_lower_jax.py +0 -0
  456. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/symbolic/test_lower_latex.py +0 -0
  457. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/symbolic/test_preprocessing.py +0 -0
  458. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/symbolic/test_sparsity.py +0 -0
  459. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/symbolic/test_unified.py +0 -0
  460. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/test_autotuning.py +0 -0
  461. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/test_cvxpygen_optional.py +0 -0
  462. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/test_discretization.py +0 -0
  463. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/test_examples.py +0 -0
  464. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/test_expert.py +0 -0
  465. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/test_init.py +0 -0
  466. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/test_initialize_syncs_guesses.py +0 -0
  467. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/test_integrators.py +0 -0
  468. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/test_loader.py +0 -0
  469. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/test_optimization_results.py +0 -0
  470. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/test_plotting.py +0 -0
  471. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/test_post_process_batched_tau_clamp.py +0 -0
  472. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/test_propagation.py +0 -0
  473. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/test_results_parameters.py +0 -0
  474. {openscvx-0.5.3.dev50 → openscvx-0.5.3.dev51}/tests/test_solve_batched_inference.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: openscvx
3
- Version: 0.5.3.dev50
3
+ Version: 0.5.3.dev51
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
@@ -91,4 +91,41 @@ def dVdt(self, tau: float, V: jnp.ndarray, u_cur: np.ndarray, u_next: np.ndarray
91
91
  )
92
92
  return dVdt.flatten()
93
93
  ```
94
-
94
+
95
+ ## Supplying your own Jacobian
96
+
97
+ The state and control Jacobians above (`dfdx`, `dfdu`) come from automatic
98
+ differentiation of the dynamics you wrote. Occasionally the exact Jacobian is
99
+ not the one you want: a drag law, a contact model, or a lookup table can be
100
+ smooth enough to integrate while its true derivative makes the convex
101
+ subproblem badly conditioned, so the trust region collapses and the SCP loop
102
+ crawls. The standard remedy is to linearize with a deliberately simplified
103
+ (inexact) Jacobian.
104
+
105
+ `Expr.with_jacobian` applies that remedy to a single term:
106
+
107
+ ``` py
108
+ drag = -0.5 * rho * ox.Norm(vel) * vel
109
+ J_drag = -0.5 * rho * ox.Norm(vel) * np.eye(3) # drops the d||v||/dv term
110
+
111
+ dynamics = {"pos": vel, "vel": thrust / m + drag.with_jacobian({vel: J_drag})}
112
+ ```
113
+
114
+ The keys are the `State` or `Control` objects the derivative is taken with
115
+ respect to, and each value is an expression (or constant array) of shape
116
+ `(*term.shape, *variable.shape)`. Directions you do not name are still
117
+ differentiated automatically, so the example above hands over `∂/∂vel` while
118
+ `∂/∂thrust` still comes from autodiff.
119
+
120
+ The *value* of the term is untouched — only the search direction changes — so a
121
+ converged trajectory still satisfies the original nonlinear dynamics; the
122
+ defect and the propagated solution are computed with the term as written. An
123
+ inexact Jacobian trades linearization accuracy (and hence convergence rate) for
124
+ conditioning, so reach for it when a term is a known source of stiffness, not
125
+ as a default.
126
+
127
+ The override lives inside the lowered JAX function, so every downstream
128
+ derivative picks it up: the discretizer's `A`/`B`, nonconvex constraint
129
+ linearization, and the sparsity pattern used for coloring. It has no meaning
130
+ inside a constraint that is handed to the convex solver as written, and lowering
131
+ one there raises.
@@ -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.dev50'
22
- __version_tuple__ = version_tuple = (0, 5, 3, 'dev50')
21
+ __version__ = version = '0.5.3.dev51'
22
+ __version_tuple__ = version_tuple = (0, 5, 3, 'dev51')
23
23
 
24
- __commit_id__ = commit_id = 'g7ab51dee3'
24
+ __commit_id__ = commit_id = 'g21d5581a4'
@@ -33,6 +33,11 @@ Module Organization:
33
33
  Array manipulation operations including `Index`, `Concat`, `Stack`, `Hstack`,
34
34
  and `Vstack` for indexing, slicing, and combining arrays.
35
35
 
36
+ User-Supplied Jacobians (autodiff.py):
37
+ `WithJacobian`, built by `Expr.with_jacobian`, replaces a subexpression's
38
+ derivative with respect to chosen variables — the inexact-Jacobian knob for
39
+ SCP conditioning.
40
+
36
41
  Constraints (constraint.py):
37
42
  Constraint types including `Constraint`, `Equality`, `Inequality`,
38
43
  `NodalConstraint`, and `CTCS` (Continuous-Time Constraint Satisfaction).
@@ -80,6 +85,9 @@ from .arithmetic import Add, Div, MatMul, Mul, Neg, Power, Sub
80
85
  # Array operations
81
86
  from .array import Block, Concat, Hstack, Index, Stack, Vstack
82
87
 
88
+ # User-supplied Jacobians
89
+ from .autodiff import WithJacobian
90
+
83
91
  # Specialized constraints
84
92
  from .constraint import (
85
93
  CTCS,
@@ -258,4 +266,6 @@ __all__ = [
258
266
  "ctcs",
259
267
  # Vmap
260
268
  "Vmap",
269
+ # User-supplied Jacobians
270
+ "WithJacobian",
261
271
  ]
@@ -0,0 +1,159 @@
1
+ """User-supplied Jacobians for a subexpression.
2
+
3
+ Successive convexification linearizes the dynamics and constraints at every
4
+ iteration, so the *Jacobian* — not the value — is what shapes each convex
5
+ subproblem. Occasionally the exact Jacobian is the wrong one to hand the
6
+ solver: an aerodynamic drag term, a contact model, or a lookup table can be
7
+ smooth enough to integrate but stiff enough that its true derivative wrecks the
8
+ conditioning of the subproblem. The standard remedy is a deliberately
9
+ simplified (inexact) Jacobian — the trajectory still converges to a solution of
10
+ the *nonlinear* problem, because the value used for the defect is untouched;
11
+ only the search direction changes.
12
+
13
+ :class:`WithJacobian` is that remedy, written at sub-expression granularity::
14
+
15
+ drag = -0.5 * rho * ox.Norm(vel) * vel
16
+ accel = thrust / m + drag.with_jacobian({vel: J_drag})
17
+
18
+ The node wraps a subexpression and carries an override Jacobian per variable.
19
+ Lowering to JAX emits a :func:`jax.custom_jvp` rule around the wrapped
20
+ subexpression, so every downstream differentiation — the discretizer's
21
+ ``jacfwd``, constraint linearization, sparse coloring — sees the user's
22
+ Jacobian in the overridden directions and autodiff everywhere else, with no
23
+ further special-casing. The primal value is always the wrapped expression
24
+ itself.
25
+ """
26
+
27
+ import hashlib
28
+ from typing import Dict, List, Tuple
29
+
30
+ import numpy as np
31
+
32
+ from .expr import Expr, to_expr
33
+ from .variable import Variable
34
+
35
+
36
+ def _without_unit_axes(shape: Tuple[int, ...]) -> Tuple[int, ...]:
37
+ """Drop length-1 axes, the way :class:`Constant` squeezes a wrapped array."""
38
+ return tuple(d for d in shape if d != 1)
39
+
40
+
41
+ class WithJacobian(Expr):
42
+ """A subexpression whose derivative w.r.t. chosen variables is user-supplied.
43
+
44
+ Construct this through :meth:`Expr.with_jacobian` rather than directly. The
45
+ node evaluates exactly like the expression it wraps; only differentiation
46
+ differs, and only in the overridden directions (see the module docstring for
47
+ the motivation).
48
+
49
+ Attributes:
50
+ expr: The wrapped expression, and the node's value.
51
+ overrides: ``(variable, jacobian)`` pairs in the order given, each
52
+ Jacobian shaped ``(*expr.shape, *variable.shape)``.
53
+ """
54
+
55
+ def __init__(self, expr: Expr, jacobians: Dict[Variable, Expr]):
56
+ """Wrap ``expr`` with an override Jacobian per variable.
57
+
58
+ Args:
59
+ expr: Expression whose derivative is being overridden.
60
+ jacobians: Map from a ``State`` or ``Control`` to the Jacobian of
61
+ ``expr`` with respect to it. Values are coerced with
62
+ :func:`to_expr`, so constant matrices are accepted.
63
+
64
+ Raises:
65
+ TypeError: If a key is not a decision variable.
66
+ ValueError: If no Jacobian is given.
67
+ """
68
+ if not jacobians:
69
+ raise ValueError(
70
+ "with_jacobian needs at least one {variable: jacobian} entry; an empty "
71
+ "mapping would wrap the expression without changing anything."
72
+ )
73
+ self.expr = to_expr(expr)
74
+ overrides = []
75
+ for var, jac in jacobians.items():
76
+ if not isinstance(var, Variable):
77
+ raise TypeError(
78
+ f"with_jacobian keys must be the State or Control the derivative is "
79
+ f"taken with respect to, got {type(var).__name__}. Write "
80
+ f"`expr.with_jacobian({{vel: J_vel}})` with `vel` the variable itself."
81
+ )
82
+ overrides.append((var, to_expr(jac)))
83
+ self.overrides: List[Tuple[Variable, Expr]] = overrides
84
+
85
+ def children(self) -> List[Expr]:
86
+ """Return the wrapped expression followed by each override Jacobian.
87
+
88
+ The overridden variables are not children: they identify *directions*,
89
+ not operands, and appear as leaves inside the Jacobian expressions only
90
+ if the user put them there.
91
+ """
92
+ return [self.expr, *(jac for _, jac in self.overrides)]
93
+
94
+ def canonicalize(self) -> Expr:
95
+ """Canonicalize the wrapped expression and every override Jacobian."""
96
+ return WithJacobian(
97
+ self.expr.canonicalize(),
98
+ {var: jac.canonicalize() for var, jac in self.overrides},
99
+ )
100
+
101
+ def check_shape(self) -> Tuple[int, ...]:
102
+ """Return the wrapped expression's shape, validating each Jacobian.
103
+
104
+ A Jacobian must be shaped ``(*expr.shape, *var.shape)``. Unit axes are
105
+ ignored in the comparison: a constant is squeezed when it is wrapped, so
106
+ an honest ``(3, 1)`` Jacobian arrives as ``(3,)``. The JAX lowering
107
+ reshapes it back before contracting.
108
+
109
+ Returns:
110
+ The shape of the wrapped expression — the wrapper is value-transparent.
111
+
112
+ Raises:
113
+ ValueError: If a Jacobian's shape is not ``(*expr.shape, *var.shape)``.
114
+ """
115
+ shape = self.expr.check_shape()
116
+ for var, jac in self.overrides:
117
+ expected = (*shape, *var.shape)
118
+ got = jac.check_shape()
119
+ if _without_unit_axes(got) != _without_unit_axes(expected):
120
+ raise ValueError(
121
+ f"Jacobian for {var.__class__.__name__} '{var.name}' has shape {got}, "
122
+ f"expected {expected}: the derivative of an expression of shape "
123
+ f"{shape} with respect to a variable of shape {var.shape}."
124
+ )
125
+ return shape
126
+
127
+ def sparsity(self, n_x: int, n_u: int) -> Tuple[np.ndarray, np.ndarray]:
128
+ """Conservative pattern: the children's, widened to the overridden columns.
129
+
130
+ The default union over children is not enough here. A user Jacobian may
131
+ be a constant (no dependence of its own) yet still couple outputs to
132
+ every entry of the overridden variable, so those columns are marked
133
+ dense on top of the children's pattern.
134
+ """
135
+ from .control import Control
136
+
137
+ S_x, S_u = super().sparsity(n_x, n_u)
138
+ for var, _ in self.overrides:
139
+ if var._slice is None:
140
+ continue
141
+ S = S_u if isinstance(var, Control) else S_x
142
+ S[:, var._slice] = True
143
+ return S_x, S_u
144
+
145
+ def _hash_into(self, hasher: "hashlib._Hash") -> None:
146
+ """Hash the wrapper, the wrapped expression, and each override in order.
147
+
148
+ Args:
149
+ hasher: A hashlib hash object to update
150
+ """
151
+ hasher.update(b"WithJacobian")
152
+ self.expr._hash_into(hasher)
153
+ for var, jac in self.overrides:
154
+ var._hash_into(hasher)
155
+ jac._hash_into(hasher)
156
+
157
+ def __repr__(self) -> str:
158
+ vars_ = ", ".join(var.name for var, _ in self.overrides)
159
+ return f"{self.expr!r}.with_jacobian({{{vars_}}})"
@@ -308,6 +308,47 @@ class Expr:
308
308
  """
309
309
  return NodeReference(self, k)
310
310
 
311
+ def with_jacobian(self, jacobians: dict) -> "Expr":
312
+ """Override this expression's derivative w.r.t. chosen variables.
313
+
314
+ Successive convexification linearizes at every iteration, so the Jacobian
315
+ of a term — not its value — is what conditions the convex subproblem. A
316
+ deliberately simplified (inexact) Jacobian is a standard remedy for a term
317
+ that is smooth enough to integrate but whose true derivative makes the
318
+ subproblem badly conditioned. The value of the expression is untouched, so
319
+ the converged trajectory still satisfies the original nonlinear problem;
320
+ only the search direction changes.
321
+
322
+ Directions that are not overridden are still differentiated automatically,
323
+ so a single term can hand-specify its state Jacobian and let the control
324
+ Jacobian fall out of autodiff.
325
+
326
+ Args:
327
+ jacobians: Map from a ``State`` or ``Control`` to the Jacobian of this
328
+ expression with respect to it, shaped ``(*self.shape, *var.shape)``
329
+ (a variable of shape ``(n,)`` and a scalar expression give shape
330
+ ``(n,)``). Constant matrices are accepted alongside expressions.
331
+
332
+ Returns:
333
+ Expr: A ``WithJacobian`` node wrapping this expression.
334
+
335
+ Example:
336
+ Damp the drag Jacobian without changing the drag force:
337
+
338
+ drag = -0.5 * rho * ox.Norm(vel) * vel
339
+ J_drag = -0.5 * rho * ox.Norm(vel) * np.eye(3) # drops the d|v|/dv term
340
+
341
+ dynamics = {"vel": thrust / m + drag.with_jacobian({vel: J_drag})}
342
+
343
+ Note:
344
+ The override applies on the JAX path — dynamics linearization and
345
+ constraint linearization. Inside a constraint lowered to CVXPy the
346
+ wrapper has no meaning and raises.
347
+ """
348
+ from .autodiff import WithJacobian
349
+
350
+ return WithJacobian(self, jacobians)
351
+
311
352
  def children(self) -> List["Expr"]:
312
353
  """Return the child expressions of this node.
313
354
 
@@ -58,6 +58,12 @@ class Variable(Leaf):
58
58
  def __repr__(self) -> str:
59
59
  return f"Var({self.name!r})"
60
60
 
61
+ # ``Expr.__eq__`` builds an Equality constraint rather than comparing, which
62
+ # makes Python drop the inherited ``__hash__``. Variables are identities, not
63
+ # values, so restore hashing by identity: it lets a variable key a dict, as in
64
+ # ``expr.with_jacobian({vel: J_vel})``.
65
+ __hash__ = object.__hash__
66
+
61
67
  def _hash_into(self, hasher: "hashlib._Hash") -> None:
62
68
  """Hash Variable using its slice (canonical position, name-invariant).
63
69
 
@@ -22,6 +22,7 @@ Example::
22
22
  from openscvx.symbolic.lowerers.cvxpy import (
23
23
  arithmetic, # noqa: F401
24
24
  array, # noqa: F401
25
+ autodiff, # noqa: F401
25
26
  constraint, # noqa: F401
26
27
  control, # noqa: F401
27
28
  expr, # noqa: F401
@@ -0,0 +1,36 @@
1
+ """CVXPy visitors for user-supplied Jacobians.
2
+
3
+ Visitors: WithJacobian
4
+
5
+ A ``WithJacobian`` override reshapes a *linearization*, and linearization happens
6
+ on the JAX path. The convex subproblem sees convex constraints verbatim, with no
7
+ derivative taken, so the wrapper has nothing to act on here and raises
8
+ ``NotImplementedError`` — the same treatment ``CTCS`` gets for being a
9
+ JAX-side construct.
10
+ """
11
+
12
+ import cvxpy as cp
13
+
14
+ from openscvx.symbolic.expr.autodiff import WithJacobian
15
+ from openscvx.symbolic.lowerers.cvxpy._registry import visitor # noqa: F401
16
+
17
+
18
+ @visitor(WithJacobian)
19
+ def _visit_with_jacobian(lowerer, node: WithJacobian) -> cp.Expression:
20
+ """Raise NotImplementedError for a Jacobian override inside a convex constraint.
21
+
22
+ Args:
23
+ node: WithJacobian expression node
24
+
25
+ Raises:
26
+ NotImplementedError: Always — see the module docstring.
27
+ """
28
+ raise NotImplementedError(
29
+ "`.with_jacobian(...)` overrides the derivative used when a nonconvex "
30
+ "expression is linearized, which only happens on the JAX path (dynamics and "
31
+ "nonconvex constraints). This expression was lowered to CVXPy as part of a "
32
+ "convex constraint, which is passed to the solver as written and never "
33
+ "differentiated, so the override has no meaning here. Apply "
34
+ "`.with_jacobian(...)` to the nonconvex term instead, or drop it from this "
35
+ "constraint."
36
+ )
@@ -23,6 +23,7 @@ Example::
23
23
  from openscvx.symbolic.lowerers.jax import (
24
24
  arithmetic, # noqa: F401
25
25
  array, # noqa: F401
26
+ autodiff, # noqa: F401
26
27
  constraint, # noqa: F401
27
28
  control, # noqa: F401
28
29
  expr, # noqa: F401
@@ -0,0 +1,82 @@
1
+ """JAX visitors for user-supplied Jacobians.
2
+
3
+ Visitors: WithJacobian
4
+
5
+ Lowers a ``WithJacobian`` node to its wrapped subexpression wrapped in a
6
+ :func:`jax.custom_jvp` rule. The rule zeroes the tangent of every overridden
7
+ variable before differentiating the inner function, then adds ``J @ dvar`` for
8
+ each override — so overridden directions come from the user's Jacobian and all
9
+ others from autodiff. Because the override lives inside the lowered function,
10
+ every downstream differentiation (the discretizer's ``jacfwd``, constraint
11
+ linearization, sparse coloring) picks it up with no further plumbing.
12
+
13
+ Unlike the ``Vmap`` and ``Cond`` visitors, this one does not pause the value
14
+ memo: the nested ``jax.jvp`` trace receives its own ``(x, u)`` tracers rather
15
+ than reusing the captured outer ones, and the memo is keyed on all four
16
+ arguments, so a value cached in one trace can never be handed to a caller in
17
+ another.
18
+ """
19
+
20
+ import jax
21
+ import jax.numpy as jnp
22
+
23
+ from openscvx.symbolic.expr.autodiff import WithJacobian
24
+ from openscvx.symbolic.expr.control import Control
25
+ from openscvx.symbolic.lowerers.jax._registry import visitor # noqa: F401
26
+
27
+
28
+ @visitor(WithJacobian)
29
+ def _visit_with_jacobian(lowerer, node: WithJacobian):
30
+ """Lower a user-Jacobian override to a ``jax.custom_jvp``-wrapped function.
31
+
32
+ Args:
33
+ node: WithJacobian expression node
34
+
35
+ Returns:
36
+ Function (x, u, node, params) -> value of the wrapped expression, whose
37
+ derivative w.r.t. each overridden variable is the user's Jacobian.
38
+
39
+ Raises:
40
+ ValueError: If an overridden variable has no slice assigned (unification
41
+ not run).
42
+ """
43
+ inner = lowerer.lower(node.expr)
44
+ out_shape = node.expr.check_shape()
45
+ overrides = []
46
+ for var, jac in node.overrides:
47
+ if var._slice is None:
48
+ raise ValueError(f"{var.__class__.__name__} {var.name!r} has no slice assigned")
49
+ # Squeezed constants come back as e.g. () for a (1, 1) Jacobian, so the
50
+ # declared shape is restored before contracting with the tangent.
51
+ jac_shape = (*out_shape, *var.shape)
52
+ overrides.append((var._slice, isinstance(var, Control), lowerer.lower(jac), jac_shape))
53
+ overrides = tuple(overrides)
54
+
55
+ def with_jacobian_fn(x, u, node_idx, params):
56
+ def inner_xu(x_, u_):
57
+ return inner(x_, u_, node_idx, params)
58
+
59
+ f = jax.custom_jvp(inner_xu)
60
+
61
+ @f.defjvp
62
+ def _jvp(primals, tangents):
63
+ x_, u_ = primals
64
+ dx, du = tangents
65
+ # Autodiff supplies the non-overridden directions: blank the
66
+ # overridden slices so their contribution comes only from below.
67
+ dx_free, du_free = dx, du
68
+ for sl, is_control, _, _ in overrides:
69
+ if is_control:
70
+ du_free = du_free.at[sl].set(0.0)
71
+ else:
72
+ dx_free = dx_free.at[sl].set(0.0)
73
+ out, tangent = jax.jvp(inner_xu, (x_, u_), (dx_free, du_free))
74
+ for sl, is_control, jac_fn, jac_shape in overrides:
75
+ J = jnp.reshape(jac_fn(x_, u_, node_idx, params), jac_shape)
76
+ dvar = du[sl] if is_control else dx[sl]
77
+ tangent = tangent + jnp.tensordot(J, dvar, axes=1)
78
+ return out, tangent
79
+
80
+ return f(x, u)
81
+
82
+ return with_jacobian_fn
@@ -27,6 +27,7 @@ Example::
27
27
  from openscvx.symbolic.lowerers.latex import (
28
28
  arithmetic, # noqa: F401
29
29
  array, # noqa: F401
30
+ autodiff, # noqa: F401
30
31
  constraint, # noqa: F401
31
32
  control, # noqa: F401
32
33
  expr, # noqa: F401
@@ -0,0 +1,17 @@
1
+ """LaTeX visitors for user-supplied Jacobians.
2
+
3
+ Visitors: WithJacobian
4
+
5
+ A Jacobian override changes how a term is differentiated, not what it equals, so
6
+ the rendered formulation shows the wrapped expression alone — the same choice the
7
+ ``CTCS`` visitor makes in rendering the constraint it stands for.
8
+ """
9
+
10
+ from openscvx.symbolic.expr.autodiff import WithJacobian
11
+ from openscvx.symbolic.lowerers.latex._registry import visitor
12
+
13
+
14
+ @visitor(WithJacobian)
15
+ def _visit_with_jacobian(lowerer, node: WithJacobian):
16
+ """Render the wrapped expression; the override is invisible in the math."""
17
+ return lowerer.lower(node.expr)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: openscvx
3
- Version: 0.5.3.dev50
3
+ Version: 0.5.3.dev51
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
@@ -281,6 +281,7 @@ openscvx/symbolic/unified.py
281
281
  openscvx/symbolic/expr/__init__.py
282
282
  openscvx/symbolic/expr/arithmetic.py
283
283
  openscvx/symbolic/expr/array.py
284
+ openscvx/symbolic/expr/autodiff.py
284
285
  openscvx/symbolic/expr/constraint.py
285
286
  openscvx/symbolic/expr/control.py
286
287
  openscvx/symbolic/expr/expr.py
@@ -305,6 +306,7 @@ openscvx/symbolic/lowerers/cvxpy/_lowerer.py
305
306
  openscvx/symbolic/lowerers/cvxpy/_registry.py
306
307
  openscvx/symbolic/lowerers/cvxpy/arithmetic.py
307
308
  openscvx/symbolic/lowerers/cvxpy/array.py
309
+ openscvx/symbolic/lowerers/cvxpy/autodiff.py
308
310
  openscvx/symbolic/lowerers/cvxpy/constraint.py
309
311
  openscvx/symbolic/lowerers/cvxpy/control.py
310
312
  openscvx/symbolic/lowerers/cvxpy/expr.py
@@ -317,6 +319,7 @@ openscvx/symbolic/lowerers/jax/_lowerer.py
317
319
  openscvx/symbolic/lowerers/jax/_registry.py
318
320
  openscvx/symbolic/lowerers/jax/arithmetic.py
319
321
  openscvx/symbolic/lowerers/jax/array.py
322
+ openscvx/symbolic/lowerers/jax/autodiff.py
320
323
  openscvx/symbolic/lowerers/jax/constraint.py
321
324
  openscvx/symbolic/lowerers/jax/control.py
322
325
  openscvx/symbolic/lowerers/jax/expr.py
@@ -334,6 +337,7 @@ openscvx/symbolic/lowerers/latex/_lowerer.py
334
337
  openscvx/symbolic/lowerers/latex/_registry.py
335
338
  openscvx/symbolic/lowerers/latex/arithmetic.py
336
339
  openscvx/symbolic/lowerers/latex/array.py
340
+ openscvx/symbolic/lowerers/latex/autodiff.py
337
341
  openscvx/symbolic/lowerers/latex/constraint.py
338
342
  openscvx/symbolic/lowerers/latex/control.py
339
343
  openscvx/symbolic/lowerers/latex/expr.py
@@ -438,6 +442,7 @@ tests/symbolic/test_unified.py
438
442
  tests/symbolic/expr/__init__.py
439
443
  tests/symbolic/expr/test_arithmetic.py
440
444
  tests/symbolic/expr/test_array.py
445
+ tests/symbolic/expr/test_autodiff.py
441
446
  tests/symbolic/expr/test_constraint.py
442
447
  tests/symbolic/expr/test_expr.py
443
448
  tests/symbolic/expr/test_guess_expr.py
@@ -267,6 +267,7 @@
267
267
  "openscvx/symbolic/expr/__init__.py",
268
268
  "openscvx/symbolic/expr/arithmetic.py",
269
269
  "openscvx/symbolic/expr/array.py",
270
+ "openscvx/symbolic/expr/autodiff.py",
270
271
  "openscvx/symbolic/expr/constraint.py",
271
272
  "openscvx/symbolic/expr/control.py",
272
273
  "openscvx/symbolic/expr/expr.py",
@@ -293,6 +294,7 @@
293
294
  "openscvx/symbolic/lowerers/cvxpy/_registry.py",
294
295
  "openscvx/symbolic/lowerers/cvxpy/arithmetic.py",
295
296
  "openscvx/symbolic/lowerers/cvxpy/array.py",
297
+ "openscvx/symbolic/lowerers/cvxpy/autodiff.py",
296
298
  "openscvx/symbolic/lowerers/cvxpy/constraint.py",
297
299
  "openscvx/symbolic/lowerers/cvxpy/control.py",
298
300
  "openscvx/symbolic/lowerers/cvxpy/expr.py",
@@ -305,6 +307,7 @@
305
307
  "openscvx/symbolic/lowerers/jax/_registry.py",
306
308
  "openscvx/symbolic/lowerers/jax/arithmetic.py",
307
309
  "openscvx/symbolic/lowerers/jax/array.py",
310
+ "openscvx/symbolic/lowerers/jax/autodiff.py",
308
311
  "openscvx/symbolic/lowerers/jax/constraint.py",
309
312
  "openscvx/symbolic/lowerers/jax/control.py",
310
313
  "openscvx/symbolic/lowerers/jax/expr.py",
@@ -322,6 +325,7 @@
322
325
  "openscvx/symbolic/lowerers/latex/_registry.py",
323
326
  "openscvx/symbolic/lowerers/latex/arithmetic.py",
324
327
  "openscvx/symbolic/lowerers/latex/array.py",
328
+ "openscvx/symbolic/lowerers/latex/autodiff.py",
325
329
  "openscvx/symbolic/lowerers/latex/constraint.py",
326
330
  "openscvx/symbolic/lowerers/latex/control.py",
327
331
  "openscvx/symbolic/lowerers/latex/expr.py",
@@ -406,6 +410,7 @@
406
410
  "tests/symbolic/expr/__init__.py",
407
411
  "tests/symbolic/expr/test_arithmetic.py",
408
412
  "tests/symbolic/expr/test_array.py",
413
+ "tests/symbolic/expr/test_autodiff.py",
409
414
  "tests/symbolic/expr/test_constraint.py",
410
415
  "tests/symbolic/expr/test_expr.py",
411
416
  "tests/symbolic/expr/test_guess_expr.py",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "tag": "0.5.2",
3
- "distance": 50,
4
- "node": "g7ab51dee32e9703abaf0ae5471aff63949bc7c5f",
3
+ "distance": 51,
4
+ "node": "g21d5581a44e245dad63fdc59c19bcf78abce2ef3",
5
5
  "dirty": false,
6
6
  "branch": "main",
7
7
  "node_date": "2026-08-15"