fomtools 0.0.2__tar.gz → 0.0.4__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.
- {fomtools-0.0.2 → fomtools-0.0.4}/.github/workflows/docs.yml +9 -13
- {fomtools-0.0.2 → fomtools-0.0.4}/.github/workflows/update-skill.yml +7 -14
- {fomtools-0.0.2 → fomtools-0.0.4}/.gitignore +5 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/AGENTS.md +27 -0
- fomtools-0.0.4/CONTRIBUTING.md +34 -0
- fomtools-0.0.4/Makefile +13 -0
- {fomtools-0.0.2/fomtools.egg-info → fomtools-0.0.4}/PKG-INFO +91 -42
- {fomtools-0.0.2 → fomtools-0.0.4}/README.md +83 -40
- fomtools-0.0.4/docs/api/canonicalizer.md +38 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/docs/api/codegen.md +4 -0
- fomtools-0.0.4/docs/api/constraint.md +17 -0
- fomtools-0.0.4/docs/api/index.md +45 -0
- fomtools-0.0.4/docs/api/linearexpression.md +6 -0
- fomtools-0.0.4/docs/api/proxablefunctions.md +35 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/docs/api/solvers.md +4 -1
- {fomtools-0.0.2 → fomtools-0.0.4}/docs/api/steps.md +4 -1
- fomtools-0.0.4/docs/api/verifier.md +7 -0
- fomtools-0.0.4/docs/assets/logo/favicon-16.png +0 -0
- fomtools-0.0.4/docs/assets/logo/favicon-32.png +0 -0
- fomtools-0.0.4/docs/assets/logo/favicon-48.png +0 -0
- fomtools-0.0.4/docs/assets/logo/favicon.svg +1 -0
- fomtools-0.0.4/docs/assets/logo/icon-512.png +0 -0
- fomtools-0.0.4/docs/assets/logo/icon-dark.svg +1 -0
- fomtools-0.0.4/docs/assets/logo/icon-mono.svg +1 -0
- fomtools-0.0.4/docs/assets/logo/icon-small.svg +1 -0
- fomtools-0.0.4/docs/assets/logo/icon.svg +1 -0
- fomtools-0.0.4/docs/assets/logo/logo-dark.svg +1 -0
- fomtools-0.0.4/docs/assets/logo/logo-mono.svg +1 -0
- fomtools-0.0.4/docs/assets/logo/logo.svg +1 -0
- fomtools-0.0.4/docs/get_started.md +140 -0
- fomtools-0.0.4/docs/index.md +101 -0
- fomtools-0.0.4/docs/quick_start.md +189 -0
- fomtools-0.0.4/docs/stylesheets/extra.css +85 -0
- {fomtools-0.0.2/docs/tutorials → fomtools-0.0.4/docs/tutorials/codegen}/_recorded_timings.json +2 -2
- fomtools-0.0.4/docs/tutorials/codegen/control.md +91 -0
- fomtools-0.0.4/docs/tutorials/codegen/control.py +293 -0
- fomtools-0.0.4/docs/tutorials/codegen/lasso.md +66 -0
- fomtools-0.0.4/docs/tutorials/codegen/lasso.py +230 -0
- fomtools-0.0.4/docs/tutorials/codegen/network.md +87 -0
- fomtools-0.0.4/docs/tutorials/codegen/network.py +304 -0
- fomtools-0.0.4/docs/tutorials/codegen/nnls.md +65 -0
- fomtools-0.0.4/docs/tutorials/codegen/nnls.py +205 -0
- fomtools-0.0.4/docs/tutorials/codegen/portfolio.md +80 -0
- fomtools-0.0.4/docs/tutorials/codegen/portfolio.py +258 -0
- fomtools-0.0.4/docs/tutorials/codegen.md +45 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/docs/tutorials/cvxpygen.md +28 -15
- fomtools-0.0.4/docs/tutorials/cvxpygen_mpc.py +188 -0
- fomtools-0.0.4/docs/tutorials/helper_functions/codegen_benchmarks.py +144 -0
- fomtools-0.0.4/docs/tutorials/helper_functions/control.py +190 -0
- fomtools-0.0.4/docs/tutorials/helper_functions/lasso.py +116 -0
- fomtools-0.0.4/docs/tutorials/helper_functions/network.py +164 -0
- fomtools-0.0.4/docs/tutorials/helper_functions/nnls.py +85 -0
- fomtools-0.0.4/docs/tutorials/helper_functions/pepit_runner.py +411 -0
- fomtools-0.0.4/docs/tutorials/helper_functions/portfolio.py +94 -0
- fomtools-0.0.4/docs/tutorials/index.md +21 -0
- fomtools-0.0.4/docs/tutorials/verification/control.py +590 -0
- fomtools-0.0.4/docs/tutorials/verification/lasso.py +475 -0
- fomtools-0.0.4/docs/tutorials/verification/network.py +641 -0
- fomtools-0.0.4/docs/tutorials/verification/nnls.py +588 -0
- fomtools-0.0.4/docs/tutorials/verification/portfolio.py +366 -0
- fomtools-0.0.4/docs/tutorials/verification.md +29 -0
- {fomtools-0.0.2/docs/tutorials → fomtools-0.0.4/docs/user_guide}/codegen.md +186 -45
- fomtools-0.0.4/docs/user_guide/index.md +293 -0
- fomtools-0.0.4/docs/user_guide/sdp.md +76 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/__init__.py +1 -1
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/canonicalizers/canonicalizer.py +10 -9
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/canonicalizers/mip.py +28 -20
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/canonicalizers/obbt_handler.py +4 -4
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/canonicalizers/sdp.py +17 -17
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/canonicalizers/simulator.py +24 -23
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/codegen/__init__.py +13 -13
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/codegen/agent/__init__.py +10 -10
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/codegen/agent/budget.py +1 -1
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/codegen/agent/claude_sdk.py +4 -4
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/codegen/agent/cli_driver.py +9 -9
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/codegen/agent/cli_specs.py +7 -7
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/codegen/agent/codex_sdk.py +5 -5
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/codegen/agent/driver.py +8 -8
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/codegen/agent/pidev_sdk.py +6 -6
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/codegen/agent/prompts.py +173 -11
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/codegen/agent/sdk_base.py +11 -11
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/codegen/agent/stub.py +3 -3
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/codegen/cli.py +18 -4
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/codegen/config.py +81 -19
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/codegen/emit.py +2 -2
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/codegen/examples.py +38 -38
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/codegen/extract.py +7 -7
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/codegen/extract_scheduled.py +10 -10
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/codegen/extract_unrolled.py +10 -10
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/codegen/factorize.py +3 -3
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/codegen/generate.py +379 -154
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/codegen/ir.py +65 -27
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/codegen/kernel_rules.py +127 -35
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/codegen/objective.py +8 -8
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/codegen/oracle.py +10 -10
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/codegen/postprocess.py +95 -6
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/codegen/schedule.py +13 -13
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/codegen/spec.py +68 -2
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/codegen/targets/base.py +40 -7
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/codegen/targets/embedded_c.py +1410 -30
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/codegen/targets/large_scale_cuda.py +20 -10
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/codegen/targets/large_scale_openmp.py +30 -15
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/constraint.py +85 -18
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/cvxpygen/__init__.py +3 -3
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/cvxpygen/api.py +4 -4
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/cvxpygen/builders.py +36 -35
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/cvxpygen/glue.py +2 -2
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/cvxpygen/interface.py +5 -5
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/cvxpygen/qpdata.py +3 -3
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/cvxpygen/scaling.py +1 -1
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/iteratetrajectory.py +11 -11
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/linearexpression.py +50 -7
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/proxable_functions/__init__.py +28 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/proxable_functions/elastic_net.py +44 -23
- fomtools-0.0.4/fomtools/proxable_functions/hinge_loss.py +111 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/proxable_functions/huber_loss.py +38 -30
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/proxable_functions/ind_affine.py +48 -34
- fomtools-0.0.4/fomtools/proxable_functions/ind_ball_l1.py +105 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/proxable_functions/ind_ball_linf.py +44 -11
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/proxable_functions/ind_box.py +47 -24
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/proxable_functions/ind_half_space.py +37 -14
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/proxable_functions/ind_nonnegative.py +34 -10
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/proxable_functions/ind_nonpositive.py +33 -10
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/proxable_functions/ind_point.py +40 -16
- fomtools-0.0.4/fomtools/proxable_functions/ind_polyhedral.py +119 -0
- fomtools-0.0.4/fomtools/proxable_functions/ind_simplex.py +92 -0
- fomtools-0.0.4/fomtools/proxable_functions/labeled_hinge_loss.py +124 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/proxable_functions/least_squares.py +35 -21
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/proxable_functions/linear.py +30 -17
- fomtools-0.0.4/fomtools/proxable_functions/norm_inf.py +120 -0
- fomtools-0.0.4/fomtools/proxable_functions/norm_l1.py +143 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/proxable_functions/quadratic.py +46 -25
- fomtools-0.0.4/fomtools/proxable_functions/soft_nonnegative.py +120 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/proxable_functions/sq_l2_norm.py +19 -13
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/proxable_functions/sum_negative.py +33 -22
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/proxable_functions/sum_positive.py +34 -18
- fomtools-0.0.4/fomtools/proxable_functions/total_variation_1d.py +157 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/sets/__init__.py +5 -5
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/sets/affine_subspace.py +3 -3
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/sets/ball.py +4 -4
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/sets/box.py +10 -10
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/sets/polyhedron.py +4 -4
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/sets/set.py +12 -12
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/solvers/cuclarabel.py +1 -1
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/solvers/factory.py +17 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/solvers/gurobi.py +36 -17
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/solvers/highs.py +20 -16
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/stepdecomposers/sdp_step_decomposer.py +1 -1
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/stepdecomposers/simulator_step_decomposer.py +19 -18
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/stepdecomposers/step_decomposer.py +46 -42
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/steps/affine.py +7 -6
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/steps/lin_prog.py +5 -5
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/steps/quad_prog.py +5 -5
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/steps/relu.py +6 -6
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/steps/saturated_linear.py +6 -6
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/steps/soft_threshold.py +3 -3
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/steps/step.py +6 -6
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/utils/matrix_utils.py +2 -2
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/verifier.py +368 -249
- {fomtools-0.0.2 → fomtools-0.0.4/fomtools.egg-info}/PKG-INFO +91 -42
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools.egg-info/SOURCES.txt +56 -12
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools.egg-info/requires.txt +10 -1
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools.egg-info/scm_file_list.json +57 -13
- fomtools-0.0.4/fomtools.egg-info/scm_version.json +8 -0
- fomtools-0.0.4/mkdocs.yml +112 -0
- fomtools-0.0.4/overrides/main.html +11 -0
- fomtools-0.0.4/overrides/partials/logo.html +3 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/pyproject.toml +12 -1
- fomtools-0.0.4/scripts/export_marimo.py +142 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/skills/README.md +2 -2
- {fomtools-0.0.2 → fomtools-0.0.4}/skills/fomtools/SKILL.md +42 -18
- {fomtools-0.0.2 → fomtools-0.0.4}/skills/fomtools/references/api.md +44 -23
- {fomtools-0.0.2 → fomtools-0.0.4}/skills/fomtools/references/codegen.md +21 -15
- {fomtools-0.0.2 → fomtools-0.0.4}/skills/fomtools/references/cvxpygen.md +4 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/skills/update-prompt.md +3 -2
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/codegen/conftest.py +46 -44
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/codegen/test_cli.py +8 -7
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/codegen/test_cvxpygen_dispatch.py +6 -6
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/codegen/test_dedup.py +3 -3
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/codegen/test_editable_ops.py +45 -8
- fomtools-0.0.4/tests/codegen/test_fused_ops.py +383 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/codegen/test_ir_extraction.py +13 -13
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/codegen/test_large_scale.py +38 -1
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/codegen/test_objective_termination.py +33 -30
- fomtools-0.0.4/tests/codegen/test_optimization_rounds.py +225 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/codegen/test_scheduled_ir.py +19 -19
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/codegen/test_static_constraints.py +23 -7
- fomtools-0.0.4/tests/codegen/test_step_iterate.py +391 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/codegen/test_unrolled_ir.py +1 -1
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/conftest.py +3 -3
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/examples/comparison_lasso.py +14 -15
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/examples/cut_experiment.py +15 -17
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/test_add_constraint.py +30 -29
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/test_affine_simulator.py +6 -6
- fomtools-0.0.4/tests/test_api.py +554 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/test_audit_regressions.py +31 -32
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/test_boxpgd_sdp_mip.py +18 -17
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/test_complementarity.py +39 -38
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/test_convex_hull_cuts.py +30 -22
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/test_copy_isolation.py +19 -18
- fomtools-0.0.4/tests/test_docs_examples.py +83 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/test_douglas_rachford.py +8 -7
- fomtools-0.0.4/tests/test_export_marimo.py +206 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/test_fixed_point_ista.py +9 -8
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/test_fixed_point_nnls.py +11 -10
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/test_ind_ball_l1.py +16 -15
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/test_ind_polyhedral.py +20 -19
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/test_ind_simplex.py +17 -16
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/test_inf_norm_sdp.py +37 -36
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/test_infinite_bounds.py +10 -10
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/test_ista_sdp_mip.py +18 -19
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/test_iterate_trajectory.py +45 -44
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/test_l1_obj_norm.py +94 -93
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/test_linear_program.py +7 -6
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/test_linsolve_simulator.py +19 -18
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/test_mip_solution_consistency.py +34 -33
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/test_nn_verify_jax.py +6 -5
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/test_nn_verify_torch.py +6 -5
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/test_nnls_sdp_mip.py +9 -8
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/test_norm_inf.py +19 -20
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/test_obbt_handler.py +27 -23
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/test_objective_bounds.py +18 -17
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/test_partial_relu.py +7 -6
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/test_partial_relu_sdp_sim.py +25 -24
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/test_prox_decomposer.py +93 -92
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/test_quadratic_program.py +22 -23
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/test_relu_simulator.py +3 -3
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/test_satlin.py +52 -51
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/test_satlin_simulator.py +3 -3
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/test_sdp_canonicalizer.py +13 -12
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/test_sdp_cuts.py +114 -113
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/test_sdp_hull.py +9 -8
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/test_sdp_inequality.py +16 -15
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/test_sdp_nnls.py +17 -16
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/test_sets.py +15 -18
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/test_simulator.py +35 -34
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/test_soft_threshold_simulator.py +3 -3
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/test_solve_kwargs.py +9 -8
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/test_stack.py +26 -25
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/test_subproblem_simulator.py +15 -14
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/test_sum_squares.py +15 -14
- fomtools-0.0.4/tests/test_tighten_residuals.py +122 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/test_total_variation_1d.py +19 -22
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/test_two_norm_mip.py +31 -30
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/test_verifier.py +13 -12
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/test_verifier_ista.py +7 -6
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/test_warm_start.py +17 -16
- {fomtools-0.0.2 → fomtools-0.0.4}/uv.lock +35 -2
- fomtools-0.0.2/docs/api/canonicalizer.md +0 -8
- fomtools-0.0.2/docs/api/constraint.md +0 -5
- fomtools-0.0.2/docs/api/linearexpression.md +0 -1
- fomtools-0.0.2/docs/api/proxablefunctions.md +0 -45
- fomtools-0.0.2/docs/api/verifier.md +0 -2
- fomtools-0.0.2/docs/api.md +0 -11
- fomtools-0.0.2/docs/index.md +0 -101
- fomtools-0.0.2/docs/installation.md +0 -41
- fomtools-0.0.2/docs/tutorials/control.py +0 -343
- fomtools-0.0.2/docs/tutorials/cvxpygen_mpc.py +0 -147
- fomtools-0.0.2/docs/tutorials/lasso.py +0 -303
- fomtools-0.0.2/docs/tutorials/network.py +0 -377
- fomtools-0.0.2/docs/tutorials/nnls.py +0 -292
- fomtools-0.0.2/docs/tutorials/nnls_verification.py +0 -183
- fomtools-0.0.2/docs/tutorials/portfolio.py +0 -290
- fomtools-0.0.2/docs/tutorials.md +0 -18
- fomtools-0.0.2/fomtools/proxable_functions/hinge_loss.py +0 -72
- fomtools-0.0.2/fomtools/proxable_functions/ind_ball_l1.py +0 -67
- fomtools-0.0.2/fomtools/proxable_functions/ind_polyhedral.py +0 -86
- fomtools-0.0.2/fomtools/proxable_functions/ind_simplex.py +0 -56
- fomtools-0.0.2/fomtools/proxable_functions/labeled_hinge_loss.py +0 -74
- fomtools-0.0.2/fomtools/proxable_functions/norm_inf.py +0 -80
- fomtools-0.0.2/fomtools/proxable_functions/norm_l1.py +0 -109
- fomtools-0.0.2/fomtools/proxable_functions/soft_nonnegative.py +0 -85
- fomtools-0.0.2/fomtools/proxable_functions/total_variation_1d.py +0 -93
- fomtools-0.0.2/fomtools.egg-info/scm_version.json +0 -8
- fomtools-0.0.2/mkdocs.yml +0 -53
- fomtools-0.0.2/tests/test_docs_examples.py +0 -16
- fomtools-0.0.2/wrangler.toml +0 -5
- {fomtools-0.0.2 → fomtools-0.0.4}/.github/workflows/ci.yml +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/.github/workflows/claude-code-review.yml +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/.github/workflows/claude.yml +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/.github/workflows/release.yml +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/.pre-commit-config.yaml +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/CLAUDE.md +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/LICENSE +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/docs/javascripts/mathjax.js +0 -0
- /fomtools-0.0.2/docs/tutorials/codegen_speedup_results.md → /fomtools-0.0.4/docs/tutorials/codegen/speedup_results.md +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/canonicalizers/__init__.py +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/codegen/agent/agents.yaml +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/codegen/dedup.py +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/codegen/harness.py +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/codegen/targets/__init__.py +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/codegen/wrapper.py +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/nn/__init__.py +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/nn/layers.py +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/proxable_functions/proximal_operator.py +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/solvers/__init__.py +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/solvers/clarabel.py +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/solvers/mip_solver.py +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/solvers/sdp_solver.py +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/solvers/solver.py +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/stepdecomposers/__init__.py +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/stepdecomposers/mip_step_decomposer.py +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/steps/__init__.py +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/utils/__init__.py +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/utils/convex_hull_cuts.py +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/utils/dict_utils.py +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/utils/envelopes.py +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/utils/math_utils.py +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/utils/range_utils.py +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools/utils/sparse_utils.py +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools.egg-info/dependency_links.txt +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools.egg-info/entry_points.txt +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/fomtools.egg-info/top_level.txt +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/setup.cfg +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/__init__.py +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/codegen/__init__.py +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/codegen/golden/boxqp/embedded_c/fom_solver.c +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/codegen/golden/cgqp/large_scale_cuda/fom_solver.cu +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/codegen/golden/cgqp/large_scale_openmp/fom_solver.c +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/codegen/golden/cvxpygen_qp/embedded_c/fom_solver.c +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/codegen/golden/cvxpygen_qp_objective/embedded_c/fom_solver.c +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/codegen/golden/dr/embedded_c/fom_solver.c +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/codegen/golden/fista/embedded_c/fom_solver.c +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/codegen/golden/fista_objective/embedded_c/fom_solver.c +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/codegen/golden/halpern/embedded_c/fom_solver.c +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/codegen/golden/indef_kkt/embedded_c/fom_solver.c +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/codegen/golden/ista/embedded_c/fom_solver.c +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/codegen/golden/ista/large_scale_cuda/fom_solver.cu +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/codegen/golden/ista/large_scale_openmp/fom_solver.c +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/codegen/golden/ista_objective/embedded_c/fom_solver.c +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/codegen/golden/ista_objective/large_scale_cuda/fom_solver.cu +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/codegen/golden/mpc/embedded_c/fom_solver.c +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/codegen/golden/pdhg_lp/embedded_c/fom_solver.c +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/codegen/golden/pdhg_lp/large_scale_cuda/fom_solver.cu +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/codegen/golden/scheduled/embedded_c/fom_solver.c +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/codegen/golden/scheduled_objective/embedded_c/fom_solver.c +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/codegen/golden/scheduled_objective/large_scale_cuda/fom_solver.cu +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/codegen/test_agent_budget.py +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/codegen/test_agent_integration.py +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/codegen/test_agent_notes.py +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/codegen/test_codegen_dispatch.py +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/codegen/test_cvxpygen_bounds.py +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/codegen/test_cvxpygen_builders.py +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/codegen/test_cvxpygen_e2e.py +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/codegen/test_cvxpygen_glue.py +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/codegen/test_cvxpygen_objective.py +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/codegen/test_cvxpygen_preflight.py +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/codegen/test_cvxpygen_qpdata.py +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/codegen/test_cvxpygen_register.py +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/codegen/test_cvxpygen_scaling.py +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/codegen/test_cvxpygen_scheduled.py +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/codegen/test_dr_pipeline.py +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/codegen/test_editable_linsolve.py +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/codegen/test_emit_scaffold.py +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/codegen/test_examples_scale.py +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/codegen/test_factorize.py +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/codegen/test_fista_pipeline.py +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/codegen/test_float32.py +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/codegen/test_indefinite_kkt.py +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/codegen/test_oracle.py +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/codegen/test_pdhg_pipeline.py +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/codegen/test_postprocess.py +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/codegen/test_profiling.py +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/codegen/test_satlin_mpc.py +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/codegen/test_scheduled_pipeline.py +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/codegen/test_spec_roundtrip.py +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/codegen/test_stationarity_gate.py +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/codegen/test_stub_pipeline.py +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/codegen/test_termination_interval.py +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/codegen/test_unrolled_emission.py +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/codegen/test_wrapper_roundtrip.py +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/cvxpy.py +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/test_LP_pdhg.py +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/test_ista.py +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/test_linearexpression.py +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/test_mincost_flow.py +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/test_placeholder.py +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/test_portfolio.py +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/test_range_functions.py +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/test_sdp_selector.py +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/test_solver_boundary.py +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/test_sparse_utils.py +0 -0
- {fomtools-0.0.2 → fomtools-0.0.4}/tests/test_vec_LUhat.py +0 -0
|
@@ -4,7 +4,7 @@ on:
|
|
|
4
4
|
push:
|
|
5
5
|
branches: [ main ]
|
|
6
6
|
pull_request:
|
|
7
|
-
branches: [ main ]
|
|
7
|
+
branches: [ main, documentation ]
|
|
8
8
|
|
|
9
9
|
permissions:
|
|
10
10
|
contents: write
|
|
@@ -54,13 +54,10 @@ jobs:
|
|
|
54
54
|
- name: Export marimo notebooks
|
|
55
55
|
env:
|
|
56
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
|
|
57
|
+
run: python scripts/export_marimo.py --force
|
|
61
58
|
|
|
62
59
|
- name: Verify html generation
|
|
63
|
-
run: ls docs/tutorials
|
|
60
|
+
run: ls -R docs/tutorials
|
|
64
61
|
|
|
65
62
|
- name: Configure Git Credentials
|
|
66
63
|
run: |
|
|
@@ -79,11 +76,10 @@ jobs:
|
|
|
79
76
|
mkdocs-material-
|
|
80
77
|
|
|
81
78
|
- name: Build MkDocs site
|
|
82
|
-
run: mkdocs build
|
|
79
|
+
run: mkdocs build --strict
|
|
83
80
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
command: deploy
|
|
81
|
+
# Pull requests only build the site; pushes to main publish it to the gh-pages
|
|
82
|
+
# branch, which GitHub Pages serves at https://stellatogrp.github.io/fomtools/
|
|
83
|
+
- name: Deploy to GitHub Pages
|
|
84
|
+
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
|
85
|
+
run: mkdocs gh-deploy --force
|
|
@@ -20,6 +20,8 @@ jobs:
|
|
|
20
20
|
- name: Checkout repository
|
|
21
21
|
uses: actions/checkout@v4
|
|
22
22
|
with:
|
|
23
|
+
# The PR branch itself (not the detached merge ref), so the sync commit can be pushed.
|
|
24
|
+
ref: ${{ github.head_ref }}
|
|
23
25
|
fetch-depth: 1
|
|
24
26
|
|
|
25
27
|
- name: Run Claude Code to update skill
|
|
@@ -27,17 +29,8 @@ jobs:
|
|
|
27
29
|
uses: anthropics/claude-code-action@v1
|
|
28
30
|
with:
|
|
29
31
|
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
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
|
|
32
|
+
# v1 inputs: `prompt` and `claude_args` (the v0 `prompt_file` and `allowed_tools`
|
|
33
|
+
# are ignored, and without a prompt the action skips silently).
|
|
34
|
+
prompt: 'Follow the instructions in skills/update-prompt.md.'
|
|
35
|
+
claude_args: >-
|
|
36
|
+
--allowedTools "Bash(git status),Bash(git diff:*),Bash(git log:*),Bash(git add:*),Bash(git commit:*),Bash(git push:*),Bash(find:*),Bash(grep:*),Bash(wc:*),Read,Edit,Write"
|
|
@@ -82,3 +82,30 @@ execution of the CUDA checks; `FOMTOOLS_CODEGEN_BACKEND` selects the agent.
|
|
|
82
82
|
- When the public API or docs change, the `update-skill` workflow refreshes
|
|
83
83
|
`skills/fomtools/`; check its output rather than editing the skill by hand
|
|
84
84
|
in the same PR.
|
|
85
|
+
|
|
86
|
+
## Tutorial math notation
|
|
87
|
+
|
|
88
|
+
All `mo.md` cells in `docs/tutorials/` (verification and codegen notebooks) use one notation per concept, following Boyd-style conventions. Keep new notebooks in sync with this table.
|
|
89
|
+
|
|
90
|
+
| Concept | Write | Never |
|
|
91
|
+
|---|---|---|
|
|
92
|
+
| Reals, ones | `\mathbf{R}`, `\mathbf{R}^n_+`, `\mathbf{1}` | `{\bf R}`, `\R`, `\mathbb{R}` |
|
|
93
|
+
| Transpose | `A^T` | `A^\top` |
|
|
94
|
+
| Calligraphic | `\mathcal{X}` | `{\cal X}` |
|
|
95
|
+
| Problem keywords | `\text{minimize}`, `\text{maximize}`, `\text{subject to}` | `\textnormal{...}` |
|
|
96
|
+
| Delimiters | inline `$...$`, display `$$...$$`, problems and updates as bare `\begin{array}{ll}`/`{rcl}` | `\(...\)`, `\[...\]` |
|
|
97
|
+
| Soft-thresholding | `\mathbf{soft}_{\lambda\eta}` (`soft_threshold` step) | `{\cal T}_\lambda`, `S_\lambda` |
|
|
98
|
+
| Projection | `\Pi_C`: `\Pi_{\mathbf{R}^n_+}` (`relu` step), `\Pi_{[l,u]}` (`satlin` step / `IndBox`) | `\mathbf{ReLU}`, `\mathbf{prox}_{\mathbb{I}_C}` |
|
|
99
|
+
| Proximal operator | `\mathbf{prox}_f` | `\operatorname{prox}` |
|
|
100
|
+
| Fractions | inline slash: `(1/2) z^T P z`, `(t_k - 1)/t_{k+1}` | `\frac` |
|
|
101
|
+
|
|
102
|
+
Norms always carry a subscript: `\|v\|_2`, `\|v\|_\infty` (never `\lVert v \rVert` or a bare `\|v\|`).
|
|
103
|
+
Define soft-thresholding where it is first used: `\mathbf{soft}_\kappa(v)_i = \mathbf{sign}(v_i)\max\{|v_i| - \kappa, 0\}`, applied element-wise.
|
|
104
|
+
Matplotlib labels (`label=`, `xlabel`, `ylabel`, `title`) are rendered by mathtext, not KaTeX: write `\geq`/`\leq` there (mathtext rejects `\ge`/`\le`), and keep `\|v\|_2` norms.
|
|
105
|
+
|
|
106
|
+
Symbol roles: `x` problem parameter in `\mathcal{X}`; `z` decision variable and primal iterate, `z^0 \in \mathcal{Z}`, `z^\star` solution; `v, w` dual or auxiliary iterates; `y` (lasso) or `w` (NNLS) for the un-extrapolated proximal output of a momentum method, matching the helper code; `k` iteration, `K` horizon, `\eta` step size, `L` smoothness constant, `r^k` residual, `R` PEP initial radius.
|
|
107
|
+
Search-box bounds are `x_\mathrm{lb}, x_\mathrm{ub}` and `z^0_\mathrm{lb}, z^0_\mathrm{ub}`; problem-data bounds keep `_{\min}, _{\max}`. Code names such as `x_lb` or `s0_samples` appear only in backticks in prose. When a math letter differs from the code name, say so once.
|
|
108
|
+
|
|
109
|
+
Iterations are written `k \to k+1` for `k = 0, 1, \dots`. A momentum coefficient `\beta_k` uses the same index as the helper code (slot `k` uses `beta_k`, and `k` starts at 1), so the update reads `z^{k+1} = w^{k+1} + \beta_{k+1}(w^{k+1} - w^k)` with `\beta_1 = 0`. Use "Nesterov-type momentum" for `\beta_k = (k-1)/(k+2)` and reserve "FISTA" for the `t_k` schedule `\beta_k = (t_{k-1}-1)/t_k`.
|
|
110
|
+
|
|
111
|
+
Known clashes kept on purpose because both uses are standard: control input `u_t` vs. OSQP upper bound `u(x)`, LQR weight `R` vs. PEP radius `R`, and `\mu` as network cost, portfolio return, or strong-convexity constant.
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Contributing to FOMTools
|
|
2
|
+
|
|
3
|
+
## Development setup
|
|
4
|
+
|
|
5
|
+
Follow the environment instructions in [docs/get_started.md](docs/get_started.md) to create a
|
|
6
|
+
virtual environment and install `fomtools` in editable mode with its `dev` and `docs` extras.
|
|
7
|
+
|
|
8
|
+
Install the pre-commit hooks once per clone:
|
|
9
|
+
|
|
10
|
+
pre-commit install
|
|
11
|
+
|
|
12
|
+
## Tests and linting
|
|
13
|
+
|
|
14
|
+
pytest # Run the test suite
|
|
15
|
+
ruff check # Check code style
|
|
16
|
+
ruff format # Auto-format
|
|
17
|
+
pre-commit run --all-files # Run all hooks
|
|
18
|
+
|
|
19
|
+
## Previewing the documentation
|
|
20
|
+
|
|
21
|
+
Install the documentation dependencies and start the local MkDocs server:
|
|
22
|
+
|
|
23
|
+
uv sync --extra docs
|
|
24
|
+
make docs-serve
|
|
25
|
+
|
|
26
|
+
The `docs-serve` target recursively discovers marimo notebooks under `docs/tutorials`, exports
|
|
27
|
+
missing or stale notebooks to ignored HTML files, and then starts MkDocs. Restart the server after
|
|
28
|
+
editing a notebook so that its HTML is refreshed.
|
|
29
|
+
|
|
30
|
+
Use these targets to export or validate the documentation without starting the server:
|
|
31
|
+
|
|
32
|
+
make docs-export # Export only missing or stale notebooks
|
|
33
|
+
make docs-export-force # Regenerate every notebook
|
|
34
|
+
make docs-build # Force export, then run a strict MkDocs build
|
fomtools-0.0.4/Makefile
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
.PHONY: docs-export docs-export-force docs-serve docs-build
|
|
2
|
+
|
|
3
|
+
docs-export:
|
|
4
|
+
uv run --extra docs python scripts/export_marimo.py
|
|
5
|
+
|
|
6
|
+
docs-export-force:
|
|
7
|
+
uv run --extra docs python scripts/export_marimo.py --force
|
|
8
|
+
|
|
9
|
+
docs-serve: docs-export
|
|
10
|
+
uv run --extra docs mkdocs serve
|
|
11
|
+
|
|
12
|
+
docs-build: docs-export-force
|
|
13
|
+
uv run --extra docs mkdocs build --strict
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fomtools
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.4
|
|
4
4
|
Summary: FOMTools: A Python Toolbox for Analysis of First-Order Methods
|
|
5
5
|
Author-email: Vinit Ranjan <vranjan1@mit.edu>, Daniel Deza <dd7022@princeton.edu>, Anushka Acharya <aa9078@princeton.edu>, Jisun Park <jisunpark@princeton.edu>, Bartolomeo Stellato <bstellato@princeton.edu>
|
|
6
6
|
License: Apache 2.0
|
|
@@ -41,22 +41,40 @@ Provides-Extra: nn
|
|
|
41
41
|
Requires-Dist: torch; extra == "nn"
|
|
42
42
|
Requires-Dist: jax<0.11.2; extra == "nn"
|
|
43
43
|
Requires-Dist: flax; extra == "nn"
|
|
44
|
+
Provides-Extra: all
|
|
45
|
+
Requires-Dist: fomtools[codegen,cvxpygen,gurobi,nn]; extra == "all"
|
|
46
|
+
Requires-Dist: fomtools[gpu]; sys_platform != "darwin" and extra == "all"
|
|
47
|
+
Requires-Dist: fomtools[cuda]; extra == "all"
|
|
44
48
|
Provides-Extra: docs
|
|
45
49
|
Requires-Dist: fomtools[gurobi]; extra == "docs"
|
|
46
50
|
Requires-Dist: marimo; extra == "docs"
|
|
47
51
|
Requires-Dist: matplotlib; extra == "docs"
|
|
48
|
-
Requires-Dist: mkdocs; extra == "docs"
|
|
52
|
+
Requires-Dist: mkdocs<2,>=1.6; extra == "docs"
|
|
49
53
|
Requires-Dist: mkdocstrings-python; extra == "docs"
|
|
50
54
|
Requires-Dist: mkdocs-marimo; extra == "docs"
|
|
51
55
|
Requires-Dist: mkdocs-material; extra == "docs"
|
|
56
|
+
Requires-Dist: networkx; extra == "docs"
|
|
57
|
+
Requires-Dist: pepit; extra == "docs"
|
|
52
58
|
Requires-Dist: pymdown-extensions; extra == "docs"
|
|
53
59
|
Dynamic: license-file
|
|
54
60
|
|
|
55
|
-
|
|
56
|
-
|
|
61
|
+
<h1>
|
|
62
|
+
<picture>
|
|
63
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/stellatogrp/fomtools/main/docs/assets/logo/logo-dark.svg">
|
|
64
|
+
<img alt="FOMTools" src="https://raw.githubusercontent.com/stellatogrp/fomtools/main/docs/assets/logo/logo.svg" height="72">
|
|
65
|
+
</picture>
|
|
66
|
+
</h1>
|
|
67
|
+
|
|
68
|
+
[](https://pypi.org/project/fomtools/)
|
|
69
|
+
[](https://stellatogrp.github.io/fomtools/)
|
|
57
70
|
|
|
58
71
|
**Development, analysis, and code generation for first-order methods.**
|
|
59
72
|
|
|
73
|
+
[Documentation](https://stellatogrp.github.io/fomtools/) |
|
|
74
|
+
[PyPI](https://pypi.org/project/fomtools/) |
|
|
75
|
+
[Paper](https://arxiv.org/abs/2610.26743) |
|
|
76
|
+
[Benchmarks](https://github.com/stellatogrp/fomtools_experiments)
|
|
77
|
+
|
|
60
78
|
FOMTools is an open-source Python package for developing, analyzing, and deploying
|
|
61
79
|
first-order methods for parametric linear and convex quadratic optimization. You write the
|
|
62
80
|
iteration in Python, with syntax close to its mathematical description, and FOMTools records
|
|
@@ -75,65 +93,73 @@ you can:
|
|
|
75
93
|
|
|
76
94
|
## Example
|
|
77
95
|
|
|
78
|
-
The following code verifies
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
96
|
+
The following code verifies projected gradient descent on the parametric quadratic program
|
|
97
|
+
|
|
98
|
+
$$
|
|
99
|
+
\begin{array}{ll}
|
|
100
|
+
\text{minimize} & (1/2) z^T P z + q^T z \\
|
|
101
|
+
\text{subject to} & z \geq 0,
|
|
102
|
+
\end{array}
|
|
103
|
+
$$
|
|
82
104
|
|
|
83
|
-
where
|
|
84
|
-
|
|
85
|
-
|
|
105
|
+
where $z \in \mathbf{R}^n$ is the optimization variable, $P$ is a fixed symmetric positive
|
|
106
|
+
semidefinite matrix, and the parameter $q$ ranges over the box $[-1, 1]^n$. Starting from
|
|
107
|
+
$z^0 = 0$, each iteration takes a gradient step with step size $\eta$ and projects onto the
|
|
108
|
+
nonnegative orthant,
|
|
109
|
+
|
|
110
|
+
$$
|
|
111
|
+
z^{k+1} = \Pi_{\mathbf{R}^n_+}\left(z^k - \eta(Pz^k + q)\right),
|
|
112
|
+
$$
|
|
113
|
+
|
|
114
|
+
and FOMTools computes the worst-case fixed-point residual $`\|z^K - z^{K-1}\|_\infty`$ over all
|
|
115
|
+
$q \in [-1, 1]^n$.
|
|
86
116
|
|
|
87
117
|
```python3
|
|
88
118
|
import numpy as np
|
|
89
119
|
import fomtools as ft
|
|
90
120
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
eta = 1 / np.linalg.norm(D, 2) ** 2
|
|
95
|
-
|
|
96
|
-
VP = ft.Verifier() # MIP verification with HiGHS; use solver="gurobi" for Gurobi
|
|
121
|
+
K, n, eta = 5, 3, 0.01
|
|
122
|
+
A = np.random.default_rng(0).normal(size=(n, n))
|
|
123
|
+
P = A @ A.T
|
|
97
124
|
|
|
98
|
-
#
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
w, beta = s[0], 1.0
|
|
125
|
+
vp = ft.Verifier() # HiGHS by default; solver="gurobi" for Gurobi
|
|
126
|
+
q = vp.parameter(n, lb=-1, ub=1) # q in [-1, 1]^n
|
|
127
|
+
z = vp.iterate(n, lb=0, ub=0) # z^0 = 0
|
|
102
128
|
|
|
103
|
-
results = []
|
|
104
129
|
for k in range(K):
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
# Worst-case residual after k + 1 iterations
|
|
111
|
-
VP.set_objective_norm(s[k + 1] - s[k], np.inf)
|
|
112
|
-
results.append(VP.solve())
|
|
130
|
+
z_prev, z = z, vp.relu(z - eta * (P @ z + q))
|
|
131
|
+
|
|
132
|
+
vp.maximize(ft.norm(z - z_prev, np.inf))
|
|
133
|
+
print("worst-case residual:", vp.solve())
|
|
134
|
+
print("worst-case q:", q.value)
|
|
113
135
|
```
|
|
114
136
|
|
|
115
137
|
Steps can also be written with proximal operators and projections, e.g.,
|
|
116
|
-
`
|
|
117
|
-
[documentation](https://github.
|
|
138
|
+
`vp.prox(NormL1(lambd), v, eta)` or `vp.project(Box(l, u), v)`. See the
|
|
139
|
+
[documentation](https://stellatogrp.github.io/fomtools/) for the full list of proxable functions and sets.
|
|
118
140
|
|
|
119
141
|
## Beyond worst-case verification
|
|
120
142
|
|
|
121
143
|
**Simulation.** Write the same loop with `ft.Verifier(method="simulator")`, and give
|
|
122
|
-
parameters sample arrays of shape `(N, d)
|
|
144
|
+
parameters sample arrays of shape `(N, d)`, as in `vp.parameter(d, samples=X)`. The
|
|
123
145
|
simulator runs all samples as batched operations, on a GPU through CuPy when one is
|
|
124
146
|
available. It then reports summary statistics and a KL-inverse bound on the probability that
|
|
125
147
|
the residual exceeds a tolerance `epsilon`:
|
|
126
148
|
|
|
127
149
|
```python3
|
|
128
|
-
|
|
129
|
-
|
|
150
|
+
vp.solve(epsilon=1e-3)
|
|
151
|
+
vp["quantiles"][0.95], vp["risk_bound"], vp["throughput"]
|
|
130
152
|
```
|
|
131
153
|
|
|
132
|
-
**Code generation.**
|
|
133
|
-
specialized solver together with a Python wrapper:
|
|
154
|
+
**Code generation.** Keep the iterates in a list and pass them, unchanged, to `codegen`.
|
|
155
|
+
It produces a specialized solver together with a Python wrapper:
|
|
134
156
|
|
|
135
157
|
```python3
|
|
136
|
-
|
|
158
|
+
z = [vp.iterate(n, lb=0, ub=0)]
|
|
159
|
+
for k in range(K):
|
|
160
|
+
z.append(vp.relu(z[-1] - eta * (P @ z[-1] + q)))
|
|
161
|
+
|
|
162
|
+
result = vp.codegen("out/pgd", iterates=z, code_optimization=True)
|
|
137
163
|
```
|
|
138
164
|
|
|
139
165
|
Targets include embedded C, multicore CPUs (OpenMP), and GPUs (CUDA). The package works with
|
|
@@ -174,11 +200,26 @@ Optional extras:
|
|
|
174
200
|
| `codegen` | LLM coding-agent backends for code generation |
|
|
175
201
|
| `cvxpygen` | CVXPYgen integration |
|
|
176
202
|
| `nn` | Neural-network verification (PyTorch, JAX, Flax) |
|
|
203
|
+
| `all` | All of the above (GPU packages skipped on macOS) |
|
|
177
204
|
| `dev` | Development tools |
|
|
178
205
|
| `docs` | Documentation build dependencies |
|
|
179
206
|
|
|
180
207
|
For example, `pip install "fomtools[gurobi,codegen]"`, or
|
|
181
|
-
`pip install -e ".[gurobi,codegen]"` from source.
|
|
208
|
+
`pip install -e ".[gurobi,codegen]"` from source. Use `pip install "fomtools[all]"`
|
|
209
|
+
to install every optional feature.
|
|
210
|
+
|
|
211
|
+
### Agent skill
|
|
212
|
+
|
|
213
|
+
FOMTools ships an [Agent Skill](https://agentskills.io/) in
|
|
214
|
+
[`skills/fomtools`](skills/fomtools/SKILL.md) that teaches coding agents (Claude
|
|
215
|
+
Code, Codex, Cursor, and others) the FOMTools API. Install it with the
|
|
216
|
+
[`skills` CLI](https://github.com/vercel-labs/skills) (requires Node.js):
|
|
217
|
+
|
|
218
|
+
```bash
|
|
219
|
+
npx skills add stellatogrp/fomtools -g
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
See [Get started](https://stellatogrp.github.io/fomtools/get_started/) for details.
|
|
182
223
|
|
|
183
224
|
FOMTools is not a solver. It relies on mathematical programming solvers such as
|
|
184
225
|
[HiGHS](https://highs.dev) (the default) and [Gurobi](https://www.gurobi.com) to solve
|
|
@@ -186,9 +227,14 @@ the verification problems it builds.
|
|
|
186
227
|
|
|
187
228
|
## Examples
|
|
188
229
|
|
|
189
|
-
The [tutorials](https://github.
|
|
190
|
-
network optimization, optimal control, and portfolio rebalancing.
|
|
191
|
-
|
|
230
|
+
The [tutorials](https://stellatogrp.github.io/fomtools/tutorials/) cover sparse coding (Lasso), nonnegative least squares,
|
|
231
|
+
network optimization, optimal control, and portfolio rebalancing.
|
|
232
|
+
|
|
233
|
+
## Benchmarks
|
|
234
|
+
|
|
235
|
+
The benchmarks and the code to reproduce the experiments in our
|
|
236
|
+
[paper](https://arxiv.org/abs/2610.26743) (verification, simulation, and code generation on
|
|
237
|
+
CPU and GPU) are in a separate repository,
|
|
192
238
|
[stellatogrp/fomtools_experiments](https://github.com/stellatogrp/fomtools_experiments).
|
|
193
239
|
|
|
194
240
|
## Contributing
|
|
@@ -215,3 +261,6 @@ If you use FOMTools for published work, we encourage you to cite our
|
|
|
215
261
|
year = {2026},
|
|
216
262
|
}
|
|
217
263
|
```
|
|
264
|
+
|
|
265
|
+
The mixed-integer verification method is described in
|
|
266
|
+
[Exact Verification of First-Order Methods via Mixed-Integer Linear Programming](https://arxiv.org/abs/2412.11330).
|
|
@@ -1,8 +1,20 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
<h1>
|
|
2
|
+
<picture>
|
|
3
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/stellatogrp/fomtools/main/docs/assets/logo/logo-dark.svg">
|
|
4
|
+
<img alt="FOMTools" src="https://raw.githubusercontent.com/stellatogrp/fomtools/main/docs/assets/logo/logo.svg" height="72">
|
|
5
|
+
</picture>
|
|
6
|
+
</h1>
|
|
7
|
+
|
|
8
|
+
[](https://pypi.org/project/fomtools/)
|
|
9
|
+
[](https://stellatogrp.github.io/fomtools/)
|
|
3
10
|
|
|
4
11
|
**Development, analysis, and code generation for first-order methods.**
|
|
5
12
|
|
|
13
|
+
[Documentation](https://stellatogrp.github.io/fomtools/) |
|
|
14
|
+
[PyPI](https://pypi.org/project/fomtools/) |
|
|
15
|
+
[Paper](https://arxiv.org/abs/2610.26743) |
|
|
16
|
+
[Benchmarks](https://github.com/stellatogrp/fomtools_experiments)
|
|
17
|
+
|
|
6
18
|
FOMTools is an open-source Python package for developing, analyzing, and deploying
|
|
7
19
|
first-order methods for parametric linear and convex quadratic optimization. You write the
|
|
8
20
|
iteration in Python, with syntax close to its mathematical description, and FOMTools records
|
|
@@ -21,65 +33,73 @@ you can:
|
|
|
21
33
|
|
|
22
34
|
## Example
|
|
23
35
|
|
|
24
|
-
The following code verifies
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
36
|
+
The following code verifies projected gradient descent on the parametric quadratic program
|
|
37
|
+
|
|
38
|
+
$$
|
|
39
|
+
\begin{array}{ll}
|
|
40
|
+
\text{minimize} & (1/2) z^T P z + q^T z \\
|
|
41
|
+
\text{subject to} & z \geq 0,
|
|
42
|
+
\end{array}
|
|
43
|
+
$$
|
|
28
44
|
|
|
29
|
-
where
|
|
30
|
-
|
|
31
|
-
|
|
45
|
+
where $z \in \mathbf{R}^n$ is the optimization variable, $P$ is a fixed symmetric positive
|
|
46
|
+
semidefinite matrix, and the parameter $q$ ranges over the box $[-1, 1]^n$. Starting from
|
|
47
|
+
$z^0 = 0$, each iteration takes a gradient step with step size $\eta$ and projects onto the
|
|
48
|
+
nonnegative orthant,
|
|
49
|
+
|
|
50
|
+
$$
|
|
51
|
+
z^{k+1} = \Pi_{\mathbf{R}^n_+}\left(z^k - \eta(Pz^k + q)\right),
|
|
52
|
+
$$
|
|
53
|
+
|
|
54
|
+
and FOMTools computes the worst-case fixed-point residual $`\|z^K - z^{K-1}\|_\infty`$ over all
|
|
55
|
+
$q \in [-1, 1]^n$.
|
|
32
56
|
|
|
33
57
|
```python3
|
|
34
58
|
import numpy as np
|
|
35
59
|
import fomtools as ft
|
|
36
60
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
eta = 1 / np.linalg.norm(D, 2) ** 2
|
|
41
|
-
|
|
42
|
-
VP = ft.Verifier() # MIP verification with HiGHS; use solver="gurobi" for Gurobi
|
|
61
|
+
K, n, eta = 5, 3, 0.01
|
|
62
|
+
A = np.random.default_rng(0).normal(size=(n, n))
|
|
63
|
+
P = A @ A.T
|
|
43
64
|
|
|
44
|
-
#
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
w, beta = s[0], 1.0
|
|
65
|
+
vp = ft.Verifier() # HiGHS by default; solver="gurobi" for Gurobi
|
|
66
|
+
q = vp.parameter(n, lb=-1, ub=1) # q in [-1, 1]^n
|
|
67
|
+
z = vp.iterate(n, lb=0, ub=0) # z^0 = 0
|
|
48
68
|
|
|
49
|
-
results = []
|
|
50
69
|
for k in range(K):
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
# Worst-case residual after k + 1 iterations
|
|
57
|
-
VP.set_objective_norm(s[k + 1] - s[k], np.inf)
|
|
58
|
-
results.append(VP.solve())
|
|
70
|
+
z_prev, z = z, vp.relu(z - eta * (P @ z + q))
|
|
71
|
+
|
|
72
|
+
vp.maximize(ft.norm(z - z_prev, np.inf))
|
|
73
|
+
print("worst-case residual:", vp.solve())
|
|
74
|
+
print("worst-case q:", q.value)
|
|
59
75
|
```
|
|
60
76
|
|
|
61
77
|
Steps can also be written with proximal operators and projections, e.g.,
|
|
62
|
-
`
|
|
63
|
-
[documentation](https://github.
|
|
78
|
+
`vp.prox(NormL1(lambd), v, eta)` or `vp.project(Box(l, u), v)`. See the
|
|
79
|
+
[documentation](https://stellatogrp.github.io/fomtools/) for the full list of proxable functions and sets.
|
|
64
80
|
|
|
65
81
|
## Beyond worst-case verification
|
|
66
82
|
|
|
67
83
|
**Simulation.** Write the same loop with `ft.Verifier(method="simulator")`, and give
|
|
68
|
-
parameters sample arrays of shape `(N, d)
|
|
84
|
+
parameters sample arrays of shape `(N, d)`, as in `vp.parameter(d, samples=X)`. The
|
|
69
85
|
simulator runs all samples as batched operations, on a GPU through CuPy when one is
|
|
70
86
|
available. It then reports summary statistics and a KL-inverse bound on the probability that
|
|
71
87
|
the residual exceeds a tolerance `epsilon`:
|
|
72
88
|
|
|
73
89
|
```python3
|
|
74
|
-
|
|
75
|
-
|
|
90
|
+
vp.solve(epsilon=1e-3)
|
|
91
|
+
vp["quantiles"][0.95], vp["risk_bound"], vp["throughput"]
|
|
76
92
|
```
|
|
77
93
|
|
|
78
|
-
**Code generation.**
|
|
79
|
-
specialized solver together with a Python wrapper:
|
|
94
|
+
**Code generation.** Keep the iterates in a list and pass them, unchanged, to `codegen`.
|
|
95
|
+
It produces a specialized solver together with a Python wrapper:
|
|
80
96
|
|
|
81
97
|
```python3
|
|
82
|
-
|
|
98
|
+
z = [vp.iterate(n, lb=0, ub=0)]
|
|
99
|
+
for k in range(K):
|
|
100
|
+
z.append(vp.relu(z[-1] - eta * (P @ z[-1] + q)))
|
|
101
|
+
|
|
102
|
+
result = vp.codegen("out/pgd", iterates=z, code_optimization=True)
|
|
83
103
|
```
|
|
84
104
|
|
|
85
105
|
Targets include embedded C, multicore CPUs (OpenMP), and GPUs (CUDA). The package works with
|
|
@@ -120,11 +140,26 @@ Optional extras:
|
|
|
120
140
|
| `codegen` | LLM coding-agent backends for code generation |
|
|
121
141
|
| `cvxpygen` | CVXPYgen integration |
|
|
122
142
|
| `nn` | Neural-network verification (PyTorch, JAX, Flax) |
|
|
143
|
+
| `all` | All of the above (GPU packages skipped on macOS) |
|
|
123
144
|
| `dev` | Development tools |
|
|
124
145
|
| `docs` | Documentation build dependencies |
|
|
125
146
|
|
|
126
147
|
For example, `pip install "fomtools[gurobi,codegen]"`, or
|
|
127
|
-
`pip install -e ".[gurobi,codegen]"` from source.
|
|
148
|
+
`pip install -e ".[gurobi,codegen]"` from source. Use `pip install "fomtools[all]"`
|
|
149
|
+
to install every optional feature.
|
|
150
|
+
|
|
151
|
+
### Agent skill
|
|
152
|
+
|
|
153
|
+
FOMTools ships an [Agent Skill](https://agentskills.io/) in
|
|
154
|
+
[`skills/fomtools`](skills/fomtools/SKILL.md) that teaches coding agents (Claude
|
|
155
|
+
Code, Codex, Cursor, and others) the FOMTools API. Install it with the
|
|
156
|
+
[`skills` CLI](https://github.com/vercel-labs/skills) (requires Node.js):
|
|
157
|
+
|
|
158
|
+
```bash
|
|
159
|
+
npx skills add stellatogrp/fomtools -g
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
See [Get started](https://stellatogrp.github.io/fomtools/get_started/) for details.
|
|
128
163
|
|
|
129
164
|
FOMTools is not a solver. It relies on mathematical programming solvers such as
|
|
130
165
|
[HiGHS](https://highs.dev) (the default) and [Gurobi](https://www.gurobi.com) to solve
|
|
@@ -132,9 +167,14 @@ the verification problems it builds.
|
|
|
132
167
|
|
|
133
168
|
## Examples
|
|
134
169
|
|
|
135
|
-
The [tutorials](https://github.
|
|
136
|
-
network optimization, optimal control, and portfolio rebalancing.
|
|
137
|
-
|
|
170
|
+
The [tutorials](https://stellatogrp.github.io/fomtools/tutorials/) cover sparse coding (Lasso), nonnegative least squares,
|
|
171
|
+
network optimization, optimal control, and portfolio rebalancing.
|
|
172
|
+
|
|
173
|
+
## Benchmarks
|
|
174
|
+
|
|
175
|
+
The benchmarks and the code to reproduce the experiments in our
|
|
176
|
+
[paper](https://arxiv.org/abs/2610.26743) (verification, simulation, and code generation on
|
|
177
|
+
CPU and GPU) are in a separate repository,
|
|
138
178
|
[stellatogrp/fomtools_experiments](https://github.com/stellatogrp/fomtools_experiments).
|
|
139
179
|
|
|
140
180
|
## Contributing
|
|
@@ -161,3 +201,6 @@ If you use FOMTools for published work, we encourage you to cite our
|
|
|
161
201
|
year = {2026},
|
|
162
202
|
}
|
|
163
203
|
```
|
|
204
|
+
|
|
205
|
+
The mixed-integer verification method is described in
|
|
206
|
+
[Exact Verification of First-Order Methods via Mixed-Integer Linear Programming](https://arxiv.org/abs/2412.11330).
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Canonicalizers
|
|
2
|
+
|
|
3
|
+
Canonicalizers translate a verification problem into a solver-ready formulation
|
|
4
|
+
(MIP or SDP), including optimization-based bound tightening (OBBT).
|
|
5
|
+
|
|
6
|
+
::: fomtools.canonicalizers.Canonicalizer
|
|
7
|
+
|
|
8
|
+
## MIP canonicalizer
|
|
9
|
+
|
|
10
|
+
::: fomtools.canonicalizers.mip
|
|
11
|
+
options:
|
|
12
|
+
show_root_heading: false
|
|
13
|
+
show_root_toc_entry: false
|
|
14
|
+
heading_level: 3
|
|
15
|
+
|
|
16
|
+
## OBBT handler
|
|
17
|
+
|
|
18
|
+
::: fomtools.canonicalizers.obbt_handler
|
|
19
|
+
options:
|
|
20
|
+
show_root_heading: false
|
|
21
|
+
show_root_toc_entry: false
|
|
22
|
+
heading_level: 3
|
|
23
|
+
|
|
24
|
+
## Simulator
|
|
25
|
+
|
|
26
|
+
::: fomtools.canonicalizers.simulator
|
|
27
|
+
options:
|
|
28
|
+
show_root_heading: false
|
|
29
|
+
show_root_toc_entry: false
|
|
30
|
+
heading_level: 3
|
|
31
|
+
|
|
32
|
+
## SDP canonicalizer
|
|
33
|
+
|
|
34
|
+
::: fomtools.canonicalizers.sdp
|
|
35
|
+
options:
|
|
36
|
+
show_root_heading: false
|
|
37
|
+
show_root_toc_entry: false
|
|
38
|
+
heading_level: 3
|
|
@@ -5,6 +5,10 @@ methods, plus a tiny Python wrapper. An LLM coding agent translates each step of
|
|
|
5
5
|
the algorithm into the target language and iterates against a Python reference
|
|
6
6
|
oracle until the generated code is numerically verified.
|
|
7
7
|
|
|
8
|
+
The [code generation guide](../user_guide/codegen.md) is the narrative reference for
|
|
9
|
+
the symbols below, and the [tutorials](../tutorials/codegen.md) work through five
|
|
10
|
+
complete examples.
|
|
11
|
+
|
|
8
12
|
::: fomtools.codegen.generate_code
|
|
9
13
|
|
|
10
14
|
::: fomtools.codegen.CodegenConfig
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Constraints
|
|
2
|
+
|
|
3
|
+
Constraints are equalities and inequalities over linear expressions, used to
|
|
4
|
+
encode assumptions on the problem data and the initial conditions.
|
|
5
|
+
|
|
6
|
+
::: fomtools.constraint.Constraint
|
|
7
|
+
::: fomtools.constraint.EqualityConstraint
|
|
8
|
+
::: fomtools.constraint.InequalityConstraint
|
|
9
|
+
|
|
10
|
+
## Objective atoms
|
|
11
|
+
|
|
12
|
+
`ft.norm` and `ft.sum_squares` build the objective passed to
|
|
13
|
+
[`Verifier.maximize`](verifier.md#fomtools.Verifier.maximize), for example
|
|
14
|
+
`vp.maximize(ft.norm(z - z_prev, np.inf))`.
|
|
15
|
+
|
|
16
|
+
::: fomtools.constraint.norm
|
|
17
|
+
::: fomtools.constraint.sum_squares
|