# Complete GUROBIPY implementation - Retry Attempt 4

import gurobipy as gp
from gurobipy import GRB

def flight_assignment_optimization():
    # 1. MODEL & DATA SETUP
    model = gp.Model("flight_assignment")
    
    # Data from the problem
    airlines = [1, 2, 3]
    routes = [1, 2, 3]
    
    # Cost data
    cost_data = {
        (1, 1): 1200.0,
        (1, 2): 1800.0,
        (1, 3): 2500.0
    }
    
    # Capacity data
    capacity_data = {
        1: 8,
        2: 12,
        3: 6
    }
    
    # Validate array lengths
    assert len(cost_data) == len(airlines) * len(routes), "Cost data length mismatch"
    assert len(capacity_data) == len(airlines), "Capacity data length mismatch"
    
    # 2. VARIABLES
    x = model.addVars(airlines, routes, vtype=GRB.BINARY, name="x")
    
    # 3. OBJECTIVE FUNCTION
    model.setObjective(gp.quicksum(cost_data[a, r] * x[a, r] for a in airlines for r in routes), GRB.MINIMIZE)
    
    # 4. CONSTRAINTS
    # Route Coverage: Each route must be assigned to exactly one airline
    for r in routes:
        model.addConstr(gp.quicksum(x[a, r] for a in airlines) == 1, name=f"route_coverage_{r}")
    
    # Airline Capacity: No airline can be assigned more routes than its capacity
    for a in airlines:
        model.addConstr(gp.quicksum(x[a, r] for r in routes) <= capacity_data[a], name=f"capacity_{a}")
    
    # 5. SOLVING & RESULTS
    model.optimize()
    
    if model.status == GRB.OPTIMAL:
        print(f"Optimal value: {model.objVal}")
        for a in airlines:
            for r in routes:
                if x[a, r].x > 1e-6:
                    print(f"Airline {a} assigned to route {r}")
    elif model.status == GRB.INFEASIBLE:
        print("Problem is infeasible")
    elif model.status == GRB.UNBOUNDED:
        print("Problem is unbounded")
    
    return model

# Execute the optimization
flight_assignment_optimization()