# Complete GUROBIPY implementation

import gurobipy as gp
from gurobipy import GRB

def optimize_classroom_assignment():
    """Optimize student assignments to classrooms to minimize the maximum number of students in any classroom."""
    
    # 1. MODEL & DATA SETUP
    model = gp.Model("classroom_assignment")
    
    # Example data setup
    students = [1, 2, 3, 4, 5]
    classrooms = [101, 102, 103]
    max_students = {101: 25, 102: 30, 103: 35}
    
    # CRITICAL: Validate array lengths before loops
    assert len(students) > 0, "No students available"
    assert len(classrooms) > 0, "No classrooms available"
    
    # 2. VARIABLES
    # Binary decision variables for student assignments
    x = model.addVars(students, classrooms, vtype=GRB.BINARY, name="x")
    
    # Auxiliary variable for the maximum number of students in any classroom
    M = model.addVar(vtype=GRB.CONTINUOUS, name="M", lb=0)
    
    # 3. OBJECTIVE FUNCTION
    # Minimize the maximum number of students in any classroom
    model.setObjective(M, GRB.MINIMIZE)
    
    # 4. CONSTRAINTS - CORRECT SYNTAX PATTERNS
    
    # Classroom capacity constraints
    model.addConstrs(
        (gp.quicksum(x[i, j] for i in students) <= max_students[j] for j in classrooms),
        name="classroom_capacity"
    )
    
    # Student assignment constraints
    model.addConstrs(
        (gp.quicksum(x[i, j] for j in classrooms) == 1 for i in students),
        name="student_assignment"
    )
    
    # Maximum students constraint
    model.addConstrs(
        (gp.quicksum(x[i, j] for i in students) <= M for j in classrooms),
        name="max_students"
    )
    
    # 5. SOLVING & RESULTS
    model.optimize()
    
    if model.status == GRB.OPTIMAL:
        print(f"Optimal value: {model.objVal}")
        for i in students:
            for j in classrooms:
                if x[i, j].x > 1e-6:
                    print(f"Student {i} assigned to classroom {j}")
    elif model.status == GRB.INFEASIBLE:
        print("Problem is infeasible")
    elif model.status == GRB.UNBOUNDED:
        print("Problem is unbounded")
    
    return model

# Run the optimization
optimize_classroom_assignment()