fomtools 0.0.1__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 (310) hide show
  1. fomtools-0.0.1/.github/workflows/ci.yml +111 -0
  2. fomtools-0.0.1/.github/workflows/claude-code-review.yml +43 -0
  3. fomtools-0.0.1/.github/workflows/claude.yml +49 -0
  4. fomtools-0.0.1/.github/workflows/docs.yml +89 -0
  5. fomtools-0.0.1/.github/workflows/release.yml +106 -0
  6. fomtools-0.0.1/.github/workflows/update-skill.yml +43 -0
  7. fomtools-0.0.1/.gitignore +387 -0
  8. fomtools-0.0.1/.pre-commit-config.yaml +24 -0
  9. fomtools-0.0.1/AGENTS.md +84 -0
  10. fomtools-0.0.1/CLAUDE.md +1 -0
  11. fomtools-0.0.1/LICENSE +201 -0
  12. fomtools-0.0.1/PKG-INFO +212 -0
  13. fomtools-0.0.1/README.md +158 -0
  14. fomtools-0.0.1/docs/api/canonicalizer.md +8 -0
  15. fomtools-0.0.1/docs/api/codegen.md +32 -0
  16. fomtools-0.0.1/docs/api/constraint.md +5 -0
  17. fomtools-0.0.1/docs/api/linearexpression.md +1 -0
  18. fomtools-0.0.1/docs/api/proxablefunctions.md +45 -0
  19. fomtools-0.0.1/docs/api/solvers.md +8 -0
  20. fomtools-0.0.1/docs/api/steps.md +11 -0
  21. fomtools-0.0.1/docs/api/verifier.md +2 -0
  22. fomtools-0.0.1/docs/api.md +11 -0
  23. fomtools-0.0.1/docs/index.md +101 -0
  24. fomtools-0.0.1/docs/installation.md +41 -0
  25. fomtools-0.0.1/docs/javascripts/mathjax.js +12 -0
  26. fomtools-0.0.1/docs/tutorials/_recorded_timings.json +84 -0
  27. fomtools-0.0.1/docs/tutorials/codegen.md +630 -0
  28. fomtools-0.0.1/docs/tutorials/codegen_speedup_results.md +23 -0
  29. fomtools-0.0.1/docs/tutorials/control.py +343 -0
  30. fomtools-0.0.1/docs/tutorials/cvxpygen.md +287 -0
  31. fomtools-0.0.1/docs/tutorials/cvxpygen_mpc.py +147 -0
  32. fomtools-0.0.1/docs/tutorials/lasso.py +303 -0
  33. fomtools-0.0.1/docs/tutorials/network.py +377 -0
  34. fomtools-0.0.1/docs/tutorials/nnls.py +292 -0
  35. fomtools-0.0.1/docs/tutorials/nnls_verification.py +183 -0
  36. fomtools-0.0.1/docs/tutorials/portfolio.py +290 -0
  37. fomtools-0.0.1/docs/tutorials.md +18 -0
  38. fomtools-0.0.1/fomtools/__init__.py +14 -0
  39. fomtools-0.0.1/fomtools/canonicalizers/__init__.py +5 -0
  40. fomtools-0.0.1/fomtools/canonicalizers/canonicalizer.py +293 -0
  41. fomtools-0.0.1/fomtools/canonicalizers/mip.py +1265 -0
  42. fomtools-0.0.1/fomtools/canonicalizers/obbt_handler.py +339 -0
  43. fomtools-0.0.1/fomtools/canonicalizers/sdp.py +2223 -0
  44. fomtools-0.0.1/fomtools/canonicalizers/simulator.py +1403 -0
  45. fomtools-0.0.1/fomtools/codegen/__init__.py +103 -0
  46. fomtools-0.0.1/fomtools/codegen/agent/__init__.py +110 -0
  47. fomtools-0.0.1/fomtools/codegen/agent/agents.yaml +33 -0
  48. fomtools-0.0.1/fomtools/codegen/agent/budget.py +132 -0
  49. fomtools-0.0.1/fomtools/codegen/agent/claude_sdk.py +221 -0
  50. fomtools-0.0.1/fomtools/codegen/agent/cli_driver.py +328 -0
  51. fomtools-0.0.1/fomtools/codegen/agent/cli_specs.py +265 -0
  52. fomtools-0.0.1/fomtools/codegen/agent/codex_sdk.py +151 -0
  53. fomtools-0.0.1/fomtools/codegen/agent/driver.py +313 -0
  54. fomtools-0.0.1/fomtools/codegen/agent/pidev_sdk.py +131 -0
  55. fomtools-0.0.1/fomtools/codegen/agent/prompts.py +246 -0
  56. fomtools-0.0.1/fomtools/codegen/agent/sdk_base.py +384 -0
  57. fomtools-0.0.1/fomtools/codegen/agent/stub.py +104 -0
  58. fomtools-0.0.1/fomtools/codegen/cli.py +263 -0
  59. fomtools-0.0.1/fomtools/codegen/config.py +336 -0
  60. fomtools-0.0.1/fomtools/codegen/dedup.py +132 -0
  61. fomtools-0.0.1/fomtools/codegen/emit.py +37 -0
  62. fomtools-0.0.1/fomtools/codegen/examples.py +483 -0
  63. fomtools-0.0.1/fomtools/codegen/extract.py +655 -0
  64. fomtools-0.0.1/fomtools/codegen/extract_scheduled.py +415 -0
  65. fomtools-0.0.1/fomtools/codegen/extract_unrolled.py +321 -0
  66. fomtools-0.0.1/fomtools/codegen/factorize.py +457 -0
  67. fomtools-0.0.1/fomtools/codegen/generate.py +625 -0
  68. fomtools-0.0.1/fomtools/codegen/harness.py +226 -0
  69. fomtools-0.0.1/fomtools/codegen/ir.py +456 -0
  70. fomtools-0.0.1/fomtools/codegen/kernel_rules.py +347 -0
  71. fomtools-0.0.1/fomtools/codegen/objective.py +463 -0
  72. fomtools-0.0.1/fomtools/codegen/oracle.py +470 -0
  73. fomtools-0.0.1/fomtools/codegen/postprocess.py +298 -0
  74. fomtools-0.0.1/fomtools/codegen/schedule.py +123 -0
  75. fomtools-0.0.1/fomtools/codegen/spec.py +584 -0
  76. fomtools-0.0.1/fomtools/codegen/targets/__init__.py +26 -0
  77. fomtools-0.0.1/fomtools/codegen/targets/base.py +151 -0
  78. fomtools-0.0.1/fomtools/codegen/targets/embedded_c.py +1751 -0
  79. fomtools-0.0.1/fomtools/codegen/targets/large_scale_cuda.py +1028 -0
  80. fomtools-0.0.1/fomtools/codegen/targets/large_scale_openmp.py +119 -0
  81. fomtools-0.0.1/fomtools/codegen/wrapper.py +167 -0
  82. fomtools-0.0.1/fomtools/constraint.py +425 -0
  83. fomtools-0.0.1/fomtools/cvxpygen/__init__.py +62 -0
  84. fomtools-0.0.1/fomtools/cvxpygen/api.py +200 -0
  85. fomtools-0.0.1/fomtools/cvxpygen/builders.py +600 -0
  86. fomtools-0.0.1/fomtools/cvxpygen/glue.py +397 -0
  87. fomtools-0.0.1/fomtools/cvxpygen/interface.py +470 -0
  88. fomtools-0.0.1/fomtools/cvxpygen/qpdata.py +240 -0
  89. fomtools-0.0.1/fomtools/cvxpygen/scaling.py +136 -0
  90. fomtools-0.0.1/fomtools/iteratetrajectory.py +212 -0
  91. fomtools-0.0.1/fomtools/linearexpression.py +837 -0
  92. fomtools-0.0.1/fomtools/nn/__init__.py +3 -0
  93. fomtools-0.0.1/fomtools/nn/layers.py +256 -0
  94. fomtools-0.0.1/fomtools/proxable_functions/__init__.py +25 -0
  95. fomtools-0.0.1/fomtools/proxable_functions/elastic_net.py +108 -0
  96. fomtools-0.0.1/fomtools/proxable_functions/hinge_loss.py +72 -0
  97. fomtools-0.0.1/fomtools/proxable_functions/huber_loss.py +137 -0
  98. fomtools-0.0.1/fomtools/proxable_functions/ind_affine.py +144 -0
  99. fomtools-0.0.1/fomtools/proxable_functions/ind_ball_l1.py +67 -0
  100. fomtools-0.0.1/fomtools/proxable_functions/ind_ball_linf.py +69 -0
  101. fomtools-0.0.1/fomtools/proxable_functions/ind_box.py +108 -0
  102. fomtools-0.0.1/fomtools/proxable_functions/ind_half_space.py +86 -0
  103. fomtools-0.0.1/fomtools/proxable_functions/ind_nonnegative.py +65 -0
  104. fomtools-0.0.1/fomtools/proxable_functions/ind_nonpositive.py +65 -0
  105. fomtools-0.0.1/fomtools/proxable_functions/ind_point.py +71 -0
  106. fomtools-0.0.1/fomtools/proxable_functions/ind_polyhedral.py +86 -0
  107. fomtools-0.0.1/fomtools/proxable_functions/ind_simplex.py +56 -0
  108. fomtools-0.0.1/fomtools/proxable_functions/labeled_hinge_loss.py +74 -0
  109. fomtools-0.0.1/fomtools/proxable_functions/least_squares.py +91 -0
  110. fomtools-0.0.1/fomtools/proxable_functions/linear.py +90 -0
  111. fomtools-0.0.1/fomtools/proxable_functions/norm_inf.py +80 -0
  112. fomtools-0.0.1/fomtools/proxable_functions/norm_l1.py +109 -0
  113. fomtools-0.0.1/fomtools/proxable_functions/proximal_operator.py +97 -0
  114. fomtools-0.0.1/fomtools/proxable_functions/quadratic.py +152 -0
  115. fomtools-0.0.1/fomtools/proxable_functions/soft_nonnegative.py +85 -0
  116. fomtools-0.0.1/fomtools/proxable_functions/sq_l2_norm.py +84 -0
  117. fomtools-0.0.1/fomtools/proxable_functions/sum_negative.py +101 -0
  118. fomtools-0.0.1/fomtools/proxable_functions/sum_positive.py +97 -0
  119. fomtools-0.0.1/fomtools/proxable_functions/total_variation_1d.py +93 -0
  120. fomtools-0.0.1/fomtools/sets/__init__.py +21 -0
  121. fomtools-0.0.1/fomtools/sets/affine_subspace.py +31 -0
  122. fomtools-0.0.1/fomtools/sets/ball.py +58 -0
  123. fomtools-0.0.1/fomtools/sets/box.py +98 -0
  124. fomtools-0.0.1/fomtools/sets/polyhedron.py +91 -0
  125. fomtools-0.0.1/fomtools/sets/set.py +112 -0
  126. fomtools-0.0.1/fomtools/solvers/__init__.py +20 -0
  127. fomtools-0.0.1/fomtools/solvers/clarabel.py +269 -0
  128. fomtools-0.0.1/fomtools/solvers/cuclarabel.py +159 -0
  129. fomtools-0.0.1/fomtools/solvers/factory.py +75 -0
  130. fomtools-0.0.1/fomtools/solvers/gurobi.py +567 -0
  131. fomtools-0.0.1/fomtools/solvers/highs.py +430 -0
  132. fomtools-0.0.1/fomtools/solvers/mip_solver.py +293 -0
  133. fomtools-0.0.1/fomtools/solvers/sdp_solver.py +48 -0
  134. fomtools-0.0.1/fomtools/solvers/solver.py +179 -0
  135. fomtools-0.0.1/fomtools/stepdecomposers/__init__.py +3 -0
  136. fomtools-0.0.1/fomtools/stepdecomposers/mip_step_decomposer.py +52 -0
  137. fomtools-0.0.1/fomtools/stepdecomposers/sdp_step_decomposer.py +201 -0
  138. fomtools-0.0.1/fomtools/stepdecomposers/simulator_step_decomposer.py +326 -0
  139. fomtools-0.0.1/fomtools/stepdecomposers/step_decomposer.py +1303 -0
  140. fomtools-0.0.1/fomtools/steps/__init__.py +7 -0
  141. fomtools-0.0.1/fomtools/steps/affine.py +133 -0
  142. fomtools-0.0.1/fomtools/steps/lin_prog.py +128 -0
  143. fomtools-0.0.1/fomtools/steps/quad_prog.py +224 -0
  144. fomtools-0.0.1/fomtools/steps/relu.py +223 -0
  145. fomtools-0.0.1/fomtools/steps/saturated_linear.py +113 -0
  146. fomtools-0.0.1/fomtools/steps/soft_threshold.py +89 -0
  147. fomtools-0.0.1/fomtools/steps/step.py +79 -0
  148. fomtools-0.0.1/fomtools/utils/__init__.py +2 -0
  149. fomtools-0.0.1/fomtools/utils/convex_hull_cuts.py +206 -0
  150. fomtools-0.0.1/fomtools/utils/dict_utils.py +69 -0
  151. fomtools-0.0.1/fomtools/utils/envelopes.py +66 -0
  152. fomtools-0.0.1/fomtools/utils/math_utils.py +86 -0
  153. fomtools-0.0.1/fomtools/utils/matrix_utils.py +60 -0
  154. fomtools-0.0.1/fomtools/utils/range_utils.py +65 -0
  155. fomtools-0.0.1/fomtools/utils/sparse_utils.py +81 -0
  156. fomtools-0.0.1/fomtools/verifier.py +1602 -0
  157. fomtools-0.0.1/fomtools.egg-info/PKG-INFO +212 -0
  158. fomtools-0.0.1/fomtools.egg-info/SOURCES.txt +308 -0
  159. fomtools-0.0.1/fomtools.egg-info/dependency_links.txt +1 -0
  160. fomtools-0.0.1/fomtools.egg-info/entry_points.txt +2 -0
  161. fomtools-0.0.1/fomtools.egg-info/requires.txt +53 -0
  162. fomtools-0.0.1/fomtools.egg-info/scm_file_list.json +304 -0
  163. fomtools-0.0.1/fomtools.egg-info/scm_version.json +8 -0
  164. fomtools-0.0.1/fomtools.egg-info/top_level.txt +1 -0
  165. fomtools-0.0.1/mkdocs.yml +53 -0
  166. fomtools-0.0.1/pyproject.toml +106 -0
  167. fomtools-0.0.1/setup.cfg +4 -0
  168. fomtools-0.0.1/skills/README.md +55 -0
  169. fomtools-0.0.1/skills/fomtools/SKILL.md +250 -0
  170. fomtools-0.0.1/skills/fomtools/references/api.md +182 -0
  171. fomtools-0.0.1/skills/fomtools/references/codegen.md +233 -0
  172. fomtools-0.0.1/skills/fomtools/references/cvxpygen.md +128 -0
  173. fomtools-0.0.1/skills/update-prompt.md +29 -0
  174. fomtools-0.0.1/tests/__init__.py +0 -0
  175. fomtools-0.0.1/tests/codegen/__init__.py +0 -0
  176. fomtools-0.0.1/tests/codegen/conftest.py +675 -0
  177. fomtools-0.0.1/tests/codegen/golden/boxqp/embedded_c/fom_solver.c +81 -0
  178. fomtools-0.0.1/tests/codegen/golden/cgqp/large_scale_cuda/fom_solver.cu +147 -0
  179. fomtools-0.0.1/tests/codegen/golden/cgqp/large_scale_openmp/fom_solver.c +84 -0
  180. fomtools-0.0.1/tests/codegen/golden/cvxpygen_qp/embedded_c/fom_solver.c +106 -0
  181. fomtools-0.0.1/tests/codegen/golden/cvxpygen_qp_objective/embedded_c/fom_solver.c +103 -0
  182. fomtools-0.0.1/tests/codegen/golden/dr/embedded_c/fom_solver.c +95 -0
  183. fomtools-0.0.1/tests/codegen/golden/fista/embedded_c/fom_solver.c +133 -0
  184. fomtools-0.0.1/tests/codegen/golden/fista_objective/embedded_c/fom_solver.c +116 -0
  185. fomtools-0.0.1/tests/codegen/golden/halpern/embedded_c/fom_solver.c +87 -0
  186. fomtools-0.0.1/tests/codegen/golden/indef_kkt/embedded_c/fom_solver.c +84 -0
  187. fomtools-0.0.1/tests/codegen/golden/ista/embedded_c/fom_solver.c +102 -0
  188. fomtools-0.0.1/tests/codegen/golden/ista/large_scale_cuda/fom_solver.cu +152 -0
  189. fomtools-0.0.1/tests/codegen/golden/ista/large_scale_openmp/fom_solver.c +89 -0
  190. fomtools-0.0.1/tests/codegen/golden/ista_objective/embedded_c/fom_solver.c +90 -0
  191. fomtools-0.0.1/tests/codegen/golden/ista_objective/large_scale_cuda/fom_solver.cu +108 -0
  192. fomtools-0.0.1/tests/codegen/golden/mpc/embedded_c/fom_solver.c +96 -0
  193. fomtools-0.0.1/tests/codegen/golden/pdhg_lp/embedded_c/fom_solver.c +105 -0
  194. fomtools-0.0.1/tests/codegen/golden/pdhg_lp/large_scale_cuda/fom_solver.cu +178 -0
  195. fomtools-0.0.1/tests/codegen/golden/scheduled/embedded_c/fom_solver.c +124 -0
  196. fomtools-0.0.1/tests/codegen/golden/scheduled_objective/embedded_c/fom_solver.c +98 -0
  197. fomtools-0.0.1/tests/codegen/golden/scheduled_objective/large_scale_cuda/fom_solver.cu +119 -0
  198. fomtools-0.0.1/tests/codegen/test_agent_budget.py +147 -0
  199. fomtools-0.0.1/tests/codegen/test_agent_integration.py +84 -0
  200. fomtools-0.0.1/tests/codegen/test_agent_notes.py +302 -0
  201. fomtools-0.0.1/tests/codegen/test_cli.py +226 -0
  202. fomtools-0.0.1/tests/codegen/test_codegen_dispatch.py +144 -0
  203. fomtools-0.0.1/tests/codegen/test_cvxpygen_bounds.py +59 -0
  204. fomtools-0.0.1/tests/codegen/test_cvxpygen_builders.py +150 -0
  205. fomtools-0.0.1/tests/codegen/test_cvxpygen_dispatch.py +613 -0
  206. fomtools-0.0.1/tests/codegen/test_cvxpygen_e2e.py +199 -0
  207. fomtools-0.0.1/tests/codegen/test_cvxpygen_glue.py +251 -0
  208. fomtools-0.0.1/tests/codegen/test_cvxpygen_objective.py +345 -0
  209. fomtools-0.0.1/tests/codegen/test_cvxpygen_preflight.py +58 -0
  210. fomtools-0.0.1/tests/codegen/test_cvxpygen_qpdata.py +118 -0
  211. fomtools-0.0.1/tests/codegen/test_cvxpygen_register.py +107 -0
  212. fomtools-0.0.1/tests/codegen/test_cvxpygen_scaling.py +177 -0
  213. fomtools-0.0.1/tests/codegen/test_cvxpygen_scheduled.py +240 -0
  214. fomtools-0.0.1/tests/codegen/test_dedup.py +183 -0
  215. fomtools-0.0.1/tests/codegen/test_dr_pipeline.py +62 -0
  216. fomtools-0.0.1/tests/codegen/test_editable_linsolve.py +109 -0
  217. fomtools-0.0.1/tests/codegen/test_editable_ops.py +546 -0
  218. fomtools-0.0.1/tests/codegen/test_emit_scaffold.py +97 -0
  219. fomtools-0.0.1/tests/codegen/test_examples_scale.py +156 -0
  220. fomtools-0.0.1/tests/codegen/test_factorize.py +312 -0
  221. fomtools-0.0.1/tests/codegen/test_fista_pipeline.py +123 -0
  222. fomtools-0.0.1/tests/codegen/test_float32.py +115 -0
  223. fomtools-0.0.1/tests/codegen/test_indefinite_kkt.py +62 -0
  224. fomtools-0.0.1/tests/codegen/test_ir_extraction.py +156 -0
  225. fomtools-0.0.1/tests/codegen/test_large_scale.py +627 -0
  226. fomtools-0.0.1/tests/codegen/test_objective_termination.py +1002 -0
  227. fomtools-0.0.1/tests/codegen/test_oracle.py +80 -0
  228. fomtools-0.0.1/tests/codegen/test_pdhg_pipeline.py +95 -0
  229. fomtools-0.0.1/tests/codegen/test_postprocess.py +102 -0
  230. fomtools-0.0.1/tests/codegen/test_profiling.py +149 -0
  231. fomtools-0.0.1/tests/codegen/test_satlin_mpc.py +204 -0
  232. fomtools-0.0.1/tests/codegen/test_scheduled_ir.py +291 -0
  233. fomtools-0.0.1/tests/codegen/test_scheduled_pipeline.py +162 -0
  234. fomtools-0.0.1/tests/codegen/test_spec_roundtrip.py +132 -0
  235. fomtools-0.0.1/tests/codegen/test_static_constraints.py +356 -0
  236. fomtools-0.0.1/tests/codegen/test_stationarity_gate.py +135 -0
  237. fomtools-0.0.1/tests/codegen/test_stub_pipeline.py +115 -0
  238. fomtools-0.0.1/tests/codegen/test_termination_interval.py +95 -0
  239. fomtools-0.0.1/tests/codegen/test_unrolled_emission.py +161 -0
  240. fomtools-0.0.1/tests/codegen/test_unrolled_ir.py +384 -0
  241. fomtools-0.0.1/tests/codegen/test_wrapper_roundtrip.py +73 -0
  242. fomtools-0.0.1/tests/conftest.py +150 -0
  243. fomtools-0.0.1/tests/cvxpy.py +246 -0
  244. fomtools-0.0.1/tests/examples/comparison_lasso.py +174 -0
  245. fomtools-0.0.1/tests/examples/cut_experiment.py +299 -0
  246. fomtools-0.0.1/tests/test_LP_pdhg.py +115 -0
  247. fomtools-0.0.1/tests/test_add_constraint.py +190 -0
  248. fomtools-0.0.1/tests/test_affine_simulator.py +124 -0
  249. fomtools-0.0.1/tests/test_audit_regressions.py +300 -0
  250. fomtools-0.0.1/tests/test_boxpgd_sdp_mip.py +163 -0
  251. fomtools-0.0.1/tests/test_complementarity.py +188 -0
  252. fomtools-0.0.1/tests/test_convex_hull_cuts.py +370 -0
  253. fomtools-0.0.1/tests/test_copy_isolation.py +129 -0
  254. fomtools-0.0.1/tests/test_docs_examples.py +16 -0
  255. fomtools-0.0.1/tests/test_douglas_rachford.py +89 -0
  256. fomtools-0.0.1/tests/test_fixed_point_ista.py +52 -0
  257. fomtools-0.0.1/tests/test_fixed_point_nnls.py +139 -0
  258. fomtools-0.0.1/tests/test_ind_ball_l1.py +144 -0
  259. fomtools-0.0.1/tests/test_ind_polyhedral.py +204 -0
  260. fomtools-0.0.1/tests/test_ind_simplex.py +159 -0
  261. fomtools-0.0.1/tests/test_inf_norm_sdp.py +227 -0
  262. fomtools-0.0.1/tests/test_infinite_bounds.py +230 -0
  263. fomtools-0.0.1/tests/test_ista.py +61 -0
  264. fomtools-0.0.1/tests/test_ista_sdp_mip.py +168 -0
  265. fomtools-0.0.1/tests/test_iterate_trajectory.py +399 -0
  266. fomtools-0.0.1/tests/test_l1_obj_norm.py +582 -0
  267. fomtools-0.0.1/tests/test_linear_program.py +151 -0
  268. fomtools-0.0.1/tests/test_linearexpression.py +368 -0
  269. fomtools-0.0.1/tests/test_linsolve_simulator.py +169 -0
  270. fomtools-0.0.1/tests/test_mincost_flow.py +241 -0
  271. fomtools-0.0.1/tests/test_mip_solution_consistency.py +344 -0
  272. fomtools-0.0.1/tests/test_nn_verify_jax.py +83 -0
  273. fomtools-0.0.1/tests/test_nn_verify_torch.py +66 -0
  274. fomtools-0.0.1/tests/test_nnls_sdp_mip.py +71 -0
  275. fomtools-0.0.1/tests/test_norm_inf.py +160 -0
  276. fomtools-0.0.1/tests/test_obbt_handler.py +570 -0
  277. fomtools-0.0.1/tests/test_objective_bounds.py +204 -0
  278. fomtools-0.0.1/tests/test_partial_relu.py +70 -0
  279. fomtools-0.0.1/tests/test_partial_relu_sdp_sim.py +341 -0
  280. fomtools-0.0.1/tests/test_placeholder.py +12 -0
  281. fomtools-0.0.1/tests/test_portfolio.py +135 -0
  282. fomtools-0.0.1/tests/test_prox_decomposer.py +1976 -0
  283. fomtools-0.0.1/tests/test_quadratic_program.py +252 -0
  284. fomtools-0.0.1/tests/test_range_functions.py +42 -0
  285. fomtools-0.0.1/tests/test_relu_simulator.py +59 -0
  286. fomtools-0.0.1/tests/test_satlin.py +257 -0
  287. fomtools-0.0.1/tests/test_satlin_simulator.py +64 -0
  288. fomtools-0.0.1/tests/test_sdp_canonicalizer.py +172 -0
  289. fomtools-0.0.1/tests/test_sdp_cuts.py +2000 -0
  290. fomtools-0.0.1/tests/test_sdp_hull.py +156 -0
  291. fomtools-0.0.1/tests/test_sdp_inequality.py +136 -0
  292. fomtools-0.0.1/tests/test_sdp_nnls.py +103 -0
  293. fomtools-0.0.1/tests/test_sdp_selector.py +206 -0
  294. fomtools-0.0.1/tests/test_sets.py +302 -0
  295. fomtools-0.0.1/tests/test_simulator.py +210 -0
  296. fomtools-0.0.1/tests/test_soft_threshold_simulator.py +58 -0
  297. fomtools-0.0.1/tests/test_solve_kwargs.py +228 -0
  298. fomtools-0.0.1/tests/test_solver_boundary.py +109 -0
  299. fomtools-0.0.1/tests/test_sparse_utils.py +65 -0
  300. fomtools-0.0.1/tests/test_stack.py +426 -0
  301. fomtools-0.0.1/tests/test_subproblem_simulator.py +230 -0
  302. fomtools-0.0.1/tests/test_sum_squares.py +203 -0
  303. fomtools-0.0.1/tests/test_total_variation_1d.py +168 -0
  304. fomtools-0.0.1/tests/test_two_norm_mip.py +168 -0
  305. fomtools-0.0.1/tests/test_vec_LUhat.py +48 -0
  306. fomtools-0.0.1/tests/test_verifier.py +108 -0
  307. fomtools-0.0.1/tests/test_verifier_ista.py +78 -0
  308. fomtools-0.0.1/tests/test_warm_start.py +151 -0
  309. fomtools-0.0.1/uv.lock +4414 -0
  310. fomtools-0.0.1/wrangler.toml +5 -0
