API Reference

The API pages below are generated from code docstrings.

Grad visit scheduling package.

class grad_visit_scheduler.Scheduler(times_by_building, student_data_filename, mode=None, movement=None, solver=Solver.HIGHS, include_legacy_faculty=False, faculty_catalog=None, faculty_aliases=None)[source]

Bases: object

Scheduler for assigning visitor-faculty meetings across time slots.

__init__(times_by_building, student_data_filename, mode=None, movement=None, solver=Solver.HIGHS, include_legacy_faculty=False, faculty_catalog=None, faculty_aliases=None)[source]

Initialize a scheduler with buildings, visitors, and faculty data.

Parameters:
  • times_by_building – Mapping of building names to ordered time-slot labels and optional "breaks" list.

  • student_data_filename – CSV file with visitor names and ranked preferences.

  • mode – Legacy building sequencing mode. Prefer movement.

  • movement – Optional movement configuration dictionary with keys: policy ("none", "travel_time", or "nonoverlap_time"), phase_slot (per-building earliest slot), and optional travel_slots (pairwise slot lags, or "auto" for timestamp- derived lags), plus optional min_buffer_minutes for auto lags.

  • solver – Solver backend used by schedule_visitors().

  • include_legacy_faculty – If True, include all legacy faculty entries from the catalog.

  • faculty_catalog – Optional faculty catalog dictionary. If omitted, a small default synthetic catalog is created.

  • faculty_aliases – Optional mapping of alias name to canonical faculty name.

_init_hard_constraint_state()[source]

Initialize user-defined hard-constraint storage.

Storage is set-based so rules are cumulative and naturally idempotent. Re-adding the same rule has no effect on model behavior.

_validate_visitor_name(visitor)[source]

Validate and return visitor name.

_validate_faculty_name(faculty)[source]

Validate and return faculty name.

_validate_slot_index(time_slot)[source]

Validate and return integer time-slot index.

_validate_slot_collection(slots)[source]

Validate optional slots iterable and return canonical tuple.

_validate_optional_nonnegative_int(value, field_name)[source]

Validate optional nonnegative integer and return normalized value.

_effective_visitor_bounds(visitor, global_min_faculty)[source]

Return effective (min_meetings, max_meetings) for one visitor.

_effective_faculty_bounds(faculty, global_min_visitors, global_max_visitors)[source]

Return effective (min_meetings, max_meetings) for one faculty.

_meeting_feasible_slots(visitor, faculty)[source]

Return slots where visitor/faculty meeting could occur before user hard constraints.

_required_specific_meeting_count(visitor, slots)[source]

Count required slot-specific meetings for visitor within given slots.

_check_break_contradictions_for_visitor(visitor)[source]

Raise if current required meetings violate any required-break hard constraint.

set_visitor_meeting_bounds(visitor, min_meetings=None, max_meetings=None)[source]

Set optional visitor-specific meeting-count bounds.

Parameters:
  • visitor – Visitor name from the loaded CSV.

  • min_meetings – Optional override for the visitor minimum meeting count. If None, the global min_faculty value is used.

  • max_meetings – Optional override for the visitor maximum meeting count. If None, no visitor-specific maximum is enforced.

Notes

Visitor-specific overrides take precedence over global bounds. Passing both arguments as None clears the visitor override and restores global-default behavior.

set_faculty_meeting_bounds(faculty, min_meetings=None, max_meetings=None)[source]

Set optional faculty-specific meeting-count bounds.

Parameters:
  • faculty – Faculty name from the active faculty catalog.

  • min_meetings – Optional override for the faculty minimum meeting count. If None, the global min_visitors value is used.

  • max_meetings – Optional override for the faculty maximum meeting count. If None, the global max_visitors value is used.

Notes

Faculty-specific overrides take precedence over global bounds. Passing both arguments as None clears the faculty override and restores global-default behavior.

forbid_meeting(visitor, faculty, time_slot=None)[source]

Hard-forbid a visitor/faculty meeting in one slot or all slots.

Parameters:
  • visitor – Visitor name from the loaded CSV.

  • faculty – Faculty name from the active faculty catalog.

  • time_slot – Optional slot index. If omitted, forbids this pair for all slots.

Raises:

ValueError – On unknown visitor/faculty, invalid slot index, or direct contradiction with previously required hard constraints.

require_meeting(visitor, faculty, time_slot=None)[source]

Hard-require a visitor/faculty meeting in one slot or exactly once overall.

Parameters:
  • visitor – Visitor name from the loaded CSV.

  • faculty – Faculty name from the active faculty catalog.

  • time_slot – Optional slot index. If omitted, enforces exactly one meeting for this visitor/faculty pair across all slots.

Raises:

ValueError – On unknown visitor/faculty, invalid slot index, infeasible slot availability, or direct contradiction with existing hard rules.

require_break(visitor, slots=None, min_breaks=1)[source]

Hard-require break slots for a visitor.

A break means the visitor has no assigned meeting in that slot.

Parameters:
  • visitor – Visitor name from the loaded CSV.

  • slots – Optional iterable of slot indices to consider. If omitted, all slots are considered.

  • min_breaks – Minimum number of break slots required within slots.

Raises:

ValueError – On unknown visitor, invalid slot indices, invalid min_breaks, or direct contradiction with existing slot-specific requirements.

_set_time_data(times_by_building)[source]

Validate building slot data and populate scheduling time metadata.

Parameters:

times_by_building – Mapping of building names to ordered slot labels, plus optional "breaks" key containing slot indices.

_configure_movement(mode, movement)[source]

Normalize movement configuration with legacy mode compatibility.

_warn_if_none_policy_real_time_overlap_risk()[source]

Warn when shifted building clocks can overlap across adjacent slots.

_normalize_break_count(value, name)[source]

Normalize a break-count argument into a nonnegative integer.

_resolve_break_requirements(enforce_breaks, faculty_breaks, student_breaks)[source]

Resolve explicit break counts plus legacy enforce_breaks alias.

_faculty_unavailable_nonbreak_count(faculty_name, break_options)[source]

Return unavailable faculty slots that already count as breaks outside break options.

_validate_required_faculty_breaks(required_faculty_breaks, break_options)[source]

Raise when the requested faculty break count cannot be satisfied.

_validate_required_student_breaks(required_student_breaks, break_options)[source]

Raise when the requested student break count cannot be satisfied.

_build_box_colors()[source]

Return a color map for configured buildings.

_load_student_preferences(filename)[source]

Load datafile with student preferences

_load_default_faculty_data()[source]

Load a minimal synthetic faculty catalog for default/demo usage.

_load_faculty_catalog(catalog)[source]

Load faculty entries from a user-provided catalog dictionary.

Parameters:

catalog – Mapping from faculty name to metadata fields.

_add_legacy_faculty_from_preferences(include_all=False)[source]

Merge legacy faculty into active scheduling set.

Parameters:

include_all – If True, include all legacy faculty regardless of requests.

_add_external_faculty_from_preferences()[source]

Create placeholder external faculty records from visitor requests.

add_external_faculty(name, building=None, room='', areas=None, available=None)[source]

Add or update an external faculty entry.

