openscvx 0.3.2.dev219__tar.gz → 0.3.2.dev228__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 (235) hide show
  1. {openscvx-0.3.2.dev219/openscvx.egg-info → openscvx-0.3.2.dev228}/PKG-INFO +1 -1
  2. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/examples/abstract/3DoF_pdg.py +0 -3
  3. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/examples/abstract/brachistochrone.py +0 -2
  4. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/examples/car/dubins_car.py +0 -2
  5. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/examples/car/dubins_car_disjoint.py +0 -1
  6. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/examples/car/dubins_car_stljax.py +0 -3
  7. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/examples/drone/cinema_vp.py +0 -1
  8. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/examples/drone/dr_double_integrator.py +0 -2
  9. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/examples/drone/drone_racing.py +0 -4
  10. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/examples/drone/obstacle_avoidance.py +0 -6
  11. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/examples/drone/obstacle_avoidance_nodal.py +0 -6
  12. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/examples/drone/obstacle_avoidance_realtime_base.py +0 -7
  13. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/examples/spacecraft/proxops_cw.py +0 -1
  14. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/openscvx/_version.py +3 -3
  15. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/openscvx/symbolic/builder.py +15 -0
  16. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/openscvx/symbolic/preprocessing.py +82 -0
  17. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228/openscvx.egg-info}/PKG-INFO +1 -1
  18. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/tests/symbolic/test_preprocessing.py +175 -0
  19. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/tests/test_brachistochrone.py +2 -11
  20. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/tests/test_expert.py +2 -0
  21. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/.github/assets/logo.svg +0 -0
  22. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/.github/release-drafter.yml +0 -0
  23. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/.github/workflows/_docs.yml +0 -0
  24. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/.github/workflows/docs.yml +0 -0
  25. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/.github/workflows/lint.yml +0 -0
  26. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/.github/workflows/nightly.yml +0 -0
  27. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/.github/workflows/release-drafter.yml +0 -0
  28. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/.github/workflows/release.yml +0 -0
  29. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/.github/workflows/tests-integration.yml +0 -0
  30. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/.github/workflows/tests-unit.yml +0 -0
  31. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/.gitignore +0 -0
  32. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/CONTRIBUTING.md +0 -0
  33. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/LICENSE +0 -0
  34. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/README.md +0 -0
  35. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/docs/Overview/constraint_reformulation.md +0 -0
  36. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/docs/Overview/control_parameterization.md +0 -0
  37. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/docs/Overview/discretization.md +0 -0
  38. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/docs/Overview/ocp.md +0 -0
  39. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/docs/Overview/scvx.md +0 -0
  40. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/docs/Overview/time_dilation.md +0 -0
  41. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/docs/UnderTheHood/lowering_architecture.md +0 -0
  42. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/docs/UnderTheHood/vectorization_and_vmapping.md +0 -0
  43. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/docs/Usage/advanced_problem_setup.md +0 -0
  44. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/docs/Usage/api.md +0 -0
  45. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/docs/Usage/api_constraints.md +0 -0
  46. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/docs/Usage/api_control.md +0 -0
  47. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/docs/Usage/api_integrators.md +0 -0
  48. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/docs/Usage/api_state.md +0 -0
  49. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/docs/Usage/api_trajoptproblem.md +0 -0
  50. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/docs/Usage/api_variable.md +0 -0
  51. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/docs/Usage/basic_problem_setup.md +0 -0
  52. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/docs/Usage/tutorial_6dof_los_guidance.md +0 -0
  53. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/docs/Usage/tutorial_6dof_obstacle_avoidance.md +0 -0
  54. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/docs/Usage/tutorials.md +0 -0
  55. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/docs/assets/favicon.png +0 -0
  56. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/docs/assets/images/ct-scvx_dark.png +0 -0
  57. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/docs/assets/images/ct-scvx_light.png +0 -0
  58. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/docs/assets/images/ctcs_dark.png +0 -0
  59. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/docs/assets/images/ctcs_light.png +0 -0
  60. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/docs/assets/images/problem_class_dark.png +0 -0
  61. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/docs/assets/images/problem_class_light.png +0 -0
  62. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/docs/assets/logo.svg +0 -0
  63. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/docs/citation.md +0 -0
  64. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/docs/examples.md +0 -0
  65. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/docs/getting-started.md +0 -0
  66. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/docs/index.md +0 -0
  67. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/docs/javascripts/mathjax.js +0 -0
  68. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/examples/arm/three_link_arm.py +0 -0
  69. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/examples/drone/cinema_vp_realtime_base.py +0 -0
  70. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/examples/drone/dr_vp.py +0 -0
  71. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/examples/drone/dr_vp_nodal.py +0 -0
  72. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/examples/drone/dr_vp_polytope.py +0 -0
  73. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/examples/drone/obstacle_avoidance_vmap.py +0 -0
  74. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/examples/plotting.py +0 -0
  75. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/examples/plotting_viser.py +0 -0
  76. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/examples/realtime/cinema_vp_realtime.py +0 -0
  77. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/examples/realtime/drone_racing_realtime.py +0 -0
  78. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/examples/realtime/dubins_car_realtime.py +0 -0
  79. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/examples/realtime/obstacle_avoidance_realtime.py +0 -0
  80. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/figures/ctlos_cine.gif +0 -0
  81. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/figures/ctlos_dr.gif +0 -0
  82. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/figures/dtlos_cine.gif +0 -0
  83. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/figures/dtlos_dr.gif +0 -0
  84. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/figures/openscvx_logo.svg +0 -0
  85. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/figures/openscvx_logo_square.png +0 -0
  86. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/figures/oscvx_structure_full_dark.svg +0 -0
  87. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/figures/video_preview.png +0 -0
  88. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/material/__init__.py +0 -0
  89. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/material/overrides/assets/images/layers/1-background.avif +0 -0
  90. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/material/overrides/assets/images/layers/1-background@1x.avif +0 -0
  91. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/material/overrides/assets/images/layers/1-background@2x.avif +0 -0
  92. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/material/overrides/assets/images/layers/1-background@3x.avif +0 -0
  93. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/material/overrides/assets/images/layers/1-background@4x.avif +0 -0
  94. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/material/overrides/assets/images/layers/2-mars.avif +0 -0
  95. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/material/overrides/assets/images/layers/2-mars@1x.avif +0 -0
  96. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/material/overrides/assets/images/layers/2-mars@2x.avif +0 -0
  97. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/material/overrides/assets/images/layers/2-mars@3x.avif +0 -0
  98. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/material/overrides/assets/images/layers/2-mars@4x.avif +0 -0
  99. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/material/overrides/assets/images/layers/3-moon.avif +0 -0
  100. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/material/overrides/assets/images/layers/3-moon@1x.avif +0 -0
  101. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/material/overrides/assets/images/layers/3-moon@2x.avif +0 -0
  102. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/material/overrides/assets/images/layers/3-moon@3x.avif +0 -0
  103. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/material/overrides/assets/images/layers/3-moon@4x.avif +0 -0
  104. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/material/overrides/assets/images/layers/4-sat1.avif +0 -0
  105. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/material/overrides/assets/images/layers/4-sat1@1x.avif +0 -0
  106. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/material/overrides/assets/images/layers/4-sat1@2x.avif +0 -0
  107. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/material/overrides/assets/images/layers/4-sat1@3x.avif +0 -0
  108. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/material/overrides/assets/images/layers/4-sat1@4x.avif +0 -0
  109. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/material/overrides/assets/images/layers/5-space.avif +0 -0
  110. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/material/overrides/assets/images/layers/5-space@1x.avif +0 -0
  111. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/material/overrides/assets/images/layers/5-space@2x.avif +0 -0
  112. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/material/overrides/assets/images/layers/5-space@3x.avif +0 -0
  113. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/material/overrides/assets/images/layers/5-space@4x.avif +0 -0
  114. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/material/overrides/assets/images/layers/6-earth.avif +0 -0
  115. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/material/overrides/assets/images/layers/6-earth@1x.avif +0 -0
  116. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/material/overrides/assets/images/layers/6-earth@2x.avif +0 -0
  117. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/material/overrides/assets/images/layers/6-earth@3x.avif +0 -0
  118. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/material/overrides/assets/images/layers/6-earth@4x.avif +0 -0
  119. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/material/overrides/assets/javascripts/parallax.js +0 -0
  120. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/material/overrides/assets/logo.svg +0 -0
  121. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/material/overrides/assets/stylesheets/custom.css +0 -0
  122. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/material/overrides/assets/stylesheets/parallax.css +0 -0
  123. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/material/overrides/home.html +0 -0
  124. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/material/overrides/main.html +0 -0
  125. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/material/overrides/partials/parallax/hero.html +0 -0
  126. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/material/overrides/partials/parallax.html +0 -0
  127. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/mkdocs.yml +0 -0
  128. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/openscvx/__init__.py +0 -0
  129. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/openscvx/algorithms/__init__.py +0 -0
  130. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/openscvx/algorithms/autotuning.py +0 -0
  131. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/openscvx/algorithms/base.py +0 -0
  132. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/openscvx/algorithms/optimization_results.py +0 -0
  133. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/openscvx/algorithms/penalized_trust_region.py +0 -0
  134. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/openscvx/config.py +0 -0
  135. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/openscvx/discretization/__init__.py +0 -0
  136. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/openscvx/discretization/discretization.py +0 -0
  137. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/openscvx/expert/__init__.py +0 -0
  138. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/openscvx/expert/byof.py +0 -0
  139. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/openscvx/expert/lowering.py +0 -0
  140. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/openscvx/expert/validation.py +0 -0
  141. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/openscvx/integrators/__init__.py +0 -0
  142. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/openscvx/integrators/runge_kutta.py +0 -0
  143. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/openscvx/lowered/__init__.py +0 -0
  144. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/openscvx/lowered/cvxpy_constraints.py +0 -0
  145. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/openscvx/lowered/cvxpy_variables.py +0 -0
  146. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/openscvx/lowered/dynamics.py +0 -0
  147. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/openscvx/lowered/jax_constraints.py +0 -0
  148. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/openscvx/lowered/parameters.py +0 -0
  149. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/openscvx/lowered/problem.py +0 -0
  150. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/openscvx/lowered/unified.py +0 -0
  151. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/openscvx/plotting/__init__.py +0 -0
  152. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/openscvx/plotting/plotting.py +0 -0
  153. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/openscvx/plotting/scp_iteration.py +0 -0
  154. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/openscvx/plotting/viser/__init__.py +0 -0
  155. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/openscvx/plotting/viser/animated.py +0 -0
  156. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/openscvx/plotting/viser/plotly_integration.py +0 -0
  157. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/openscvx/plotting/viser/primitives.py +0 -0
  158. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/openscvx/plotting/viser/scp.py +0 -0
  159. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/openscvx/plotting/viser/server.py +0 -0
  160. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/openscvx/problem.py +0 -0
  161. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/openscvx/propagation/__init__.py +0 -0
  162. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/openscvx/propagation/post_processing.py +0 -0
  163. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/openscvx/propagation/propagation.py +0 -0
  164. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/openscvx/solvers/__init__.py +0 -0
  165. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/openscvx/solvers/cvxpy.py +0 -0
  166. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/openscvx/symbolic/__init__.py +0 -0
  167. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/openscvx/symbolic/augmentation.py +0 -0
  168. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/openscvx/symbolic/constraint_set.py +0 -0
  169. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/openscvx/symbolic/expr/__init__.py +0 -0
  170. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/openscvx/symbolic/expr/arithmetic.py +0 -0
  171. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/openscvx/symbolic/expr/array.py +0 -0
  172. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/openscvx/symbolic/expr/constraint.py +0 -0
  173. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/openscvx/symbolic/expr/control.py +0 -0
  174. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/openscvx/symbolic/expr/expr.py +0 -0
  175. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/openscvx/symbolic/expr/lie/__init__.py +0 -0
  176. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/openscvx/symbolic/expr/lie/adjoint.py +0 -0
  177. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/openscvx/symbolic/expr/lie/se3.py +0 -0
  178. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/openscvx/symbolic/expr/lie/so3.py +0 -0
  179. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/openscvx/symbolic/expr/linalg.py +0 -0
  180. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/openscvx/symbolic/expr/math.py +0 -0
  181. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/openscvx/symbolic/expr/spatial.py +0 -0
  182. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/openscvx/symbolic/expr/state.py +0 -0
  183. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/openscvx/symbolic/expr/stl.py +0 -0
  184. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/openscvx/symbolic/expr/variable.py +0 -0
  185. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/openscvx/symbolic/expr/vmap.py +0 -0
  186. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/openscvx/symbolic/hashing.py +0 -0
  187. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/openscvx/symbolic/lower.py +0 -0
  188. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/openscvx/symbolic/lowerers/__init__.py +0 -0
  189. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/openscvx/symbolic/lowerers/cvxpy.py +0 -0
  190. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/openscvx/symbolic/lowerers/jax.py +0 -0
  191. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/openscvx/symbolic/problem.py +0 -0
  192. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/openscvx/symbolic/time.py +0 -0
  193. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/openscvx/symbolic/unified.py +0 -0
  194. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/openscvx/utils/__init__.py +0 -0
  195. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/openscvx/utils/cache.py +0 -0
  196. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/openscvx/utils/caching.py +0 -0
  197. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/openscvx/utils/printing.py +0 -0
  198. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/openscvx/utils/profiling.py +0 -0
  199. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/openscvx/utils/utils.py +0 -0
  200. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/openscvx.egg-info/SOURCES.txt +0 -0
  201. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/openscvx.egg-info/dependency_links.txt +0 -0
  202. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/openscvx.egg-info/requires.txt +0 -0
  203. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/openscvx.egg-info/top_level.txt +0 -0
  204. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/pyproject.toml +0 -0
  205. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/scripts/gen_example_pages.py +0 -0
  206. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/scripts/gen_ref_pages.py +0 -0
  207. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/setup.cfg +0 -0
  208. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/tests/__init__.py +0 -0
  209. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/tests/brachistochrone_analytical.py +0 -0
  210. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/tests/symbolic/__init__.py +0 -0
  211. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/tests/symbolic/expr/__init__.py +0 -0
  212. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/tests/symbolic/expr/test_arithmetic.py +0 -0
  213. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/tests/symbolic/expr/test_array.py +0 -0
  214. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/tests/symbolic/expr/test_constraint.py +0 -0
  215. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/tests/symbolic/expr/test_expr.py +0 -0
  216. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/tests/symbolic/expr/test_lie.py +0 -0
  217. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/tests/symbolic/expr/test_linalg.py +0 -0
  218. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/tests/symbolic/expr/test_math.py +0 -0
  219. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/tests/symbolic/expr/test_node_reference.py +0 -0
  220. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/tests/symbolic/expr/test_parameters.py +0 -0
  221. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/tests/symbolic/expr/test_scaling.py +0 -0
  222. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/tests/symbolic/expr/test_spatial.py +0 -0
  223. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/tests/symbolic/expr/test_variable.py +0 -0
  224. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/tests/symbolic/expr/test_vmap.py +0 -0
  225. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/tests/symbolic/test_augmentation.py +0 -0
  226. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/tests/symbolic/test_hashing.py +0 -0
  227. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/tests/symbolic/test_lower_cvxpy.py +0 -0
  228. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/tests/symbolic/test_lower_jax.py +0 -0
  229. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/tests/symbolic/test_unified.py +0 -0
  230. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/tests/test_cvxpygen_optional.py +0 -0
  231. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/tests/test_discretization.py +0 -0
  232. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/tests/test_examples.py +0 -0
  233. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/tests/test_integrators.py +0 -0
  234. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/tests/test_plotting.py +0 -0
  235. {openscvx-0.3.2.dev219 → openscvx-0.3.2.dev228}/tests/test_propagation.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: openscvx
