SIBA
Back to Projects
Introducing Acme.ai

Introducing Acme.ai

dillionverma

Introducing Acme.ai, a cutting-edge AI solution for modern businesses.

Hybrid Scheduling System - Complete Architecture

Last Updated: 2025-12-02 Status: Design Phase - Intelligent Conflict Resolution with Graph-Based Optimization Version: 2.0 - All-or-Nothing Validation + Subject Reordering


Table of Contents

  1. System Overview
  2. Architecture Principles
  3. Algorithm Analysis
  4. Scheduling Workflow
  5. Conflict Resolution System
  6. All-or-Nothing Validation
  7. Subject Reordering Logic
  8. User Interface Design
  9. API Architecture
  10. Database Schema

System Overview

The hybrid scheduling system implements an intelligent constraint satisfaction approach with all-or-nothing guarantees and automatic conflict resolution through subject reordering.

Core Innovation: Conflict-Driven Reordering

Traditional Approach (❌ Suboptimal):

  • Schedule Class A → complete
  • Schedule Class B → teacher conflict → stop and fail

Our Approach (✅ Intelligent):

  • Schedule Class A → complete
  • Schedule Class B → teacher conflict detected
  • Identify blocking class (Class A)
  • Reorder Class A's subjects to free up teacher
  • Reschedule Class A with new order
  • Continue Class B - conflict resolved!

Key Features

  1. All-or-Nothing Validation: Class schedule either completes fully or fails cleanly with detailed diagnostics
  2. Graph-Based Optimization: Hybrid greedy + CSP backtracking for optimal performance
  3. Intelligent Reordering: Automatically reorders previously scheduled classes to resolve conflicts
  4. Actionable Error Messages: UI provides one-click resolution options (change teacher OR reorder subjects)
  5. Transaction Safety: Database rollback on any failure ensures consistency

Architecture Principles

Three-Phase Scheduling Architecture

graph TB
    A[Phase 1: Configuration] --> B[Time Slots + Teachers]
    B --> C[Phase 2: Validation]
    C --> D{All Subjects<br/>Schedulable?}
    D -->|No| E[Conflict Resolution]
    D -->|Yes| F[Phase 3: Period Creation]
 
    E --> G[Reorder Blocking Classes]
    E --> H[Suggest Alternative Teachers]
    E --> I[Show Detailed Diagnostics]
 
    G --> J[Retry Validation]
    J --> D
 
    F --> K[Atomic DB Transaction]
    K --> L[Complete Schedule]
 
    I --> M[User Manual Resolution]
    M --> A
 

Separation of Concerns

Layer Responsibility Data Store
Slot Planning MORNING/AFTERNOON preferences timetables (teacherId: null)
Teacher Assignment Per-subject teacher allocation classSubjectProgress
Validation Engine Check all constraints before creation In-memory simulation
Period Generation Create actual schedule atomically periods (transaction)

Algorithm Analysis

We compared four approaches to find the optimal scheduling algorithm:

Option A: CSP with Backtracking

function cspScheduling(classes: Class[]): Schedule {
  for (const classToSchedule of classes) {
    if (!canSchedule(classToSchedule)) {
      // Backtrack and reorder previous classes
      const conflictingClass = findBlockingClass(classToSchedule);
      reorderAndReschedule(conflictingClass);
      retry(classToSchedule);
    }
  }
}
Aspect Assessment
Completeness ✅ Guaranteed to find solution if one exists
Performance ❌ Exponential O(n! × m!) - slow for 100+ classes
Determinism ✅ Same input = same output
Best For 10-50 classes per semester

Option B: Graph-Based Greedy

function greedyScheduling(classes: Class[]): Schedule {
  const conflictGraph = buildConflictGraph(classes);
  const sortedClasses = topologicalSort(conflictGraph); // Most constrained first
 
  for (const cls of sortedClasses) {
    while (!canSchedule(cls)) {
      const bestReordering = findMinimalConflictReordering(conflictGraph);
      applyReordering(bestReordering);
    }
  }
}
Aspect Assessment
Performance ✅ Polynomial O(n² × m) - fast for 200+ classes
Completeness ❌ May miss solutions (local minima)
Scalability ✅ Handles large datasets well
Best For 50-200 classes per semester