Parameters:
  • name – Faculty display name.

  • building – Building key. Defaults to building A.

  • room – Room label used in exports and plots.

  • areas – Optional list of research areas for area-based preference boosts.

  • available – Optional list of available time-slot indices.

_is_legacy_faculty(name)[source]

Return whether name belongs to the legacy faculty pool.

faculty_limited_availability(name, available)[source]

Set the available time slots for a faculty member.

Parameters:
  • name – Faculty name.

  • available – List of integer slot indices where meetings are allowed.

update_weights(faculty_weight={'Prof1': 4.0, 'Prof2': 3.0, 'Prof3': 2.0, 'Prof4': 1.0, 'Prof5': 0.5}, area_weight={'Area1': 1.0, 'Area2': 0.5}, base_weight=0.2)[source]

Set preference weights and rebuild visitor-faculty utility scores.

Parameters:
  • faculty_weight – Either a scalar applied to all ranked faculty columns, or a dict keyed by preference column names (for example Prof1).

  • area_weight – Either a scalar applied to all area columns, or a dict keyed by area column names (for example Area1).

  • base_weight – Baseline utility assigned to any feasible visitor-faculty match.

_update_student_preferences()[source]

Recompute utility weights for each visitor-faculty pair.

specify_limited_student_availability(students_available)[source]

Restrict availability for a subset of visitors.

Parameters:

students_available – Mapping of visitor name to allowed slot indices. Visitors not listed remain available for all time slots.

plot_preferences()[source]

Plot a heatmap of visitor-faculty utility weights.

Returns:

(fig, ax) matplotlib objects for further customization.

Return type:

tuple

schedule_visitors(group_penalty=0.1, min_visitors=0, max_visitors=8, min_faculty=0, max_group=2, enforce_breaks=None, faculty_breaks=0, student_breaks=0, debug_infeasible=False, tee=False, run_name='')[source]

Solve the mixed-integer scheduling model.

Parameters:
  • group_penalty – Utility penalty for adding a second (or later) visitor to the same faculty-time meeting.

  • min_visitors – Minimum total meetings per available faculty member.

  • max_visitors – Maximum total meetings per faculty member.

  • min_faculty – Minimum number of meetings required per visitor.

  • max_group – Maximum number of visitors allowed in a single faculty-time meeting.

  • enforce_breaks – Legacy compatibility alias. False maps to faculty_breaks=0, student_breaks=0 and True maps to faculty_breaks=1, student_breaks=1 when the explicit break arguments are left at zero.

  • faculty_breaks – Minimum number of automatic faculty breaks required per eligible faculty member. Faculty-unavailable slots outside the break window count toward this total.

  • student_breaks – Minimum number of automatic student breaks required within the configured break-option slots.

  • debug_infeasible – If False (default), run pre-solve consistency checks before model construction and fail fast on obvious contradictions. If True, build the model first, then run checks so advanced users can inspect self.model after a raised pre-solve error.

  • tee – If True, stream solver output.

  • run_name – Optional suffix for saved plot filenames.

Returns:

Snapshot of the solved schedule when a feasible solution is found. Returns None if the solve is infeasible or otherwise has no feasible assignment.

Return type:

SolutionResult | None

schedule_visitors_top_n(n_solutions=5, group_penalty=0.1, min_visitors=0, max_visitors=8, min_faculty=0, max_group=2, enforce_breaks=None, faculty_breaks=0, student_breaks=0, debug_infeasible=False, tee=False, run_name='')[source]

Solve for up to the best n_solutions unique schedules.

Uses no-good integer cuts over the full assignment vector y[s, f, t] so each returned solution differs from all previous solutions.

_build_model(group_penalty, min_visitors, max_visitors, min_faculty, max_group, enforce_breaks=None, faculty_breaks=0, student_breaks=0)[source]

Build the Pyomo MILP model for the current scheduler state.

Parameters:
  • group_penalty – Penalty applied to group meetings.

  • min_visitors – Minimum required meetings per available faculty member.

  • max_visitors – Maximum total meetings per faculty member.

  • min_faculty – Minimum required meetings per visitor.

  • max_group – Maximum number of visitors in a single faculty-time meeting.

  • enforce_breaks – Legacy compatibility alias for both break counts.

  • faculty_breaks – Automatic faculty break count.

  • student_breaks – Automatic student break count.

_collect_presolve_hard_constraint_issues(min_visitors, max_visitors, min_faculty, max_group)[source]

Return a list of obvious hard-constraint contradictions.

_run_presolve_hard_constraint_checks(min_visitors, max_visitors, min_faculty, max_group, raise_on_issue=True)[source]

Collect and optionally raise on obvious hard-constraint contradictions.

_solve_model(tee, record_results=True)[source]

Solve the currently built model with the configured solver backend.

Parameters:

tee – If True, stream solver output to stdout.

_build_solution_context()[source]

Build immutable metadata context for solution snapshots.

_snapshot_solution(rank)[source]

Capture the current solved model values as an immutable snapshot.

_add_no_good_cut(solution)[source]

Exclude an already-found binary assignment from future solves.

has_feasible_solution()[source]

Return True if the latest solver run was feasible or optimal.

infeasibility_report()[source]

Summarize likely causes when the model has no feasible solution.

current_solution()[source]

Return a rich snapshot for the currently loaded feasible model.

Returns:

Immutable snapshot of the currently loaded solved assignment.

Return type:

SolutionResult

Raises:

RuntimeError – If no feasible solution is currently loaded.

_current_solution_result()[source]

Backward-compatible alias for current_solution().

show_faculty_schedule(save_files=True, abbreviate_student_names=True, solution=None, show_solution_rank=False)[source]

Plot the solved schedule grouped by faculty.

Parameters:
  • save_files – If True, save faculty_schedule*.pdf and .png.

  • abbreviate_student_names – If True, shorten visitor names in labels.

  • solution – Optional SolutionResult to plot. If omitted, uses the most recently solved model on this scheduler.

  • show_solution_rank – If True and solution is provided, append solution rank to the figure title.

show_visitor_schedule(save_files=True, abbreviate_student_names=True, solution=None, show_solution_rank=False)[source]

Plot the solved schedule grouped by visitor.

Parameters:
  • save_files – If True, save visitor_schedule*.pdf and .png.

  • abbreviate_student_names – If True, shorten visitor names in y-axis labels.

  • solution – Optional SolutionResult to plot. If omitted, uses the most recently solved model on this scheduler.

  • show_solution_rank – If True and solution is provided, append solution rank to the figure title.

export_visitor_docx(filename, solution=None, **kwargs)[source]

Export solved visitor schedules to a DOCX file.

Parameters:
show_utility()[source]

Plot realized meetings and display total utility for a solved model.

check_requests()[source]

Print unmet requested faculty meetings and meeting-count distribution.

class grad_visit_scheduler.Mode(value)[source]

Bases: Enum

Building sequencing constraints for visitor movement.

BUILDING_A_FIRST = 1
BUILDING_B_FIRST = 2
NO_OFFSET = 3
class grad_visit_scheduler.MovementPolicy(value)[source]

Bases: Enum

Building movement policy for multi-building schedules.

NONE = 'none'
TRAVEL_TIME = 'travel_time'
NONOVERLAP_TIME = 'nonoverlap_time'
class grad_visit_scheduler.Solver(value)[source]

Bases: Enum

