openscvx 0.3.2.dev333__tar.gz → 0.3.2.dev339__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 (265) hide show
  1. {openscvx-0.3.2.dev333/openscvx.egg-info → openscvx-0.3.2.dev339}/PKG-INFO +1 -1
  2. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/_version.py +3 -3
  3. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/problem.py +1 -2
  4. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/symbolic/builder.py +13 -7
  5. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/symbolic/preprocessing.py +136 -0
  6. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339/openscvx.egg-info}/PKG-INFO +1 -1
  7. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/tests/symbolic/test_preprocessing.py +175 -0
  8. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/.github/assets/logo.svg +0 -0
  9. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/.github/release-drafter.yml +0 -0
  10. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/.github/workflows/_docs.yml +0 -0
  11. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/.github/workflows/branch-name.yml +0 -0
  12. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/.github/workflows/docs.yml +0 -0
  13. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/.github/workflows/lint.yml +0 -0
  14. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/.github/workflows/nightly.yml +0 -0
  15. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/.github/workflows/release-drafter.yml +0 -0
  16. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/.github/workflows/release.yml +0 -0
  17. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/.github/workflows/tests-integration.yml +0 -0
  18. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/.github/workflows/tests-unit.yml +0 -0
  19. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/.gitignore +0 -0
  20. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/CONTRIBUTING.md +0 -0
  21. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/LICENSE +0 -0
  22. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/README.md +0 -0
  23. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/docs/Foundations/constraint_reformulation.md +0 -0
  24. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/docs/Foundations/control_parameterization.md +0 -0
  25. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/docs/Foundations/discretization.md +0 -0
  26. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/docs/Foundations/ocp.md +0 -0
  27. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/docs/Foundations/scvx.md +0 -0
  28. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/docs/Foundations/time_dilation.md +0 -0
  29. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/docs/UnderTheHood/lowering_architecture.md +0 -0
  30. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/docs/UnderTheHood/vectorization_and_vmapping.md +0 -0
  31. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/docs/UsersGuide/00_introduction.md +0 -0
  32. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/docs/UsersGuide/01_hello_world_brachistochrone.md +0 -0
  33. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/docs/UsersGuide/02_drone_racing_constraints.md +0 -0
  34. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/docs/UsersGuide/03_obstacle_avoidance_vmap.md +0 -0
  35. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/docs/UsersGuide/04_viewpoint_constraints.md +0 -0
  36. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/docs/UsersGuide/05_visualization.md +0 -0
  37. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/docs/UsersGuide/06_logic.md +0 -0
  38. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/docs/UsersGuide/07_lie.md +0 -0
  39. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/docs/assets/favicon.png +0 -0
  40. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/docs/assets/images/ct-scvx_dark.png +0 -0
  41. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/docs/assets/images/ct-scvx_light.png +0 -0
  42. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/docs/assets/images/ctcs_dark.png +0 -0
  43. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/docs/assets/images/ctcs_light.png +0 -0
  44. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/docs/assets/images/problem_class_dark.png +0 -0
  45. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/docs/assets/images/problem_class_light.png +0 -0
  46. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/docs/assets/logo.svg +0 -0
  47. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/docs/citation.md +0 -0
  48. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/docs/examples.md +0 -0
  49. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/docs/getting-started.md +0 -0
  50. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/docs/index.md +0 -0
  51. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/docs/javascripts/mathjax.js +0 -0
  52. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/examples/abstract/brachistochrone.py +0 -0
  53. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/examples/arm/three_link_arm.py +0 -0
  54. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/examples/car/dubins_car.py +0 -0
  55. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/examples/car/dubins_car_conditional.py +0 -0
  56. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/examples/car/dubins_car_disjoint.py +0 -0
  57. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/examples/car/dubins_car_stljax.py +0 -0
  58. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/examples/drone/cinema_vp.py +0 -0
  59. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/examples/drone/cinema_vp_realtime_base.py +0 -0
  60. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/examples/drone/dr_double_integrator.py +0 -0
  61. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/examples/drone/dr_vp.py +0 -0
  62. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/examples/drone/dr_vp_nodal.py +0 -0
  63. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/examples/drone/dr_vp_polytope.py +0 -0
  64. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/examples/drone/drone_racing.py +0 -0
  65. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/examples/drone/obstacle_avoidance.py +0 -0
  66. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/examples/drone/obstacle_avoidance_nodal.py +0 -0
  67. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/examples/drone/obstacle_avoidance_realtime_base.py +0 -0
  68. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/examples/drone/obstacle_avoidance_vmap.py +0 -0
  69. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/examples/plotting.py +0 -0
  70. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/examples/plotting_viser.py +0 -0
  71. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/examples/realtime/cinema_vp_realtime.py +0 -0
  72. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/examples/realtime/drone_racing_realtime.py +0 -0
  73. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/examples/realtime/dubins_car_realtime.py +0 -0
  74. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/examples/realtime/obstacle_avoidance_realtime.py +0 -0
  75. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/examples/rocket/3DoF_pdg.py +0 -0
  76. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/examples/spacecraft/proxops_cw.py +0 -0
  77. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/figures/ctlos_cine.gif +0 -0
  78. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/figures/ctlos_dr.gif +0 -0
  79. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/figures/dtlos_cine.gif +0 -0
  80. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/figures/dtlos_dr.gif +0 -0
  81. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/figures/openscvx_logo.svg +0 -0
  82. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/figures/openscvx_logo_square.png +0 -0
  83. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/figures/oscvx_structure_full_dark.svg +0 -0
  84. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/figures/video_preview.png +0 -0
  85. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/material/__init__.py +0 -0
  86. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/material/overrides/assets/images/layers/1-background.avif +0 -0
  87. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/material/overrides/assets/images/layers/1-background@1x.avif +0 -0
  88. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/material/overrides/assets/images/layers/1-background@2x.avif +0 -0
  89. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/material/overrides/assets/images/layers/1-background@3x.avif +0 -0
  90. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/material/overrides/assets/images/layers/1-background@4x.avif +0 -0
  91. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/material/overrides/assets/images/layers/2-mars.avif +0 -0
  92. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/material/overrides/assets/images/layers/2-mars@1x.avif +0 -0
  93. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/material/overrides/assets/images/layers/2-mars@2x.avif +0 -0
  94. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/material/overrides/assets/images/layers/2-mars@3x.avif +0 -0
  95. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/material/overrides/assets/images/layers/2-mars@4x.avif +0 -0
  96. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/material/overrides/assets/images/layers/3-moon.avif +0 -0
  97. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/material/overrides/assets/images/layers/3-moon@1x.avif +0 -0
  98. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/material/overrides/assets/images/layers/3-moon@2x.avif +0 -0
  99. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/material/overrides/assets/images/layers/3-moon@3x.avif +0 -0
  100. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/material/overrides/assets/images/layers/3-moon@4x.avif +0 -0
  101. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/material/overrides/assets/images/layers/4-sat1.avif +0 -0
  102. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/material/overrides/assets/images/layers/4-sat1@1x.avif +0 -0
  103. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/material/overrides/assets/images/layers/4-sat1@2x.avif +0 -0
  104. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/material/overrides/assets/images/layers/4-sat1@3x.avif +0 -0
  105. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/material/overrides/assets/images/layers/4-sat1@4x.avif +0 -0
  106. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/material/overrides/assets/images/layers/5-space.avif +0 -0
  107. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/material/overrides/assets/images/layers/5-space@1x.avif +0 -0
  108. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/material/overrides/assets/images/layers/5-space@2x.avif +0 -0
  109. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/material/overrides/assets/images/layers/5-space@3x.avif +0 -0
  110. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/material/overrides/assets/images/layers/5-space@4x.avif +0 -0
  111. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/material/overrides/assets/images/layers/6-earth.avif +0 -0
  112. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/material/overrides/assets/images/layers/6-earth@1x.avif +0 -0
  113. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/material/overrides/assets/images/layers/6-earth@2x.avif +0 -0
  114. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/material/overrides/assets/images/layers/6-earth@3x.avif +0 -0
  115. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/material/overrides/assets/images/layers/6-earth@4x.avif +0 -0
  116. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/material/overrides/assets/javascripts/parallax.js +0 -0
  117. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/material/overrides/assets/logo.svg +0 -0
  118. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/material/overrides/assets/stylesheets/custom.css +0 -0
  119. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/material/overrides/assets/stylesheets/parallax.css +0 -0
  120. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/material/overrides/home.html +0 -0
  121. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/material/overrides/main.html +0 -0
  122. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/material/overrides/partials/parallax/hero.html +0 -0
  123. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/material/overrides/partials/parallax.html +0 -0
  124. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/mkdocs.yml +0 -0
  125. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/__init__.py +0 -0
  126. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/algorithms/__init__.py +0 -0
  127. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/algorithms/autotuning.py +0 -0
  128. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/algorithms/base.py +0 -0
  129. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/algorithms/optimization_results.py +0 -0
  130. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/algorithms/penalized_trust_region.py +0 -0
  131. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/config.py +0 -0
  132. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/discretization/__init__.py +0 -0
  133. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/discretization/discretization.py +0 -0
  134. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/expert/__init__.py +0 -0
  135. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/expert/byof.py +0 -0
  136. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/expert/lowering.py +0 -0
  137. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/expert/validation.py +0 -0
  138. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/init/__init__.py +0 -0
  139. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/init/interpolation.py +0 -0
  140. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/integrators/__init__.py +0 -0
  141. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/integrators/runge_kutta.py +0 -0
  142. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/lowered/__init__.py +0 -0
  143. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/lowered/cvxpy_constraints.py +0 -0
  144. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/lowered/cvxpy_variables.py +0 -0
  145. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/lowered/dynamics.py +0 -0
  146. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/lowered/jax_constraints.py +0 -0
  147. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/lowered/parameters.py +0 -0
  148. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/lowered/problem.py +0 -0
  149. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/lowered/unified.py +0 -0
  150. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/plotting/__init__.py +0 -0
  151. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/plotting/plotting.py +0 -0
  152. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/plotting/scp_iteration.py +0 -0
  153. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/plotting/viser/__init__.py +0 -0
  154. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/plotting/viser/animated.py +0 -0
  155. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/plotting/viser/plotly_integration.py +0 -0
  156. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/plotting/viser/primitives.py +0 -0
  157. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/plotting/viser/scp.py +0 -0
  158. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/plotting/viser/server.py +0 -0
  159. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/propagation/__init__.py +0 -0
  160. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/propagation/post_processing.py +0 -0
  161. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/propagation/propagation.py +0 -0
  162. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/solvers/__init__.py +0 -0
  163. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/solvers/base.py +0 -0
  164. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/solvers/ptr_solver.py +0 -0
  165. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/symbolic/__init__.py +0 -0
  166. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/symbolic/augmentation.py +0 -0
  167. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/symbolic/constraint_set.py +0 -0
  168. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/symbolic/expr/__init__.py +0 -0
  169. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/symbolic/expr/arithmetic.py +0 -0
  170. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/symbolic/expr/array.py +0 -0
  171. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/symbolic/expr/constraint.py +0 -0
  172. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/symbolic/expr/control.py +0 -0
  173. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/symbolic/expr/expr.py +0 -0
  174. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/symbolic/expr/lie/__init__.py +0 -0
  175. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/symbolic/expr/lie/adjoint.py +0 -0
  176. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/symbolic/expr/lie/se3.py +0 -0
  177. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/symbolic/expr/lie/so3.py +0 -0
  178. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/symbolic/expr/linalg.py +0 -0
  179. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/symbolic/expr/logic.py +0 -0
  180. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/symbolic/expr/math.py +0 -0
  181. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/symbolic/expr/spatial.py +0 -0
  182. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/symbolic/expr/state.py +0 -0
  183. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/symbolic/expr/stl.py +0 -0
  184. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/symbolic/expr/variable.py +0 -0
  185. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/symbolic/expr/vmap.py +0 -0
  186. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/symbolic/hashing.py +0 -0
  187. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/symbolic/lower.py +0 -0
  188. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/symbolic/lowerers/__init__.py +0 -0
  189. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/symbolic/lowerers/cvxpy/__init__.py +0 -0
  190. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/symbolic/lowerers/cvxpy/_lowerer.py +0 -0
  191. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/symbolic/lowerers/cvxpy/_registry.py +0 -0
  192. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/symbolic/lowerers/cvxpy/arithmetic.py +0 -0
  193. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/symbolic/lowerers/cvxpy/array.py +0 -0
  194. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/symbolic/lowerers/cvxpy/constraint.py +0 -0
  195. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/symbolic/lowerers/cvxpy/control.py +0 -0
  196. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/symbolic/lowerers/cvxpy/expr.py +0 -0
  197. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/symbolic/lowerers/cvxpy/linalg.py +0 -0
  198. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/symbolic/lowerers/cvxpy/logic.py +0 -0
  199. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/symbolic/lowerers/cvxpy/math.py +0 -0
  200. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/symbolic/lowerers/cvxpy/state.py +0 -0
  201. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/symbolic/lowerers/jax/__init__.py +0 -0
  202. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/symbolic/lowerers/jax/_lowerer.py +0 -0
  203. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/symbolic/lowerers/jax/_registry.py +0 -0
  204. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/symbolic/lowerers/jax/arithmetic.py +0 -0
  205. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/symbolic/lowerers/jax/array.py +0 -0
  206. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/symbolic/lowerers/jax/constraint.py +0 -0
  207. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/symbolic/lowerers/jax/control.py +0 -0
  208. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/symbolic/lowerers/jax/expr.py +0 -0
  209. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/symbolic/lowerers/jax/lie.py +0 -0
  210. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/symbolic/lowerers/jax/linalg.py +0 -0
  211. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/symbolic/lowerers/jax/logic.py +0 -0
  212. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/symbolic/lowerers/jax/math.py +0 -0
  213. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/symbolic/lowerers/jax/spatial.py +0 -0
  214. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/symbolic/lowerers/jax/state.py +0 -0
  215. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/symbolic/lowerers/jax/stl.py +0 -0
  216. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/symbolic/lowerers/jax/vmap.py +0 -0
  217. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/symbolic/problem.py +0 -0
  218. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/symbolic/time.py +0 -0
  219. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/symbolic/unified.py +0 -0
  220. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/utils/__init__.py +0 -0
  221. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/utils/cache.py +0 -0
  222. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/utils/caching.py +0 -0
  223. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/utils/printing.py +0 -0
  224. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/utils/profiling.py +0 -0
  225. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx/utils/utils.py +0 -0
  226. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx.egg-info/SOURCES.txt +0 -0
  227. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx.egg-info/dependency_links.txt +0 -0
  228. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx.egg-info/requires.txt +0 -0
  229. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/openscvx.egg-info/top_level.txt +0 -0
  230. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/pyproject.toml +0 -0
  231. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/scripts/gen_example_pages.py +0 -0
  232. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/scripts/gen_ref_pages.py +0 -0
  233. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/setup.cfg +0 -0
  234. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/tests/__init__.py +0 -0
  235. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/tests/brachistochrone_analytical.py +0 -0
  236. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/tests/symbolic/__init__.py +0 -0
  237. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/tests/symbolic/expr/__init__.py +0 -0
  238. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/tests/symbolic/expr/test_arithmetic.py +0 -0
  239. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/tests/symbolic/expr/test_array.py +0 -0
  240. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/tests/symbolic/expr/test_constraint.py +0 -0
  241. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/tests/symbolic/expr/test_expr.py +0 -0
  242. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/tests/symbolic/expr/test_lie.py +0 -0
  243. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/tests/symbolic/expr/test_linalg.py +0 -0
  244. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/tests/symbolic/expr/test_logic.py +0 -0
  245. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/tests/symbolic/expr/test_math.py +0 -0
  246. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/tests/symbolic/expr/test_node_reference.py +0 -0
  247. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/tests/symbolic/expr/test_parameters.py +0 -0
  248. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/tests/symbolic/expr/test_scaling.py +0 -0
  249. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/tests/symbolic/expr/test_spatial.py +0 -0
  250. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/tests/symbolic/expr/test_variable.py +0 -0
  251. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/tests/symbolic/expr/test_vmap.py +0 -0
  252. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/tests/symbolic/test_augmentation.py +0 -0
  253. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/tests/symbolic/test_hashing.py +0 -0
  254. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/tests/symbolic/test_lower_cvxpy.py +0 -0
  255. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/tests/symbolic/test_lower_jax.py +0 -0
  256. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/tests/symbolic/test_unified.py +0 -0
  257. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/tests/test_brachistochrone.py +0 -0
  258. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/tests/test_cvxpygen_optional.py +0 -0
  259. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/tests/test_discretization.py +0 -0
  260. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/tests/test_examples.py +0 -0
  261. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/tests/test_expert.py +0 -0
  262. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/tests/test_init.py +0 -0
  263. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/tests/test_integrators.py +0 -0
  264. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/tests/test_plotting.py +0 -0
  265. {openscvx-0.3.2.dev333 → openscvx-0.3.2.dev339}/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.dev333