Option C: Simulated Annealing

function annealingScheduling(classes: Class[]): Schedule {
  let current = greedyInitialSchedule(classes);
  let temperature = 1000;
 
  while (temperature > 0.1) {
    const neighbor = randomReordering(current);
    const delta = evaluate(neighbor) - evaluate(current);
 
    // Accept better OR probabilistically accept worse (to escape local minima)
    if (delta > 0 || Math.random() < Math.exp(delta / temperature)) {
      current = neighbor;
    }
 
    temperature *= 0.95; // Cool down
  }
}
Aspect Assessment
Quality ✅ Near-optimal solutions
Determinism ❌ Non-deterministic results
Complexity ⚠️ Requires parameter tuning
Best For 100+ classes, optimal quality needed

Option D: Integer Linear Programming (ILP)

function ilpScheduling(classes: Class[]): Schedule {
  const objective = minimizeTeacherConflicts;
  const constraints = [
    eachSubjectScheduledOnce,
    teacherNotDoubleBooked,
    respectDisplayOrder,
    maxPeriodsPerDay,
  ];
 
  return solver.solve(objective, constraints); // Google OR-Tools
}
Aspect Assessment
Optimality ✅ Mathematically provable optimal
Dependencies ❌ Requires external solver library
Black Box ❌ Harder to customize
Best For Mission-critical scheduling

⭐ Recommended: Hybrid Greedy + CSP

Best of both worlds: Fast for common cases, complete for edge cases.

function hybridScheduling(classes: Class[]): Schedule {
  // Phase 1: Greedy (handles 90% of cases quickly)
  const greedyResult = greedyScheduling(classes);
 
  if (greedyResult.success) {
    return greedyResult.schedule; // ✅ Fast path
  }
 
  // Phase 2: CSP Backtracking (handles complex conflicts)
  console.log("⚙️ Greedy failed, using CSP backtracking...");
  return cspBacktrackingSchedule(
    greedyResult.partialSchedule,
    greedyResult.failedClasses
  );
}

Performance Characteristics:

  • Average Case: O(n² × m) - greedy dominates
  • Worst Case: O(n! × m!) - CSP fallback (rare)
  • Success Rate: ~95% greedy, ~5% CSP

Why Optimal:

  1. Fast for typical schedules (polynomial)
  2. Complete for edge cases (finds solution if exists)
  3. Production-Ready (reliable and debuggable)
  4. Graceful Degradation (smart fallback)

Scheduling Workflow

Complete End-to-End Flow

flowchart TD
    A[User: Schedule Class Semester] --> B[Validate All Prerequisites]
    B --> C{All Subjects<br/>Configured?}
    C -->|No| D[Error: Configure subjects first]
    C -->|Yes| E[START: Atomic Transaction]
 
    E --> F[Phase 1: Simulation]
    F --> G[For each subject in order]
    G --> H[Simulate Period Creation]
    H --> I{Teacher<br/>Available?}
 
    I -->|Yes| J[Mark simulation success]
    I -->|No| K[Conflict Detected!]
 
    K --> L{Can Reorder<br/>Blocking Class?}
    L -->|Yes| M[Reorder Algorithm]
    L -->|No| N{Alternative<br/>Teacher Available?}
 
    M --> O[Reschedule Blocking Class]
    O --> P[Retry Current Subject]
    P --> I
 
    N -->|Yes| Q[Suggest Teacher Change]
    N -->|No| R[FAIL: Impossible to Schedule]
 
    J --> S{More<br/>Subjects?}
    S -->|Yes| G
    S -->|No| T[All Subjects Validated ✓]
 
    T --> U[Phase 2: Period Creation]
    U --> V[Create ALL Periods in DB]
    V --> W[COMMIT Transaction]
    W --> X[Success: Complete Schedule]
 
    R --> Y[ROLLBACK Transaction]
    Y --> Z[Show Conflict Diagnostics]
    Z --> AA[User Action Required]
 
    Q --> AA
    D --> AA
 
    AA --> AB{User<br/>Choice}
    AB -->|Change Teacher| AC[Update Configuration]
    AB -->|Reorder Subjects| AD[Automatic Reorder]
    AB -->|Cancel| AE[Exit]
 
    AC --> A
    AD --> A
 
    style E fill:#e3f2fd
    style K fill:#fff3e0
    style M fill:#fce4ec
    style U fill:#e8f5e8
    style W fill:#f3e5f5
    style Y fill:#ffebee

