# Complete GUROBIPY implementation - Retry Attempt 4

import gurobipy as gp
from gurobipy import GRB

def aircraft_assignment_optimization():
    # 1. MODEL & DATA SETUP
    model = gp.Model("AircraftAssignment")
    
    # Aircraft types and airports
    aircraft_types = ['Boeing 737', 'Airbus A320', 'Boeing 777']
    airports = ['JFK', 'LAX', 'ORD']
    
    # Operational costs (aircraft_type, airport_code): cost
    operational_costs = {
        ('Boeing 737', 'JFK'): 5000.0,
        ('Airbus A320', 'JFK'): 5500.0,
        ('Boeing 777', 'JFK'): 8000.0,
        ('Boeing 737', 'LAX'): 4800.0,
        ('Airbus A320', 'LAX'): 5200.0,
        ('Boeing 737', 'ORD'): 5000.0,
        ('Airbus A320', 'ORD'): 5500.0,
        ('Boeing 777', 'ORD'): 8000.0
    }
    
    # Passenger capacities (aircraft_type): capacity
    passenger_capacities = {
        'Boeing 737': 150,
        'Airbus A320': 180,
        'Boeing 777': 300
    }
    
    # Airport demands and movements (airport_code): (demand, movements)
    airport_data = {
        'JFK': (15000, 50),
        'LAX': (20000, 60),
        'ORD': (18000, 55)
    }
    
    # 2. VARIABLES
    x = model.addVars(aircraft_types, airports, vtype=GRB.INTEGER, name="x", lb=0)
    
    # 3. OBJECTIVE FUNCTION
    model.setObjective(
        gp.quicksum(operational_costs[(i, j)] * x[i, j] for i in aircraft_types for j in airports),
        GRB.MINIMIZE
    )
    
    # 4. CONSTRAINTS
    # Passenger Demand Constraint
    for j in airports:
        model.addConstr(
            gp.quicksum(passenger_capacities[i] * x[i, j] for i in aircraft_types) >= airport_data[j][0],
            name=f"passenger_demand_{j}"
        )
    
    # Aircraft Movement Constraint
    for j in airports:
        model.addConstr(
            gp.quicksum(x[i, j] for i in aircraft_types) <= airport_data[j][1],
            name=f"aircraft_movement_{j}"
        )
    
    # 5. SOLVING & RESULTS
    model.optimize()
    
    if model.status == GRB.OPTIMAL:
        print(f"Optimal value: {model.objVal}")
        for i in aircraft_types:
            for j in airports:
                if x[i, j].x > 1e-6:
                    print(f"x[{i}, {j}] = {x[i, j].x:.0f}")
    elif model.status == GRB.INFEASIBLE:
        print("Problem is infeasible")
    elif model.status == GRB.UNBOUNDED:
        print("Problem is unbounded")
    
    return model

# Execute the optimization
aircraft_assignment_optimization()