3
- Version: 0.3.2.dev219
3
+ Version: 0.3.2.dev228
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
@@ -38,14 +38,12 @@ position.max = np.array([3000, 3000, 3000])
38
38
  position.min = np.array([-3000, -3000, 0])
39
39
  position.initial = np.array([2000, 0, 1500])
40
40
  position.final = np.array([0, 0, 0])
41
- position.guess = np.linspace(position.initial, position.final, n)
42
41
 
43
42
  velocity = ox.State("velocity", shape=(3,)) # 3D velocity [vx, vy, vz]
44
43
  velocity.max = np.array([v_max, v_max, v_max])
45
44
  velocity.min = np.array([-v_max, -v_max, -v_max])
46
45
  velocity.initial = np.array([80, 30, -75])
47
46
  velocity.final = np.array([0, 0, 0])
48
- velocity.guess = np.linspace(velocity.initial, velocity.final, n)
49
47
 
50
48
  mass = ox.State("mass", shape=(1,)) # Vehicle mass
51
49
  mass.max = np.array([1905])
@@ -54,7 +52,6 @@ mass.initial = np.array([1905])
54
52
  mass.final = [("maximize", 1690)]
55
53
  mass.scaling_min = np.array([1690])
56
54
  # mass.scaling_max = np.array([1700])