Conflict Resolution System

Conflict Detection & Classification

When scheduling a period for Class B, we check:

  1. Teacher Availability: Is teacher free at this date/time?
  2. If Occupied: Who is the teacher teaching? → Class A (blocking class)
  3. Subject Match: Is it the same subject?
  4. Reorder Feasibility: Can we reorder Class A's subjects?

Example Scenario

Setup:

  • Class 10A (IT Major): Math, Physics, Programming
  • Class 10B (IT Major): Math, Physics, Programming
  • Teacher Nguyễn Văn A teaches Math for both classes

Initial Schedule (Class 10A already completed):

Monday 07:15 - Class 10A - Math - Teacher Nguyễn Văn A ✓
Monday 08:15 - Class 10A - Physics - Teacher Trần Thị B ✓
Tuesday 07:15 - Class 10A - Programming - Teacher Lê Văn C ✓

Scheduling Class 10B:

// Try to schedule Math for Class 10B at Monday 07:15
const conflict = checkTeacherAvailability(
  teacherId: "Nguyễn Văn A",
  date: "2025-01-06",
  time: "07:15"
);
 
// Result:
conflict = {
  isAvailable: false,
  blockingClass: {
    classId: 10A,
    className: "Lớp 10A",
    subject: "Math",
    date: "2025-01-06",
    time: "07:15"
  }
}

Resolution Options:

Option 1: Reorder Blocking Class (Class 10A)

// Current order: Math(1) → Physics(2) → Programming(3)
// New order:     Physics(1) → Math(2) → Programming(3)
 
reorderClass({
  classId: 10A,
  newSubjectOrder: [
    { subjectId: 2, newOrder: 1 }, // Physics moves to 1
    { subjectId: 1, newOrder: 2 }, // Math moves to 2
    { subjectId: 3, newOrder: 3 }  // Programming stays
  ]
});
 
// Result: Math moved to Tuesday 07:15
// Monday 07:15 now FREE for Class 10B!

Option 2: Change Teacher for Class 10B

// Find alternative qualified teachers
const alternatives = getQualifiedTeachers({
  subjectId: 1, // Math
  available: true,
  date: "2025-01-06",
  time: "07:15",
});
 
// Result: [Teacher Phạm Thị D, Teacher Hoàng Văn E]
// Suggest to user: "Use Teacher Phạm Thị D instead?"

All-or-Nothing Validation

Core Principle

Schedule entire class semester OR fail completely with diagnostics.

No partial schedules. No orphaned periods. Clean success or informative failure.

Implementation Architecture

sequenceDiagram
    participant UI as User Interface
    participant API as Scheduling API
    participant V as Validation Engine
    participant R as Reorder Engine
    participant DB as Database
 
    UI->>API: scheduleClassSemester(classId, semesterId)
    API->>DB: BEGIN TRANSACTION
 
    API->>V: Validate ALL subjects
 
    loop For each subject
        V->>V: Simulate period creation
        V->>R: Check teacher availability
 
        alt Teacher Available
            V->>V: Mark subject valid ✓
        else Conflict Detected
            R->>R: Try reorder blocking class
            alt Reorder Success
                R->>V: Conflict resolved ✓
            else Reorder Failed
                R->>R: Find alternative teachers
                alt Alternatives Found
                    R-->>UI: Suggest teacher change
                    UI-->>API: User decision
                else No Solution
                    R-->>API: FAIL with diagnostics
                    API->>DB: ROLLBACK TRANSACTION
                    API-->>UI: Show conflict details
                end
            end
        end
    end
 
    alt All Subjects Valid
        API->>DB: CREATE all periods
        API->>DB: COMMIT TRANSACTION
        API-->>UI: Success ✓
    else Validation Failed
        API->>DB: ROLLBACK TRANSACTION
        API-->>UI: Detailed error
    end

Validation Vs Creation Separation

Phase 1: Validation (Simulation)

