Skip to main content

Graduate Visit Scheduler

Docs Latest Docs Stable CI codecov Open In Colab

MILP-based scheduling utilities for graduate visit days. Created by Alex Dowling and Jeff Kantor at the University of Notre Dame.

Motivation

Most chemical engineering graduate programs in the U.S. host admitted or prospective students for a visit or open house. A core part of those events is one-on-one or small-group meetings with individual faculty members. Building a fair, feasible schedule is challenging: faculty availability, room locations, and student preferences must all be respected simultaneously.

This package is the meeting scheduler used by Notre Dame Chemical and Biomolecular Engineering, released as a general-purpose, open-source tool. Under the hood, it formulates a mixed-integer linear program (MILP) in Pyomo, solves it with a standard solver, visualizes the results, and can export customized student schedules to DOCX.

Data Gathering

Each visitor is asked to rank up to four faculty members for meetings and to choose up to two topic areas within the department. Likewise, faculty are asked to provide any afternoon meeting conflicts. This information is used to generate three key input files:

  • A faculty catalog YAML file (names, buildings, rooms, areas, status, and optional aliases).
  • A run configuration YAML file (time slots by building, breaks, area weights, and any faculty availability constraints).
  • A visitor preferences CSV file.

Research areas are department-specific. In the included example data, they are represented as simple labels such as Area1 and Area2, but you can define any set of areas in your faculty catalog. Time slots should be written with explicit AM/PM labels or 24-hour times such as 1:00 PM-1:25 PM or 13:00-13:25. Bare labels like 1:00-1:25 still work via a visit-day heuristic, but they emit a warning because they are ambiguous.

What It Produces

  • An optimal assignment of visitors to faculty across time slots.
  • Visual summaries (plots) of the resulting schedule.
  • Optional DOCX exports with individualized visitor schedules.

Install

pip install grad-visitor-scheduler

Solver setup:

  • HiGHS is installed by default via the highspy dependency.
  • To use CBC, install the solver binary with conda:
conda install -c conda-forge coincbc

CI and Coverage

GitHub Actions runs the test suite on pushes to main and on pull requests targeting main. Coverage is uploaded to Codecov from the Python 3.11 job. For this public repository, coverage upload uses GitHub OIDC (no CODECOV_TOKEN secret required).

Automated PyPI Releases

Releases are tag-driven via GitHub Actions:

  • Push a semantic version tag like v0.2.0.
  • Workflow .github/workflows/release.yml runs tests, builds sdist/wheel, and checks package metadata.
  • Package is published to TestPyPI first.
  • CI performs a smoke install of that exact tagged version from TestPyPI.
  • If smoke install passes, CI publishes the same artifact to PyPI.

Publishing uses PyPI Trusted Publishing (OIDC), so no API token secret is required. Configure both PyPI and TestPyPI trusted publishers to point to this repository and the release.yml workflow file. Detailed release instructions are in docs/releasing.md.

Manual release workflow runs are also supported (workflow_dispatch):

  • target=testpypi: build, publish to TestPyPI, smoke install, stop.
  • target=pypi: run the full pipeline (TestPyPI + smoke + PyPI publish).
  • Optional version input lets smoke install pin a specific version.

Quickstart

from pathlib import Path
from grad_visit_scheduler import scheduler_from_configs, Solver

root = Path("examples")

s = scheduler_from_configs(
    root / "faculty_formulation.yaml",
    root / "config_two_buildings_close.yaml",
    root / "data_formulation_visitors.csv",
    solver=Solver.HIGHS,
)

sol = s.schedule_visitors(
    group_penalty=0.2,
    min_visitors=2,
    max_visitors=8,
    min_faculty=1,
    max_group=2,
    faculty_breaks=1,
    student_breaks=1,
    tee=False,
    run_name="demo",
)

if sol is not None:
    sol.plot_visitor_schedule(save_files=True, show_solution_rank=False)
    sol.plot_faculty_schedule(save_files=True, show_solution_rank=False)
    sol.export_visitor_docx("visitor_schedule.docx")
else:
    print(s.infeasibility_report())

Note: the examples/ folder referenced above is included in the repository, but it is not packaged on PyPI. If you installed from PyPI, clone the repo to access the example files.

All shipped example configs now use explicit AM/PM slot labels to avoid ambiguity warnings.

Buildings and Movement

