solver-support
A generic, domain-agnostic pipeline for running constraint-modelling and planning solvers: Conjure / Savile Row (driving a SAT solver, Minion, OR-Tools CP-SAT, Gecode or Chuffed), Fast Downward, SymK, ENHSP, and UPF-constructed models. It handles the mechanics that every such run needs — building solver command lines from a model registry, spawning subprocesses with timeouts and clean teardown, naming the per-run files, parsing solver output into a uniform timing / cost-layer model, and driving the horizon (increasing-difficulty) loop.
It carries no notion of any particular problem domain or objective. A consumer supplies:
- its own model registry (a
models.yaml) via a config path — the loader is generic, the model content is the consumer's; - its scoring / objective strategy via injection — the core reports the raw objective a solver emits and lets the consumer interpret it (is-this-an- optimisation-model, how to read the objective, any reporting multiplier).
Status
Beta. The pipeline is in day-to-day use by several consumers and is covered
by its own test suite. The injection seams and the run-summary vocabulary
(outcome, stop_reason, verdict) are stable: later releases add to them
rather than rename them. Other API may still shift between 0.x releases. Each
release's changes are listed on the
releases page.
The package ships unwired, by design and on every release: a bare
import solver_support gives a pipeline that resolves no model registry and
interprets no objective, because it has no way to guess either. Constructing a
ModelRegistry raises rather than falling back on a guess. A consumer
registers its scoring, registry paths, warning logger and UPF CLI once, before
first use — see Usage.
Installation
pip install solver-support
Requires Python 3.9 or newer (3.9.6 is the system Python on macOS, and is
supported deliberately — each release is built and tested against it). The only
runtime dependencies are psutil and PyYAML.
Quick start
The package ships no model registry, but it carries a commented starter one (Conjure, Savile Row, Fast Downward, SymK and ENHSP) to copy and edit. Writing it out does not wire it; you point the registry at it:
from pathlib import Path
from solver_support import (
write_starter_config, set_default_config_path, set_resource_root,
global_state, SolverRunner, FastDownwardSolver, fd_backstop,
)
config = write_starter_config("config/models.yaml") # once; then edit it
set_default_config_path(config)
set_resource_root(".") # where the models' `path:` entries resolve
registry = global_state.model_registry
runner = SolverRunner(instance="p01", model="pddl", solver="fd", timeout=60,
timestamp="run1", summary_file=Path("p01.json"))
try:
plan = FastDownwardSolver(runner).solve(
Path("p01.pddl"), model_path=str(registry.get_model_path("pddl")),
watchdog=fd_backstop(60)) # let the planner's own limit fire
status = "done" if plan else "failed"
except TimeoutError:
status = "timeout"
runner.finalize_summary(status, proves_unsat=registry.get_proves_unsat("pddl"))
print(runner.summary.outcome) # solved / unsat / unknown / error
Usage
See docs/injection-api.md
for the four injection points a consumer wires — model-registry paths, objective
extraction, warning logger, UPF CLI — with a worked example.
Docs
injection-api.md— the four seams a consumer wires.solver-runner.md— running a solver as a subprocess:SolverResult, timeout vs duration, phases.timing-model.md— how solver timing is recorded, how the backends map onto one shape, and the invariants parsers rely on.
Development
To work on this package, clone and install it editable:
git clone https://github.com/ott2/solver-support
pip install -e solver-support
Consumers pin a released version from PyPI rather than the working tree, so a change here reaches them only when it is released. To try an unreleased change against a consumer, install this editable into that consumer's environment deliberately — it is not the default arrangement.
Tests
pytest tests/ — the core's own suite, and the home for solver-level
development. It runs against solver_support alone: no consumer need be
installed, and none is imported.
Since the core ships unwired, a test that needs a seam wired wires a stand-in
(tests/conftest.py):
| fixture | supplies |
|---|---|
fixture_registry |
a ModelRegistry over tests/fixtures/models.yaml, this suite's own synthetic config — never a consumer's |
wired_stdout_score |
a consumer-style Score: N extractor, so a score reaches solver_stats |
wired_timeout_score |
a consumer-style extractor for a salvaged timeout solution |
Wiring a fixture config rather than mocking the registry keeps the real loader
and accessors in the path. Anything a test needs from the registry goes in
tests/fixtures/models.yaml, keeping its shape faithful to a real consumer
config — that shape is the contract the loader implements.
Licence
BSD-3-Clause — see
LICENSE.
By András Salamon, with Claude Opus 4.8, 5 and 5.5.
Metadata
Release files for solver-support 0.4.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| solver_support-0.4.1.tar.gz | 153.8 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| solver_support-0.4.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 247.1 kB
Release files / solver_support-0.4.1.tar.gz
| Download URL | solver_support-0.4.1.tar.gz |
|---|---|
| Size | 153.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
399ed852e06991900f7d9f1a65bb992c86a43452dec955940c8df14a32293288
|
|
BLAKE2b-256 checksum How to use checksums |
3f6824963be4111ea8396140952eebdcb4f86574138d9653965cae9d49f98f81
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.7
|
Release files / solver_support-0.4.1-py3-none-any.whl
| Download URL | solver_support-0.4.1-py3-none-any.whl |
|---|---|
| Size | 93.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
20570c114aa85cae2be246f17271708b6170ebbc40fe750d165ec9b3601cb926
|
|
BLAKE2b-256 checksum How to use checksums |
0c28a7e3a4d50d40a8f2c0bb4f634b2da3fa7eb43257e5f1d1b4ff5ccc01a77f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.7
|
Security for solver-support 0.4.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.