const validationResults = await validateAllSubjects({
  classId,
  semesterId,
  subjects,
});
 
// In-memory simulation - NO database writes
// Returns: {
//   success: boolean,
//   validSubjects: Subject[],
//   conflicts: Conflict[],
//   suggestions: Resolution[]
// }

Phase 2: Period Creation (Atomic)

if (validationResults.success) {
  await ctx.db.transaction(async (trx) => {
    // Create ALL periods for ALL subjects
    for (const subject of subjects) {
      const periods = generatePeriodsForSubject(subject);
      await trx.insert(periods).values(periods);
    }
    // Commits only if no errors
  });
}

Subject Reordering Logic

When to Reorder

Reordering is triggered when:

  1. Teacher conflict detected for current class
  2. Blocking class is identified (has same teacher + time slot)
  3. ignoreDisplayOrder configuration allows reordering
  4. Reordering creates a valid schedule

Reordering Algorithm: Greedy Conflict Minimization

function findOptimalReordering(
  blockingClass: Class,
  conflictingSubject: Subject,
  targetTimeSlot: TimeSlot
): SubjectOrder[] {
  const currentOrder = blockingClass.subjectOrder;
 
  // Try all permutations of subjects (limited depth search)
  const permutations = generateSmartPermutations(
    currentOrder,
    conflictingSubject
  );
 
  for (const newOrder of permutations) {
    const simulation = simulateScheduleWithOrder(blockingClass, newOrder);
 
    if (simulation.freesTargetTimeSlot && simulation.noNewConflicts) {
      return newOrder; // ✅ Found valid reordering
    }
  }
 
  return null; // ❌ No valid reordering found
}

Smart Permutation Generation

Instead of trying all n! permutations, use heuristics:

  1. Local Swap: Try swapping conflicting subject with neighbors
  2. Move to End: Move conflicting subject to end of sequence
  3. Move to Start: Move conflicting subject to start
  4. Binary Search: Split subjects into before/after groups
function generateSmartPermutations(
  currentOrder: Subject[],
  conflictingSubject: Subject
): SubjectOrder[][] {
  const index = currentOrder.indexOf(conflictingSubject);
  const permutations = [];
 
  // Strategy 1: Swap with next subject
  if (index < currentOrder.length - 1) {
    permutations.push(swap(currentOrder, index, index + 1));
  }
 
  // Strategy 2: Move to end
  permutations.push(moveToEnd(currentOrder, index));
 
  // Strategy 3: Move to position after lunch break
  permutations.push(moveToAfternoon(currentOrder, index));
 
  // Sort by predicted conflict reduction
  return permutations.sort(
    (a, b) => estimateConflicts(a) - estimateConflicts(b)
  );
}

Reordering Example

Scenario:

Class 10A (Blocking): Math → Physics → Programming
Class 10B (Current):  Math → Physics → Programming

Conflict: Math @ Monday 07:15
Blocking Class: 10A
Target: Free up Monday 07:15

Reordering Process:

// Step 1: Identify subject to move (Math)
const subjectToMove = "Math";
 
// Step 2: Generate candidate reorderings
const candidates = [
  ["Physics", "Math", "Programming"], // Swap with next
  ["Physics", "Programming", "Math"], // Move to end
  ["Programming", "Physics", "Math"], // Full **reorder**
];
 
// Step 3: Simulate each candidate
for (const newOrder of candidates) {
  const result = simulateReorder(Class10A, newOrder);
 
  if (result.success && result.freesMonday0715) {
    applyReordering(Class10A, newOrder);
    return; // ✅ Conflict resolved
  }
}

After Reordering:

Class 10A (New Order): Physics → Math → Programming

Monday 07:15 - Class 10A - Physics ✓ (was Math)
Monday 08:15 - Class 10A - Math ✓ (moved from 07:15)
Tuesday 07:15 - Class 10A - Programming ✓

Monday 07:15 - Class 10B - Math ✓ (conflict resolved!)

Reordering Constraints

Reordering must respect:

  1. DisplayOrder Configuration: Only reorder if ignoreDisplayOrder allows
  2. No New Conflicts: Reordering must not create new teacher conflicts
  3. Minimal Disruption: Prefer smallest reordering (swap > move > full reorder)
  4. Transaction Safety: Reorder in same transaction as validation