57
- mass.guess = np.linspace(mass.initial, 1690, n).reshape(-1, 1)
58
55
 
59
56
  # Define control
60
57
  thrust = ox.Control("thrust", shape=(3,)) # Thrust force vector [Tx, Ty, Tz]
@@ -38,14 +38,12 @@ position.max = np.array([10.0, 10.0])
38
38
  position.min = np.array([0.0, 0.0])
39
39
  position.initial = np.array([0.0, 10.0])
40
40
  position.final = [10.0, 5.0]
41
- position.guess = np.linspace(position.initial, position.final, n)
42
41
 
43
42
  velocity = ox.State("velocity", shape=(1,)) # Scalar speed
44
43
  velocity.max = np.array([10.0])
45
44
  velocity.min = np.array([0.0])
46
45
  velocity.initial = np.array([0.0])
47
46
  velocity.final = [("free", 10.0)]
48
- velocity.guess = np.linspace(0.0, 10.0, n).reshape(-1, 1)
49
47
 
50
48
  # Define control
51
49
  theta = ox.Control("theta", shape=(1,)) # Angle from vertical
@@ -35,14 +35,12 @@ position.min = np.array([-5.0, -5.0])
35
35
  position.max = np.array([5.0, 5.0])
36
36
  position.initial = np.array([0, -2])
