A constraint solver for generating schedules
Project description
Course Constraint Scheduler
A powerful constraint satisfaction solver for generating academic course schedules using the Z3 theorem prover.
Overview
The Course Constraint Scheduler is designed to solve complex academic scheduling problems by modeling them as constraint satisfaction problems. It can handle:
- Faculty Constraints: Availability, credit limits, course preferences
- Room Constraints: Room assignments, lab requirements, capacity limits
- Time Constraints: Time slot conflicts, meeting patterns, duration requirements
- Course Constraints: Prerequisites, conflicts, section limits
- Optimization: Multiple optimization strategies for better schedules
Features
- Z3 Integration: Uses Microsoft's Z3 theorem prover for efficient constraint solving
- Flexible Configuration: JSON-based configuration with comprehensive validation
- Multiple Output Formats: JSON and CSV output support with type-safe serialization
- REST API: Full HTTP API for integration with web applications
- Asynchronous Processing: Background schedule generation for large problems
- Session Management: Persistent sessions for iterative schedule generation
- Optimization Flags: Configurable optimization strategies
- Type Safety: Comprehensive TypedDict definitions for all JSON structures
- Enhanced Validation: Cross-reference validation and business logic constraints
- Improved Error Handling: Detailed error messages for configuration debugging
- Strict Type Validation: Pydantic models with strict validation and custom type definitions
- Computed Fields: Automatic serialization with computed fields for clean JSON output
Quick Start
Requires a minimum version of Python 3.12
Installation
pip install course-constraint-scheduler
Command Line Usage
# Generate schedules from configuration file
scheduler example.json --limit 10 --format json --output schedules
# Interactive mode
scheduler example.json --limit 5
Python API
from scheduler import (
Scheduler,
load_config_from_file,
)
from scheduler.config import CombinedConfig
# Load configuration
config = load_config_from_file(CombinedConfig, "example.json")
# Create scheduler
scheduler = Scheduler(config)
# Generate schedules
for schedule in scheduler.get_models():
print("Schedule:")
for course in schedule:
print(f"{course.as_csv()}")
Note on naming: scheduler.config defines Course as a course-id string type alias (used in JSON config). scheduler.models defines a Course class representing a course with credits and meetings. Schedules from get_models() yield CourseInstance objects whose .course attribute is the models Course; use .course.course_id to get the config-style course id.
REST API
# Start the server with custom options
scheduler-server --port 8000 --host 0.0.0.0 --log-level info --workers 16
# Submit a schedule request
curl -X POST "http://localhost:8000/submit" \
-H "Content-Type: application/json" \
-d @example.json
# Get the next schedule
curl -X POST "http://localhost:8000/schedules/{schedule_id}/next"
# Check generation progress
curl -X GET "http://localhost:8000/schedules/{schedule_id}/count"
Server deployment and security
The REST API is convenient for local use and trusted integrations. For production or internet-facing deployments:
- No built-in authentication — use a reverse proxy, API gateway, or private network; do not expose the process directly without controls you trust.
- In-memory sessions — active schedule sessions are lost on restart and are not shared across multiple server processes.
- CORS — set the
CORS_ORIGINSenvironment variable to a comma-separated list of allowed origins when browsers must send credentials. If unset, the server allows all origins without credentials (typical for local development).
See SECURITY.md for how to report vulnerabilities.
Documentation
Published docs (configuration, Python API, REST API, development): https://mucsci-scheduler.docs.buildwithfern.com
CI publishes this site on pushes to main that touch fern/, scripts/, or src/scheduler/ (see .github/workflows/docs.yml). The repository needs a FERN_TOKEN Actions secret from the Fern CLI (fern token) or dashboard.
Local REST API (OpenAPI UI)
scheduler-server
# open http://localhost:8000/docs/ in a web browser
The /submit request body matches CombinedConfig (same JSON as the CLI and Python API).
Local Fern preview
With Node.js and dev dependencies installed:
npm install -g fern-api
uv run python scripts/export_openapi.py
uv run python scripts/export_config_schema.py
uv run python scripts/gen_python_api_mdx.py
fern docs dev
Configuration quick link
A short pointer to the new docs location: docs/configuration.md.
Configuration
The scheduler uses a JSON configuration file that defines:
- Rooms and Labs: Available facilities and their constraints
- Courses: Course requirements, conflicts, and faculty assignments
- Faculty: Availability, preferences, and teaching constraints
- Time Slots: Available time blocks and class patterns
- Optimization: Flags for different optimization strategies
Example configuration:
{
"config": {
"rooms": ["Room A", "Room B"],
"labs": ["Lab 1"],
"courses": [
{
"course_id": "CS101",
"credits": 3,
"room": ["Room A"],
"lab": ["Lab 1"],
"conflicts": [],
"faculty": ["Dr. Smith"]
}
],
"faculty": [
{
"name": "Dr. Smith",
"maximum_credits": 12,
"minimum_credits": 6,
"unique_course_limit": 3,
"times": {
"MON": ["09:00-17:00"],
"TUE": ["09:00-17:00"],
"WED": ["09:00-17:00"],
"THU": ["09:00-17:00"],
"FRI": ["09:00-17:00"]
}
}
]
},
"time_slot_config": {
"times": {
"MON": [
{
"start": "09:00",
"spacing": 60,
"end": "17:00"
}
]
},
"classes": [
{
"credits": 3,
"meetings": [
{
"day": "MON",
"duration": 150,
"lab": false
}
]
}
]
},
"limit": 10,
"optimizer_flags": ["faculty_course", "pack_rooms"]
}
Architecture
The scheduler is built with a modular architecture:
- Core Solver: Z3-based constraint satisfaction engine
- Configuration Management: Pydantic-based configuration validation with comprehensive error handling
- Model Classes: Enhanced data structures for courses, faculty, and time slots with improved serialization
- JSON Types: Comprehensive TypedDict definitions for type-safe JSON handling
- Output Writers: JSON and CSV output formatters with context manager support
- REST Server: FastAPI-based HTTP API with asynchronous processing and session management
- Session Management: Persistent session handling for large problems with background task support
Performance
- Small Problems (< 10 courses): Near-instantaneous solving
- Medium Problems (10-50 courses): Seconds to minutes
- Large Problems (50+ courses): May take several minutes
- Optimization: Use appropriate optimizer flags to reduce solving time
Development
Setup
# Clone the repository
git clone <repository-url>
cd course-constraint-scheduler
# Install dependencies (includes dev tools via uv default-groups; see pyproject.toml)
uv sync
# Run tests
uv run pytest
# Run linting
uv run ruff check .
Using pip without optional extras: dev dependencies are declared under [dependency-groups] in pyproject.toml. Either use uv as above, or add a matching [project.optional-dependencies] dev group if you need pip install -e ".[dev]".
Logging
The scheduler does not configure logging on import. The CLI (scheduler) and HTTP server (scheduler-server) call configure_logging() at startup. When embedding the scheduler as a library, configure logging in your application (e.g. logging.basicConfig(...)) before using the scheduler.
Project Structure
tests/ # Pytest suite
src/scheduler/
├── __init__.py # Main package exports with all types
├── config.py # Configuration models with strict validation and type definitions
├── json_types.py # TypedDict definitions for JSON structures
├── logging.py # Logging setup
├── main.py # Command-line interface
├── scheduler.py # Core scheduling logic with Z3 integration
├── server.py # REST API server with session management
├── time_slot_generator.py # Utility for generating valid time slots
├── models/ # Enhanced data models
│ ├── __init__.py # Model exports
│ ├── course.py # Course and instance models with computed fields
│ ├── day.py # Day enumeration (IntEnum)
│ └── time_slot.py # Time-related models with comprehensive methods
└── writers/ # Output formatters
├── __init__.py # Writer exports
├── csv_writer.py # CSV output with context manager support
└── json_writer.py # JSON output with context manager support
Contributing
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests for new functionality
- Ensure all tests pass
- Submit a pull request
License
This project is licensed under the MIT License - see the LICENSE file for details.
Support
For questions, issues, or feature requests:
- Check the documentation
- Review existing issues
- Create a new issue with detailed information
- Include configuration examples and error messages
Recent Updates
Enhanced Configuration Validation
- Comprehensive cross-reference validation ensures all IDs exist
- Business logic validation prevents impossible constraints
- Detailed error messages for easier debugging
- Support for preference scores (0-10) with improved validation
Improved Type Safety
- New
json_types.pymodule with comprehensive TypedDict definitions - Type-safe JSON handling throughout the application
- Enhanced serialization with computed fields
- Better integration with modern Python type checking
Enhanced REST API
- Improved session management with background task support
- Better error handling and status codes
- Enhanced command-line options for server configuration
- Comprehensive API documentation with examples
Model Improvements
- Enhanced Course and TimeSlot models with better methods
- Improved serialization with computed fields
- Better time handling with IntEnum for days
- Context manager support for writers
Roadmap
- Web-based configuration interface
- Schedule visualization tools
- Multi-objective optimization support
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file course_constraint_scheduler-2.6.2.tar.gz.
File metadata
- Download URL: course_constraint_scheduler-2.6.2.tar.gz
- Upload date:
- Size: 168.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4c7b5a622001a85ecd8cc72c08ca117f8ff4a827f8355f748c59949854171411
|
|
| MD5 |
ef76f80b4b82dcdab084d51573623062
|
|
| BLAKE2b-256 |
c01c7f544e2c446d0ce861df7c534d9a0aab22a5d9e5ce248c9781ab6ada6102
|
Provenance
The following attestation bundles were made for course_constraint_scheduler-2.6.2.tar.gz:
Publisher:
publish.yml on mucsci/Scheduler
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
course_constraint_scheduler-2.6.2.tar.gz -
Subject digest:
4c7b5a622001a85ecd8cc72c08ca117f8ff4a827f8355f748c59949854171411 - Sigstore transparency entry: 1153605109
- Sigstore integration time:
-
Permalink:
mucsci/Scheduler@db2ece6fe44d7b27f0de51d4783e9a7e93486df4 -
Branch / Tag:
refs/tags/2.6.2 - Owner: https://github.com/mucsci
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@db2ece6fe44d7b27f0de51d4783e9a7e93486df4 -
Trigger Event:
push
-
Statement type:
File details
Details for the file course_constraint_scheduler-2.6.2-py3-none-any.whl.
File metadata
- Download URL: course_constraint_scheduler-2.6.2-py3-none-any.whl
- Upload date:
- Size: 38.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6d94e57f3b55c3b6828693c4ce952cca4466c9a39bbf41756b635c93e647aa56
|
|
| MD5 |
93c7505236130bf7370cc08019c36b28
|
|
| BLAKE2b-256 |
c7df2913d70851c130cd10c3795dce461d659c466e47d52b8ec9a1bb42cae322
|
Provenance
The following attestation bundles were made for course_constraint_scheduler-2.6.2-py3-none-any.whl:
Publisher:
publish.yml on mucsci/Scheduler
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
course_constraint_scheduler-2.6.2-py3-none-any.whl -
Subject digest:
6d94e57f3b55c3b6828693c4ce952cca4466c9a39bbf41756b635c93e647aa56 - Sigstore transparency entry: 1153605186
- Sigstore integration time:
-
Permalink:
mucsci/Scheduler@db2ece6fe44d7b27f0de51d4783e9a7e93486df4 -
Branch / Tag:
refs/tags/2.6.2 - Owner: https://github.com/mucsci
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@db2ece6fe44d7b27f0de51d4783e9a7e93486df4 -
Trigger Event:
push
-
Statement type: