trellis-runner
Trellis
Trellis is a generic execution engine for iterative numerical algorithms.
Rather than implementing optimisation loops, integration loops or search loops directly, a procedure describes a single iteration of an algorithm while Trellis manages execution, convergence, termination, observation and checkpointing.
The library separates the concerns of:
- algorithm implementation (
Procedure) - problem definition (the problem supplied to the procedure)
- algorithm state (
UserState) - execution control (policies)
- instrumentation (observers)
This separation allows algorithms to focus solely on their numerical method, while Trellis provides a reusable execution framework.
Execution model
Every Trellis calculation follows the same execution model:
Problem
│
▼
┌───────────┐
│ Procedure │
└─────┬─────┘
│
updates state
│
▼
┌───────────┐
│ UserState │
└─────┬─────┘
│
emits Progress events
│
┌──────────┴──────────┐
▼ ▼
Engine Policies Observers
│
▼
Engine Actions
The principal abstractions are:
- Problem — the specific problem instance being solved.
- Procedure — performs a single iteration of the algorithm.
- UserState — stores the evolving state of the computation and reports progress.
- Policies — inspect progress and control execution.
- Observers — inspect progress without affecting execution.
A simple example
A calculation is configured using the builder returned by
[GenerateBuilder::build_for]:
use ;
;
;
let engine = Solver
.build_for
.with_initial_state
.and_policy
.and_policy
.finalise;
let result = engine.run;
The builder configures the execution environment rather than the numerical algorithm itself.
Procedures
A [Procedure] implements the numerical algorithm.
Each call to step() performs a single iteration of the algorithm, while
finalise() converts the final algorithm state into the value returned to the
caller.
Both infallible and fallible procedures are supported.
User state
[UserState] stores the evolving state of the computation.
In addition to algorithm-specific data, it reports progress to the engine via
[Progress], allowing policies and observers to monitor execution.
States implementing [Snapshotable] can additionally participate in
checkpointing, allowing long-running computations to be resumed.
Policies
Policies control solver execution.
During a run, the engine collects progress emitted by the procedure and passes it to one or more policies. Policies inspect this information and decide whether the solver should:
- continue running,
- terminate successfully,
- terminate early,
- request a checkpoint,
- or perform another engine action.
Policies influence execution.
Observers do not.
Progress ──► Policy ──► Engine Action
│
└────► Observer
Multiple policies may be attached simultaneously.
The engine stops as soon as any policy requests termination.
Custom policies can be created implementing the [EnginePolicy] trait.
Built-in policies
| Policy | Description |
|---|---|
MaxIterationPolicy |
Stops after a fixed number of iterations. |
TimeoutPolicy |
Stops after a maximum wall-clock duration. |
AbsoluteTolerancePolicy |
Stops when the mean absolute error over a rolling window falls below a tolerance. |
RelativeTolerancePolicy |
Stops when the mean relative error over a rolling window falls below a tolerance. |
TargetValuePolicy |
Stops when the mean distance to a target value remains below a tolerance. |
NoProgressPolicy |
Stops when no meaningful improvement has been observed for a specified number of iterations. |
StagnationPolicy |
Stops when improvement over a rolling window falls below a relative threshold. |
CheckpointPolicy |
Requests periodic checkpoint generation. |
Observers
Observers receive every event emitted by the engine but never influence execution.
Typical applications include:
- structured logging,
- tracing,
- CSV export,
- plotting,
- metrics collection,
- progress reporting,
- custom visualisation.
Checkpointing
User states implementing [Snapshotable] may be checkpointed during
execution.
Checkpoints may be requested by policies or generated manually, allowing interrupted computations to be resumed.
Extending Trellis
Trellis is designed to be extended through traits.
Most applications only need to implement:
- [
Procedure] to define the numerical algorithm, - [
UserState] to store algorithm state, - [
EnginePolicy] for custom stopping criteria, - [
Observe] for custom instrumentation.
These components compose naturally, allowing new algorithms, policies and observers to be combined without modifying the execution engine itself.
License: MIT