schedulr
Scheduling framework (activity/resource/interval DSL) for Rust, built
on unifier's CSP/COP constraint
model and solvers, which in turn build on
pathwise's generic search and
optimization traits.
pathwise → unifier → schedulr → (application: timetabling, appointment booking, ...)
Status
Version 0.8 is implemented. It provides:
- domain-neutral
Resource,Participant,Activity,Assignment,Score, and structuredConflicttypes without exposing solver internals; - synchronous create/move/cancel/participant-update checks through
SchedulingState, including self-exclusion when moving an activity; - resource matching by type, capacity and feature, named resource and participant pools, and hierarchical/overlapping participant groups;
- periodic slot calendars with absolute exceptions and lexicographic Strong/Medium/Weak score components;
compile→solveplusanalyze,evaluate_move,suggest,compare,explain, and baseline-awarerepairpaths.
The single-activity path evaluates only constraints affected by the proposed change and does not start a solver search. Persistence remains an application concern; solutions carry score components so applications can store them with their immutable schedule versions.
Problem class
Scheduling / timetabling / appointment booking on top of unifier's
CSP/COP model: activities placed against resources over time, subject
to hard constraints (no double-booking, capacity, precedence,
calendar/opening-hours exclusions) and soft preferences (e.g.
proximity to a requested time slot).
Usage
Synchronous single-activity checks (e.g. a live booking desk), via
SchedulingState — no solver search, only the constraints touching the
proposed activity are evaluated:
use ;
let mut state = new;
let proposal = new
.with_requirement
.with_participant;
// Blocking conflicts (e.g. room double-booked) prevent commit; advisory
// conflicts (e.g. a participant already booked elsewhere) do not.
let activity_id = state.commit.expect;
// Moving an activity excludes its own prior booking from the check via
// `excluding`, so it does not conflict with itself:
let moved = new
.with_requirement
.with_participant
.excluding;
state.commit.expect;
Batch scheduling with a minimal compile → solve → explain path for
hard resource conflicts:
use ;
let room = new;
let first = new
.with_requirement;
let second = new
.with_requirement;
let compiled = compile
.expect;
let result = compiled.solve;
if result.status != Feasible
Installation
= "0.8"
License
MIT — see LICENSE.