3
+ Version: 0.3.2.dev339
4
4
  Summary: A general Python-based successive convexification implementation which uses a JAX backend.
5
5
  Author-email: Chris Hayner and Griffin Norris <haynec@uw.edu>
6
6
  License: Apache Software License
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
28
28
  commit_id: COMMIT_ID
29
29
  __commit_id__: COMMIT_ID
30
30
 
31
- __version__ = version = '0.3.2.dev333'
32
- __version_tuple__ = version_tuple = (0, 3, 2, 'dev333')
31
+ __version__ = version = '0.3.2.dev339'
32
+ __version_tuple__ = version_tuple = (0, 3, 2, 'dev339')
33
33
 
34
- __commit_id__ = commit_id = 'g298f4bc4f'
34
+ __commit_id__ = commit_id = 'g0ad465892'
@@ -50,7 +50,6 @@ from openscvx.lowered.jax_constraints import (
50
50
  from openscvx.propagation import get_propagation_solver, propagate_trajectory_results
51
51
  from openscvx.solvers import PTRSolver
52
52
  from openscvx.symbolic.builder import preprocess_symbolic_problem
53
- from openscvx.symbolic.constraint_set import ConstraintSet
54
53
  from openscvx.symbolic.expr import CTCS, Constraint
55
54
  from openscvx.symbolic.expr.control import Control
56
55
  from openscvx.symbolic.expr.state import State
@@ -128,7 +127,7 @@ class Problem:
128
127
  # Symbolic Preprocessing & Augmentation
129
128
  self.symbolic: SymbolicProblem = preprocess_symbolic_problem(
130
129
  dynamics=dynamics,
131
- constraints=ConstraintSet(unsorted=list(constraints)),
130
+ constraints=constraints,
132
131
  states=states,
133
132
  controls=controls,
134
133
  N=N,
@@ -55,6 +55,8 @@ from openscvx.symbolic.preprocessing import (
55
55
  validate_dynamics_dict_dimensions,
56
56
  validate_dynamics_dimension,
57
57
  validate_guesses,
58
+ validate_input_types,
59
+ validate_propagation_input_types,
58
60
  validate_shapes,
59
61
  validate_variable_names,
60
62
  )
@@ -64,7 +66,7 @@ from openscvx.symbolic.time import Time
64
66
 
65
67
  def preprocess_symbolic_problem(
66
68
  dynamics: dict,
67
- constraints: ConstraintSet,
69
+ constraints: list,
68
70
  states: List[State],
69
71
  controls: List[Control],
70
72
  N: int,
@@ -99,8 +101,8 @@ def preprocess_symbolic_problem(
99
101
  Args:
100
102
  dynamics: Dictionary mapping state names to dynamics expressions.
101
103
  Example: {"x": v, "v": u}
102
- constraints: ConstraintSet with raw constraints in `unsorted` field.
103
- Create with: ConstraintSet(unsorted=[c1, c2, c3])
104
+ constraints: List of constraint objects (Constraint, NodalConstraint,
105
+ CrossNodeConstraint, or CTCS).
104
106
  states: List of user-defined State objects (should NOT include time or CTCS states)
105
107
  controls: List of user-defined Control objects (should NOT include time dilation)
106
108
  N: Number of discretization nodes in the trajectory
@@ -140,16 +142,13 @@ def preprocess_symbolic_problem(
140
142
  Basic usage with CTCS constraint::
141
143
 
142
144
  import openscvx as ox
143
- from openscvx.symbolic.constraint_set import ConstraintSet
144
145
 
145
146
  x = ox.State("x", shape=(2,))
146
147
  v = ox.State("v", shape=(2,))
147
148
  u = ox.Control("u", shape=(2,))
148
149
 
149
150
  dynamics = {"x": v, "v": u}
150
- constraints = ConstraintSet(unsorted=[
151
- (ox.Norm(x) <= 5.0).over((0, 50))
152
- ])
151
+ constraints = [(ox.Norm(x) <= 5.0).over((0, 50))]
153
152
 
154
153
  problem = preprocess_symbolic_problem(
155
154
  dynamics=dynamics,
@@ -187,6 +186,13 @@ def preprocess_symbolic_problem(
187
186
  print([s.name for s in problem.states_prop])
188
187
  """
189
188
 
189
+ # Validate input types before anything else
190
+ validate_input_types(dynamics, states, controls, constraints, N, time)
191
+ validate_propagation_input_types(dynamics_prop_extra, states_prop_extra)
192
+
193
+ # Wrap validated constraints into a ConstraintSet
194
+ constraints = ConstraintSet(unsorted=list(constraints))
195
+
190
196
  # Validate user-provided variables have required attributes
191
197
  validate_boundary_conditions(states)
192
198
  validate_bounds(states + controls)
@@ -748,6 +748,142 @@ def validate_bounds(variables: List[Variable]) -> None:
748
748
  )
749
749
 
750
750
 
751
+ def validate_input_types(
752
+ dynamics: any,
753
+ states: any,
754
+ controls: any,
755
+ constraints: any,
756
+ N: any,
757
+ time: any,
758
+ ) -> None:
759
+ """Validate that all user-facing inputs have correct types.
760
+
761
+ This catches common user errors like passing a single State or Control
762
+ instead of a list, or passing wrong types for dynamics, N, or time.
763
+ Should be called before any other validation in the preprocessing pipeline.
764
+
765
+ Raises:
766
+ TypeError: If any input has the wrong type
767
+ ValueError: If N is not positive
768
+ """
769
+ from openscvx.symbolic.expr import CTCS, Constraint, CrossNodeConstraint, NodalConstraint
770
+ from openscvx.symbolic.time import Time
771
+
772
+ if not isinstance(dynamics, dict):
773
+ raise TypeError(
774
+ f"'dynamics' must be a dict mapping state names to expressions, "
775
+ f"got {type(dynamics).__name__}"
776
+ )
777
+
778
+ if not isinstance(states, list):
779
+ hint = ""
780
+ if isinstance(states, State):
781
+ hint = f" Hint: use states=[{states.name}] instead of states={states.name}"
782
+ raise TypeError(
783
+ f"'states' must be a list of State objects, got {type(states).__name__}.{hint}"
784
+ )
785
+
786
+ for i, s in enumerate(states):
787
+ if not isinstance(s, State):
788
+ raise TypeError(f"states[{i}] must be a State, got {type(s).__name__}")
789
+
790
+ if not isinstance(controls, list):
791
+ hint = ""
792
+ if isinstance(controls, Control):
793
+ hint = f" Hint: use controls=[{controls.name}] instead of controls={controls.name}"
794
+ raise TypeError(
795
+ f"'controls' must be a list of Control objects, got {type(controls).__name__}.{hint}"
796
+ )
797
+
798
+ for i, c in enumerate(controls):
799
+ if not isinstance(c, Control):
800
+ raise TypeError(f"controls[{i}] must be a Control, got {type(c).__name__}")
801
+
802
+ if not isinstance(constraints, list):
803
+ raise TypeError(
804
+ f"'constraints' must be a list of Constraint objects, got {type(constraints).__name__}"
805
+ )
806
+
807
+ valid_constraint_types = (Constraint, NodalConstraint, CrossNodeConstraint, CTCS)
808
+ for i, c in enumerate(constraints):
809
+ if not isinstance(c, valid_constraint_types):
810
+ raise TypeError(
811
+ f"constraints[{i}] must be a Constraint, NodalConstraint, "
812
+ f"CrossNodeConstraint, or CTCS, got {type(c).__name__}"
813
+ )
814
+
815
+ if not isinstance(N, int):
816
+ raise TypeError(f"'N' must be an integer, got {type(N).__name__}")
817
+
818
+ if N < 1:
819
+ raise ValueError(f"'N' must be positive, got {N}")
820
+
821
+ if not isinstance(time, Time):
822
+ raise TypeError(f"'time' must be a Time object, got {type(time).__name__}")
823
+
824
+
825
+ def validate_propagation_input_types(
826
+ dynamics_prop_extra: any,
827
+ states_prop_extra: any,
828
+ ) -> None:
829
+ """Validate types for optional propagation inputs.
830
+
831
+ These parameters must either both be None or both be provided.
832
+ When provided, dynamics_prop_extra must be a dict and states_prop_extra
833
+ must be a list of State objects.
834
+
835
+ Args:
836
+ dynamics_prop_extra: Should be None or a dict mapping state names to expressions
837
+ states_prop_extra: Should be None or a list of State objects
838
+
839
+ Raises:
840
+ TypeError: If either input has the wrong type
841
+ ValueError: If only one of the two is provided
842
+
843
+ Example:
844
+ distance = ox.State("distance", shape=(1,))
845
+
846
+ # Wrong: passing bare State instead of list
847
+ validate_propagation_input_types({"distance": expr}, distance)
848
+ # Raises TypeError: 'states_prop_extra' must be a list ...
849
+ """
850
+ both_none = dynamics_prop_extra is None and states_prop_extra is None
851
+ both_set = dynamics_prop_extra is not None and states_prop_extra is not None
852
+
853
+ if not both_none and not both_set:
854
+ provided = "dynamics_prop" if dynamics_prop_extra is not None else "states_prop"
855
+ missing = "states_prop" if dynamics_prop_extra is not None else "dynamics_prop"
856
+ raise ValueError(
857
+ f"'{provided}' was provided but '{missing}' was not. "
858
+ f"Both must be provided together, or both omitted."
859
+ )
860
+
861
+ if both_none:
862
+ return
863
+
864
+ if not isinstance(dynamics_prop_extra, dict):
865
+ raise TypeError(
866
+ f"'dynamics_prop' must be a dict mapping state names to expressions, "
867
+ f"got {type(dynamics_prop_extra).__name__}"
868
+ )
869
+
870
+ if not isinstance(states_prop_extra, list):
871
+ hint = ""
872
+ if isinstance(states_prop_extra, State):
873
+ hint = (
874
+ f" Hint: use states_prop=[{states_prop_extra.name}]"
875
+ f" instead of states_prop={states_prop_extra.name}"
876
+ )
877
+ raise TypeError(
878
+ f"'states_prop' must be a list of State objects, "
879
+ f"got {type(states_prop_extra).__name__}.{hint}"
880
+ )
881
+
882
+ for i, s in enumerate(states_prop_extra):
883
+ if not isinstance(s, State):
884
+ raise TypeError(f"states_prop[{i}] must be a State, got {type(s).__name__}")
885
+
886
+
751
887
  def validate_guesses(variables: List[Variable]) -> None:
752
888
  """Validate that all variables have initial guesses set.
753
889
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: openscvx
3
- Version: 0.3.2.dev333
3
+ Version: 0.3.2.dev339
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
@@ -15,6 +15,8 @@ from openscvx.symbolic.preprocessing import (
15
15
  validate_dynamics_dict_dimensions,
16
16
  validate_dynamics_dimension,
17
17
  validate_guesses,
18
+ validate_input_types,
19
+ validate_propagation_input_types,
18
20
  validate_variable_names,
19
21
  )
20
22
 
@@ -976,3 +978,176 @@ def test_validate_guesses_raises_missing():
976
978
  match="Control 'thrust' is missing initial guess.*controls require explicit guesses",
977
979
  ):
978
980
  validate_guesses([u])
981
+
982
+
983
+ # =============================================================================
984
+ # validate_input_types Tests
985
+ # =============================================================================
986
+
987
+
988
+ @pytest.fixture
989
+ def valid_inputs():
990
+ """Provide a minimal set of valid inputs for validate_input_types."""
991
+ from openscvx.symbolic.time import Time
992
+
993
+ x = State("x", shape=(3,))
994
+ u = Control("u", shape=(2,))
995
+ dynamics = {"x": x}
996
+ constraints = [x <= 5]
997
+ time = Time(initial=0.0, final=10.0, min=0.0, max=20.0)
998
+ return dynamics, [x], [u], constraints, 50, time
999
+
1000
+
1001
+ def test_validate_input_types_passes(valid_inputs):
1002
+ """Test that valid inputs pass validation."""
1003
+ dynamics, states, controls, constraints, N, time = valid_inputs
1004
+ validate_input_types(dynamics, states, controls, constraints, N, time)
1005
+
1006
+
1007
+ def test_validate_input_types_bare_control(valid_inputs):
1008
+ """Test that passing a bare Control instead of a list raises TypeError with hint."""
1009
+ dynamics, states, _, constraints, N, time = valid_inputs
1010
+ u = Control("thrust", shape=(2,))
1011
+
1012
+ with pytest.raises(
1013
+ TypeError, match=r"'controls' must be a list.*Control.*Hint.*controls=\[thrust\]"
1014
+ ):
1015
+ validate_input_types(dynamics, states, u, constraints, N, time)
1016
+
1017
+
1018
+ def test_validate_input_types_bare_state(valid_inputs):
1019
+ """Test that passing a bare State instead of a list raises TypeError with hint."""
1020
+ dynamics, _, controls, constraints, N, time = valid_inputs
1021
+ x = State("position", shape=(3,))
1022
+
1023
+ with pytest.raises(
1024
+ TypeError, match=r"'states' must be a list.*State.*Hint.*states=\[position\]"
1025
+ ):
1026
+ validate_input_types(dynamics, x, controls, constraints, N, time)
1027
+
1028
+
1029
+ def test_validate_input_types_wrong_element_in_states(valid_inputs):
1030
+ """Test that a non-State element in the states list raises TypeError."""
1031
+ dynamics, _, controls, constraints, N, time = valid_inputs
1032
+
1033
+ with pytest.raises(TypeError, match=r"states\[0\] must be a State, got str"):
1034
+ validate_input_types(dynamics, ["not_a_state"], controls, constraints, N, time)
1035
+
1036
+
1037
+ def test_validate_input_types_wrong_element_in_controls(valid_inputs):
1038
+ """Test that a non-Control element in the controls list raises TypeError."""
1039
+ dynamics, states, _, constraints, N, time = valid_inputs
1040
+
1041
+ with pytest.raises(TypeError, match=r"controls\[0\] must be a Control, got int"):
1042
+ validate_input_types(dynamics, states, [42], constraints, N, time)
1043
+
1044
+
1045
+ def test_validate_input_types_dynamics_not_dict(valid_inputs):
1046
+ """Test that passing non-dict dynamics raises TypeError."""
1047
+ _, states, controls, constraints, N, time = valid_inputs
1048
+
1049
+ with pytest.raises(TypeError, match="'dynamics' must be a dict"):
1050
+ validate_input_types([1, 2, 3], states, controls, constraints, N, time)
1051
+
1052
+
1053
+ def test_validate_input_types_constraints_not_list(valid_inputs):
1054
+ """Test that passing a non-list constraints raises TypeError."""
1055
+ dynamics, states, controls, _, N, time = valid_inputs
1056
+
1057
+ with pytest.raises(TypeError, match="'constraints' must be a list"):
1058
+ validate_input_types(dynamics, states, controls, "not_a_list", N, time)
1059
+
1060
+
1061
+ def test_validate_input_types_constraints_invalid_element(valid_inputs):
1062
+ """Test that non-constraint elements raise TypeError."""
1063
+ dynamics, states, controls, _, N, time = valid_inputs
1064
+
1065
+ with pytest.raises(TypeError, match=r"constraints\[0\] must be a Constraint.*got int"):
1066
+ validate_input_types(dynamics, states, controls, [42], N, time)
1067
+
1068
+
1069
+ def test_validate_input_types_constraints_mixed_valid_and_invalid(valid_inputs):
1070
+ """Test that invalid element is caught even after valid ones."""
1071
+ dynamics, states, controls, _, N, time = valid_inputs
1072
+ x = State("x", shape=(3,))
1073
+
1074
+ with pytest.raises(TypeError, match=r"constraints\[1\] must be a Constraint.*got str"):
1075
+ validate_input_types(dynamics, states, controls, [x <= 5, "bad"], N, time)
1076
+
1077
+
1078
+ def test_validate_input_types_N_not_int(valid_inputs):
1079
+ """Test that passing non-int N raises TypeError."""
1080
+ dynamics, states, controls, constraints, _, time = valid_inputs
1081
+
1082
+ with pytest.raises(TypeError, match="'N' must be an integer, got float"):
1083
+ validate_input_types(dynamics, states, controls, constraints, 50.0, time)
1084
+
1085
+
1086
+ def test_validate_input_types_N_not_positive(valid_inputs):
1087
+ """Test that passing non-positive N raises ValueError."""
1088
+ dynamics, states, controls, constraints, _, time = valid_inputs
1089
+
1090
+ with pytest.raises(ValueError, match="'N' must be positive, got 0"):
1091
+ validate_input_types(dynamics, states, controls, constraints, 0, time)
1092
+
1093
+ with pytest.raises(ValueError, match="'N' must be positive, got -5"):
1094
+ validate_input_types(dynamics, states, controls, constraints, -5, time)
1095
+
1096
+
1097
+ def test_validate_input_types_time_not_time(valid_inputs):
1098
+ """Test that passing non-Time object raises TypeError."""
1099
+ dynamics, states, controls, constraints, N, _ = valid_inputs
1100
+
1101
+ with pytest.raises(TypeError, match="'time' must be a Time object, got float"):
1102
+ validate_input_types(dynamics, states, controls, constraints, N, 10.0)
1103
+
1104
+
1105
+ # =============================================================================
1106
+ # validate_propagation_input_types Tests
1107
+ # =============================================================================
1108
+
1109
+
1110
+ def test_validate_propagation_input_types_both_none():
1111
+ """Test that both None passes validation."""
1112
+ validate_propagation_input_types(None, None)
1113
+
1114
+
1115
+ def test_validate_propagation_input_types_both_valid():
1116
+ """Test that valid dict + list passes validation."""
1117
+ distance = State("distance", shape=(1,))
1118
+ validate_propagation_input_types({"distance": distance}, [distance])
1119
+
1120
+
1121
+ def test_validate_propagation_input_types_only_dynamics():
1122
+ """Test that providing dynamics_prop without states_prop raises ValueError."""
1123
+ with pytest.raises(ValueError, match="'dynamics_prop' was provided but 'states_prop' was not"):
1124
+ validate_propagation_input_types({"distance": 1.0}, None)
1125
+
1126
+
1127
+ def test_validate_propagation_input_types_only_states():
1128
+ """Test that providing states_prop without dynamics_prop raises ValueError."""
1129
+ distance = State("distance", shape=(1,))
1130
+ with pytest.raises(ValueError, match="'states_prop' was provided but 'dynamics_prop' was not"):
1131
+ validate_propagation_input_types(None, [distance])
1132
+
1133
+
1134
+ def test_validate_propagation_input_types_bare_state():
1135
+ """Test that passing a bare State instead of a list raises TypeError with hint."""
1136
+ distance = State("distance", shape=(1,))
1137
+ with pytest.raises(
1138
+ TypeError, match=r"'states_prop' must be a list.*Hint.*states_prop=\[distance\]"
1139
+ ):
1140
+ validate_propagation_input_types({"distance": distance}, distance)
1141
+
1142
+
1143
+ def test_validate_propagation_input_types_dynamics_not_dict():
1144
+ """Test that passing non-dict dynamics_prop raises TypeError."""
1145
+ distance = State("distance", shape=(1,))
1146
+ with pytest.raises(TypeError, match="'dynamics_prop' must be a dict"):
1147
+ validate_propagation_input_types([distance], [distance])
1148
+
1149
+
1150
+ def test_validate_propagation_input_types_wrong_element_in_states():
1151
+ """Test that a non-State element in states_prop raises TypeError."""
1152
+ with pytest.raises(TypeError, match=r"states_prop\[0\] must be a State, got str"):
1153
+ validate_propagation_input_types({"x": 1.0}, ["not_a_state"])
File without changes