37
37
  position.final = np.array([0, 2])
38
- position.guess = np.linspace(position.initial, position.final, n)
39
38
 
40
39
  theta = ox.State("theta", shape=(1,)) # Heading angle
41
40
  theta.min = np.array([-2 * jnp.pi])
42
41
  theta.max = np.array([2 * jnp.pi])
43
42
  theta.initial = np.array([0])
44
43
  theta.final = [ox.Free(0)]
45
- theta.guess = np.zeros((n, 1))
46
44
 
47
45
  # Define control components
48
46
  speed = ox.Control("speed", shape=(1,)) # Forward speed
@@ -41,7 +41,6 @@ theta.min = np.array([-2 * jnp.pi])
41
41
  theta.max = np.array([2 * jnp.pi])
42
42
  theta.initial = np.array([0])
43
43
  theta.final = [("free", 0)]
44
- theta.guess = np.zeros((n, 1))
45
44
 
46
45
  # Define control components
47
46
  speed = ox.Control("speed", shape=(1,)) # Forward speed
@@ -37,14 +37,12 @@ position.min = np.array([-5.0, -5.0])
37
37
  position.max = np.array([5.0, 5.0])
38
38
  position.initial = np.array([0, -2])
39
39
  position.final = np.array([0, 2])
40
- position.guess = np.linspace(position.initial, position.final, n)
41
40
 
42
41
  theta = ox.State("theta", shape=(1,)) # Heading angle
43
42
  theta.min = np.array([-2 * jnp.pi])
44
43
  theta.max = np.array([2 * jnp.pi])
45
44
  theta.initial = np.array([0])
46
45
  theta.final = [("free", 0)]
47
- theta.guess = np.zeros((n, 1))
48
46
 
49
47
  # Define control components
50
48
  speed = ox.Control("speed", shape=(1,)) # Forward speed
@@ -63,7 +61,6 @@ time.max = np.array([10])
63
61
  time.min = np.array([0.0])
64
62
  time.initial = np.array([0.0])
65
63
  time.final = [ox.Minimize(total_time)]
66
- time.guess = np.linspace(0.0, total_time, n).reshape(-1, 1)
67
64
 
68
65
 
69
66
  # Define list of all states and controls
@@ -70,7 +70,6 @@ time.max = np.array([total_time])
70
70
  time.min = np.array([0.0])
71
71
  time.initial = np.array([0.0])
72
72
  time.final = np.array([total_time])
73
- time.guess = np.linspace(0.0, total_time, n).reshape(-1, 1)
74
73
 
75
74
  # Define control components
76
75
  thrust_force = ox.Control("thrust_force", shape=(3,)) # Thrust forces [fx, fy, fz]
@@ -38,14 +38,12 @@ position.max = np.array([200.0, 100, 50])
38
38
  position.min = np.array([-200.0, -100, 15])
39
39
  position.initial = np.array([10.0, 0, 20])
40
40
  position.final = [10.0, 0, 20]
41
- position.guess = np.linspace(position.initial, position.final, n)
42
41
 
43
42
  velocity = ox.State("velocity", shape=(3,)) # 3D velocity [vx, vy, vz]
44
43
  velocity.max = np.array([100, 100, 100])
45
44
  velocity.min = np.array([-100, -100, -100])
46
45
  velocity.initial = np.array([0, 0, 0])
47
46
  velocity.final = [("free", 0), ("free", 0), ("free", 0)]
48
- velocity.guess = np.linspace(velocity.initial, [0, 0, 0], n)
49
47
 
50
48
  # Define control
51
49
  force = ox.Control("force", shape=(3,)) # Control forces [fx, fy, fz]
@@ -37,28 +37,24 @@ position.max = np.array([200.0, 100, 200])
37
37
  position.min = np.array([-200.0, -100, 15])
38
38
  position.initial = np.array([10.0, 0, 20])
39
39
  position.final = [10.0, 0, 20]
40
- position.guess = np.linspace(position.initial, position.final, n)
41
40
 
42
41
  velocity = ox.State("velocity", shape=(3,)) # 3D velocity [vx, vy, vz]
43
42
  velocity.max = np.array([100, 100, 100])
44
43
  velocity.min = np.array([-100, -100, -100])
45
44
  velocity.initial = np.array([0, 0, 0])
46
45
  velocity.final = [("free", 0), ("free", 0), ("free", 0)]
47
- velocity.guess = np.linspace(velocity.initial, [0, 0, 0], n)
48
46
 
