# Complete GUROBIPY implementation - Retry Attempt 4

import gurobipy as gp
from gurobipy import GRB

def school_bus_optimization():
    """Optimize school bus driver assignments to minimize experience mismatch."""
    
    # 1. MODEL & DATA SETUP
    model = gp.Model("school_bus")
    
    # Data from the database schema
    drivers = [1, 2, 3]
    schools = [101, 102, 103]
    
    # Experience mismatch data
    years_mismatch = {
        (1, 101): 2,
        (2, 102): 1,
        (3, 103): 0
    }
    
    # Full-time status of drivers
    is_full_time = {
        1: True,
        2: True,
        3: True
    }
    
    # School requirements
    required_drivers = {
        101: 3,
        102: 4,
        103: 5
    }
    
    # Validate data lengths
    assert len(drivers) == len(is_full_time), "Driver data length mismatch"
    assert len(schools) == len(required_drivers), "School data length mismatch"
    
    # 2. VARIABLES
    x = model.addVars(drivers, schools, vtype=GRB.BINARY, name="x")
    
    # 3. OBJECTIVE FUNCTION
    model.setObjective(
        gp.quicksum(years_mismatch.get((i, j), 0) * x[i, j] for i in drivers for j in schools),
        GRB.MINIMIZE
    )
    
    # 4. CONSTRAINTS
    
    # Each driver can be assigned to at most one school
    for i in drivers:
        if is_full_time[i]:
            model.addConstr(gp.quicksum(x[i, j] for j in schools) <= 1, name=f"driver_{i}_assignment")
    
    # Each school must receive the exact number of drivers it requires
    for j in schools:
        model.addConstr(gp.quicksum(x[i, j] for i in drivers) == required_drivers[j], name=f"school_{j}_requirement")
    
    # 5. SOLVING & RESULTS
    model.optimize()
    
    if model.status == GRB.OPTIMAL:
        print(f"Optimal value: {model.objVal}")
        for i in drivers:
            for j in schools:
                if x[i, j].x > 0.5:  # Binary variable threshold
                    print(f"Driver {i} assigned to School {j}")
    elif model.status == GRB.INFEASIBLE:
        print("Problem is infeasible")
    elif model.status == GRB.UNBOUNDED:
        print("Problem is unbounded")
    else:
        print("Optimization ended with status", model.status)

# Run the optimization
school_bus_optimization()