Notre Dame CBE is split across two buildings (Nieuwland Science Hall and McCourtney Hall) separated by about a 7-minute walk. A key aspect of the scheduler is to ensure that any visitor who needs to move buildings does so during their break slot. A typical schedule uses six meeting slots, and each visitor and faculty member gets at least one middle-slot break.

The run config now supports one, two, or many buildings. building_order controls plotting/export ordering. Movement behavior is configured with the movement section:

  • movement.policy: none: close-proximity buildings; no explicit travel-time constraints.
  • movement.policy: travel_time: explicit inter-building travel-time lag constraints.
  • movement.policy: nonoverlap_time: auto-derive inter-building lag constraints from absolute slot timestamps.
  • movement.phase_slot: earliest slot allowed by building (for staggered starts like Building A first vs Building B first).
  • movement.travel_slots: auto: auto-derive lag matrix under travel_time for shifted/nonuniform clocks.

Important shifted-clock note: if buildings have offset time grids, policy: none can allow real-time overlaps across adjacent slot indices. Prefer policy: nonoverlap_time (or policy: travel_time with travel_slots: auto) for those schedules.

Legacy Mode.* options are still available with FutureWarning.

See docs/movement.md and scripts/run_building_configuration_examples.py for full examples. For common configuration mistakes and fixes, see the Failure Modes and Diagnostics section in docs/movement.md.

Refine the Schedule

The solver exposes several tunable parameters on schedule_visitors to refine the schedule:

  • group_penalty: penalize group meetings to bias toward one-on-one meetings; higher values discourage multi-visitor meetings.
  • min_visitors: minimum number of visitors each available faculty member must meet.
  • max_visitors: maximum number of visitors each faculty member may meet.
  • min_faculty: minimum number of faculty each visitor must meet.
  • max_group: maximum size of a meeting group at any time slot.
  • faculty_breaks: minimum automatic faculty breaks. Faculty-unavailable slots outside the break window count toward this total.
  • student_breaks: minimum automatic visitor breaks within the configured break-option slots.
  • enforce_breaks: legacy compatibility alias for setting both counts to 0 or 1 together.
  • debug_infeasible: if True, build the model before raising pre-solve contradiction errors (useful for IIS/manual inspection of s.model).
  • tee: print solver output for debugging.
  • run_name: label used when saving plots/exports.

For advanced hard constraints, per-entity bounds, pre-solve checks, and debug infeasibility workflows, see docs/advanced_customization.md.

To generate multiple ranked schedules, use no-good cuts:

top = s.schedule_visitors_top_n(n_solutions=3, faculty_breaks=2, student_breaks=1)
report = top.summarize(ranks_to_plot=(1, 2), show_solution_rank=True)
print(report["summary"])
print(report["compact"])

Export DOCX

Preferred modern path:

sol = s.schedule_visitors(...)
if sol is not None:
    sol.export_visitor_docx("visitor_schedule.docx")

Legacy helper grad_visit_scheduler.export_visitor_docx(...) remains available for compatibility but emits FutureWarning.

License

This software is released under the BSD-3-Clause license. Please adapt it to your needs and share.

Metadata

Release files for grad-visitor-scheduler 0.5.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for grad-visitor-scheduler 0.5.0
File Size Uploaded
grad_visitor_scheduler-0.5.0.tar.gz 63.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for grad-visitor-scheduler 0.5.0
File Interpreter ABI Platform
grad_visitor_scheduler-0.5.0-py3-none-any.whl Python 3 none any Details

Total release size: 100.2 kB

Release files / grad_visitor_scheduler-0.5.0.tar.gz

Download URL grad_visitor_scheduler-0.5.0.tar.gz
Size 63.7 kB
Tags Source
SHA-256 checksum
How to use checksums
a51f551f03d928ef383b741a9fb7cf3ccb0736dcb92249391a46a1d826f1dd4b
BLAKE2b-256 checksum
How to use checksums
43de9cd682031f5672f767ba8282cc37222cd51fb7ab8c90bae2c431093bde36
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Mar 11, 2026.

Transparency log

Release files / grad_visitor_scheduler-0.5.0-py3-none-any.whl

Download URL grad_visitor_scheduler-0.5.0-py3-none-any.whl
Size 36.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
f8b4b5959f31a0bb4d9bbf46031911753473b572a4f830623290894d99bec877
BLAKE2b-256 checksum
How to use checksums
59d4526ec8ce195ab1859f9da95d254fdc5893826d26158024fb9b4e907ba5bb
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Mar 11, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.5.0 This release

2 release files

0.4.0

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.2

2 release files

0.1.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page