Supported optimization solver backends.

HIGHS = 1
CBC = 2
GUROBI = 3
GUROBI_IIS = 4
class grad_visit_scheduler.FacultyStatus(value)[source]

Bases: Enum

Faculty catalog status labels.

ACTIVE = 'active'
LEGACY = 'legacy'
EXTERNAL = 'external'
class grad_visit_scheduler.SolutionResult(rank, objective_value, termination_condition, solver_status, visitors, faculty, time_slots, active_meetings, context)[source]

Bases: object

Rich, self-contained representation of one solved schedule.

A SolutionResult is intentionally independent from the mutable Scheduler and Pyomo model state. It contains all assignment and metadata needed to:

  • inspect per-solution quality statistics,

  • produce schedule visualizations,

  • export visitor DOCX schedules,

  • serialize/pickle for later analysis.

Parameters:
  • rank (int) – 1-based rank in the top-N solve sequence.

  • objective_value (float) – Objective value for this ranked solution.

  • termination_condition (str) – Solver termination label (string form).

  • solver_status (str) – Solver status label (string form).

  • visitors (tuple[str, ...]) – Ordered visitor labels included in the solved model.

  • faculty (tuple[str, ...]) – Ordered faculty labels included in the solved model.

  • time_slots (tuple[int, ...]) – Ordered integer time-slot indices.

  • active_meetings (frozenset[tuple[str, str, int]]) – Set of active binary assignments (visitor, faculty, slot).

  • context (grad_visit_scheduler.core.SolutionContext) – Immutable rendering/reporting context copied from the scheduler at solve time (times, faculty metadata, colors, preferences, requests, etc.).

rank: int
objective_value: float
termination_condition: str
solver_status: str
visitors: tuple[str, ...]
faculty: tuple[str, ...]
time_slots: tuple[int, ...]
active_meetings: frozenset[tuple[str, str, int]]
context: SolutionContext
meeting_assigned(visitor, faculty, time_slot)[source]

Return whether the visitor/faculty/time assignment is active.

Parameters:
  • visitor (str)

  • faculty (str)

  • time_slot (int)

Return type:

bool

_meeting_sizes()[source]
summary_row(best_objective=None)[source]

Return one summary row dictionary for this solution.

_schedule_filename(base, include_rank=True, suffix='')[source]
Parameters:
  • base (str)

  • include_rank (bool)

  • suffix (str)

_show_building_labels()[source]

Return whether plot labels should include building names.

plot_faculty_schedule(save_files=True, abbreviate_student_names=True, show_solution_rank=False, include_rank_in_filename=True, fontsize=8, tight=False)[source]

Plot schedule grouped by faculty for this single solution.

plot_visitor_schedule(save_files=True, abbreviate_student_names=True, show_solution_rank=False, include_rank_in_filename=True, fontsize=8, tight=False)[source]

Plot schedule grouped by visitor for this single solution.

export_visitor_docx(filename, *, building=None, font_name='Arial', font_size_pt=11, include_breaks=True)[source]

Export this solution to a visitor schedule DOCX file.

Parameters:
  • building (str | None)

  • font_name (str)

  • font_size_pt (int)

  • include_breaks (bool)

__init__(rank, objective_value, termination_condition, solver_status, visitors, faculty, time_slots, active_meetings, context)
Parameters:
  • rank (int)

  • objective_value (float)

  • termination_condition (str)

  • solver_status (str)

  • visitors (tuple[str, ...])

  • faculty (tuple[str, ...])

  • time_slots (tuple[int, ...])

  • active_meetings (frozenset[tuple[str, str, int]])

  • context (SolutionContext)

Return type:

None

class grad_visit_scheduler.SolutionSet(solutions)[source]

Bases: object

Collection object for ranked SolutionResult instances.

__init__(solutions)[source]
best()[source]

Return the top-ranked solution, if present.

get(rank)[source]

Return a ranked solution (1-based rank).

Parameters:

rank (int)

to_dataframe()[source]

Return a summary dataframe of ranked solution quality statistics.

summarize(*, compact_columns=None, ranks_to_plot=(1, 2), save_files=True, show_solution_rank=True, plot_prefix=None, export_docx=False, docx_prefix='visitor_schedule_top')[source]

Build a reusable top-N solution review bundle.

This helper packages the common “inspect top-N solutions” workflow used in examples and notebooks:

  1. Build a full summary table with one row per ranked solution.

  2. Build a compact summary view with key comparison columns.

  3. Optionally generate visitor/faculty schedule plots for selected ranks.

  4. Optionally export all ranked solutions to DOCX.

Parameters:
  • compact_columns – Optional list of column names to include in a compact comparison table. If omitted, a default set of high-signal columns is used.

  • ranks_to_plot – Iterable of 1-based ranks to render (for example (1, 2)). Invalid ranks are ignored.

  • save_files – If True, plotting helpers write files to disk and return their paths in the output dictionary.

  • show_solution_rank – If True, append "(Solution Rank X)" to plot titles for generated ranked-solution figures.

  • plot_prefix – Optional run-name override used while generating plots. If provided, output plot filenames become *_plot_prefix_rankX.*.

  • export_docx – If True, export all ranked solutions to DOCX files.

  • docx_prefix – Prefix used when export_docx=True. Filenames are generated as {docx_prefix}_rank{rank}.docx.

Returns:

Dictionary with the following keys:

  • summary: full summary dataframe from to_dataframe().

  • compact: compact comparison dataframe.

  • plotted_ranks: tuple of ranks that were plotted.

  • visitor_plot_files: tuple of PNG filenames (if saved).

  • faculty_plot_files: tuple of PNG filenames (if saved).

  • docx_files: tuple of exported DOCX filenames.

Return type:

dict

Notes

  • This helper is intentionally non-destructive: it restores the scheduler run name after temporary overrides.

  • Plot filenames are returned only when save_files=True.

  • Compact columns that are not present in the summary dataframe are silently skipped.

plot_faculty_schedule(rank=1, show_solution_rank=True, **kwargs)[source]

Plot faculty schedule for the selected ranked solution.

plot_visitor_schedule(rank=1, show_solution_rank=True, **kwargs)[source]

Plot visitor schedule for the selected ranked solution.

export_visitor_docx(filename, rank=1, **kwargs)[source]

Export a selected ranked solution to DOCX.

export_visitor_docx_all(prefix='visitor_schedule', suffix='.docx', **kwargs)[source]

Export all ranked solutions to separate DOCX files.

grad_visit_scheduler.compute_min_travel_lags(times_by_building, min_buffer_minutes=0)[source]

Derive minimum inter-building slot lags from absolute slot timestamps.

Parameters:
  • times_by_building – Mapping from building name to ordered slot labels ("H:MM-H:MM"). A "breaks" key is ignored when present.

  • min_buffer_minutes – Optional nonnegative buffer (in minutes) required between consecutive meetings in different buildings.

Returns:

Pairwise lag matrix travel_slots[b_from][b_to] suitable for the travel-time movement constraints. A lag value L forbids transitions from slot t in b_from to slots t+1 through t+L in b_to.

Return type:

dict[str, dict[str, int]]

grad_visit_scheduler.load_faculty_catalog(path)[source]

Load and validate a faculty catalog YAML file.

Parameters:

