# Complete GUROBIPY implementation

import gurobipy as gp
from gurobipy import GRB

def optimize_aircraft_allocation():
    """Optimize aircraft allocation to maximize passenger transport"""
    
    # 1. MODEL & DATA SETUP
    model = gp.Model("aircraft_allocation")
    
    # Data: Passenger capacities and aircraft assignments
    capacities = [150, 180, 200]  # Example capacities for aircraft types
    number_of_aircraft = [3, 5, 7]  # Example number of aircraft assigned to airports
    movement_limits = [10, 15, 20]  # Example movement limits for airports
    
    n_aircraft_types = len(capacities)
    n_airports = len(number_of_aircraft)
    
    # CRITICAL: Validate array lengths before loops
    assert len(capacities) == n_aircraft_types, "Capacity array length mismatch"
    assert len(number_of_aircraft) == n_airports, "Aircraft assignment array length mismatch"
    assert len(movement_limits) == n_airports, "Movement limits array length mismatch"
    
    # 2. VARIABLES
    # Decision variables: x[i, j] is the number of aircraft of type i assigned to airport j
    x = model.addVars(n_aircraft_types, n_airports, vtype=GRB.INTEGER, name="x", lb=0)
    
    # 3. OBJECTIVE FUNCTION
    # Maximize total number of passengers transported
    model.setObjective(gp.quicksum(capacities[i] * x[i, j] for i in range(n_aircraft_types) for j in range(n_airports)), GRB.MAXIMIZE)
    
    # 4. CONSTRAINTS
    
    # Aircraft Capacity Constraint
    for i in range(n_aircraft_types):
        model.addConstr(gp.quicksum(x[i, j] for j in range(n_airports)) <= number_of_aircraft[i], name=f"capacity_constraint_{i}")
    
    # Airport Movement Constraint
    for j in range(n_airports):
        model.addConstr(gp.quicksum(x[i, j] for i in range(n_aircraft_types)) <= movement_limits[j], name=f"movement_constraint_{j}")
    
    # 5. SOLVING & RESULTS
    model.optimize()
    
    if model.status == GRB.OPTIMAL:
        print(f"Optimal value: {model.objVal}")
        for i in range(n_aircraft_types):
            for j in range(n_airports):
                if x[i, j].x > 1e-6:
                    print(f"x[{i},{j}] = {x[i, j].x:.3f}")
    elif model.status == GRB.INFEASIBLE:
        print("Problem is infeasible")
    elif model.status == GRB.UNBOUNDED:
        print("Problem is unbounded")
    
    return model

# Run the optimization
optimize_aircraft_allocation()