Built on unifier
schedulr is the domain layer of a three-crate solver stack. It compiles scheduling concepts into unifier's constraint model and keeps the solver internals out of its public API.
The stack
pathwise → unifier → schedulr → (application: timetabling, appointment booking, ...)
- pathwise provides generic search and optimisation traits and strategies.
- unifier is a constraint satisfaction and optimisation (CSP/COP) framework: integer variables with domains, constraints, weighted objectives and several solvers. Its source is at github.com/casoon/unifier.
- schedulr adds the scheduling vocabulary on top: activities, resources, participants, calendars, preferences, conflicts.
schedulr depends on unifier and nothing else: the 0.14.0 release on unifier 0.6, 0.10.0 to
0.13.0 on unifier 0.5, the 0.9.0 release on unifier 0.4, the 0.8.0 release on unifier 0.3.1.
What schedulr compiles into
compile walks the SchedulingProblem and builds a unifier model with its ModelBuilder:
| schedulr | unifier |
|---|---|
Activity with window and duration |
an interval: start and end variables, fixed duration |
Resource with capacity 1 |
NoOverlap over the activities using it |
Resource with capacity above 1 |
Cumulative over the activities using it |
Participant |
a resource with capacity 1 |
| flexible requirement (type, pool, candidates) | one presence variable per candidate, ExactlyOne of them, plus schedulr’s own AlternativeResourceCapacity constraint per candidate |
ScheduleTemplate |
a PeriodicValues restriction on each start |
| unavailable ranges | ForbiddenValues on the start, optional per candidate |
SameStart, Consecutive |
Equal on start/start or end/start |
Precedence { min_gap } |
Precedence |
FixedOffset { offset } |
Equal on the two starts, shifted by offset |
NoOverlap relation |
NoOverlap over the two intervals |
ScoreRule |
a scored objective on its level |
Participant groups are expanded to their members before this step, so unifier only ever sees individual participants.
Solvers
schedulr picks the solver per call:
solve()without score rules or goals: a construction phase only — a short run of unifier’sBacktrackingSolver; if that finds nothing, a greedy placement that unifier’sLocalSearchSolverrepairs until the hard constraints hold.solve()with score rules or goals: the same construction, then, by default, unifier’sParallelSolverfor the rest of the budget (SolveStrategy::ConstructThenOptimizeusesBranchAndBoundSolverinstead).repair(): unifier’sLnsSolver, started from the baseline.SchedulingStateandevaluate_move: no solver, only unifier’s incremental check of the constraints adjacent to the changed variables.
What stays hidden
Apart from CancellationToken, which schedulr re-exports from unifier, no unifier type appears
in schedulr’s public API. Variables, constraint ids and unifier’s
violation structs are mapped back to ActivityId, ResourceId, ParticipantId and the names
you gave, so a Conflict can be shown to users directly. If you need constraints schedulr does
not model, work with unifier directly; the unifier documentation
describes its model and solvers.