Solver as a Service
Sign Up Now →Sign Up Now

Milestone 1: the smallest useful retail rota

Preview

Our first question is intentionally small:

Who covers each shift?

The decision model names the entity collection (staff) and the group collection (shifts). The one rule requires at least one placement in each shift. At this milestone, the model does not understand skills, time, hours, availability, or preferences.

domain: RetailRostering
problem_type: my_rota
version: "0.1"
description: "Minimum retail shift coverage tutorial"

decision:
  entities:
    source: staff
    identity: id
  groups:
    source: shifts
    identity: id
  domain:
    total_over_entities: false
    total_over_groups: true

search:
  acceptor: simulated_annealing

constraints:
  staffed:
    name: "Every shift is covered"
    description: "At least one employee must be assigned to every shift."
    type: hard
    default_enabled: true
    contract: aggregate
    parameters:
      collect: count
      compare: ">="
      limit: 1

The manifest says what the problem means. The records say what this instance contains:

{
  "staff": [
    {"id": "alice"},
    {"id": "ben"}
  ],
  "shifts": [
    {"id": "mon-open"},
    {"id": "mon-close"}
  ]
}

Run the same contract directly in Python while developing the model:

from pathlib import Path
import yaml

from helixor_solvers.manifest_solver import solve_from_manifest

manifest = yaml.safe_load(Path("retail_rota.yaml").read_text())
problem = {
    "staff": [{"id": "alice"}, {"id": "ben"}],
    "shifts": [{"id": "mon-open"}, {"id": "mon-close"}],
}

result = solve_from_manifest(manifest, problem, problem_type="my_rota")
assert result["is_feasible"] is True
assert result["unevaluable_rules"] == []
print(result["placements"])
print(result["admission"])

The important result is not only the placement list. It is the admission certificate. A plan that cannot say which declared rules were evaluated is not a trustworthy answer.

What the first model does not mean#

It may assign one employee to both shifts. That is correct for the manifest we wrote: no rule forbids it. When an answer surprises you, ask which missing business statement would make it wrong, then add that statement through a shared contract. Do not patch the returned assignment in application code.