49
47
  attitude = ox.State("attitude", shape=(4,)) # Quaternion [qw, qx, qy, qz]
50
48
  attitude.max = np.array([1, 1, 1, 1])
51
49
  attitude.min = np.array([-1, -1, -1, -1])
52
50
  attitude.initial = [("free", 1.0), ("free", 0), ("free", 0), ("free", 0)]
53
51
  attitude.final = [("free", 1), ("free", 0), ("free", 0), ("free", 0)]
54
- attitude.guess = np.tile([1.0, 0.0, 0.0, 0.0], (n, 1))
55
52
 
56
53
  angular_velocity = ox.State("angular_velocity", shape=(3,)) # Angular velocity [wx, wy, wz]
57
54
  angular_velocity.max = np.array([10, 10, 10])
58
55
  angular_velocity.min = np.array([-10, -10, -10])
59
56
  angular_velocity.initial = [("free", 0), ("free", 0), ("free", 0)]
60
57
  angular_velocity.final = [("free", 0), ("free", 0), ("free", 0)]
61
- angular_velocity.guess = np.zeros((n, 3))
62
58
 
63
59
  # Define control components
64
60
  thrust_force = ox.Control("thrust_force", shape=(3,)) # Thrust forces [fx, fy, fz]
@@ -137,12 +137,6 @@ for center, A in zip(obstacle_centers, A_obs):
137
137
  obstacle_constraint = ox.ctcs(1.0 <= diff.T @ A_const @ diff)
138
138
  constraints.append(obstacle_constraint)
139
139
 
140
- # Set initial guesses
141
- position.guess = np.linspace(position.initial, position.final, n)
142
- velocity.guess = np.linspace(velocity.initial, [0, 0, 0], n)
143
- attitude.guess = np.tile([1.0, 0.0, 0.0, 0.0], (n, 1))
144
- angular_velocity.guess = np.zeros((n, 3))
145
-
146
140
 
