Repository navigation
Configure SMT solvers in solvers.toml, generated by configure-solvers - #55
Conversation
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
|
I was also thinking about swapping everything to configs - we can even extend these configs to full synthesis configs (all milq.py arguments prepared in .toml), gate-set defining + presets, setting custom portfolio of solvers. One open question is whether it would be useful to somehow nest configs -- e.g. portfolio.toml denotes some solvers of the portfolio manually, and some other solvers are added by referring to another config (this would also be useful for the full synthesis configs, which can refer to a gate-set config, solver config etc.) |
good point, I'm still vibe-coding the basic functionality, we can build on top of that - changed to draft PR for now |
2fbc2bc to
3cfdc5c
Compare
The paths and command-line arguments of the SMT solvers were hard-coded in Synthesizer.add_solvers. They now come from solvers.toml in the repository root (or --solver-config FILE / $MILQ_SOLVER_CONFIG), which also lists the logics each solver supports and whether the portfolio runs it. A solver added to the file can be selected with -a NAME. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0177AhE9SXm3iJ1KP8GTSk6o
pySMT keeps generic solvers registered for the whole process, so a second pySMT synthesis in one process failed with SolverRedefinitionError. An identical registration is now reused, and one with another command or logics gives a SolverConfigError. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0177AhE9SXm3iJ1KP8GTSk6o
Selecting dreal switched the formula to QF_NRA. That only mattered for FiveTuple (Classic is QF_NRA already), where the encoding then failed with "rescaling with wrong logic". solvers.toml already lists QF_NRA as dReal's only logic, so -a dreal -c FiveTuple now reports that dReal does not support QF_LIA. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0177AhE9SXm3iJ1KP8GTSk6o
On Python 3.14, multiprocessing starts processes with forkserver by default, and pySMT's portfolio processes then lack the generic solvers registered from solvers.toml. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0177AhE9SXm3iJ1KP8GTSk6o
The repository no longer ships SMT solver binaries (solvers/, about 100 MB of yices2, cvc5, OpenSMT, SMTInterpol and z3alpha builds from SMT-COMP), and solvers.toml is no longer tracked. ./configure-solvers writes it instead: it looks for yices-smt2 (or yices_smt2), cvc5, opensmt, smtinterpol, z3 and dreal on PATH (dReal also in /opt/dreal), in directories given with -s, and keeps each one that answers sat to a trivial formula of its first logic, so e.g. SMTInterpol without Java is left out. The arguments and logics of each solver are those of the old solvers.toml. Without the file, milq names the script. The pySMT portfolio ran a hard-coded list of solvers; it now runs only those that are configured (z3 is pySMT's own). The tests generate their own configuration the same way and pass it through MILQ_SOLVER_CONFIG, so they neither read nor change the user's solvers.toml. CI installs yices2 2.6.5 and cvc5 1.3.1 from their releases. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0177AhE9SXm3iJ1KP8GTSk6o
--download downloads the release binaries of yices2 2.7.0, cvc5 1.3.1 and OpenSMT 2.9.2 for this platform from GitHub into solvers/ (not tracked), checks them against the sha256 GitHub reports, and links the executables into solvers/bin, where configure-solvers looks (after the --search directories, before PATH). --download yices2,cvc5 downloads only those, --download-dir keeps them elsewhere, and a solver that is already downloaded is kept. SMTInterpol and dReal have no release binaries to download. CI uses it instead of fetching yices2 and cvc5 itself, so the tests run with OpenSMT too. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0177AhE9SXm3iJ1KP8GTSk6o
b10cd24 to
441add4
Compare
With yices2 2.7.0, which configure-solvers --download now gets, the test hung CI: in the incremental search, yices2 2.7.0 does not answer the depth-1 query of the GHZ2 fidelity encoding within minutes. 2.6.5 answers it in about a second, but only after the depth-0 query; on the depth-1 query alone it does not answer within a minute either, so it was luck. z3 and cvc5 take well under a second on the same session. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0177AhE9SXm3iJ1KP8GTSk6o
The download URLs, versions and sha256 sums were a separate table in solver_download.py, keyed by platform. They are now part of each KnownSolver in solver_detection.py (releases, by platform), next to the executable names, arguments and logics, so everything about a solver is in one place. solver_download.py keeps only the downloading; a download links the solver's first executable name. The releases are unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0177AhE9SXm3iJ1KP8GTSk6o
The SMT solvers' paths and command-line arguments were hard-coded in
Synthesizer.add_solvers, and the repository shipped about 100 MB of solver binaries insolvers/. Now:solvers.toml;./configure-solverswrites that file for the solvers installed on the computer;./configure-solvers --downloadfirst downloads some of them.Neither the binaries nor
solvers.tomlare tracked any more.Solver configuration (
solvers.toml)src/solver_config.pyloads and validates the file. Unknown keys, wrong types, unknown logics, a missing file and invalid TOML each give aSolverConfigErrorthat names the file and table. If the default file is missing, the error tells you to runconfigure-solvers.--solver-config FILE(CLI) orsolver_config=(Python) wins over theMILQ_SOLVER_CONFIGenvironment variable, which wins oversolvers.tomlin the repository root.-a NAMEaccepts any configured solver, so adding a solver needs no code change.portfolio,gurobiandcbcare reserved names.milq: error: ...and exit code 2:SolverConfigErrorinstead.drealused to switch FiveTuple formulas to QF_NRA, which made the encoding fail with "rescaling with wrong logic". Now-a dreal -c FiveTuplereports that dReal does not support QF_LIA../configure-solversyices-smt2/yices_smt2,cvc5,opensmt,smtinterpol,z3anddreal, in this order of places:-s DIRdirectories;PATH;/opt/dreal/*/bin.satto a trivial formula of its first logic. For example, SMTInterpol without Java is reported and left out.solvers.toml. SMTInterpol has no QF_NRA, as decided in Don't register SMTInterpol for QF_NRA #100.-o FILEwrites another file, and-o -prints to standard output;--forceis given.--download [yices2,cvc5,opensmt]first downloads release binaries from GitHub intosolvers/(gitignored):solvers/bin;Tests and CI
MILQ_SOLVER_CONFIG, so they don't depend on the user'ssolvers.toml.tests/test_solver_config.pycovers loading, file precedence, validation, custom solvers, the portfolio, pySMT and the CLI;tests/test_solver_detection.pyandtests/test_solver_download.pycover detection and downloads. They use fake solvers and localfile://archives, so they need no network../configure-solvers --download -o -before the tests, so it runs them with yices2, cvc5, OpenSMT and z3.Docs
docs/installation.mdhas a new solver table with install links and a "Solver configuration" section coveringconfigure-solversand--download. The README,docs/reference.mdanddocs/index.mdare updated too.🤖 Generated with Claude Code
https://claude.ai/code/session_0177AhE9SXm3iJ1KP8GTSk6o