Metadata-Version: 2.4
Name: solver-support
Version: 0.3.2
Summary: Generic Conjure / Savile Row / Fast Downward / SymK / ENHSP / UPF solver pipeline
Author: András Salamon
License-Expression: BSD-3-Clause
Project-URL: Homepage, https://github.com/ott2/solver-support
Project-URL: Repository, https://github.com/ott2/solver-support
Project-URL: Issues, https://github.com/ott2/solver-support/issues
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: psutil>=5.8.0
Requires-Dist: PyYAML>=5.4
Dynamic: license-file

# 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

**Alpha.** The pipeline is in day-to-day use by several consumers and is covered
by its own test suite, but the API may still shift between 0.x releases. Each
release's changes are listed on the
[releases page](https://github.com/ott2/solver-support/releases).

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](#usage).

## Installation

```bash
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`.

## Usage

See [`docs/injection-api.md`](https://github.com/ott2/solver-support/blob/main/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`](https://github.com/ott2/solver-support/blob/main/docs/injection-api.md)
  — the four seams a consumer wires.
- [`solver-runner.md`](https://github.com/ott2/solver-support/blob/main/docs/solver-runner.md)
  — running a solver as a subprocess: `SolverResult`, timeout vs duration, phases.
- [`timing-model.md`](https://github.com/ott2/solver-support/blob/main/docs/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:

```bash
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`](https://github.com/ott2/solver-support/blob/main/LICENSE).

By András Salamon, with Claude Opus 4.8 and 5.