147
141
  time = ox.Time(
148
142
  initial=0.0,
@@ -136,12 +136,6 @@ for center, A in zip(obstacle_centers, A_obs):
136
136
  obstacle_constraint = 1.0 <= diff.T @ A_const @ diff
137
137
  constraints.append(obstacle_constraint)
138
138
 
139
- # Set initial guesses
140
- position.guess = np.linspace(position.initial, position.final, n)
141
- velocity.guess = np.linspace(velocity.initial, [0, 0, 0], n)
142
- attitude.guess = np.tile([1.0, 0.0, 0.0, 0.0], (n, 1))
143
- angular_velocity.guess = np.zeros((n, 3))
144
-
145
139
  time = ox.Time(
146
140
  initial=0.0,
147
141
  final=("minimize", total_time),
@@ -137,13 +137,6 @@ for center, A in zip(obstacle_centers, A_obs):
137
137
  obstacle_constraint = ox.ctcs(1.0 <= diff.T @ A_const @ diff)
138
138
  constraints.append(obstacle_constraint)
139
139
 
140
- # Set initial guesses
141
- position.guess = np.linspace(position.initial, position.final, n)
142
- velocity.guess = np.linspace(velocity.initial, [0, 0, 0], n)
143
- attitude.guess = np.tile([1.0, 0.0, 0.0, 0.0], (n, 1))
144
- angular_velocity.guess = np.zeros((n, 3))
145
-
146
-
147
140
  time = ox.Time(
148
141
  initial=0.0,
149
142
  final=("minimize", total_time),
@@ -54,7 +54,6 @@ position.max = np.array([100.0, 100.0, 100.0])
54
54
  position.min = np.array([-100.0, -100.0, -100.0])
55
55
  position.initial = np.array([0.0, -100.0, 0.0]) # Start 100m behind target (V-bar position)
56
56
  position.final = np.array([0.0, 0.0, 0.0]) # Dock at origin
57
- position.guess = np.linspace(position.initial, position.final, n_nodes)
58
57
 
59
58
  # Velocity in CW frame [vx, vy, vz] in m/s
60
59
  velocity = ox.State("velocity", shape=(3,))
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
28
28
  commit_id: COMMIT_ID
29
29
  __commit_id__: COMMIT_ID
30
30
 
31
- __version__ = version = '0.3.2.dev219'
32
- __version_tuple__ = version_tuple = (0, 3, 2, 'dev219')
31
+ __version__ = version = '0.3.2.dev228'
32
+ __version_tuple__ = version_tuple = (0, 3, 2, 'dev228')
33
33
 
34
- __commit_id__ = commit_id = 'g507eddb5a'
34
+ __commit_id__ = commit_id = 'g44572a46d'
@@ -47,11 +47,15 @@ from openscvx.symbolic.expr.state import State
47
47
  from openscvx.symbolic.preprocessing import (
48
48
  collect_and_assign_slices,
49
49
  convert_dynamics_dict_to_expr,
50
+ fill_default_guesses,
50
51
  validate_and_normalize_constraint_nodes,
52
+ validate_boundary_conditions,
53
+ validate_bounds,
51
54
  validate_constraints_at_root,
52
55
  validate_dynamics_dict,
53
56
  validate_dynamics_dict_dimensions,
54
57
  validate_dynamics_dimension,
58
+ validate_guesses,
55
59
  validate_shapes,
56
60
  validate_time_parameters,
57
61
  validate_variable_names,
@@ -185,6 +189,17 @@ def preprocess_symbolic_problem(
185
189
  print([s.name for s in problem.states_prop])
186
190
  """
187
191
 
192
+ # Validate user-provided variables have required attributes
193
+ validate_boundary_conditions(states)
194
+ validate_bounds(states + controls)
195
+
196
+ # Fill in default guesses for user-provided states
197
+ # (augmented states get their guesses set by augmentation code)
198
+ fill_default_guesses(states, N)
199
+
200
+ # Validate that all user-provided variables have guesses
201
+ validate_guesses(states + controls)
202
+
188
203
  # ==================== PHASE 1: Time Handling & Validation ====================
189
204
 
190
205
  # Validate time handling approach and get processed parameters
@@ -54,6 +54,7 @@ from openscvx.symbolic.expr import (
54
54
  Expr,
55
55
  NodalConstraint,
56
56
  State,
57
+ Variable,
57
58
  traverse,
58
59
  )
59
60
 
@@ -755,3 +756,84 @@ def convert_dynamics_dict_to_expr(
755
756
  dynamics_concat = Concat(*dynamics_exprs)
756
757
 
757
758
  return dynamics_converted, dynamics_concat
759
+
760
+
761
+ def fill_default_guesses(states: List[State], N: int) -> None:
762
+ """Fill in default linspace guesses for states with guess=None.
763
+
764
+ For states with both initial and final conditions set, generates a linear
765
+ interpolation from initial to final values.
766
+
767
+ This function modifies states in-place.
768
+
769
+ Args:
770
+ states: List of State objects to fill guesses for
771
+ N: Number of discretization nodes
772
+ """
773
+ for state in states:
774
+ if state.guess is None and state.initial is not None and state.final is not None:
775
+ # state.initial and state.final are already numpy arrays of values
776
+ # (the setter handles parsing tuples like ("free", value))
777
+ state.guess = np.linspace(state.initial, state.final, N)
778
+
779
+
780
+ def validate_boundary_conditions(states: List[State]) -> None:
781
+ """Validate that all states have initial and final boundary conditions set.
782
+
783
+ Args:
784
+ states: List of State objects to validate
785
+
786
+ Raises:
787
+ ValueError: If any state is missing initial or final conditions
788
+ """
789
+ for state in states:
790
+ if state.initial is None:
791
+ raise ValueError(
792
+ f"State '{state.name}' is missing initial condition. "
793
+ f"Please set {state.name}.initial"
794
+ )
795
+ if state.final is None:
796
+ raise ValueError(
797
+ f"State '{state.name}' is missing final condition. Please set {state.name}.final"
798
+ )
799
+
800
+
801
+ def validate_bounds(variables: List[Variable]) -> None:
802
+ """Validate that all variables have min and max bounds set.
803
+
804
+ Args:
805
+ variables: List of Variable objects (State or Control) to validate
806
+
807
+ Raises:
808
+ ValueError: If any variable is missing min or max bounds
809
+ """
810
+ for var in variables:
811
+ if var.min is None:
812
+ raise ValueError(
813
+ f"Variable '{var.name}' is missing min bound. Please set {var.name}.min"
814
+ )
815
+ if var.max is None:
816
+ raise ValueError(
817
+ f"Variable '{var.name}' is missing max bound. Please set {var.name}.max"
818
+ )
819
+
820
+
821
+ def validate_guesses(variables: List[Variable]) -> None:
822
+ """Validate that all variables have initial guesses set.
823
+
824
+ Args:
825
+ variables: List of Variable objects (State or Control) to validate
826
+
827
+ Raises:
828
+ ValueError: If any variable is missing a guess
829
+ """
830
+ for var in variables:
831
+ if var.guess is None:
832
+ if isinstance(var, Control):
833
+ raise ValueError(
834
+ f"Control '{var.name}' is missing initial guess. "
835
+ f"Please set {var.name}.guess (controls require explicit guesses)"
836
+ )
837
+ raise ValueError(
838
+ f"State '{var.name}' is missing initial guess. Please set {var.name}.guess"
839
+ )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: openscvx
3
- Version: 0.3.2.dev219
3
+ Version: 0.3.2.dev228
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
@@ -6,11 +6,15 @@ from openscvx.symbolic.expr import Add, Concat, Constant, Control, CrossNodeCons
6
6
  from openscvx.symbolic.preprocessing import (
7
7
  collect_and_assign_slices,
8
8
  convert_dynamics_dict_to_expr,
9
+ fill_default_guesses,
10
+ validate_boundary_conditions,
11
+ validate_bounds,
9
12
  validate_constraints_at_root,
10
13
  validate_cross_node_constraint,
11
14
  validate_dynamics_dict,
12
15
  validate_dynamics_dict_dimensions,
13
16
  validate_dynamics_dimension,
17
+ validate_guesses,
14
18
  validate_variable_names,
15
19
  )
16
20
 
@@ -801,3 +805,174 @@ def test_cross_node_constraint_both_sides():
801
805
  constraint2 = CrossNodeConstraint(velocity <= position.at(5))
802
806
  with pytest.raises(ValueError, match="without .at\\(\\).*vel"):
803
807
  validate_cross_node_constraint(constraint2, N)
808
+
809
+
810
+ # =============================================================================
811
+ # fill_default_guesses Tests
812
+ # =============================================================================
813
+
814
+
815
+ def test_fill_default_guesses_state_linspace():
816
+ """Test that state guesses are filled with linspace from initial to final."""
817
+ N = 11 # Use 11 so middle index (5) is exactly at midpoint
818
+ x = State("x", shape=(3,))
819
+ x.initial = np.array([0.0, 1.0, 2.0])
820
+ x.final = np.array([10.0, 11.0, 12.0])
821
+
822
+ fill_default_guesses([x], N)
823
+
824
+ assert x.guess is not None
825
+ assert x.guess.shape == (N, 3)
826
+ # Check first and last rows match initial and final
827
+ np.testing.assert_array_almost_equal(x.guess[0], [0.0, 1.0, 2.0])
828
+ np.testing.assert_array_almost_equal(x.guess[-1], [10.0, 11.0, 12.0])
829
+ # Check it's actually a linspace (middle index should be exactly at midpoint)
830
+ np.testing.assert_array_almost_equal(x.guess[N // 2], [5.0, 6.0, 7.0])
831
+
832
+
833
+ def test_fill_default_guesses_preserves_existing():
834
+ """Test that existing guesses are not overwritten."""
835
+ N = 10
836
+ x = State("x", shape=(2,))
837
+ x.initial = np.array([0.0, 0.0])
838
+ x.final = np.array([10.0, 10.0])
839
+ custom_guess = np.ones((N, 2)) * 99.0
840
+ x.guess = custom_guess
841
+
842
+ fill_default_guesses([x], N)
843
+
844
+ # Guess should be unchanged
845
+ np.testing.assert_array_equal(x.guess, custom_guess)
846
+
847
+
848
+ def test_fill_default_guesses_with_free_boundary_conditions():
849
+ """Test that states with free boundary conditions use the guess values."""
850
+ N = 10
851
+ x = State("x", shape=(3,))
852
+ # Mixed: first fixed, second free, third fixed
853
+ x.initial = [0.0, ("free", 5.0), 2.0]
854
+ x.final = [10.0, ("free", 15.0), 12.0]
855
+
856
+ fill_default_guesses([x], N)
857
+
858
+ assert x.guess is not None
859
+ assert x.guess.shape == (N, 3)
860
+ # The setter extracts values from tuples, so initial=[0, 5, 2], final=[10, 15, 12]
861
+ np.testing.assert_array_almost_equal(x.guess[0], [0.0, 5.0, 2.0])
862
+ np.testing.assert_array_almost_equal(x.guess[-1], [10.0, 15.0, 12.0])
863
+
864
+
865
+ def test_fill_default_guesses_multiple_states():
866
+ """Test filling guesses for multiple states at once."""
867
+ N = 5
868
+ x1 = State("x1", shape=(2,))
869
+ x1.initial = np.array([0.0, 0.0])
870
+ x1.final = np.array([4.0, 8.0])
871
+
872
+ x2 = State("x2", shape=(1,))
873
+ x2.initial = np.array([10.0])
874
+ x2.final = np.array([20.0])
875
+
876
+ fill_default_guesses([x1, x2], N)
877
+
878
+ # Check x1
879
+ assert x1.guess.shape == (N, 2)
880
+ np.testing.assert_array_almost_equal(x1.guess[0], [0.0, 0.0])
881
+ np.testing.assert_array_almost_equal(x1.guess[-1], [4.0, 8.0])
882
+
883
+ # Check x2
884
+ assert x2.guess.shape == (N, 1)
885
+ np.testing.assert_array_almost_equal(x2.guess[0], [10.0])
886
+ np.testing.assert_array_almost_equal(x2.guess[-1], [20.0])
887
+
888
+
889
+ # =============================================================================
890
+ # validate_boundary_conditions Tests
891
+ # =============================================================================
892
+
893
+
894
+ def test_validate_boundary_conditions_passes():
895
+ """Test that validation passes when all states have initial and final."""
896
+ x = State("position", shape=(3,))
897
+ x.initial = np.zeros(3)
898
+ x.final = np.ones(3)
899
+
900
+ validate_boundary_conditions([x])
901
+ validate_boundary_conditions([])
902
+
903
+
904
+ def test_validate_boundary_conditions_raises_missing():
905
+ """Test that validation fails fast on first missing attribute."""
906
+ x = State("position", shape=(2,))
907
+ # No initial or final set
908
+
909
+ with pytest.raises(ValueError, match="'position' is missing initial"):
910
+ validate_boundary_conditions([x])
911
+
912
+ # With initial but no final
913
+ x.initial = np.zeros(2)
914
+ with pytest.raises(ValueError, match="'position' is missing final"):
915
+ validate_boundary_conditions([x])
916
+
917
+
918
+ # =============================================================================
919
+ # validate_bounds Tests
920
+ # =============================================================================
921
+
922
+
923
+ def test_validate_bounds_passes():
924
+ """Test that validation passes when all variables have min and max."""
925
+ x = State("position", shape=(3,))
926
+ x.min = np.array([-10, -10, -10])
927
+ x.max = np.array([10, 10, 10])
928
+
929
+ u = Control("thrust", shape=(2,))
930
+ u.min = np.zeros(2)
931
+ u.max = np.array([100, 100])
932
+
933
+ validate_bounds([x, u])
934
+ validate_bounds([])
935
+
936
+
937
+ def test_validate_bounds_raises_missing():
938
+ """Test that validation fails fast on first missing attribute."""
939
+ u = Control("thrust", shape=(2,))
940
+ # No min or max set
941
+
942
+ with pytest.raises(ValueError, match="'thrust' is missing min"):
943
+ validate_bounds([u])
944
+
945
+ # With min but no max
946
+ u.min = np.zeros(2)
947
+ with pytest.raises(ValueError, match="'thrust' is missing max"):
948
+ validate_bounds([u])
949
+
950
+
951
+ # =============================================================================
952
+ # validate_guesses Tests
953
+ # =============================================================================
954
+
955
+
956
+ def test_validate_guesses_passes():
957
+ """Test that validation passes when all variables have guesses."""
958
+ N = 10
959
+ x = State("position", shape=(3,))
960
+ x.guess = np.zeros((N, 3))
961
+
962
+ u = Control("thrust", shape=(2,))
963
+ u.guess = np.ones((N, 2))
964
+
965
+ validate_guesses([x, u])
966
+ validate_guesses([])
967
+
968
+
969
+ def test_validate_guesses_raises_missing():
970
+ """Test that validation fails fast on first missing guess."""
971
+ u = Control("thrust", shape=(2,))
972
+ # No guess set
973
+
974
+ with pytest.raises(
975
+ ValueError,
976
+ match="Control 'thrust' is missing initial guess.*controls require explicit guesses",
977
+ ):
978
+ validate_guesses([u])
@@ -158,7 +158,6 @@ def test_monolithic():
158
158
  x.min = np.array([0.0, 0.0, 0.0]) # Lower bounds
159
159
  x.initial = np.array([x0, y0, 0.0]) # [x0, y0, v0]
160
160
  x.final = [x1, y1, ("free", 10.0)] # [x1, y1, v_free]
161
- x.guess = np.linspace(x.initial, x.final, n)
162
161
 
163
162
  # Define control
164
163
  u = ox.Control("u", shape=(1,)) # Angle from vertical
@@ -261,14 +260,12 @@ def test_constraint_types(constraint_type):
261
260
  position.min = np.array([0.0, 0.0])
262
261
  position.initial = np.array([x0, y0])
263
262
  position.final = [x1, y1]
264
- position.guess = np.linspace(position.initial, position.final, n)
265
263
 
266
264
  velocity = ox.State("velocity", shape=(1,)) # Scalar speed
267
265
  velocity.max = np.array([10.0])
268
266
  velocity.min = np.array([0.0])
269
267
  velocity.initial = np.array([0.0])
270
268
  velocity.final = [("free", 10.0)]
271
- velocity.guess = np.linspace(0.0, 10.0, n).reshape(-1, 1)
272
269
 
273
270
  # Define control
274
271
  theta = ox.Control("theta", shape=(1,)) # Angle from vertical
@@ -407,14 +404,12 @@ def test_cross_nodal(test_case):
407
404
  position.min = np.array([0.0, 0.0])
408
405
  position.initial = np.array([x0, y0])
409
406
  position.final = [x1, y1]
410
- position.guess = np.linspace(position.initial, position.final, n)
411
407
 
412
408
  velocity = ox.State("velocity", shape=(1,)) # Scalar speed
413
409
  velocity.max = np.array([10.0])
414
410
  velocity.min = np.array([0.0])
415
411
  velocity.initial = np.array([0.0])
416
412
  velocity.final = [("free", 10.0)]
417
- velocity.guess = np.linspace(0.0, 10.0, n).reshape(-1, 1)
418
413
 
419
414
  # Define control
420
415
  theta = ox.Control("theta", shape=(1,)) # Angle from vertical
@@ -556,14 +551,12 @@ def test_parameters():
556
551
  position.min = np.array([0.0, 0.0])
557
552
  position.initial = np.array([x0, y0])
558
553
  position.final = [x1, y1]
559
- position.guess = np.linspace(position.initial, position.final, n)
560
554
 
561
555
  velocity = ox.State("velocity", shape=(1,)) # Scalar speed
562
556
  velocity.max = np.array([10.0])
563
557
  velocity.min = np.array([0.0])
564
558
  velocity.initial = np.array([0.0])
565
559
  velocity.final = [("free", 10.0)]
566
- velocity.guess = np.linspace(0.0, 10.0, n).reshape(-1, 1)
567
560
 
568
561
  # Define control
569
562
  theta = ox.Control("theta", shape=(1,)) # Angle from vertical
@@ -735,14 +728,12 @@ def test_propagation():
735
728
  position.min = np.array([0.0, 0.0])
736
729
  position.initial = np.array([x0, y0])
737
730
  position.final = [x1, y1]
738
- position.guess = np.linspace(position.initial, position.final, n)
739
731
 
740
732
  velocity = ox.State("velocity", shape=(1,)) # Scalar speed
741
733
  velocity.max = np.array([10.0])
742
734
  velocity.min = np.array([0.0])
743
735
  velocity.initial = np.array([0.0])
744
736
  velocity.final = [("free", 10.0)]
745
- velocity.guess = np.linspace(0.0, 10.0, n).reshape(-1, 1)
746
737
 
747
738
  # Define control
748
739
  theta = ox.Control("theta", shape=(1,)) # Angle from vertical
@@ -755,6 +746,8 @@ def test_propagation():
755
746
  controls = [theta]
756
747
 
757
748
  # Define propagation-only state for tracking total distance traveled
749
+ # Note: propagation states need explicit guesses since fill_default_guesses
750
+ # only runs on main optimization states
758
751
  distance = ox.State("distance", shape=(1,))
759
752
  distance.initial = np.array([0.0])
760
753
  distance.min = np.array([0.0])
@@ -1003,14 +996,12 @@ def test_byof(byof_mode):
1003
996
  position.min = np.array([0.0, 0.0])
1004
997
  position.initial = np.array([x0, y0])
1005
998
  position.final = [x1, y1]
1006
- position.guess = np.linspace(position.initial, position.final, n)
1007
999
 
1008
1000
  velocity = ox.State("velocity", shape=(1,))
1009
1001
  velocity.max = np.array([10.0])
1010
1002
  velocity.min = np.array([0.0])
1011
1003
  velocity.initial = np.array([0.0])
1012
1004
  velocity.final = [("free", 10.0)]
1013
- velocity.guess = np.linspace(0.0, 10.0, n).reshape(-1, 1)
1014
1005
 
1015
1006
  # Define control
1016
1007
  theta = ox.Control("theta", shape=(1,))
@@ -651,10 +651,12 @@ def test_problem_validates_byof_during_construction():
651
651
  velocity.min = np.array([0.0])
652
652
  velocity.max = np.array([10.0])
653
653
  velocity.initial = np.array([0.0])
654
+ velocity.final = [("free", 5.0)]
654
655
 
655
656
  theta = ox.Control("theta", shape=(1,))
656
657
  theta.min = np.array([0.0])
657
658
  theta.max = np.array([np.pi / 2])
659
+ theta.guess = np.zeros((2, 1))
658
660
 
659
661
  dynamics = {"position": ox.Concat(velocity[0], velocity[0])}
660
662
  time = ox.Time(initial=0.0, final=1.0, min=0.0, max=2.0)