openscvx 0.5.3.dev37__tar.gz → 0.5.3.dev39__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 (457) hide show
  1. {openscvx-0.5.3.dev37/openscvx.egg-info → openscvx-0.5.3.dev39}/PKG-INFO +1 -1
  2. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/spacecraft/relative_loitering.py +0 -1
  3. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/__init__.py +3 -0
  4. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/_version.py +3 -3
  5. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/problem.py +112 -10
  6. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/symbolic/augmentation.py +31 -35
  7. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/symbolic/builder.py +5 -10
  8. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/symbolic/expr/constraint.py +46 -2
  9. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/symbolic/expr/expr.py +19 -0
  10. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/symbolic/expr/stl.py +13 -1
  11. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/symbolic/expr/stljax.py +11 -1
  12. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/symbolic/lower.py +42 -0
  13. openscvx-0.5.3.dev39/openscvx/symbolic/lowerers/latex/__init__.py +49 -0
  14. openscvx-0.5.3.dev39/openscvx/symbolic/lowerers/latex/_lowerer.py +263 -0
  15. openscvx-0.5.3.dev39/openscvx/symbolic/lowerers/latex/_registry.py +82 -0
  16. openscvx-0.5.3.dev39/openscvx/symbolic/lowerers/latex/arithmetic.py +58 -0
  17. openscvx-0.5.3.dev39/openscvx/symbolic/lowerers/latex/array.py +62 -0
  18. openscvx-0.5.3.dev39/openscvx/symbolic/lowerers/latex/constraint.py +73 -0
  19. openscvx-0.5.3.dev39/openscvx/symbolic/lowerers/latex/control.py +14 -0
  20. openscvx-0.5.3.dev39/openscvx/symbolic/lowerers/latex/expr.py +27 -0
  21. openscvx-0.5.3.dev39/openscvx/symbolic/lowerers/latex/formulation.py +465 -0
  22. openscvx-0.5.3.dev39/openscvx/symbolic/lowerers/latex/lie.py +97 -0
  23. openscvx-0.5.3.dev39/openscvx/symbolic/lowerers/latex/linalg.py +55 -0
  24. openscvx-0.5.3.dev39/openscvx/symbolic/lowerers/latex/logic.py +78 -0
  25. openscvx-0.5.3.dev39/openscvx/symbolic/lowerers/latex/math.py +182 -0
  26. openscvx-0.5.3.dev39/openscvx/symbolic/lowerers/latex/spatial.py +41 -0
  27. openscvx-0.5.3.dev39/openscvx/symbolic/lowerers/latex/state.py +31 -0
  28. openscvx-0.5.3.dev39/openscvx/symbolic/lowerers/latex/stl.py +120 -0
  29. openscvx-0.5.3.dev39/openscvx/symbolic/lowerers/latex/vmap.py +37 -0
  30. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39/openscvx.egg-info}/PKG-INFO +1 -1
  31. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx.egg-info/SOURCES.txt +19 -0
  32. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx.egg-info/scm_file_list.json +19 -0
  33. openscvx-0.5.3.dev39/openscvx.egg-info/scm_version.json +8 -0
  34. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/symbolic/test_augmentation.py +74 -34
  35. openscvx-0.5.3.dev39/tests/symbolic/test_latex_formulation.py +314 -0
  36. openscvx-0.5.3.dev39/tests/symbolic/test_lower_latex.py +786 -0
  37. openscvx-0.5.3.dev37/openscvx.egg-info/scm_version.json +0 -8
  38. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/.github/assets/logo.svg +0 -0
  39. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/.github/release-drafter.yml +0 -0
  40. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/.github/workflows/_docs.yml +0 -0
  41. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/.github/workflows/_extra.yml +0 -0
  42. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/.github/workflows/branch-name.yml +0 -0
  43. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/.github/workflows/docs.yml +0 -0
  44. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/.github/workflows/lint.yml +0 -0
  45. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/.github/workflows/nightly.yml +0 -0
  46. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/.github/workflows/release-drafter.yml +0 -0
  47. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/.github/workflows/release.yml +0 -0
  48. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/.github/workflows/tests-cvxpygen.yml +0 -0
  49. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/.github/workflows/tests-examples.yml +0 -0
  50. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/.github/workflows/tests-lie.yml +0 -0
  51. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/.github/workflows/tests-mjx.yml +0 -0
  52. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/.github/workflows/tests-qpax.yml +0 -0
  53. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/.github/workflows/tests.yml +0 -0
  54. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/.gitignore +0 -0
  55. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/.gitmodules +0 -0
  56. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/CONTRIBUTING.md +0 -0
  57. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/LICENSE +0 -0
  58. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/README.md +0 -0
  59. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/docs/Foundations/constraint_reformulation.md +0 -0
  60. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/docs/Foundations/control_parameterization.md +0 -0
  61. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/docs/Foundations/discretization.md +0 -0
  62. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/docs/Foundations/ocp.md +0 -0
  63. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/docs/Foundations/scvx.md +0 -0
  64. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/docs/Foundations/time_dilation.md +0 -0
  65. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/docs/UnderTheHood/batching_jit_grad.md +0 -0
  66. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/docs/UnderTheHood/custom_algorithms_autotuners.md +0 -0
  67. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/docs/UnderTheHood/lowering_architecture.md +0 -0
  68. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/docs/UnderTheHood/vectorization_and_vmapping.md +0 -0
  69. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/docs/UsersGuide/00_introduction.md +0 -0
  70. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/docs/UsersGuide/01_hello_world_brachistochrone.md +0 -0
  71. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/docs/UsersGuide/02_drone_racing_constraints.md +0 -0
  72. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/docs/UsersGuide/03_obstacle_avoidance_vmap.md +0 -0
  73. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/docs/UsersGuide/04_viewpoint_constraints.md +0 -0
  74. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/docs/UsersGuide/05_visualization.md +0 -0
  75. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/docs/UsersGuide/06_logic.md +0 -0
  76. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/docs/UsersGuide/07_lie.md +0 -0
  77. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/docs/UsersGuide/08_mpcc.md +0 -0
  78. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/docs/UsersGuide/09_mjx_dynamics.md +0 -0
  79. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/docs/assets/favicon.png +0 -0
  80. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/docs/assets/images/ct-scvx_dark.png +0 -0
  81. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/docs/assets/images/ct-scvx_light.png +0 -0
  82. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/docs/assets/images/ctcs_dark.png +0 -0
  83. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/docs/assets/images/ctcs_light.png +0 -0
  84. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/docs/assets/images/problem_class_dark.png +0 -0
  85. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/docs/assets/images/problem_class_light.png +0 -0
  86. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/docs/assets/logo.svg +0 -0
  87. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/docs/assets/openscvx_logo_square.png +0 -0
  88. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/docs/assets/viser-client/index.html +0 -0
  89. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/docs/assets/viser-recordings/drone_racing.viser +0 -0
  90. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/docs/assets/viser-recordings/franka_fr3v2_pick_place.viser +0 -0
  91. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/docs/citation.md +0 -0
  92. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/docs/examples.md +0 -0
  93. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/docs/index.md +0 -0
  94. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/docs/javascripts/mathjax.js +0 -0
  95. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/docs/versions.json +0 -0
  96. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/_viser_embed_export.py +0 -0
  97. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/abstract/brachistochrone.py +0 -0
  98. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/abstract/brachistochrone_batched.py +0 -0
  99. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/abstract/flappy_bird.py +0 -0
  100. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/abstract/hypersensitive.py +0 -0
  101. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/abstract/impulsive.py +0 -0
  102. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/abstract/stl_integer_variable.py +0 -0
  103. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/abstract/stl_or.py +0 -0
  104. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/aircraft/dynamic_soaring.py +0 -0
  105. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/aircraft/supersonic_time_to_climb.py +0 -0
  106. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/animations/7_dof_arm.py +0 -0
  107. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/animations/_camera.py +0 -0
  108. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/animations/_render.py +0 -0
  109. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/animations/_sensor_view.py +0 -0
  110. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/animations/dr_vp_polytope.py +0 -0
  111. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/animations/franka_fr3v2_pick_place.py +0 -0
  112. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/animations/logo.py +0 -0
  113. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/animations/obstacle_avoidance_vmap.py +0 -0
  114. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/arm/3_dof_arm.py +0 -0
  115. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/arm/7_dof_arm.py +0 -0
  116. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/arm/7_dof_arm_collision.py +0 -0
  117. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/arm/7_dof_arm_vp.py +0 -0
  118. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/arm/franka_fr3v2_pick_place.py +0 -0
  119. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/arm/franka_fr3v2_viewplanning.py +0 -0
  120. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/arm/franka_fr3v2_viewplanning_nodal.py +0 -0
  121. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/car/dubins_car.py +0 -0
  122. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/car/dubins_car_disjoint.py +0 -0
  123. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/car/dubins_car_obstacle_conditional.py +0 -0
  124. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/car/dubins_car_obstacle_stl.py +0 -0
  125. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/car/dubins_car_stl_or.py +0 -0
  126. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/car/dubins_car_waypoint_stl.py +0 -0
  127. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/double_integrator/_plotting.py +0 -0
  128. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/double_integrator/moving_safe_zones.py +0 -0
  129. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/drone/2d_obstacle_avoidance_batched_ic.py +0 -0
  130. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/drone/cinema_vp.py +0 -0
  131. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/drone/cinema_vp_nodal.py +0 -0
  132. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/drone/dr_double_integrator.py +0 -0
  133. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/drone/dr_vp.py +0 -0
  134. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/drone/dr_vp_nodal.py +0 -0
  135. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/drone/dr_vp_polytope.py +0 -0
  136. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/drone/drone_racing.py +0 -0
  137. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/drone/drone_racing_batched_gates.py +0 -0
  138. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/drone/logo.py +0 -0
  139. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/drone/logo_utils/acl_logo.svg +0 -0
  140. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/drone/logo_utils/openscvx_logo_single.svg +0 -0
  141. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/drone/logo_utils/quadrotor_mesh.py +0 -0
  142. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/drone/logo_utils/svg_path_utils.py +0 -0
  143. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/drone/multi_agent_circle_swap.py +0 -0
  144. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/drone/obstacle_avoidance.py +0 -0
  145. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/drone/obstacle_avoidance_nodal.py +0 -0
  146. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/drone/obstacle_avoidance_vmap.py +0 -0
  147. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/drone/obstacle_avoidance_vmap_2d.py +0 -0
  148. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/drone/openscvx_logo.py +0 -0
  149. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/frax/panda_frax.py +0 -0
  150. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/frax/panda_frax_pick_place.py +0 -0
  151. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/frax/panda_frax_viewplanning.py +0 -0
  152. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/frax/panda_frax_waypoint.py +0 -0
  153. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/mjx/cartpole_mjx.py +0 -0
  154. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/mjx/double_cartpole_mjx.py +0 -0
  155. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/mjx/skydio_x2_mjx.py +0 -0
  156. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/mjx/triple_cartpole_3d_mjx.py +0 -0
  157. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/mjx/triple_cartpole_game.py +0 -0
  158. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/mjx/triple_cartpole_mjx.py +0 -0
  159. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/mpc/double_integrator_discrete.py +0 -0
  160. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/mpc/double_integrator_drone_racing.py +0 -0
  161. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/mpc/dubins_car_circle_analytical.py +0 -0
  162. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/mpc/dubins_car_circle_discrete.py +0 -0
  163. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/mpc/realtime_double_integrator_drone_racing.py +0 -0
  164. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/plotting.py +0 -0
  165. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/plotting_viser.py +0 -0
  166. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/realtime/3DoF_pdg_realtime.py +0 -0
  167. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/realtime/6DoF_pdg_realtime.py +0 -0
  168. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/realtime/base_problems/3DoF_pdg_realtime_base.py +0 -0
  169. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/realtime/base_problems/6DoF_pdg_realtime_base.py +0 -0
  170. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/realtime/base_problems/cinema_vp_realtime_base.py +0 -0
  171. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/realtime/base_problems/drone_racing_realtime_base.py +0 -0
  172. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/realtime/base_problems/dubins_car_realtime_base.py +0 -0
  173. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/realtime/base_problems/obstacle_avoidance_realtime_base.py +0 -0
  174. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/realtime/cinema_vp_realtime.py +0 -0
  175. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/realtime/drone_racing_realtime.py +0 -0
  176. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/realtime/dubins_car_realtime.py +0 -0
  177. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/realtime/obstacle_avoidance_realtime.py +0 -0
  178. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/rocket/3DoF_pdg.py +0 -0
  179. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/rocket/6DoF_pdg.py +0 -0
  180. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/rocket/6DoF_pdg_batched_ic.py +0 -0
  181. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/rocket/ascent_launch_vehicle.py +0 -0
  182. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/spacecraft/halo_orbit.py +0 -0
  183. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/spacecraft/hohmann_transfer.py +0 -0
  184. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/spacecraft/let_transfer.py +0 -0
  185. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/examples/spacecraft/proxops_cw.py +0 -0
  186. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/figures/ctlos_cine.gif +0 -0
  187. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/figures/ctlos_dr.gif +0 -0
  188. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/figures/dtlos_cine.gif +0 -0
  189. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/figures/dtlos_dr.gif +0 -0
  190. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/figures/openscvx_logo.svg +0 -0
  191. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/figures/openscvx_logo_square.png +0 -0
  192. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/figures/oscvx_structure_full_dark.svg +0 -0
  193. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/figures/video_preview.png +0 -0
  194. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/material/__init__.py +0 -0
  195. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/material/overrides/assets/stylesheets/custom.css +0 -0
  196. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/material/overrides/assets/stylesheets/home-dropin.css +0 -0
  197. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/material/overrides/assets/stylesheets/home-hero.css +0 -0
  198. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/material/overrides/assets/stylesheets/home-viser.css +0 -0
  199. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/material/overrides/home.html +0 -0
  200. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/material/overrides/main.html +0 -0
  201. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/material/overrides/partials/home-diagram.html +0 -0
  202. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/material/overrides/partials/home-dropin-banner.html +0 -0
  203. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/material/overrides/partials/home-hero.html +0 -0
  204. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/material/overrides/partials/home-pipeline.html +0 -0
  205. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/material/overrides/partials/home-viser-strip.html +0 -0
  206. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/mkdocs.yml +0 -0
  207. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/__main__.py +0 -0
  208. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/algorithms/__init__.py +0 -0
  209. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/algorithms/autotuner/__init__.py +0 -0
  210. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/algorithms/autotuner/acceptance_ratio.py +0 -0
  211. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/algorithms/autotuner/adaptive_proximal_weight.py +0 -0
  212. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/algorithms/autotuner/augmented_lagrangian.py +0 -0
  213. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/algorithms/autotuner/base.py +0 -0
  214. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/algorithms/autotuner/constant_proximal_weight.py +0 -0
  215. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/algorithms/autotuner/ramp_proximal_weight.py +0 -0
  216. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/algorithms/base.py +0 -0
  217. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/algorithms/history.py +0 -0
  218. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/algorithms/hyperparams.py +0 -0
  219. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/algorithms/loop.py +0 -0
  220. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/algorithms/optimization_results.py +0 -0
  221. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/algorithms/penalty.py +0 -0
  222. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/algorithms/scvx/__init__.py +0 -0
  223. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/algorithms/scvx/iteration.py +0 -0
  224. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/algorithms/scvx/penalized_trust_region.py +0 -0
  225. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/algorithms/state.py +0 -0
  226. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/algorithms/weights.py +0 -0
  227. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/config.py +0 -0
  228. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/discretization/__init__.py +0 -0
  229. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/discretization/base.py +0 -0
  230. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/discretization/discretize_linearize.py +0 -0
  231. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/discretization/linearize_discretize.py +0 -0
  232. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/discretization/linearize_discretize_sparse.py +0 -0
  233. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/discretization/sparse_utils/__init__.py +0 -0
  234. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/discretization/sparse_utils/bcoo_helpers.py +0 -0
  235. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/discretization/sparse_utils/sparse_jacobian.py +0 -0
  236. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/expert/__init__.py +0 -0
  237. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/expert/byof.py +0 -0
  238. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/expert/lowering.py +0 -0
  239. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/expert/validation.py +0 -0
  240. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/init/__init__.py +0 -0
  241. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/init/interpolation.py +0 -0
  242. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/init/inverse_kinematics.py +0 -0
  243. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/integrations/__init__.py +0 -0
  244. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/integrations/_utils.py +0 -0
  245. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/integrations/base.py +0 -0
  246. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/integrations/frax.py +0 -0
  247. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/integrations/menagerie.py +0 -0
  248. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/integrations/mjx.py +0 -0
  249. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/integrators/__init__.py +0 -0
  250. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/integrators/diffrax.py +0 -0
  251. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/integrators/runge_kutta.py +0 -0
  252. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/loader.py +0 -0
  253. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/lowered/__init__.py +0 -0
  254. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/lowered/cvxpy_constraints.py +0 -0
  255. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/lowered/cvxpy_variables.py +0 -0
  256. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/lowered/dynamics.py +0 -0
  257. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/lowered/jax_constraints.py +0 -0
  258. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/lowered/parameters.py +0 -0
  259. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/lowered/problem.py +0 -0
  260. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/lowered/unified.py +0 -0
  261. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/plotting/__init__.py +0 -0
  262. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/plotting/plotting.py +0 -0
  263. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/plotting/publication.py +0 -0
  264. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/plotting/scp_iteration.py +0 -0
  265. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/plotting/viser/__init__.py +0 -0
  266. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/plotting/viser/animated.py +0 -0
  267. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/plotting/viser/coordinates.py +0 -0
  268. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/plotting/viser/orbits.py +0 -0
  269. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/plotting/viser/plotly_integration.py +0 -0
  270. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/plotting/viser/primitives.py +0 -0
  271. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/plotting/viser/scp.py +0 -0
  272. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/plotting/viser/server.py +0 -0
  273. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/propagation/__init__.py +0 -0
  274. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/propagation/post_processing.py +0 -0
  275. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/propagation/propagation.py +0 -0
  276. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/solvers/__init__.py +0 -0
  277. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/solvers/base.py +0 -0
  278. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/solvers/cones.py +0 -0
  279. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/solvers/cvxpy_ptr_solver.py +0 -0
  280. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/solvers/moreau_ptr_solver.py +0 -0
  281. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/solvers/ptr_solver.py +0 -0
  282. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/solvers/qpax_ptr_solver.py +0 -0
  283. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/symbolic/__init__.py +0 -0
  284. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/symbolic/affine.py +0 -0
  285. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/symbolic/canonicalize.py +0 -0
  286. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/symbolic/constraint_set.py +0 -0
  287. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/symbolic/expr/__init__.py +0 -0
  288. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/symbolic/expr/arithmetic.py +0 -0
  289. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/symbolic/expr/array.py +0 -0
  290. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/symbolic/expr/control.py +0 -0
  291. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/symbolic/expr/lie/__init__.py +0 -0
  292. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/symbolic/expr/lie/adjoint.py +0 -0
  293. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/symbolic/expr/lie/se3.py +0 -0
  294. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/symbolic/expr/lie/so3.py +0 -0
  295. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/symbolic/expr/linalg.py +0 -0
  296. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/symbolic/expr/logic.py +0 -0
  297. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/symbolic/expr/math.py +0 -0
  298. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/symbolic/expr/parameter.py +0 -0
  299. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/symbolic/expr/spatial.py +0 -0
  300. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/symbolic/expr/state.py +0 -0
  301. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/symbolic/expr/time.py +0 -0
  302. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/symbolic/expr/variable.py +0 -0
  303. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/symbolic/expr/vmap.py +0 -0
  304. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/symbolic/hashing.py +0 -0
  305. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/symbolic/lowerers/__init__.py +0 -0
  306. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/symbolic/lowerers/cvxpy/__init__.py +0 -0
  307. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/symbolic/lowerers/cvxpy/_lowerer.py +0 -0
  308. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/symbolic/lowerers/cvxpy/_registry.py +0 -0
  309. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/symbolic/lowerers/cvxpy/arithmetic.py +0 -0
  310. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/symbolic/lowerers/cvxpy/array.py +0 -0
  311. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/symbolic/lowerers/cvxpy/constraint.py +0 -0
  312. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/symbolic/lowerers/cvxpy/control.py +0 -0
  313. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/symbolic/lowerers/cvxpy/expr.py +0 -0
  314. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/symbolic/lowerers/cvxpy/linalg.py +0 -0
  315. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/symbolic/lowerers/cvxpy/logic.py +0 -0
  316. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/symbolic/lowerers/cvxpy/math.py +0 -0
  317. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/symbolic/lowerers/cvxpy/state.py +0 -0
  318. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/symbolic/lowerers/jax/__init__.py +0 -0
  319. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/symbolic/lowerers/jax/_lowerer.py +0 -0
  320. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/symbolic/lowerers/jax/_registry.py +0 -0
  321. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/symbolic/lowerers/jax/arithmetic.py +0 -0
  322. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/symbolic/lowerers/jax/array.py +0 -0
  323. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/symbolic/lowerers/jax/constraint.py +0 -0
  324. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/symbolic/lowerers/jax/control.py +0 -0
  325. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/symbolic/lowerers/jax/expr.py +0 -0
  326. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/symbolic/lowerers/jax/lie.py +0 -0
  327. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/symbolic/lowerers/jax/linalg.py +0 -0
  328. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/symbolic/lowerers/jax/logic.py +0 -0
  329. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/symbolic/lowerers/jax/math.py +0 -0
  330. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/symbolic/lowerers/jax/spatial.py +0 -0
  331. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/symbolic/lowerers/jax/state.py +0 -0
  332. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/symbolic/lowerers/jax/stl.py +0 -0
  333. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/symbolic/lowerers/jax/stljax.py +0 -0
  334. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/symbolic/lowerers/jax/vmap.py +0 -0
  335. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/symbolic/parser/__init__.py +0 -0
  336. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/symbolic/parser/_registry.py +0 -0
  337. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/symbolic/parser/array.py +0 -0
  338. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/symbolic/parser/constraint.py +0 -0
  339. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/symbolic/parser/lie.py +0 -0
  340. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/symbolic/parser/linalg.py +0 -0
  341. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/symbolic/parser/logic.py +0 -0
  342. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/symbolic/parser/math.py +0 -0
  343. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/symbolic/parser/parser.py +0 -0
  344. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/symbolic/parser/spatial.py +0 -0
  345. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/symbolic/parser/stl.py +0 -0
  346. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/symbolic/parser/stljax.py +0 -0
  347. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/symbolic/parser/tokenizer.py +0 -0
  348. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/symbolic/preprocessing.py +0 -0
  349. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/symbolic/problem.py +0 -0
  350. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/symbolic/sparsity.py +0 -0
  351. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/symbolic/unified.py +0 -0
  352. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/utils/__init__.py +0 -0
  353. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/utils/cache.py +0 -0
  354. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/utils/caching.py +0 -0
  355. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/utils/printing.py +0 -0
  356. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/utils/profiling.py +0 -0
  357. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx/utils/utils.py +0 -0
  358. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx.egg-info/dependency_links.txt +0 -0
  359. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx.egg-info/entry_points.txt +0 -0
  360. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx.egg-info/requires.txt +0 -0
  361. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/openscvx.egg-info/top_level.txt +0 -0
  362. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/pyproject.toml +0 -0
  363. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/scripts/gen_example_pages.py +0 -0
  364. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/scripts/gen_ref_pages.py +0 -0
  365. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/scripts/mkdocs_copy_viser_client_hook.py +0 -0
  366. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/setup.cfg +0 -0
  367. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/__init__.py +0 -0
  368. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/algorithms/__init__.py +0 -0
  369. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/algorithms/_iteration_helpers.py +0 -0
  370. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/algorithms/autotuner/__init__.py +0 -0
  371. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/algorithms/autotuner/test_defaults_agreement.py +0 -0
  372. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/algorithms/autotuner/test_hyper_overrides.py +0 -0
  373. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/algorithms/autotuner/test_update_weights_jit.py +0 -0
  374. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/algorithms/test_algorithm_state_pytree.py +0 -0
  375. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/algorithms/test_iteration_fn_jit.py +0 -0
  376. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/algorithms/test_iteration_fn_parity.py +0 -0
  377. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/algorithms/test_make_solve_loop.py +0 -0
  378. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/brachistochrone_analytical.py +0 -0
  379. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/conftest.py +0 -0
  380. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/e2e/__init__.py +0 -0
  381. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/e2e/test_brachistochrone.py +0 -0
  382. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/e2e/test_impulsive.py +0 -0
  383. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/e2e/test_multishot_propagation.py +0 -0
  384. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/e2e/test_solve_batched_brachistochrone.py +0 -0
  385. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/e2e/test_solve_batched_cvxpy_export_errors.py +0 -0
  386. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/e2e/test_solve_batched_export_roundtrip.py +0 -0
  387. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/e2e/test_solve_jax_bare_brachistochrone.py +0 -0
  388. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/e2e/test_solve_jax_jit_brachistochrone.py +0 -0
  389. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/e2e/test_solve_jax_vmap_brachistochrone.py +0 -0
  390. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/e2e/test_solve_jax_vmap_converged_no_drift.py +0 -0
  391. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/fixtures/brachistochrone.json +0 -0
  392. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/fixtures/brachistochrone.yaml +0 -0
  393. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/hohmann_analytical.py +0 -0
  394. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/integrations/__init__.py +0 -0
  395. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/integrations/test_mjx.py +0 -0
  396. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/integrations/test_mjx_dynamics.py +0 -0
  397. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/solvers/__init__.py +0 -0
  398. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/solvers/_iteration_callback_helpers.py +0 -0
  399. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/solvers/test_cvxpy_callback_jit_spike.py +0 -0
  400. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/solvers/test_iteration_callback_cvxpy.py +0 -0
  401. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/solvers/test_iteration_callback_moreau.py +0 -0
  402. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/solvers/test_iteration_callback_qpax.py +0 -0
  403. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/solvers/test_iteration_callback_vmap.py +0 -0
  404. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/solvers/test_moreau_ptr_solver.py +0 -0
  405. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/solvers/test_qpax_ptr_solver.py +0 -0
  406. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/solvers/test_subproblem_pytree.py +0 -0
  407. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/symbolic/__init__.py +0 -0
  408. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/symbolic/expr/__init__.py +0 -0
  409. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/symbolic/expr/test_arithmetic.py +0 -0
  410. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/symbolic/expr/test_array.py +0 -0
  411. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/symbolic/expr/test_constraint.py +0 -0
  412. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/symbolic/expr/test_expr.py +0 -0
  413. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/symbolic/expr/test_lie.py +0 -0
  414. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/symbolic/expr/test_linalg.py +0 -0
  415. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/symbolic/expr/test_logic.py +0 -0
  416. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/symbolic/expr/test_math.py +0 -0
  417. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/symbolic/expr/test_node_reference.py +0 -0
  418. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/symbolic/expr/test_parameters.py +0 -0
  419. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/symbolic/expr/test_scaling.py +0 -0
  420. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/symbolic/expr/test_spatial.py +0 -0
  421. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/symbolic/expr/test_stl.py +0 -0
  422. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/symbolic/expr/test_variable.py +0 -0
  423. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/symbolic/expr/test_vmap.py +0 -0
  424. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/symbolic/parser/__init__.py +0 -0
  425. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/symbolic/parser/test_array.py +0 -0
  426. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/symbolic/parser/test_constraint.py +0 -0
  427. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/symbolic/parser/test_lie.py +0 -0
  428. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/symbolic/parser/test_linalg.py +0 -0
  429. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/symbolic/parser/test_load.py +0 -0
  430. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/symbolic/parser/test_logic.py +0 -0
  431. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/symbolic/parser/test_math.py +0 -0
  432. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/symbolic/parser/test_parser.py +0 -0
  433. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/symbolic/parser/test_spatial.py +0 -0
  434. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/symbolic/parser/test_stl.py +0 -0
  435. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/symbolic/parser/test_tokenizer.py +0 -0
  436. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/symbolic/parser/test_vmap.py +0 -0
  437. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/symbolic/test_gmsr.py +0 -0
  438. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/symbolic/test_hashing.py +0 -0
  439. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/symbolic/test_lower_cvxpy.py +0 -0
  440. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/symbolic/test_lower_jax.py +0 -0
  441. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/symbolic/test_preprocessing.py +0 -0
  442. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/symbolic/test_sparsity.py +0 -0
  443. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/symbolic/test_unified.py +0 -0
  444. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/test_autotuning.py +0 -0
  445. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/test_cvxpygen_optional.py +0 -0
  446. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/test_discretization.py +0 -0
  447. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/test_examples.py +0 -0
  448. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/test_expert.py +0 -0
  449. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/test_init.py +0 -0
  450. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/test_integrators.py +0 -0
  451. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/test_loader.py +0 -0
  452. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/test_optimization_results.py +0 -0
  453. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/test_plotting.py +0 -0
  454. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/test_post_process_batched_tau_clamp.py +0 -0
  455. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/test_propagation.py +0 -0
  456. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/tests/test_results_parameters.py +0 -0
  457. {openscvx-0.5.3.dev37 → openscvx-0.5.3.dev39}/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.dev37