path (str | Path) – Path to the faculty catalog YAML file.

Returns:

A tuple of (faculty, aliases) dictionaries.

Return type:

tuple[dict, dict]

Raises:

ValueError – If the catalog has no faculty section or an alias points to an unknown faculty name.

grad_visit_scheduler.load_run_config(path)[source]

Load and validate a run configuration YAML file.

Parameters:

path (str | Path) – Path to the run configuration YAML file.

Returns:

Parsed run configuration.

Return type:

dict

Raises:

ValueError – If required sections are missing, building ordering is invalid, or movement configuration is invalid.

grad_visit_scheduler.build_times_by_building(run_config)[source]

Build scheduler times_by_building data from a run config.

Parameters:

run_config (Dict[str, Any]) – Parsed run configuration dictionary.

Returns:

Mapping of building names to slot strings, with optional "breaks".

Return type:

dict

grad_visit_scheduler.scheduler_from_configs(faculty_catalog_path, run_config_path, student_data_filename, mode=None, solver=Solver.HIGHS, include_legacy_faculty=False)[source]

Create and configure a Scheduler.

Parameters:
  • faculty_catalog_path (str | Path) – Path to the faculty catalog YAML file.

  • run_config_path (str | Path) – Path to the run configuration YAML file.

  • student_data_filename (str | Path) – Path to visitor preference CSV data.

  • mode (Mode | None) – Legacy building sequencing mode. Prefer movement configuration in the run config.

  • solver (Solver) – Solver backend to use.

  • include_legacy_faculty (bool) – If True, include all legacy faculty from the catalog even when they were not explicitly requested by visitors.

Returns:

Configured scheduler instance.

Return type:

grad_visit_scheduler.core.Scheduler

grad_visit_scheduler.export_visitor_docx(scheduler, filename, *, solution=None, building=None, font_name='Arial', font_size_pt=11, include_breaks=True)[source]

Export a solved visitor schedule to a DOCX document.

Parameters:
  • scheduler – Solved scheduler instance containing model and metadata.

  • filename – Output DOCX filename.

  • solution – Optional SolutionResult snapshot to export. If omitted, uses the scheduler’s most recently solved model assignment.

  • building (str | None) – Building key used to pick displayed time labels. Defaults to the first configured building.

  • font_name (str) – Font family used in the generated document.

  • font_size_pt (int) – Font size in points.

  • include_breaks (bool) – If True, include explicit “Break” rows for unscheduled slots.

Returns:

Path to the written DOCX file.

Return type:

pathlib.Path

Raises:
  • RuntimeError – If the scheduler does not have a feasible solution.

  • ImportError – If python-docx is not installed.

Top-level imports provided by grad_visit_scheduler:

  • Scheduler

  • Mode

  • MovementPolicy

  • Solver

  • FacultyStatus

  • SolutionResult

  • SolutionSet

  • compute_min_travel_lags

  • scheduler_from_configs

  • load_faculty_catalog

  • load_run_config

  • build_times_by_building

  • export_visitor_docx

Preferred interface note: use run-config movement: settings and MovementPolicy; Mode remains as a legacy compatibility enum.

Preferred Single-Solution Workflow

For single-solution solves, use schedule_visitors(...) directly:

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

You can also access the loaded solved snapshot with Scheduler.current_solution(). This raises RuntimeError if no feasible solution is loaded.

Visitor-Specific Hard Constraints

Scheduler provides hard-constraint APIs for visitor-specific exceptions:

  • forbid_meeting(visitor, faculty, time_slot=None)

  • require_meeting(visitor, faculty, time_slot=None)

  • require_break(visitor, slots=None, min_breaks=1)

  • set_visitor_meeting_bounds(visitor, min_meetings=None, max_meetings=None)

  • set_faculty_meeting_bounds(faculty, min_meetings=None, max_meetings=None)

See Advanced Customization for detailed examples, override precedence, pre-solve checks, and debug_infeasible workflows.

Top-N Review Helper

SolutionSet.summarize(...) packages the common “review top-N solutions” workflow:

  • Full summary dataframe (report["summary"])

  • Compact comparison dataframe (report["compact"])

  • Optional ranked plot generation

  • Optional ranked DOCX export

For the mathematical no-good-cut constraint that enforces uniqueness between ranked solutions, see Mathematical Formulation (“Top-N No-Good Cuts” section).

Internal review pattern (keep rank labels visible in plot titles):

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

External-facing pattern (hide rank labels for faculty/visitor handouts):

top = s.schedule_visitors_top_n(n_solutions=3, faculty_breaks=2, student_breaks=1)
report = top.summarize(
    ranks_to_plot=(1,),
    save_files=True,
    show_solution_rank=False,
    plot_prefix="final_schedule",
    export_docx=True,
    docx_prefix="visitor_schedule_final",
)

Top-N Exhaustion Semantics (Developer Note)

When schedule_visitors_top_n(n_solutions=...) requests more schedules than are uniquely feasible, the solve loop stops after the first infeasible no-good-cut iteration. In this case:

  • SolutionSet contains all feasible unique solutions found so far.

  • Scheduler.last_solution_set points to that SolutionSet.

  • Scheduler.results / has_feasible_solution() remain aligned with the last feasible loaded model state.

  • Scheduler.current_solution() therefore returns the last feasible schedule (with rank 1 as a current-state snapshot rank).

This behavior is intentional so legacy scheduler-level plotting/export methods continue to operate after top-N exhaustion.

Core Model API

Core scheduling model, solver integration, and plotting helpers.

class grad_visit_scheduler.core.Solver(value)[source]

Bases: Enum

Supported optimization solver backends.

HIGHS = 1
CBC = 2
GUROBI = 3
GUROBI_IIS = 4
class grad_visit_scheduler.core.FacultyStatus(value)[source]

Bases: Enum

Faculty catalog status labels.

ACTIVE = 'active'
LEGACY = 'legacy'
EXTERNAL = 'external'
class grad_visit_scheduler.core.Mode(value)[source]

Bases: Enum

Building sequencing constraints for visitor movement.

BUILDING_A_FIRST = 1
BUILDING_B_FIRST = 2
NO_OFFSET = 3
class grad_visit_scheduler.core.MovementPolicy(value)[source]

Bases: Enum

Building movement policy for multi-building schedules.

NONE = 'none'
TRAVEL_TIME = 'travel_time'
NONOVERLAP_TIME = 'nonoverlap_time'
grad_visit_scheduler.core._flatten_schedule_time_labels(time_labels)[source]

Return a flat list of slot labels from a mapping or iterable input.

grad_visit_scheduler.core._schedule_tick_data(time_labels=None, nslots=7)[source]

Return x-axis limits and ticks for a schedule plot.

grad_visit_scheduler.core.schedule_axes(figsize, nslots=7, time_labels=None)[source]

Create a matplotlib axis formatted for visit-day schedule plots.

Parameters:
  • figsize – Figure size passed to plt.subplots.

  • nslots – Number of schedule slots to display.

  • time_labels – Optional concrete slot labels used to derive x-axis limits and ticks. Accepts either an iterable of "H:MM-H:MM" strings or a times_by_building-style mapping.

Returns:

Configured axis with time ticks and grid lines.

Return type:

matplotlib.axes.Axes

