Changelog — heusor (Python)¶
Before 1.0, a minor version may contain breaking changes; a patch version may not.
0.1.0 — 2026-10-25¶
First release: a constraint solver for planning and scheduling, driven from Python. Your problem is ordinary dataclasses; your rules are constraint streams of lambdas, compiled once when the problem is built — no Python runs while the solver searches.
Modelling
- @problem_fact, @planning_entity, @planning_solution dataclasses.
- PlanningVariable (optionally allows_unassigned=True),
PlanningListVariable for ordered lists such as routes, PlanningPin.
- Shadows on list elements: InverseRelationShadow, PreviousElementShadow,
NextElementShadow, IndexShadow, CascadingShadow(fn) (e.g. arrival
times).
- Field types: int, bool, str, Enum, datetime, date, time,
timedelta, fact classes, and list / set of those.
- Scores: SimpleScore, HardSoftScore, HardMediumSoftScore.
Constraints
- for_each, for_each_including_unassigned, for_each_unique_pair,
filter, join, if_exists, if_not_exists, flatten_last.
- group_by on one to four keys, with count, sum, min, max,
count_distinct; complement; load_balance for fairness.
- Joiners: equal, less_than, less_than_or_equal, greater_than,
greater_than_or_equal, overlapping.
- penalize / reward with a per-match weight. A negative weight is refused
(constraint.negative_weight) rather than silently turning a penalty into a
reward.
- A lambda the compiler cannot translate fails when the problem is built,
naming the file, the line and the construct.
Solving and explaining
- heusor.solve(…, time_limit=…, step_limit=…, seed=…); step_limit with a
seed is reproducible.
- cancel=heusor.Cancel() from another thread; on_progress=… callbacks.
- heusor.config_for(…) shows the exact configuration a solve would use.
- heusor.score(…): the score, each constraint's share, and which objects
each constraint's matches involve (indictments, blame).
- Every error is a heusor.HeusorError with a stable code.
Platforms: Python ≥ 3.11 (one abi3 wheel per platform): Linux x86-64
(glibc ≥ 2.17), macOS arm64, Windows x86-64 — each built, installed and run in
CI, with the seeded determinism scores reproduced on all three. Linux aarch64
is left out of 0.1.0: its wheel was built but never run.
Known limits: see Current limits in the README — no three-way joins, no
group_by after a join or after a group_by (except load_balance),
lambdas must be defined in a file.