# Complete DOCPLEX implementation

from docplex.mp.model import Model

def optimize_pilot_assignments():
    """Optimize the assignment of pilots to aircraft to minimize total flights."""
    
    # 1. MODEL & DATA SETUP
    mdl = Model(name="pilot_record")
    
    # Data from the database schema
    pilots = [1, 2, 3]
    aircrafts = [101, 102, 103]
    
    # Minimum flights required for each pilot
    min_flights = {1: 10, 2: 15, 3: 12}
    
    # Maximum flights allowed for each aircraft
    max_flights = {101: 120, 102: 100, 103: 110}
    
    # Validate array lengths to prevent IndexError
    assert len(pilots) == len(min_flights), "Mismatch in pilots and min_flights"
    assert len(aircrafts) == len(max_flights), "Mismatch in aircrafts and max_flights"
    
    # Safe indexing range
    safe_pilot_range = range(len(pilots))
    safe_aircraft_range = range(len(aircrafts))
    
    # 2. VARIABLES
    # Decision variables: number of flights assigned to each pilot for each aircraft
    x = {(i, j): mdl.integer_var(name=f"x_{i}_{j}", lb=0) for i in pilots for j in aircrafts}
    
    # 3. OBJECTIVE FUNCTION
    # Minimize the total number of flights assigned
    objective = mdl.sum(x[i, j] for i in pilots for j in aircrafts)
    mdl.minimize(objective)
    
    # 4. CONSTRAINTS
    
    # Pilot minimum flight requirement
    for i in pilots:
        mdl.add_constraint(mdl.sum(x[i, j] for j in aircrafts) >= min_flights[i], ctname=f"min_flights_{i}")
    
    # Aircraft maximum flight capacity
    for j in aircrafts:
        mdl.add_constraint(mdl.sum(x[i, j] for i in pilots) <= max_flights[j], ctname=f"max_flights_{j}")
    
    # 5. SOLVING & RESULTS
    solution = mdl.solve()
    
    if solution:
        print(f"Optimal value: {solution.objective_value}")
        for i in pilots:
            for j in aircrafts:
                value = solution.get_value(x[i, j])
                if value > 1e-6:
                    print(f"x[{i},{j}] = {value:.3f}")
    else:
        print("No solution found")
        print(f"Status: {mdl.solve_details.status}")

    return mdl

# Run the optimization
optimize_pilot_assignments()