grad_visit_scheduler.core._measure_label_widths_pts(fig, ax, labels, fontsize)[source]

Return the rendered width, in points, of each label at fontsize.

Draws each label invisibly on ax, measures it via fig.canvas.get_renderer() and Text.get_window_extent(), then removes it. This is a dry-run measurement pass so figure sizing can react to the actual rendered geometry of a label instead of a guess.

grad_visit_scheduler.core._box_width_pts(fig, ax, duration_minutes)[source]

Return the on-screen width, in points, of a box spanning duration_minutes.

ax.transData is an affine transform, so the pixel distance between two x-values depends only on their difference, not their absolute position – this works regardless of where the axes’ xlim starts.

grad_visit_scheduler.core._base_schedule_figsize(num_rows, num_slots, lw, tight=False)[source]

Return a first-pass figsize sized from row count, slot count, and lw.

Height scales with the number of rows actually drawn (visitors or faculty) and with lw (box height, itself derived from fontsize), so neither a sparse schedule nor a large fontsize inherits a mismatched fixed constant. The row-count*row-height figure divides out matplotlib’s default axes-height fraction (the figure.subplot top/bottom rcParams) rather than adding a flat margin, since that fraction – not a fixed inch count – is what the title/x-axis area actually costs regardless of total figure height. Width scales with the number of time slots shown; _fit_schedule_figsize may widen it further if a label would otherwise overrun its box. tight swaps in a smaller row-to-box ratio, for callers who want minimal vertical whitespace over comfortable row spacing.

grad_visit_scheduler.core._fit_schedule_figsize(base_figsize, nslots, time_labels, min_duration_minutes, worst_labels, fontsize, margin=1.15)[source]

Widen base_figsize so worst_labels fit inside the narrowest schedule box.

Box width is schedule-driven: it falls out of slot duration, figsize, and the axes’ time range, with no dependency on the label text or fontsize. So a label that overruns its box can only be fixed by growing the figure (which grows the box), not by any per-box parameter. This renders a throwaway probe figure at base_figsize to measure the worst-case label width and the pixel width implied by min_duration_minutes, then widens the figure – height is left alone, since it is already sized from row count – by the ratio needed to fit, plus a safety margin.

grad_visit_scheduler.core.slot2min(slot)[source]

Convert a slot string like '1:00-1:25' to integer minutes.

Parameters:

slot – Schedule slot label in start-end format. Supports plain clock times (H:MM-H:MM), 24-hour times (13:00-13:25), and meridiem-qualified 12-hour times (8:30 AM-8:55 AM).

Returns:

Start and end times in minutes.

Return type:

tuple[int, int]

grad_visit_scheduler.core._normalize_building_times(times_by_building)[source]

Return a copy of building time lists without the optional breaks key.

grad_visit_scheduler.core.compute_min_travel_lags(times_by_building, min_buffer_minutes=0)[source]

Derive minimum inter-building slot lags from absolute slot timestamps.

Parameters:
  • times_by_building – Mapping from building name to ordered slot labels ("H:MM-H:MM"). A "breaks" key is ignored when present.

  • min_buffer_minutes – Optional nonnegative buffer (in minutes) required between consecutive meetings in different buildings.

Returns:

Pairwise lag matrix travel_slots[b_from][b_to] suitable for the travel-time movement constraints. A lag value L forbids transitions from slot t in b_from to slots t+1 through t+L in b_to.

Return type:

dict[str, dict[str, int]]

grad_visit_scheduler.core.abbreviate_name(full_name)[source]

Abbreviate a full name for compact schedule labels.

Examples

"Jane Doe" -> "Jane D." "John Michael Doe" -> "John M. D."

Notes

If non-initial tokens are not alphabetic (for example "Visitor 01"), the original name is returned unchanged to avoid ambiguous labels.

class grad_visit_scheduler.core.SolutionContext(times_by_building, faculty, box_colors, number_time_slots, run_name, student_preferences, requests, legacy_faculty, external_faculty)[source]

Bases: object

Immutable rendering and reporting context shared by solution snapshots.

Parameters:
  • times_by_building (dict[str, tuple[str, ...]])

  • faculty (dict[str, dict[str, object]])

  • box_colors (dict[str, str])

  • number_time_slots (int)

  • run_name (str)

  • student_preferences (dict[tuple[str, str], float])

  • requests (dict[str, tuple[str, ...]])

  • legacy_faculty (frozenset[str])

  • external_faculty (frozenset[str])

times_by_building: dict[str, tuple[str, ...]]
faculty: dict[str, dict[str, object]]
box_colors: dict[str, str]
number_time_slots: int
run_name: str
student_preferences: dict[tuple[str, str], float]
requests: dict[str, tuple[str, ...]]
legacy_faculty: frozenset[str]
external_faculty: frozenset[str]
is_legacy(faculty_name)[source]

Return whether a faculty entry is marked legacy.

Parameters:

faculty_name (str)

Return type:

bool

is_external(faculty_name)[source]

Return whether a faculty entry is marked external.

Parameters:

faculty_name (str)

Return type:

bool

__init__(times_by_building, faculty, box_colors, number_time_slots, run_name, student_preferences, requests, legacy_faculty, external_faculty)
Parameters:
  • times_by_building (dict[str, tuple[str, ...]])

  • faculty (dict[str, dict[str, object]])

  • box_colors (dict[str, str])

  • number_time_slots (int)

  • run_name (str)

  • student_preferences (dict[tuple[str, str], float])

  • requests (dict[str, tuple[str, ...]])

  • legacy_faculty (frozenset[str])

  • external_faculty (frozenset[str])

Return type:

None

class grad_visit_scheduler.core.SolutionResult(rank, objective_value, termination_condition, solver_status, visitors, faculty, time_slots, active_meetings, context)[source]

Bases: object

Rich, self-contained representation of one solved schedule.

A SolutionResult is intentionally independent from the mutable Scheduler and Pyomo model state. It contains all assignment and metadata needed to:

  • inspect per-solution quality statistics,

  • produce schedule visualizations,

  • export visitor DOCX schedules,

  • serialize/pickle for later analysis.

Parameters:
  • rank (int) – 1-based rank in the top-N solve sequence.

  • objective_value (float) – Objective value for this ranked solution.

  • termination_condition (str) – Solver termination label (string form).

  • solver_status (str) – Solver status label (string form).

  • visitors (tuple[str, ...]) – Ordered visitor labels included in the solved model.

  • faculty (tuple[str, ...]) – Ordered faculty labels included in the solved model.

  • time_slots (tuple[int, ...]) – Ordered integer time-slot indices.

  • active_meetings (frozenset[tuple[str, str, int]]) – Set of active binary assignments (visitor, faculty, slot).

  • context (grad_visit_scheduler.core.SolutionContext) – Immutable rendering/reporting context copied from the scheduler at solve time (times, faculty metadata, colors, preferences, requests, etc.).

rank: int
objective_value: float
termination_condition: str
solver_status: str
visitors: tuple[str, ...]
faculty: tuple[str, ...]
time_slots: tuple[int, ...]
active_meetings: frozenset[tuple[str, str, int]]
context: SolutionContext
meeting_assigned(visitor, faculty, time_slot)[source]

Return whether the visitor/faculty/time assignment is active.