User Interface Design

Conflict Resolution Modal

When scheduling fails, show actionable diagnostics:

interface ConflictDiagnostics {
  message: string;
  conflicts: Array<{
    subject: string;
    teacher: string;
    timeSlot: string;
    blockingClass: string;
    blockingSubject: string;
  }>;
  resolutions: Array<{
    type: "CHANGE_TEACHER" | "REORDER_SUBJECTS";
    description: string;
    actionLabel: string;
    onClick: () => void;
  }>;
}

UI Mockup:

╔═══════════════════════════════════════════════════════════╗
║ ⚠️ Cannot Schedule Class 10B                              ║
╠═══════════════════════════════════════════════════════════╣
║                                                            ║
║ Conflicts Detected (2):                                   ║
║                                                            ║
║ 1. Math @ Monday 07:15                                    ║
║    Teacher: Nguyễn Văn A                                  ║
║    Conflict with: Class 10A - Math                        ║
║                                                            ║
║    Suggested Solutions:                                   ║
║    [🔄 Reorder Class 10A]  [👤 Change Teacher]           ║
║                                                            ║
║ 2. Physics @ Tuesday 08:15                                ║
║    Teacher: Trần Thị B                                    ║
║    Conflict with: Class 9A - Chemistry                    ║
║                                                            ║
║    Suggested Solutions:                                   ║
║    [🔄 Reorder Class 9A]  [👤 Use Teacher Lê Văn C]      ║
║                                                            ║
╠═══════════════════════════════════════════════════════════╣
║              [❌ Cancel]         [🔍 View Details]         ║
╚═══════════════════════════════════════════════════════════╝

Button Actions

Reorder Button:

const handleReorder = async (blockingClass: Class) => {
  const confirmed = await showConfirmation({
    title: "Reorder Class Schedule?",
    message: `This will reschedule ${blockingClass.name} to resolve conflicts. Continue?`,
    confirmLabel: "Reorder",
    cancelLabel: "Cancel",
  });
 
  if (confirmed) {
    await api.scheduling.reorderClassSubjects.mutate({
      classId: blockingClass.id,
      semesterId,
      autoResolveConflicts: true,
    });
 
    // Retry current class scheduling
    retryScheduling();
  }
};

Change Teacher Button:

const handleChangeTeacher = async (
  subject: Subject,
  alternativeTeacher: Teacher
) => {
  await api.scheduling.updateSubjectConfig.mutate({
    classId: currentClass.id,
    semesterId,
    subjectId: subject.id,
    assignedTeacherId: alternativeTeacher.id,
  });
 
  // Retry scheduling with new teacher
  retryScheduling();
};

API Architecture

New Endpoints for Intelligent Scheduling

1. scheduleClassSemester (All-or-Nothing)

api.scheduling.scheduleClassSemester.useMutation({
  input: {
    classId: number;
    semesterId: number;
    autoResolveConflicts: boolean; // Enable automatic reordering
  },
  output: {
    success: boolean;
    periodsCreated?: number;
    conflicts?: ConflictDiagnostics;
  }
});

Process:

  1. Validate all subjects can be scheduled
  2. If conflicts → attempt automatic reordering (if enabled)
  3. If still conflicts → return detailed diagnostics
  4. If all valid → create all periods atomically
  5. Return success or failure with actionable errors

2. validateClassSchedule (Simulation Only)

api.scheduling.validateClassSchedule.useQuery({
  input: {
    classId: number;
    semesterId: number;
  },
  output: {
    isValid: boolean;
    conflicts: Conflict[];
    suggestions: Resolution[];
  }
});

Purpose: Dry-run validation without creating periods.

3. reorderClassSubjects (Conflict Resolution)

api.scheduling.reorderClassSubjects.useMutation({
  input: {
    classId: number;
    semesterId: number;
    autoResolveConflicts: boolean;
  },
  output: {
    success: boolean;
    newOrder: SubjectOrder[];
    periodsRescheduled: number;
  }
});

Process:

  1. Delete existing periods for class
  2. Find optimal subject ordering
  3. Recreate periods with new order
  4. Validate no new conflicts introduced