@@ -0,0 +1,111 @@
1
+ name: Python build and test
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ linter:
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - uses: actions/checkout@v4
14
+ - uses: actions/setup-python@v5
15
+ with:
16
+ python-version: "3.13"
17
+ - name: ruff
18
+ uses: chartboost/ruff-action@v1
19
+
20
+ package:
21
+ runs-on: ubuntu-latest
22
+ steps:
23
+ - uses: actions/checkout@v4
24
+ with:
25
+ fetch-depth: 0
26
+
27
+ - uses: actions/setup-python@v5
28
+ with:
29
+ python-version: "3.13"
30
+
31
+ - name: Set up uv
32
+ uses: astral-sh/setup-uv@v6
33
+ with:
34
+ version: "0.11.15"
35
+
36
+ - name: Build wheel
37
+ run: uv build --wheel
38
+
39
+ - name: Install into clean venv (no extras)
40
+ run: |
41
+ uv venv /tmp/pkg-test
42
+ uv pip install --python /tmp/pkg-test/bin/python dist/*.whl
43
+
44
+ - name: Smoke-test import and CLI
45
+ run: |
46
+ /tmp/pkg-test/bin/python -c "import fomtools; print(fomtools.__version__)"
47
+ /tmp/pkg-test/bin/fomtools-codegen --help
48
+
49
+ - name: Verify HiGHS default works
50
+ run: |
51
+ /tmp/pkg-test/bin/python -c "
52
+ from fomtools.verifier import Verifier
53
+ v = Verifier()
54
+ assert v.canonicalizer.solver.__class__.__name__ == 'HiGHSSolver'
55
+ print('HiGHS default: OK')
56
+ "
57
+
58
+ - name: Verify Gurobi ImportError message
59
+ run: |
60
+ /tmp/pkg-test/bin/python -c "
61
+ import sys
62
+ from fomtools.verifier import Verifier
63
+ try:
64
+ Verifier(solver='gurobi')
65
+ sys.exit('expected ImportError')
66
+ except ImportError as e:
67
+ assert 'fomtools[gurobi]' in str(e)
68
+ print(f'ImportError hint: OK ({e})')
69
+ "
70
+
71
+ test:
72
+ runs-on: ubuntu-latest
73
+ strategy:
74
+ matrix:
75
+ python-version: ["3.12", "3.13"]
76
+
77
+ steps:
78
+ - uses: actions/checkout@v4
79
+
80
+ - name: Install OpenBLAS (needed for SCS)
81
+ run: sudo apt-get update && sudo apt-get install -y libopenblas-dev
82
+
83
+ - name: Set up Python ${{ matrix.python-version }}
84
+ uses: actions/setup-python@v5
85
+ with:
86
+ python-version: ${{ matrix.python-version }}
87
+
88
+ - name: Set up uv
89
+ uses: astral-sh/setup-uv@v6
90
+ with:
91
+ version: "0.11.15"
92
+
93
+ - shell: bash
94
+ id: write-license
95
+ env:
96
+ LICENSE: ${{ secrets.GUROBI_LICENSE}}
97
+ run: |
98
+ echo "$LICENSE" > $PWD/gurobi.lic
99
+
100
+ - name: Install the project
101
+ run: uv sync --extra dev --extra docs --extra nn --extra cvxpygen
102
+
103
+ - name: Check Gurobi License
104
+ env:
105
+ GRB_LICENSE_FILE: ${{ github.workspace }}/gurobi.lic
106
+ run: uv run --frozen python -c "import gurobipy; gurobipy.Model()"
107
+
108
+ - name: Run tests
109
+ env:
110
+ GRB_LICENSE_FILE: ${{ github.workspace }}/gurobi.lic
111
+ run: uv run --frozen pytest tests
@@ -0,0 +1,43 @@
1
+ name: Claude Code Review
2
+
3
+ on:
4
+ pull_request:
5
+ types: [opened, synchronize, ready_for_review, reopened]
6
+ # Optional: Only run on specific file changes
7
+ # paths:
8
+ # - "src/**/*.ts"
9
+ # - "src/**/*.tsx"
10
+ # - "src/**/*.js"
11
+ # - "src/**/*.jsx"
12
+
13
+ jobs:
14
+ claude-review:
15
+ # Optional: Filter by PR author
16
+ # if: |
17
+ # github.event.pull_request.user.login == 'external-contributor' ||
18
+ # github.event.pull_request.user.login == 'new-developer' ||
19
+ # github.event.pull_request.author_association == 'FIRST_TIME_CONTRIBUTOR'
20
+
21
+ runs-on: ubuntu-latest
22
+ permissions:
23
+ contents: read
24
+ pull-requests: read
25
+ issues: read
26
+ id-token: write
27
+
28
+ steps:
29
+ - name: Checkout repository
30
+ uses: actions/checkout@v4
31
+ with:
32
+ fetch-depth: 1
33
+
34
+ - name: Run Claude Code Review
35
+ id: claude-review
36
+ uses: anthropics/claude-code-action@v1
37
+ with:
38
+ claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
39
+ plugin_marketplaces: 'https://github.com/anthropics/claude-code.git'
40
+ plugins: 'code-review@claude-code-plugins'
41
+ prompt: '/code-review:code-review ${{ github.repository }}/pull/${{ github.event.pull_request.number }}'
42
+ # See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
43
+ # or https://code.claude.com/docs/en/cli-reference for available options
@@ -0,0 +1,49 @@
1
+ name: Claude Code
2
+
3
+ on:
4
+ issue_comment:
5
+ types: [created]
6
+ pull_request_review_comment:
7
+ types: [created]
8
+ issues:
9
+ types: [opened, assigned]
10
+ pull_request_review:
11
+ types: [submitted]
12
+
13
+ jobs:
14
+ claude:
15
+ if: |
16
+ (github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
17
+ (github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) ||
18
+ (github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) ||
19
+ (github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude')))
20
+ runs-on: ubuntu-latest
21
+ permissions:
22
+ contents: read
23
+ pull-requests: read
24
+ issues: read
25
+ id-token: write
26
+ actions: read # Required for Claude to read CI results on PRs
27
+ steps:
28
+ - name: Checkout repository
29
+ uses: actions/checkout@v4
30
+ with:
31
+ fetch-depth: 1
32
+
33
+ - name: Run Claude Code
34
+ id: claude
35
+ uses: anthropics/claude-code-action@v1
36
+ with:
37
+ claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
38
+
39
+ # This is an optional setting that allows Claude to read CI results on PRs
40
+ additional_permissions: |
41
+ actions: read
42
+
43
+ # Optional: Give a custom prompt to Claude. If this is not specified, Claude will perform the instructions specified in the comment that tagged it.
44
+ # prompt: 'Update the pull request description to include a summary of changes.'
45
+
46
+ # Optional: Add claude_args to customize behavior and configuration
47
+ # See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
48
+ # or https://code.claude.com/docs/en/cli-reference for available options
49
+ # claude_args: '--allowed-tools Bash(gh pr:*)'
@@ -0,0 +1,89 @@
1
+ name: Docs
2
+
3
+ on:
4
+ push:
5
+ branches: [ main ]
6
+ pull_request:
7
+ branches: [ main ]
8
+
9
+ permissions:
10
+ contents: write
11
+
12
+ jobs:
13
+ deploy:
14
+ runs-on: ubuntu-latest
15
+ strategy:
16
+ matrix:
17
+ python: [ "3.13" ]
18
+
19
+ steps:
20
+ - name: Setup Python
21
+ uses: actions/setup-python@v4
22
+ with:
23
+ python-version: ${{ matrix.python }}
24
+
25
+ - uses: actions/checkout@v4
26
+
27
+ - name: Upgrade setuptools/build
28
+ run: |
29
+ pip install wheel --upgrade
30
+ pip install setuptools --upgrade
31
+ python -m pip install --upgrade build
32
+
33
+ - name: Build wheels for package
34
+ run: python -m build
35
+
36
+ - name: Install Package with docs extra
37
+ run: pip install ."[docs, cvxpygen]"
38
+
39
+ - name: List dependencies
40
+ run: pip freeze
41
+
42
+ - shell: bash
43
+ id: write-license
44
+ env:
45
+ LICENSE: ${{ secrets.GUROBI_LICENSE}}
46
+ run: |
47
+ echo "$LICENSE" > $PWD/gurobi.lic
48
+
49
+ - name: Check Gurobi License
50
+ env:
51
+ GRB_LICENSE_FILE: ${{ github.workspace }}/gurobi.lic
52
+ run: python -c "import gurobipy; gurobipy.Model()"
53
+
54
+ - name: Export marimo notebooks
55
+ env:
56
+ GRB_LICENSE_FILE: ${{ github.workspace }}/gurobi.lic
57
+ run: |
58
+ for file in docs/tutorials/*.py; do
59
+ marimo export html "$file" -o "${file%.py}.html"
60
+ done
61
+
62
+ - name: Verify html generation
63
+ run: ls docs/tutorials
64
+
65
+ - name: Configure Git Credentials
66
+ run: |
67
+ git config user.name github-actions[bot]
68
+ git config user.email 41898282+github-actions[bot]@users.noreply.github.com
69
+
70
+ - name: Set weekly cache ID
71
+ run: echo "cache_id=$(date --utc '+%V')" >> $GITHUB_ENV
72
+
73
+ - name: Cache MkDocs Material build files
74
+ uses: actions/cache@v4
75
+ with:
76
+ key: mkdocs-material-${{ env.cache_id }}
77
+ path: ~/.cache
78
+ restore-keys: |
79
+ mkdocs-material-
80
+
81
+ - name: Build MkDocs site
82
+ run: mkdocs build
83
+
84
+ - name: Deploy to Cloudflare Pages with Wrangler
85
+ uses: cloudflare/wrangler-action@v4.0.0
86
+ with:
87
+ apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
88
+ accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
89
+ command: deploy
@@ -0,0 +1,106 @@
1
+ name: Release to PyPI
2
+
3
+ # Publishes only when BOTH hold:
4
+ # 1. a tag matching v* is pushed, and
5
+ # 2. the tagged commit is on main.
6
+ # Tag the merge commit on main after the PR is merged, then push the tag.
7
+
8
+ on:
9
+ push:
10
+ tags: ["v*"]
11
+
12
+ permissions:
13
+ contents: read
14
+
15
+ jobs:
16
+ build:
17
+ runs-on: ubuntu-latest
18
+ steps:
19
+ - uses: actions/checkout@v4
20
+ with:
21
+ fetch-depth: 0 # setuptools_scm needs the history and tags
22
+
23
+ - name: Require the tagged commit to be on main
24
+ run: |
25
+ git fetch origin main
26
+ if ! git merge-base --is-ancestor "$GITHUB_SHA" origin/main; then
27
+ echo "::error::Tag $GITHUB_REF_NAME ($GITHUB_SHA) is not on main; refusing to publish."
28
+ exit 1
29
+ fi
30
+
31
+ - uses: actions/setup-python@v5
32
+ with:
33
+ python-version: "3.13"
34
+
35
+ - name: Set up uv
36
+ uses: astral-sh/setup-uv@v6
37
+ with:
38
+ version: "0.11.15"
39
+
40
+ - name: Build sdist and wheel
41
+ run: uv build
42
+
43
+ - name: Check the built version matches the tag
44
+ run: |
45
+ VERSION="${GITHUB_REF_NAME#v}"
46
+ ls dist
47
+ test -f "dist/fomtools-${VERSION}.tar.gz" \
48
+ || { echo "::error::sdist for version $VERSION not found"; exit 1; }
49
+ test -f dist/fomtools-"${VERSION}"-*.whl \
50
+ || { echo "::error::wheel for version $VERSION not found"; exit 1; }
51
+
52
+ - name: Smoke-test the wheel in a clean venv
53
+ run: |
54
+ uv venv /tmp/pkg-test
55
+ uv pip install --python /tmp/pkg-test/bin/python dist/*.whl
56
+ /tmp/pkg-test/bin/python -c "
57
+ import fomtools
58
+ assert fomtools.__version__ == '${GITHUB_REF_NAME#v}', fomtools.__version__
59
+ from fomtools.verifier import Verifier
60
+ Verifier()
61
+ print('fomtools', fomtools.__version__, 'OK')
62
+ "
63
+ /tmp/pkg-test/bin/fomtools-codegen --help
64
+
65
+ - uses: actions/upload-artifact@v4
66
+ with:
67
+ name: dist
68
+ path: dist/
69
+
70
+ publish:
71
+ needs: build
72
+ runs-on: ubuntu-latest
73
+ environment:
74
+ name: pypi
75
+ url: https://pypi.org/project/fomtools/
76
+ permissions:
77
+ id-token: write # Trusted Publishing (OIDC); no API token needed
78
+ steps:
79
+ - uses: actions/download-artifact@v4
80
+ with:
81
+ name: dist
82
+ path: dist/
83
+
84
+ - name: Publish to PyPI
85
+ uses: pypa/gh-action-pypi-publish@release/v1
86
+
87
+ github-release:
88
+ needs: publish
89
+ runs-on: ubuntu-latest
90
+ permissions:
91
+ contents: write
92
+ steps:
93
+ - uses: actions/download-artifact@v4
94
+ with:
95
+ name: dist
96
+ path: dist/
97
+
98
+ - name: Create GitHub Release
99
+ env:
100
+ GH_TOKEN: ${{ github.token }}
101
+ run: |
102
+ gh release create "$GITHUB_REF_NAME" dist/* \
103
+ --repo "$GITHUB_REPOSITORY" \
104
+ --title "$GITHUB_REF_NAME" \
105
+ --generate-notes \
106
+ --verify-tag
@@ -0,0 +1,43 @@
1
+ name: Update FOMTools Skill
2
+
3
+ on:
4
+ pull_request:
5
+ branches: [main]
6
+ paths:
7
+ - 'docs/**'
8
+ - 'fomtools/**'
9
+ - 'AGENTS.md'
10
+
11
+ permissions:
12
+ contents: write
13
+ pull-requests: write
14
+ id-token: write
15
+
16
+ jobs:
17
+ update-skill:
18
+ runs-on: ubuntu-latest
19
+ steps:
20
+ - name: Checkout repository
21
+ uses: actions/checkout@v4
22
+ with:
23
+ fetch-depth: 1
24
+
25
+ - name: Run Claude Code to update skill
26
+ id: claude
27
+ uses: anthropics/claude-code-action@v1
28
+ with:
29
+ claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
30
+ prompt_file: skills/update-prompt.md
31
+
32
+ allowed_tools: |
33
+ Bash(git status)
34
+ Bash(git diff:*)
35
+ Bash(git log:*)
36
+ Bash(git add:*)
37
+ Bash(git commit:*)
38
+ Bash(find:*)
39
+ Bash(grep:*)
40
+ Bash(wc:*)
41
+ Read
42
+ Edit
43
+ Write