Parameters:
  • visitor (str)

  • faculty (str)

  • time_slot (int)

Return type:

bool

_meeting_sizes()[source]
summary_row(best_objective=None)[source]

Return one summary row dictionary for this solution.

_schedule_filename(base, include_rank=True, suffix='')[source]
Parameters:
  • base (str)

  • include_rank (bool)

  • suffix (str)

_show_building_labels()[source]

Return whether plot labels should include building names.

plot_faculty_schedule(save_files=True, abbreviate_student_names=True, show_solution_rank=False, include_rank_in_filename=True, fontsize=8, tight=False)[source]

Plot schedule grouped by faculty for this single solution.

plot_visitor_schedule(save_files=True, abbreviate_student_names=True, show_solution_rank=False, include_rank_in_filename=True, fontsize=8, tight=False)[source]

Plot schedule grouped by visitor for this single solution.

export_visitor_docx(filename, *, building=None, font_name='Arial', font_size_pt=11, include_breaks=True)[source]

Export this solution to a visitor schedule DOCX file.

Parameters:
  • building (str | None)

  • font_name (str)

  • font_size_pt (int)

  • include_breaks (bool)

__init__(rank, objective_value, termination_condition, solver_status, visitors, faculty, time_slots, active_meetings, context)
Parameters:
  • rank (int)

  • objective_value (float)

  • termination_condition (str)

  • solver_status (str)

  • visitors (tuple[str, ...])

  • faculty (tuple[str, ...])

  • time_slots (tuple[int, ...])

  • active_meetings (frozenset[tuple[str, str, int]])

  • context (SolutionContext)

Return type:

None

class grad_visit_scheduler.core.SolutionSet(solutions)[source]

Bases: object

Collection object for ranked SolutionResult instances.

__init__(solutions)[source]
best()[source]

Return the top-ranked solution, if present.

get(rank)[source]

Return a ranked solution (1-based rank).

Parameters:

rank (int)

to_dataframe()[source]

Return a summary dataframe of ranked solution quality statistics.

summarize(*, compact_columns=None, ranks_to_plot=(1, 2), save_files=True, show_solution_rank=True, plot_prefix=None, export_docx=False, docx_prefix='visitor_schedule_top')[source]

Build a reusable top-N solution review bundle.

This helper packages the common “inspect top-N solutions” workflow used in examples and notebooks:

  1. Build a full summary table with one row per ranked solution.

  2. Build a compact summary view with key comparison columns.

  3. Optionally generate visitor/faculty schedule plots for selected ranks.

  4. Optionally export all ranked solutions to DOCX.

Parameters:
  • compact_columns – Optional list of column names to include in a compact comparison table. If omitted, a default set of high-signal columns is used.

  • ranks_to_plot – Iterable of 1-based ranks to render (for example (1, 2)). Invalid ranks are ignored.

  • save_files – If True, plotting helpers write files to disk and return their paths in the output dictionary.

  • show_solution_rank – If True, append "(Solution Rank X)" to plot titles for generated ranked-solution figures.

  • plot_prefix – Optional run-name override used while generating plots. If provided, output plot filenames become *_plot_prefix_rankX.*.

  • export_docx – If True, export all ranked solutions to DOCX files.

  • docx_prefix – Prefix used when export_docx=True. Filenames are generated as {docx_prefix}_rank{rank}.docx.

Returns:

Dictionary with the following keys:

  • summary: full summary dataframe from to_dataframe().

  • compact: compact comparison dataframe.

  • plotted_ranks: tuple of ranks that were plotted.

  • visitor_plot_files: tuple of PNG filenames (if saved).

  • faculty_plot_files: tuple of PNG filenames (if saved).

  • docx_files: tuple of exported DOCX filenames.

Return type:

dict

Notes

  • This helper is intentionally non-destructive: it restores the scheduler run name after temporary overrides.

  • Plot filenames are returned only when save_files=True.

  • Compact columns that are not present in the summary dataframe are silently skipped.

plot_faculty_schedule(rank=1, show_solution_rank=True, **kwargs)[source]

Plot faculty schedule for the selected ranked solution.

plot_visitor_schedule(rank=1, show_solution_rank=True, **kwargs)[source]

Plot visitor schedule for the selected ranked solution.

export_visitor_docx(filename, rank=1, **kwargs)[source]

Export a selected ranked solution to DOCX.

export_visitor_docx_all(prefix='visitor_schedule', suffix='.docx', **kwargs)[source]

Export all ranked solutions to separate DOCX files.

class grad_visit_scheduler.core.Scheduler(times_by_building, student_data_filename, mode=None, movement=None, solver=Solver.HIGHS, include_legacy_faculty=False, faculty_catalog=None, faculty_aliases=None)[source]

Bases: object

Scheduler for assigning visitor-faculty meetings across time slots.

__init__(times_by_building, student_data_filename, mode=None, movement=None, solver=Solver.HIGHS, include_legacy_faculty=False, faculty_catalog=None, faculty_aliases=None)[source]

Initialize a scheduler with buildings, visitors, and faculty data.

Parameters:
  • times_by_building – Mapping of building names to ordered time-slot labels and optional "breaks" list.

  • student_data_filename – CSV file with visitor names and ranked preferences.

  • mode – Legacy building sequencing mode. Prefer movement.

  • movement – Optional movement configuration dictionary with keys: policy ("none", "travel_time", or "nonoverlap_time"), phase_slot (per-building earliest slot), and optional travel_slots (pairwise slot lags, or "auto" for timestamp- derived lags), plus optional min_buffer_minutes for auto lags.

  • solver – Solver backend used by schedule_visitors().

  • include_legacy_faculty – If True, include all legacy faculty entries from the catalog.

  • faculty_catalog – Optional faculty catalog dictionary. If omitted, a small default synthetic catalog is created.

  • faculty_aliases – Optional mapping of alias name to canonical faculty name.

_init_hard_constraint_state()[source]

Initialize user-defined hard-constraint storage.

Storage is set-based so rules are cumulative and naturally idempotent. Re-adding the same rule has no effect on model behavior.

_validate_visitor_name(visitor)[source]

Validate and return visitor name.

_validate_faculty_name(faculty)[source]

Validate and return faculty name.

_validate_slot_index(time_slot)[source]

Validate and return integer time-slot index.

_validate_slot_collection(slots)[source]

Validate optional slots iterable and return canonical tuple.

_validate_optional_nonnegative_int(value, field_name)[source]

Validate optional nonnegative integer and return normalized value.

_effective_visitor_bounds(visitor, global_min_faculty)[source]

Return effective (min_meetings, max_meetings) for one visitor.

_effective_faculty_bounds(faculty, global_min_visitors, global_max_visitors)[source]

Return effective (min_meetings, max_meetings) for one faculty.

_meeting_feasible_slots(visitor, faculty)[source]

Return slots where visitor/faculty meeting could occur before user hard constraints.

_required_specific_meeting_count(visitor, slots)[source]

Count required slot-specific meetings for visitor within given slots.

_check_break_contradictions_for_visitor(visitor)[source]

Raise if current required meetings violate any required-break hard constraint.

set_visitor_meeting_bounds(visitor, min_meetings=None, max_meetings=None)[source]

