An open-source, constraint-based engine for generating school timetables.
Website: aldahir.dev/timetable
Timetable combines student groups, subjects, teachers, teaching teams, rooms, availability, and grouping rules to produce feasible weekly schedules. It is built with Python and Google OR-Tools CP-SAT.
The project is in pre-alpha development. Its current focus is a reusable, well-tested backend. A spreadsheet importer, REST API, and web interface are planned after the core model stabilizes.
Documentación en español: docs/es/README.md
School timetabling is not the same as choosing a personal course schedule. An institution must coordinate shared teachers, rooms, student groups, team teaching, fixed joint lessons, and groups that may combine differently across the week. Timetable models these as explicit constraints and verifies the generated solution independently.
- Individual course requirements.
- Fixed multi-group sessions.
- Flexible group combinations, including optional singleton sessions.
- Physical teachers and logical teaching teams.
- Teacher and room availability.
- Room conflict prevention.
- Consecutive multi-period sessions.
- Daily subject and teacher limits.
- Preferred starting slots as a soft objective.
- Independent input and output validation.
- Structured infeasibility diagnostics with conflicting requirement IDs.
- JSON input and JSON/CSV output.
- Deterministic solving with a configurable random seed.
The versioned input contract is documented in Problem format v0.1 and published as JSON Schema. See Infeasibility diagnostics when a model cannot be solved.
git clone https://github.com/aldahiiir/timetable.git
cd timetable
python -m venv .venv
source .venv/bin/activate
pip install -e '.[dev]'
timetable validate examples/basic_school/problem.json
timetable solve examples/basic_school/problem.json --output outputGenerated files:
output/
├── solution.json
├── sessions.csv
└── groups/
├── group_grade_7_a.csv
├── group_grade_7_b.csv
└── group_grade_7_c.csv
from timetable.io import load_problem
from timetable.solver import solve
from timetable.validation import validate_solution
problem = load_problem("examples/basic_school/problem.json")
solution = solve(problem, time_limit_seconds=60, random_seed=42)
assert not validate_solution(solution, problem)
print(solution.status, len(solution.sessions))src/timetable/
├── models.py Domain model
├── validation.py Pre-solve and post-solve validation
├── solver.py OR-Tools CP-SAT model
├── io.py JSON input and output
├── export.py Human-readable CSV exports
└── cli.py Command-line interface
- Generic domain language. The engine must not contain school names, country-specific grade assumptions, or special cases keyed by subject names.
- Hard constraints and preferences are different. Invalid schedules are rejected; preferences influence quality without hiding feasibility.
- Validate twice. Input is checked before solving, and output is verified independently from the optimization model.
- Privacy by default. Examples use fictional people and institutions. Real school data must never be committed.
- Backend first. The CLI, future API, and future web application all use the same core engine.
See ROADMAP.md. The first public preview will be tagged v0.1.0
when its data format and core constraint behavior are documented and tested.
The publication gates are tracked in docs/release-checklist.md.
Contributions are welcome. Read CONTRIBUTING.md and the Code of Conduct before opening a pull request.
Do not report exposed personal information in a public issue. Follow the private reporting instructions in SECURITY.md.
Licensed under the Apache License 2.0.