← Back to the notebook

Engineering · Optimization

When scheduling becomes mathematics

Building a CP-SAT engine: human rules, mathematical constraints, and a decision that stays with the person using it.

It was more than a calendar

A finished roster looks straightforward: names assigned to dates and shifts. Getting there is the hard part. Filling one shift today can remove the only feasible option for tomorrow.

Conditionals help validate individual situations. Finding an assignment that satisfies all the rules together requires a different approach. That is where Google OR-Tools and its CP-SAT solver entered the project.

Turning rules into variables

The solver receives a model: decision variables, constraints, and an objective. Each eligible person–slot combination can be represented by a Boolean variable. Each slot must have exactly one assignment.

Schedule conflicts, hour limits, and other conditions constrain the available combinations. The solver searches across the whole model. It does not learn from previous rosters; it solves the mathematical problem we define.

Domain logic comes first

If domain rules already exclude a person from a slot, creating a variable for that combination adds no value. Deterministic filtering reduces the search space and makes ineligibility easier to explain.

It also separates testing concerns. Eligibility is domain logic; the mathematical formulation can be checked with small, controlled inputs. Data, filtering, and model errors become easier to distinguish.

Feasible does not mean optimal

An assignment can meet every constraint and still distribute work poorly. The objective must express what balance means in that domain, accounting for different availability and limits.

Depending on the problem and time limit, CP-SAT may find a feasible solution or prove optimality for the model. Promising an optimal roster every time would be misleading.

Making infeasibility useful

INFEASIBLE can be mathematically correct and still leave a user with no clear next step. Diagnosing infeasibility is therefore part of the product.

Candidate counts and exclusion reasons provide useful operational clues. A relaxed scenario can explore possible compromises, provided it is clearly distinguished from a strictly valid solution.

A suggestion, not a verdict

The engine produces editable suggestions. A person reviews and confirms assignments. Mathematics cannot eliminate recent information or exceptions that are absent from the model.

OR-Tools runs locally in a Python and FastAPI backend. React and TypeScript support configuration and review, with MySQL and asynchronous SQLAlchemy for persistence.

The hardest part was explaining

Calling the solver was only part of the work. Translating human rules, distinguishing hard constraints from flexible ones, and explaining missing solutions required more care.

Reliability depends on the whole system: backend, data, interface, and human review. A mathematical model becomes useful when its decisions can be understood.

Diagnostique screenshots