Set optional visitor-specific meeting-count bounds.

Parameters:
  • visitor – Visitor name from the loaded CSV.

  • min_meetings – Optional override for the visitor minimum meeting count. If None, the global min_faculty value is used.

  • max_meetings – Optional override for the visitor maximum meeting count. If None, no visitor-specific maximum is enforced.

Notes

Visitor-specific overrides take precedence over global bounds. Passing both arguments as None clears the visitor override and restores global-default behavior.

set_faculty_meeting_bounds(faculty, min_meetings=None, max_meetings=None)[source]

Set optional faculty-specific meeting-count bounds.

Parameters:
  • faculty – Faculty name from the active faculty catalog.

  • min_meetings – Optional override for the faculty minimum meeting count. If None, the global min_visitors value is used.

  • max_meetings – Optional override for the faculty maximum meeting count. If None, the global max_visitors value is used.

Notes

Faculty-specific overrides take precedence over global bounds. Passing both arguments as None clears the faculty override and restores global-default behavior.

forbid_meeting(visitor, faculty, time_slot=None)[source]

Hard-forbid a visitor/faculty meeting in one slot or all slots.

Parameters:
  • visitor – Visitor name from the loaded CSV.

  • faculty – Faculty name from the active faculty catalog.

  • time_slot – Optional slot index. If omitted, forbids this pair for all slots.

Raises:

ValueError – On unknown visitor/faculty, invalid slot index, or direct contradiction with previously required hard constraints.

require_meeting(visitor, faculty, time_slot=None)[source]

Hard-require a visitor/faculty meeting in one slot or exactly once overall.

Parameters:
  • visitor – Visitor name from the loaded CSV.

  • faculty – Faculty name from the active faculty catalog.

  • time_slot – Optional slot index. If omitted, enforces exactly one meeting for this visitor/faculty pair across all slots.

Raises:

ValueError – On unknown visitor/faculty, invalid slot index, infeasible slot availability, or direct contradiction with existing hard rules.

require_break(visitor, slots=None, min_breaks=1)[source]

Hard-require break slots for a visitor.

A break means the visitor has no assigned meeting in that slot.

Parameters:
  • visitor – Visitor name from the loaded CSV.

  • slots – Optional iterable of slot indices to consider. If omitted, all slots are considered.

  • min_breaks – Minimum number of break slots required within slots.

Raises:

ValueError – On unknown visitor, invalid slot indices, invalid min_breaks, or direct contradiction with existing slot-specific requirements.

_set_time_data(times_by_building)[source]

Validate building slot data and populate scheduling time metadata.

Parameters:

times_by_building – Mapping of building names to ordered slot labels, plus optional "breaks" key containing slot indices.

_configure_movement(mode, movement)[source]

Normalize movement configuration with legacy mode compatibility.

_warn_if_none_policy_real_time_overlap_risk()[source]

Warn when shifted building clocks can overlap across adjacent slots.

_normalize_break_count(value, name)[source]

Normalize a break-count argument into a nonnegative integer.

_resolve_break_requirements(enforce_breaks, faculty_breaks, student_breaks)[source]

Resolve explicit break counts plus legacy enforce_breaks alias.

_faculty_unavailable_nonbreak_count(faculty_name, break_options)[source]

Return unavailable faculty slots that already count as breaks outside break options.

_validate_required_faculty_breaks(required_faculty_breaks, break_options)[source]

Raise when the requested faculty break count cannot be satisfied.

_validate_required_student_breaks(required_student_breaks, break_options)[source]

Raise when the requested student break count cannot be satisfied.

_build_box_colors()[source]

Return a color map for configured buildings.

_load_student_preferences(filename)[source]

Load datafile with student preferences

_load_default_faculty_data()[source]

Load a minimal synthetic faculty catalog for default/demo usage.

_load_faculty_catalog(catalog)[source]

Load faculty entries from a user-provided catalog dictionary.

Parameters:

catalog – Mapping from faculty name to metadata fields.

_add_legacy_faculty_from_preferences(include_all=False)[source]

Merge legacy faculty into active scheduling set.

Parameters:

include_all – If True, include all legacy faculty regardless of requests.

_add_external_faculty_from_preferences()[source]

Create placeholder external faculty records from visitor requests.

add_external_faculty(name, building=None, room='', areas=None, available=None)[source]

Add or update an external faculty entry.

Parameters:
  • name – Faculty display name.

  • building – Building key. Defaults to building A.

  • room – Room label used in exports and plots.

  • areas – Optional list of research areas for area-based preference boosts.

  • available – Optional list of available time-slot indices.

_is_legacy_faculty(name)[source]

Return whether name belongs to the legacy faculty pool.

faculty_limited_availability(name, available)[source]

Set the available time slots for a faculty member.

Parameters:
  • name – Faculty name.

  • available – List of integer slot indices where meetings are allowed.

update_weights(faculty_weight={'Prof1': 4.0, 'Prof2': 3.0, 'Prof3': 2.0, 'Prof4': 1.0, 'Prof5': 0.5}, area_weight={'Area1': 1.0, 'Area2': 0.5}, base_weight=0.2)[source]

Set preference weights and rebuild visitor-faculty utility scores.

Parameters:
  • faculty_weight – Either a scalar applied to all ranked faculty columns, or a dict keyed by preference column names (for example Prof1).

  • area_weight – Either a scalar applied to all area columns, or a dict keyed by area column names (for example Area1).

  • base_weight – Baseline utility assigned to any feasible visitor-faculty match.

_update_student_preferences()[source]

Recompute utility weights for each visitor-faculty pair.

specify_limited_student_availability(students_available)[source]

Restrict availability for a subset of visitors.

Parameters:

students_available – Mapping of visitor name to allowed slot indices. Visitors not listed remain available for all time slots.

plot_preferences()[source]

Plot a heatmap of visitor-faculty utility weights.

Returns:

(fig, ax) matplotlib objects for further customization.

Return type:

tuple

schedule_visitors(group_penalty=0.1, min_visitors=0, max_visitors=8, min_faculty=0, max_group=2, enforce_breaks=None, faculty_breaks=0, student_breaks=0, debug_infeasible=False, tee=False, run_name='')[source]

Solve the mixed-integer scheduling model.

Parameters:
  • group_penalty – Utility penalty for adding a second (or later) visitor to the same faculty-time meeting.

  • min_visitors – Minimum total meetings per available faculty member.

  • max_visitors – Maximum total meetings per faculty member.

  • min_faculty – Minimum number of meetings required per visitor.

  • max_group – Maximum number of visitors allowed in a single faculty-time meeting.

  • enforce_breaks – Legacy compatibility alias. False maps to faculty_breaks=0, student_breaks=0 and True maps to faculty_breaks=1, student_breaks=1 when the explicit break arguments are left at zero.

  • faculty_breaks – Minimum number of automatic faculty breaks required per eligible faculty member. Faculty-unavailable slots outside the break window count toward this total.

  • student_breaks – Minimum number of automatic student breaks required within the configured break-option slots.

  • debug_infeasible – If False (default), run pre-solve consistency checks before model construction and fail fast on obvious contradictions. If True, build the model first, then run checks so advanced users can inspect self.model after a raised pre-solve error.

  • tee – If True, stream solver output.

  • run_name – Optional suffix for saved plot filenames.