3
+ Version: 0.5.3.dev39
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
@@ -353,7 +353,6 @@ def build_relative_loitering_problem(
353
353
  time=time,
354
354
  constraints=constraints,
355
355
  N=n_nodes,
356
- licq_min=0.0,
357
356
  licq_max=1e-8,
358
357
  discretizer={
359
358
  "ode_solver": "Dopri8",
@@ -90,6 +90,7 @@ from openscvx.symbolic.expr import (
90
90
  ctcs,
91
91
  )
92
92
  from openscvx.symbolic.expr.time import Time
93
+ from openscvx.symbolic.lower import to_latex
93
94
  from openscvx.utils.cache import clear_cache, get_cache_dir, get_cache_size
94
95
 
95
96
  load_results = OptimizationResults.load
@@ -186,6 +187,8 @@ __all__ = [
186
187
  "ctcs",
187
188
  # Data parallelism
188
189
  "Vmap",
190
+ # LaTeX rendering
191
+ "to_latex",
189
192
  # Submodules
190
193
  "init",
191
194
  "stl",
@@ -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.dev37'
22
- __version_tuple__ = version_tuple = (0, 5, 3, 'dev37')
21
+ __version__ = version = '0.5.3.dev39'
22
+ __version_tuple__ = version_tuple = (0, 5, 3, 'dev39')
23
23
 
24
- __commit_id__ = commit_id = 'gdb86fef25'
24
+ __commit_id__ = commit_id = 'g56a68269b'
@@ -26,7 +26,7 @@ import time
26
26
  import warnings
27
27
  from dataclasses import fields as dc_fields
28
28
  from dataclasses import replace as dc_replace
29
- from typing import Any, Dict, List, Optional, Tuple, Union
29
+ from typing import Any, Dict, List, Literal, Optional, Tuple, Union
30
30
 
31
31
  import jax
32
32
  import numpy as np
@@ -340,8 +340,7 @@ class Problem:
340
340
  dynamics_prop: Optional[dict] = None,
341
341
  states_prop: Optional[List[State]] = None,
342
342
  algebraic_prop: Optional[dict] = None,
343
- licq_min: Union[float, Dict[int, float]] = 0.0,
344
- licq_max: Union[float, Dict[int, float]] = 1e-4,
343
+ licq_max: float = 1e-4,
345
344
  algorithm: Optional[Union[Algorithm, dict]] = None,
346
345
  discretizer: Optional[Union[Discretizer, dict]] = None,
347
346
  solver: Optional[Union[ConvexSolver, dict]] = None,
@@ -373,12 +372,11 @@ class Problem:
373
372
  Only specify additional states beyond optimization states. Used with dynamics_prop.
374
373
  algebraic_prop (dict, optional): Dictionary mapping names to symbolic expressions
375
374
  for outputs evaluated (not integrated) during propagation.
376
- licq_min: Minimum LICQ constraint value. Defaults to 0.0.
377
- Either a scalar (applied to all CTCS groups) or a dict
378
- mapping CTCS group ``idx`` to per-group bounds.
379
- licq_max: Maximum LICQ constraint value. Defaults to 1e-4.
380
- Either a scalar (applied to all CTCS groups) or a dict
381
- mapping CTCS group ``idx`` to per-group bounds.
375
+ licq_max: Problem-wide upper bound for CTCS augmented states
376
+ (default: 1e-4). Serves as the default for all constraint
377
+ groups; a ``licq_max`` set on an individual constraint (via
378
+ ``ctcs(...)`` or ``.over(...)``) overrides it for that
379
+ constraint's augmented state.
382
380
  algorithm: SCP algorithm configuration. Accepts:
383
381
 
384
382
  - ``None`` — uses ``PenalizedTrustRegion()`` with defaults.
@@ -527,6 +525,10 @@ class Problem:
527
525
  dynamics, adapter_byof = dynamics.expand()
528
526
  byof = _merge_byof(byof, adapter_byof)
529
527
 
528
+ # Stash the user-authored dynamics (pre-augmentation) for `to_latex`.
529
+ # Shallow-copy so later user mutation of their dict doesn't alias.
530
+ self._dynamics_dict: dict = dict(dynamics)
531
+
530
532
  # Resolve byof: dict → ByofSpec (validates keys and nested specs)
531
533
  if byof is not None:
532
534
  byof = ByofSpec.model_validate(byof)
@@ -539,7 +541,6 @@ class Problem:
539
541
  controls=controls,
540
542
  N=N,
541
543
  time=time,
542
- licq_min=licq_min,
543
544
  licq_max=licq_max,
544
545
  dynamics_prop_extra=dynamics_prop,
545
546
  states_prop_extra=states_prop,
@@ -681,6 +682,107 @@ class Problem:
681
682
 
682
683
  # SCP algorithm (resolved from `algorithm` parameter above)
683
684
 
685
+ @property
686
+ def dynamics(self) -> dict:
687
+ """The user-authored dynamics dict, ``{state_name: expr}``.
688
+
689
+ This is the problem as written, *before* the solver augments it with a
690
+ time-dilation control and per-CTCS penalty states. Handy for rendering
691
+ or inspecting a single equation, e.g. ``ox.to_latex(problem.dynamics["v"])``.
692
+
693
+ Returns:
694
+ A dict mapping each user state name to its symbolic time derivative.
695
+ """
696
+ return self._dynamics_dict
697
+
698
+ def to_latex(
699
+ self,
700
+ *,
701
+ dynamics: Literal["inline", "separate"] = "separate",
702
+ constraints: Literal["inline", "symbolic", "separate"] = "inline",
703
+ weights: Literal["symbolic", "numeric"] = "symbolic",
704
+ ) -> str:
705
+ """Render the problem as a Mayer-form LaTeX formulation.
706
+
707
+ The rendered problem is the one you wrote — pre-augmentation, so no
708
+ time-dilation control or CTCS penalty states appear; CTCS constraints
709
+ show up as continuous-time path constraints. The result is a complete
710
+ display-math fragment — a ``subequations`` + ``align`` block (with
711
+ ``"separate"`` definitions as bare ``align`` blocks) that pastes into a
712
+ paper as-is, no ``$$`` wrapping.
713
+
714
+ Dynamics render at one of two detail levels:
715
+
716
+ - ``"separate"`` (default): the formulation carries ``\\dot{x} = f(x, u)``
717
+ and the per-state ``\\dot{x}_{i} = \\ldots`` definitions follow as
718
+ their own ``align`` block.
719
+ - ``"inline"``: one ``\\dot{x}_{i} = \\ldots`` row per equation inside
720
+ the formulation.
721
+
722
+ Constraints add a middle level:
723
+
724
+ - ``"inline"`` (default): full constraint bodies with annotations.
725
+ - ``"symbolic"``: numbered ``g_i(x, u) \\le 0`` / ``h_j(x, u) = 0``
726
+ references only (with their ``\\forall t`` / node annotations).
727
+ - ``"separate"``: symbolic references plus an appended definition block.
728
+
729
+ Args:
730
+ dynamics: Detail level for the dynamics section.
731
+ constraints: Detail level for the constraint section.
732
+ weights: How objective coefficients render. ``"symbolic"`` (the
733
+ default) shows each as a ``\\lambda`` subscripted by the state's
734
+ symbol and element (``\\lambda_{t}``, ``\\lambda_{\\mathrm{v},1}``);
735
+ ``"numeric"`` substitutes the tuned ``lam_cost`` values (``%g``,
736
+ omitted when equal to 1).
737
+
738
+ Returns:
739
+ The formulation as a single LaTeX string; ``"separate"`` modes append
740
+ the definition blocks after it.
741
+
742
+ Example:
743
+ Default (separate dynamics, inline constraints, symbolic weights)::
744
+
745
+ print(problem.to_latex())
746
+
747
+ Everything expanded in a single block::
748
+
749
+ print(problem.to_latex(dynamics="inline"))
750
+
751
+ Substitute the tuned objective weights::
752
+
753
+ print(problem.to_latex(weights="numeric"))
754
+ """
755
+ from openscvx.symbolic.lowerers.latex import problem_to_latex
756
+
757
+ return problem_to_latex(
758
+ self.symbolic,
759
+ self._dynamics_dict,
760
+ self.algorithm.lam_cost,
761
+ dynamics=dynamics,
762
+ constraints=constraints,
763
+ weights=weights,
764
+ )
765
+
766
+ def _repr_latex_(self) -> str:
767
+ """Render as display math in Jupyter (default detail levels, in ``$$``).
768
+
769
+ Uses the builder's ``aligned`` envelope rather than the ``subequations``
770
+ + ``align`` form ``to_latex`` returns: MathJax/KaTeX (the notebook and
771
+ docs renderers) do not implement ``subequations``, and ``align`` cannot
772
+ nest inside ``$$``, whereas ``aligned`` can.
773
+ """
774
+ from openscvx.symbolic.lowerers.latex import problem_to_latex
775
+
776
+ body = problem_to_latex(
777
+ self.symbolic,
778
+ self._dynamics_dict,
779
+ self.algorithm.lam_cost,
780
+ dynamics="separate",
781
+ constraints="inline",
782
+ env="aligned",
783
+ )
784
+ return f"$$\n{body}\n$$"
785
+
684
786
  @property
685
787
  def solver(self) -> ConvexSolver:
686
788
  """Access the convex subproblem solver instance.
@@ -54,7 +54,7 @@ Example:
54
54
  # controls_aug includes original controls + time dilation
55
55
  """
56
56
 
57
- from typing import Dict, List, Optional, Tuple, Union
57
+ from typing import Dict, List, Optional, Tuple
58
58
 
59
59
  import numpy as np
60
60
 
@@ -448,8 +448,7 @@ def augment_dynamics_with_ctcs(
448
448
  N: int,
449
449
  xdelta: Optional[Expr] = None,
450
450
  *,
451
- licq_min: Union[float, Dict[int, float]] = 0.0,
452
- licq_max: Union[float, Dict[int, float]] = 1e-4,
451
+ licq_max: float = 1e-4,
453
452
  ) -> Tuple[Expr, Optional[Expr], List[State], List[Control]]:
454
453
  """Augment dynamics with continuous-time constraint satisfaction states.
455
454
 
@@ -467,18 +466,20 @@ def augment_dynamics_with_ctcs(
467
466
  aug_dot = penalty(g(x, u)) # For each constraint group
468
467
  time_dot = 1.0
469
468
 
469
+ Each augmented state is bounded to [0, licq_max], where the group's bound
470
+ is taken from its member constraints' ``licq_max`` attribute (constraints in
471
+ a group must agree) and falls back to the problem-wide ``licq_max`` when no
472
+ member specifies one.
473
+
470
474
  Args:
471
475
  xdot: Original dynamics expression for states
472
476
  states: List of state variables (must include a state named "time")
473
477
  controls: List of control variables
474
478
  constraints_ctcs: List of CTCS constraints (should be sorted and grouped)
475
479
  N: Number of discretization nodes
476
- licq_min: Minimum bound for augmented states (default: 0.0).
477
- Either a scalar (applied to all groups) or a dict mapping
478
- CTCS group ``idx`` to per-group bounds.
479
- licq_max: Maximum bound for augmented states (default: 1e-4).
480
- Either a scalar (applied to all groups) or a dict mapping
481
- CTCS group ``idx`` to per-group bounds.
480
+ licq_max: Problem-wide default upper bound for augmented states
481
+ (default: 1e-4). Per-constraint ``licq_max`` values override it
482
+ for their group.
482
483
 
483
484
  Returns:
484
485
  Tuple of:
@@ -489,6 +490,8 @@ def augment_dynamics_with_ctcs(
489
490
 
490
491
  Raises:
491
492
  ValueError: If no state named "time" is found in the states list
493
+ ValueError: If constraints sharing an augmented state specify
494
+ conflicting ``licq_max`` values
492
495
 
493
496
  Example:
494
497
  Augment dynamics with CTCS penalty states:
@@ -509,6 +512,9 @@ def augment_dynamics_with_ctcs(
509
512
  states_aug includes x, time, and _ctcs_aug_0,
510
513
  controls_aug includes u and _time_dilation
511
514
  """
515
+ if licq_max <= 0:
516
+ raise ValueError(f"licq_max must be a positive number, got {licq_max!r}")
517
+
512
518
  # Save if discrete dynamics is null
513
519
  discrete_dynamics_set = xdelta is not None
514
520
 
@@ -535,24 +541,6 @@ def augment_dynamics_with_ctcs(
535
541
  penalty_groups[ctcs.idx] = []
536
542
  penalty_groups[ctcs.idx].append(ctcs)
537
543
 
538
- # Validate dict-valued licq_min / licq_max keys against actual groups.
539
- valid_ids = set(penalty_groups.keys())
540
- for name, val in [("licq_min", licq_min), ("licq_max", licq_max)]:
541
- if isinstance(val, dict):
542
- unknown = set(val.keys()) - valid_ids
543
- if unknown:
544
- raise ValueError(
545
- f"{name} dict contains unknown CTCS group idx: {unknown}. "
546
- f"Valid idx values: {sorted(valid_ids)}"
547
- )
548
- missing = valid_ids - set(val.keys())
549
- if missing:
550
- raise ValueError(
551
- f"{name} dict is missing entries for CTCS group idx: "
552
- f"{sorted(missing)}. When using a dict, all groups must "
553
- f"have an entry. Valid idx values: {sorted(valid_ids)}"
554
- )
555
-
556
544
  # Create augmented state expressions for each group and corresponding
557
545
  # augmented state variables. For discrete dynamics, preserve these states
558
546
  # by identity mapping across impulsive updates.
@@ -566,17 +554,25 @@ def augment_dynamics_with_ctcs(
566
554
  augmented_state_expr = Add(*penalty_terms)
567
555
  augmented_state_exprs.append(augmented_state_expr)
568
556
 
569
- # Resolve per-group LICQ bounds
570
- idx_min = licq_min[idx] if isinstance(licq_min, dict) else licq_min
571
- idx_max = licq_max[idx] if isinstance(licq_max, dict) else licq_max
557
+ # Resolve the group's LICQ bound from its member constraints:
558
+ # explicit values must agree; otherwise fall back to the
559
+ # problem-wide default.
560
+ explicit = {c.licq_max for c in penalty_terms if c.licq_max is not None}
561
+ if len(explicit) > 1:
562
+ raise ValueError(
563
+ f"CTCS constraints sharing augmented state idx={idx} specify "
564
+ f"conflicting licq_max values: {sorted(explicit)}. Constraints "
565
+ f"in the same group must agree on licq_max; set the same value "
566
+ f"on each, or separate them into different groups via idx."
567
+ )
568
+ group_licq_max = explicit.pop() if explicit else licq_max
572
569
 
573
570
  aug_var = State(f"_ctcs_aug_{idx}", shape=(1,))
574
- aug_var.initial = np.array([idx_min]) # Set initial to respect bounds
571
+ aug_var.initial = np.array([0.0])
575
572
  aug_var.final = [("free", 0)]
576
- aug_var.min = np.array([idx_min])
577
- aug_var.max = np.array([idx_max])
578
- # Set guess to idx_min as well
579
- aug_var.guess = np.full([N, 1], idx_min) # N x num augmented states
573
+ aug_var.min = np.array([0.0])
574
+ aug_var.max = np.array([group_licq_max])
575
+ aug_var.guess = np.zeros([N, 1]) # N x num augmented states
580
576
  states_augmented.append(aug_var)
581
577
  augmented_state_exprs_discrete.append(aug_var)
582
578
 
@@ -29,7 +29,7 @@ Pipeline stages:
29
29
  See `preprocess_symbolic_problem()` for the main entry point.
30
30
  """
31
31
 
32
- from typing import Dict, List, Optional, Tuple, Union
32
+ from typing import Dict, List, Optional, Tuple
33
33
 
34
34
  import numpy as np
35
35
 
@@ -71,8 +71,7 @@ def preprocess_symbolic_problem(
71
71
  controls: List[Control],
72
72
  N: int,
73
73
  time: Time,
74
- licq_min: Union[float, Dict[int, float]] = 0.0,
75
- licq_max: Union[float, Dict[int, float]] = 1e-4,
74
+ licq_max: float = 1e-4,
76
75
  dynamics_prop_extra: dict = None,
77
76
  dynamics_discrete: dict = None,
78
77
  states_prop_extra: List[State] = None,
@@ -106,12 +105,9 @@ def preprocess_symbolic_problem(
106
105
  controls: List of user-defined Control objects (should NOT include time dilation)
107
106
  N: Number of discretization nodes in the trajectory
108
107
  time: Time configuration object specifying time bounds and constraints
109
- licq_min: Minimum bound for CTCS augmented states (default: 0.0).
110
- Either a scalar (applied to all groups) or a dict mapping
111
- CTCS group ``idx`` to per-group bounds.
112
- licq_max: Maximum bound for CTCS augmented states (default: 1e-4).
113
- Either a scalar (applied to all groups) or a dict mapping
114
- CTCS group ``idx`` to per-group bounds.
108
+ licq_max: Problem-wide default upper bound for CTCS augmented states
109
+ (default: 1e-4). Per-constraint ``licq_max`` values override it
110
+ for their group.
115
111
  dynamics_prop_extra: Optional dictionary of additional dynamics for propagation-only
116
112
  states (default: None)
117
113
  states_prop_extra: Optional list of additional State objects for propagation only
@@ -350,7 +346,6 @@ def preprocess_symbolic_problem(
350
346
  constraints.ctcs,
351
347
  N,
352
348
  xdelta=dynamics_discrete_concat,
353
- licq_min=licq_min,
354
349
  licq_max=licq_max,
355
350
  )
356
351
 
@@ -127,6 +127,7 @@ class Constraint(Expr):
127
127
  penalty: str = "squared_relu",
128
128
  idx: Optional[int] = None,
129
129
  check_nodally: bool = False,
130
+ licq_max: Optional[float] = None,
130
131
  ) -> "CTCS":
131
132
  """Apply this constraint over a continuous interval using CTCS.
132
133
 
@@ -135,11 +136,22 @@ class Constraint(Expr):
135
136
  penalty: Penalty function type ("squared_relu", "huber", "smooth_relu")
136
137
  idx: Optional grouping index for multiple augmented states
137
138
  check_nodally: Whether to also enforce this constraint nodally
139
+ licq_max: Optional upper bound on the augmented state that accumulates
140
+ this constraint's violation penalty. Constraints sharing an
141
+ augmented state must agree on the value; groups without one use
142
+ the problem-wide ``licq_max`` (a ``Problem`` argument).
138
143
 
139
144
  Returns:
140
145
  CTCS constraint wrapping this constraint with interval specification
141
146
  """
142
- return CTCS(self, penalty=penalty, nodes=interval, idx=idx, check_nodally=check_nodally)
147
+ return CTCS(
148
+ self,
149
+ penalty=penalty,
150
+ nodes=interval,
151
+ idx=idx,
152
+ check_nodally=check_nodally,
153
+ licq_max=licq_max,
154
+ )
143
155
 
144
156
  def convex(self) -> "Constraint":
145
157
  """Mark this constraint as convex for CVXPy lowering.
@@ -609,6 +621,11 @@ class CTCS(Expr):
609
621
  an augmented state. If None, auto-assigned based on node intervals.
610
622
  check_nodally: Whether to also enforce the constraint at discrete nodes for
611
623
  additional numerical robustness (creates both continuous and nodal constraints)
624
+ licq_max: Optional upper bound on the augmented state accumulating this
625
+ constraint's violation penalty. Smaller values enforce the constraint
626
+ more strictly between nodes. Constraints sharing an augmented state
627
+ must agree on the value; groups without one use the problem-wide
628
+ ``licq_max`` (a ``Problem`` argument).
612
629
 
613
630
  Example:
614
631
  Single augmented state (default behavior - same node interval):
@@ -642,6 +659,7 @@ class CTCS(Expr):
642
659
  nodes: Optional[Tuple[int, int]] = None,
643
660
  idx: Optional[int] = None,
644
661
  check_nodally: bool = False,
662
+ licq_max: Optional[float] = None,
645
663
  ):
646
664
  """Initialize a CTCS constraint.
647
665
 
@@ -662,11 +680,16 @@ class CTCS(Expr):
662
680
  check_nodally: If True, also enforce the constraint at discrete nodes for
663
681
  numerical stability (creates both continuous and nodal constraints).
664
682
  Defaults to False.
683
+ licq_max: Optional upper bound on the augmented state accumulating this
684
+ constraint's violation penalty. Constraints sharing an augmented
685
+ state must agree on the value; groups without one use the
686
+ problem-wide ``licq_max`` (a ``Problem`` argument).
665
687
 
666
688
  Raises:
667
689
  TypeError: If constraint is not a Constraint instance
668
690
  ValueError: If nodes is not None or a 2-tuple of integers
669
691
  ValueError: If nodes[0] >= nodes[1] (invalid interval)
692
+ ValueError: If licq_max is not a positive number
670
693
  """
671
694
  if not isinstance(constraint, Constraint):
672
695
  raise TypeError("CTCS must wrap a Constraint")
@@ -683,12 +706,19 @@ class CTCS(Expr):
683
706
  if nodes[0] >= nodes[1]:
684
707
  raise ValueError("CTCS node range must have start < end")
685
708
 
709
+ if licq_max is not None:
710
+ if not isinstance(licq_max, (int, float)) or licq_max <= 0:
711
+ raise ValueError(f"licq_max must be a positive number, got {licq_max!r}")
712
+ licq_max = float(licq_max)
713
+
686
714
  self.constraint = constraint
687
715
  self.penalty = penalty
688
716
  self.nodes = nodes # (start, end) node range or None for all nodes
689
717
  self.idx = idx # Optional grouping index for multiple augmented states
690
718
  # Whether to also enforce this constraint nodally for numerical stability
691
719
  self.check_nodally = check_nodally
720
+ # Upper bound on the augmented state; None defers to the group default
721
+ self.licq_max = licq_max
692
722
 
693
723
  def children(self) -> List[Expr]:
694
724
  """Return the wrapped constraint as the only child.
@@ -711,6 +741,7 @@ class CTCS(Expr):
711
741
  nodes=self.nodes,
712
742
  idx=self.idx,
713
743
  check_nodally=self.check_nodally,
744
+ licq_max=self.licq_max,
714
745
  )
715
746
 
716
747
  def check_shape(self) -> Tuple[int, ...]:
@@ -767,6 +798,11 @@ class CTCS(Expr):
767
798
  hasher.update(b"None")
768
799
  # Hash check_nodally
769
800
  hasher.update(b"1" if self.check_nodally else b"0")
801
+ # Hash licq_max
802
+ if self.licq_max is not None:
803
+ hasher.update(struct.pack(">d", self.licq_max))
804
+ else:
805
+ hasher.update(b"None")
770
806
  # Hash the wrapped constraint
771
807
  self.constraint._hash_into(hasher)
772
808
 
@@ -794,6 +830,7 @@ class CTCS(Expr):
794
830
  nodes=interval,
795
831
  idx=self.idx,
796
832
  check_nodally=self.check_nodally,
833
+ licq_max=self.licq_max,
797
834
  )
798
835
 
799
836
  def __repr__(self) -> str:
@@ -809,6 +846,8 @@ class CTCS(Expr):
809
846
  parts.append(f"idx={self.idx}")
810
847
  if self.check_nodally:
811
848
  parts.append(f"check_nodally={self.check_nodally}")
849
+ if self.licq_max is not None:
850
+ parts.append(f"licq_max={self.licq_max}")
812
851
  return f"CTCS({', '.join(parts)})"
813
852
 
814
853
  def penalty_expr(self) -> Expr:
@@ -861,6 +900,7 @@ def ctcs(
861
900
  nodes: Optional[Tuple[int, int]] = None,
862
901
  idx: Optional[int] = None,
863
902
  check_nodally: bool = False,
903
+ licq_max: Optional[float] = None,
864
904
  ) -> CTCS:
865
905
  """Helper function to create CTCS (Continuous-Time Constraint Satisfaction) constraints.
866
906
 
@@ -876,6 +916,10 @@ def ctcs(
876
916
  idx: Optional grouping index for multiple augmented states
877
917
  check_nodally: Whether to also enforce constraint at discrete nodes.
878
918
  Defaults to False.
919
+ licq_max: Optional upper bound on the augmented state accumulating this
920
+ constraint's violation penalty. Constraints sharing an augmented
921
+ state must agree on the value; groups without one use the
922
+ problem-wide ``licq_max`` (a ``Problem`` argument).
879
923
 
880
924
  Returns:
881
925
  CTCS: A CTCS constraint wrapping the input constraint
@@ -899,4 +943,4 @@ def ctcs(
899
943
 
900
944
  altitude_constraint = (altitude >= 10).over((0, 100), penalty="huber")
901
945
  """
902
- return CTCS(constraint, penalty, nodes, idx, check_nodally)
946
+ return CTCS(constraint, penalty, nodes, idx, check_nodally, licq_max)
@@ -420,6 +420,25 @@ class Expr:
420
420
  lines.append(child.pretty(indent + 1))
421
421
  return "\n".join(lines)
422
422
 
423
+ def _repr_latex_(self) -> Union[str, None]:
424
+ """Render this expression as inline LaTeX for Jupyter.
425
+
426
+ Jupyter calls this hook to display an object as math. The expression
427
+ is lowered to LaTeX and wrapped in ``$...$``. Nodes without a
428
+ registered LaTeX visitor return ``None`` so Jupyter falls back to the
429
+ plain ``__repr__``.
430
+
431
+ Returns:
432
+ The inline-math string ``"$...$"``, or ``None`` when the
433
+ expression contains a node the LaTeX backend does not support.
434
+ """
435
+ from openscvx.symbolic.lower import to_latex
436
+
437
+ try:
438
+ return f"${to_latex(self)}$"
439
+ except NotImplementedError:
440
+ return None
441
+
423
442
  def _hash_into(self, hasher: "hashlib._Hash") -> None:
424
443
  """Contribute this expression's structural identity to a hash.
425
444
 
@@ -310,6 +310,7 @@ class STLExpr(Expr):
310
310
  penalty: str = "smooth_relu",
311
311
  idx: Optional[int] = None,
312
312
  check_nodally: bool = False,
313
+ licq_max: Optional[float] = None,
313
314
  interval_type: IntervalKind = "nodes",
314
315
  ) -> "CTCS":
315
316
  """Apply this STL expression over an enforcement interval using CTCS.
@@ -323,6 +324,10 @@ class STLExpr(Expr):
323
324
  penalty: Penalty function type for CTCS
324
325
  idx: Optional grouping index for multiple augmented states
325
326
  check_nodally: Whether to also enforce at discrete nodes
327
+ licq_max: Optional upper bound on the augmented state accumulating
328
+ this constraint's violation penalty. Constraints sharing an
329
+ augmented state must agree on the value; groups without one use
330
+ the problem-wide ``licq_max`` (a ``Problem`` argument).
326
331
 
327
332
  Returns:
328
333
  Continuous-time constraint satisfaction wrapper
@@ -359,6 +364,7 @@ class STLExpr(Expr):
359
364
  nodes=(coerced.start, coerced.end),
360
365
  idx=idx,
361
366
  check_nodally=check_nodally,
367
+ licq_max=licq_max,
362
368
  )
363
369
 
364
370
  def at(self, nodes: Union[list, tuple]) -> "NodalConstraint":
@@ -863,6 +869,7 @@ class Always(_TemporalSTLExpr):
863
869
  penalty: str = "smooth_relu",
864
870
  idx: Optional[int] = None,
865
871
  check_nodally: bool = False,
872
+ licq_max: Optional[float] = None,
866
873
  interval_type: IntervalKind = "nodes",
867
874
  ) -> "CTCS":
868
875
  """Convert this ``Always`` to a ``CTCS`` constraint.
@@ -876,6 +883,10 @@ class Always(_TemporalSTLExpr):
876
883
  penalty: CTCS penalty function name.
877
884
  idx: Optional grouping index for multiple augmented states.
878
885
  check_nodally: Whether to additionally enforce at discrete nodes.
886
+ licq_max: Optional upper bound on the augmented state accumulating
887
+ this constraint's violation penalty. Constraints sharing an
888
+ augmented state must agree on the value; groups without one use
889
+ the problem-wide ``licq_max`` (a ``Problem`` argument).
879
890
 
880
891
  Returns:
881
892
  A ``CTCS`` constraint enforcing the inner predicate over the
@@ -903,7 +914,7 @@ class Always(_TemporalSTLExpr):
903
914
 
904
915
  if isinstance(self.predicate, STLExpr):
905
916
  return self.predicate.over(
906
- chosen, penalty=penalty, idx=idx, check_nodally=check_nodally
917
+ chosen, penalty=penalty, idx=idx, check_nodally=check_nodally, licq_max=licq_max
907
918
  )
908
919
 
909
920
  from .constraint import CTCS
@@ -914,6 +925,7 @@ class Always(_TemporalSTLExpr):
914
925
  nodes=(chosen.start, chosen.end),
915
926
  idx=idx,
916
927
  check_nodally=check_nodally,
928
+ licq_max=licq_max,
917
929
  )
918
930
 
919
931
  def __repr__(self) -> str:
@@ -59,6 +59,7 @@ class STLJaxExpr(Expr):
59
59
  penalty: str = "squared_relu",
60
60
  idx: Optional[int] = None,
61
61
  check_nodally: bool = False,
62
+ licq_max: Optional[float] = None,
62
63
  ) -> "CTCS":
63
64
  """Apply this STL expression over a continuous interval using CTCS.
64
65
 
@@ -70,6 +71,10 @@ class STLJaxExpr(Expr):
70
71
  penalty: Penalty function type for CTCS
71
72
  idx: Optional grouping index for multiple augmented states
72
73
  check_nodally: Whether to also enforce at discrete nodes
74
+ licq_max: Optional upper bound on the augmented state accumulating
75
+ this constraint's violation penalty. Constraints sharing an
76
+ augmented state must agree on the value; groups without one use
77
+ the problem-wide ``licq_max`` (a ``Problem`` argument).
73
78
 
74
79
  Returns:
75
80
  Continuous-time constraint satisfaction wrapper
@@ -89,7 +94,12 @@ class STLJaxExpr(Expr):
89
94
  constraint = Inequality(Neg(self), Constant(np.array(0.0)))
90
95
 
91
96
  return CTCS(
92
- constraint, penalty=penalty, nodes=interval, idx=idx, check_nodally=check_nodally
97
+ constraint,
98
+ penalty=penalty,
99
+ nodes=interval,
100
+ idx=idx,
101
+ check_nodally=check_nodally,
102
+ licq_max=licq_max,
93
103
  )
94
104
 
95
105
  def at(self, nodes: Union[list, tuple]) -> "NodalConstraint":