Database Schema

Key Tables

classSubjectProgress

ALTER TABLE class_subject_progress
ADD COLUMN canReorder BOOLEAN NOT NULL DEFAULT true,
ADD COLUMN reorderPriority INTEGER, -- Lower = less likely to be reordered
ADD COLUMN lastReordered TIMESTAMP;

schedulingConflicts (New - Audit Trail)

CREATE TABLE scheduling_conflicts (
  id SERIAL PRIMARY KEY,
  classId INTEGER NOT NULL,
  semesterId INTEGER NOT NULL,
  subjectId INTEGER NOT NULL,
  conflictType VARCHAR(50) NOT NULL, -- 'TEACHER_UNAVAILABLE', 'TIME_CONFLICT'
  blockingClassId INTEGER,
  blockingSubjectId INTEGER,
  resolutionType VARCHAR(50), -- 'REORDER', 'CHANGE_TEACHER', 'MANUAL'
  resolvedAt TIMESTAMP,
  createdAt TIMESTAMP DEFAULT NOW()
);

subjectReorderHistory (New - Track Reorderings)

CREATE TABLE subject_reorder_history (
  id SERIAL PRIMARY KEY,
  classId INTEGER NOT NULL,
  semesterId INTEGER NOT NULL,
  oldOrder JSONB NOT NULL, -- [{"subjectId": 1, "order": 1}, ...]
  newOrder JSONB NOT NULL,
  reason TEXT,
  triggeredBy INTEGER, -- User ID or NULL for automatic
  createdAt TIMESTAMP DEFAULT NOW()
);

Performance Considerations

Optimization Strategies

  1. Early Termination: Stop validation on first unresolvable conflict
  2. Greedy First: Use fast greedy algorithm, fallback to CSP only if needed
  3. Memoization: Cache conflict checks for same teacher/time combinations
  4. Parallel Validation: Check multiple subjects concurrently (where independent)
  5. Smart Permutations: Limit reordering search space with heuristics

Complexity Analysis

Operation Average Case Worst Case
Validation (No Conflicts) O(n × m) O(n × m)
Greedy Scheduling O(n² × m) O(n² × m)
CSP Backtracking O(n × m × k) O(n! × m!)
Reordering Search O(m²) O(m!)
Complete Schedule O(n² × m) O(n! × m!)

Where:

  • n = number of classes
  • m = number of subjects per class
  • k = average reordering attempts before success

Expected Performance:

  • 50 classes × 10 subjects: ~2-5 seconds
  • 100 classes × 10 subjects: ~10-20 seconds
  • 200 classes × 10 subjects: ~30-60 seconds (greedy path)

Implementation Roadmap

Phase 1: All-or-Nothing Validation (Priority: HIGH)

  • Implement simulation-based validation
  • Add transaction wrapper for atomic creation
  • Build conflict detection system
  • Create detailed error diagnostics

Phase 2: Subject Reordering (Priority: HIGH)

  • Implement greedy reordering algorithm
  • Build conflict graph data structure
  • Add reorder history tracking
  • Create reorder API endpoints

Phase 3: UI Enhancement (Priority: MEDIUM)

  • Design conflict resolution modal
  • Implement actionable buttons (reorder/change teacher)
  • Add real-time validation feedback
  • Create progress indicators for long operations

Phase 4: Advanced Optimization (Priority: LOW)

  • Implement CSP backtracking fallback
  • Add simulated annealing option
  • Build performance profiling dashboard
  • Create batch scheduling API

Testing Strategy

Unit Tests

  • Conflict detection logic
  • Reordering algorithms
  • Validation simulation
  • Transaction rollback scenarios

Integration Tests

  • End-to-end scheduling workflow
  • Cross-class conflict resolution
  • Database transaction safety
  • API endpoint behavior

Performance Tests

  • Large dataset scheduling (200+ classes)
  • Worst-case CSP scenarios
  • Concurrent scheduling requests
  • Memory usage under load

User Acceptance Tests

  • Conflict resolution flow
  • Error message clarity
  • Button action effectiveness
  • Schedule visualization accuracy

Document Status: ✅ Complete Architecture Design - Ready for Implementation Approval