Returns:

Snapshot of the solved schedule when a feasible solution is found. Returns None if the solve is infeasible or otherwise has no feasible assignment.

Return type:

SolutionResult | None

schedule_visitors_top_n(n_solutions=5, group_penalty=0.1, min_visitors=0, max_visitors=8, min_faculty=0, max_group=2, enforce_breaks=None, faculty_breaks=0, student_breaks=0, debug_infeasible=False, tee=False, run_name='')[source]

Solve for up to the best n_solutions unique schedules.

Uses no-good integer cuts over the full assignment vector y[s, f, t] so each returned solution differs from all previous solutions.

_build_model(group_penalty, min_visitors, max_visitors, min_faculty, max_group, enforce_breaks=None, faculty_breaks=0, student_breaks=0)[source]

Build the Pyomo MILP model for the current scheduler state.

Parameters:
  • group_penalty – Penalty applied to group meetings.

  • min_visitors – Minimum required meetings per available faculty member.

  • max_visitors – Maximum total meetings per faculty member.

  • min_faculty – Minimum required meetings per visitor.

  • max_group – Maximum number of visitors in a single faculty-time meeting.

  • enforce_breaks – Legacy compatibility alias for both break counts.

  • faculty_breaks – Automatic faculty break count.

  • student_breaks – Automatic student break count.

_collect_presolve_hard_constraint_issues(min_visitors, max_visitors, min_faculty, max_group)[source]

Return a list of obvious hard-constraint contradictions.

_run_presolve_hard_constraint_checks(min_visitors, max_visitors, min_faculty, max_group, raise_on_issue=True)[source]

Collect and optionally raise on obvious hard-constraint contradictions.

_solve_model(tee, record_results=True)[source]

Solve the currently built model with the configured solver backend.

Parameters:

tee – If True, stream solver output to stdout.

_build_solution_context()[source]

Build immutable metadata context for solution snapshots.

_snapshot_solution(rank)[source]

Capture the current solved model values as an immutable snapshot.

_add_no_good_cut(solution)[source]

Exclude an already-found binary assignment from future solves.

has_feasible_solution()[source]

Return True if the latest solver run was feasible or optimal.

infeasibility_report()[source]

Summarize likely causes when the model has no feasible solution.

current_solution()[source]

Return a rich snapshot for the currently loaded feasible model.

Returns:

Immutable snapshot of the currently loaded solved assignment.

Return type:

SolutionResult

Raises:

RuntimeError – If no feasible solution is currently loaded.

_current_solution_result()[source]

Backward-compatible alias for current_solution().

show_faculty_schedule(save_files=True, abbreviate_student_names=True, solution=None, show_solution_rank=False)[source]

Plot the solved schedule grouped by faculty.

Parameters:
  • save_files – If True, save faculty_schedule*.pdf and .png.

  • abbreviate_student_names – If True, shorten visitor names in labels.

  • solution – Optional SolutionResult to plot. If omitted, uses the most recently solved model on this scheduler.

  • show_solution_rank – If True and solution is provided, append solution rank to the figure title.

show_visitor_schedule(save_files=True, abbreviate_student_names=True, solution=None, show_solution_rank=False)[source]

Plot the solved schedule grouped by visitor.

Parameters:
  • save_files – If True, save visitor_schedule*.pdf and .png.

  • abbreviate_student_names – If True, shorten visitor names in y-axis labels.

  • solution – Optional SolutionResult to plot. If omitted, uses the most recently solved model on this scheduler.

  • show_solution_rank – If True and solution is provided, append solution rank to the figure title.

export_visitor_docx(filename, solution=None, **kwargs)[source]

Export solved visitor schedules to a DOCX file.

Parameters:
show_utility()[source]

Plot realized meetings and display total utility for a solved model.

check_requests()[source]

Print unmet requested faculty meetings and meeting-count distribution.

Config API

Config loading and helpers for grad visit scheduling.

grad_visit_scheduler.config.load_yaml(path)[source]

Load a YAML file and return its contents.

Parameters:

path (str | Path) – Path to the YAML file.

Returns:

Parsed YAML content, or an empty dictionary if the file is empty.

Return type:

dict

grad_visit_scheduler.config.load_faculty_catalog(path)[source]

Load and validate a faculty catalog YAML file.

Parameters:

path (str | Path) – Path to the faculty catalog YAML file.

Returns:

A tuple of (faculty, aliases) dictionaries.

Return type:

tuple[dict, dict]

Raises:

ValueError – If the catalog has no faculty section or an alias points to an unknown faculty name.

grad_visit_scheduler.config.load_run_config(path)[source]

Load and validate a run configuration YAML file.

Parameters:

path (str | Path) – Path to the run configuration YAML file.

Returns:

Parsed run configuration.

Return type:

dict

Raises:

ValueError – If required sections are missing, building ordering is invalid, or movement configuration is invalid.

grad_visit_scheduler.config.build_times_by_building(run_config)[source]

Build scheduler times_by_building data from a run config.

Parameters:

run_config (Dict[str, Any]) – Parsed run configuration dictionary.

Returns:

Mapping of building names to slot strings, with optional "breaks".

Return type:

dict

grad_visit_scheduler.config.scheduler_from_configs(faculty_catalog_path, run_config_path, student_data_filename, mode=None, solver=Solver.HIGHS, include_legacy_faculty=False)[source]

Create and configure a Scheduler.

Parameters:
  • faculty_catalog_path (str | Path) – Path to the faculty catalog YAML file.

  • run_config_path (str | Path) – Path to the run configuration YAML file.

  • student_data_filename (str | Path) – Path to visitor preference CSV data.

  • mode (Mode | None) – Legacy building sequencing mode. Prefer movement configuration in the run config.

  • solver (Solver) – Solver backend to use.

  • include_legacy_faculty (bool) – If True, include all legacy faculty from the catalog even when they were not explicitly requested by visitors.

Returns:

Configured scheduler instance.

Return type:

grad_visit_scheduler.core.Scheduler

Export API

Export helpers.

grad_visit_scheduler.export.export_visitor_docx(scheduler, filename, *, solution=None, building=None, font_name='Arial', font_size_pt=11, include_breaks=True)[source]

Export a solved visitor schedule to a DOCX document.

Parameters:
  • scheduler – Solved scheduler instance containing model and metadata.

  • filename – Output DOCX filename.

  • solution – Optional SolutionResult snapshot to export. If omitted, uses the scheduler’s most recently solved model assignment.

  • building (str | None) – Building key used to pick displayed time labels. Defaults to the first configured building.

  • font_name (str) – Font family used in the generated document.

  • font_size_pt (int) – Font size in points.

  • include_breaks (bool) – If True, include explicit “Break” rows for unscheduled slots.

Returns:

Path to the written DOCX file.

Return type:

pathlib.Path

Raises:
  • RuntimeError – If the scheduler does not have a feasible solution.

  • ImportError – If python-docx is not installed.

Data API

Data loading helpers.

grad_visit_scheduler.data.load_visitor_csv(path)[source]

Load visitor preference data from CSV.

Parameters:

path (str) – Path to a CSV file containing visitor preferences.

Returns:

Loaded CSV contents.

Return type:

pandas.DataFrame