# Complete Optimization Problem and Solution: aircraft

## 1. Problem Context and Goals

### Context  
The objective is to optimize the allocation of aircraft to various airports to maximize the total number of passengers transported. This involves making decisions about the number of aircraft assigned to each airport, which is represented by the decision variable 'number_of_aircraft[i]'. Each aircraft has a specific passenger capacity, and the goal is to maximize the total passengers transported, calculated as the sum of the product of each aircraft's capacity and the number of aircraft assigned to each airport.

Operational parameters include the maximum weight capacity of each aircraft, which serves as a constraint to ensure that the number of passengers transported by any aircraft does not exceed its capacity. Additionally, there is a constraint on the maximum number of aircraft movements allowed at each airport, ensuring that the total aircraft movements do not exceed this limit. These constraints are critical to maintaining operational feasibility and are derived from the business configuration parameters.

### Goals  
The primary goal of this optimization problem is to maximize the total number of passengers transported across all airports. This is achieved by optimizing the allocation of aircraft to airports, ensuring that the total passenger capacity is fully utilized. The success of this optimization is measured by the total number of passengers transported, which is directly linked to the aircraft capacities and the number of aircraft assigned to each airport. The optimization goal is clearly defined in linear terms, focusing on maximizing the sum of the passenger capacities of the assigned aircraft.

## 2. Constraints    

The optimization problem is subject to several constraints that ensure operational feasibility:

- **Aircraft Capacity Constraint**: For each aircraft, the number of passengers transported cannot exceed its capacity. This constraint ensures that the allocation of aircraft respects the maximum weight capacity of each aircraft, as defined in the business configuration.

- **Airport Movement Constraint**: The total number of aircraft movements at each airport cannot exceed the specified limit. This constraint ensures that the operations at each airport remain within the allowable movement limits, maintaining efficient and feasible airport operations.

These constraints are expressed in business terms that naturally lead to linear mathematical forms, ensuring that the optimization problem remains within the realm of linear programming.

## 3. Available Data  

### Database Schema  
```sql
-- Iteration 1 Database Schema
-- Objective: Schema changes include adding tables for passenger capacity and aircraft assignments, modifying existing tables to include missing data, and updating configuration logic for scalar parameters and formulas.

CREATE TABLE passenger_capacity (
  aircraft_id INTEGER,
  capacity INTEGER
);

CREATE TABLE aircraft_assignment (
  airport_id INTEGER,
  number_of_aircraft INTEGER
);
```

### Data Dictionary  
The data dictionary provides a comprehensive mapping of tables and columns to their business purposes and optimization roles:

- **Passenger Capacity Table**: This table stores the passenger capacity for each aircraft. The 'aircraft_id' column uniquely identifies each aircraft, while the 'capacity' column represents the passenger capacity of the aircraft. This data is crucial for determining the coefficients in the optimization objective, linking each aircraft's capacity to its potential contribution to the total passengers transported.

- **Aircraft Assignment Table**: This table tracks the number of aircraft assigned to each airport. The 'airport_id' column uniquely identifies each airport, and the 'number_of_aircraft' column indicates the number of aircraft assigned to that airport. This data serves as the decision variable in the optimization model, directly influencing the allocation strategy to maximize passenger transport.

### Current Stored Values  
```sql
-- Iteration 1 Realistic Data
-- Generated by triple expert (business + data + optimization)
-- Values were determined based on typical aircraft capacities and airport movement limits, ensuring a balance between aircraft capabilities and airport constraints.

-- Realistic data for passenger_capacity
INSERT INTO passenger_capacity (aircraft_id, capacity) VALUES (1, 150);
INSERT INTO passenger_capacity (aircraft_id, capacity) VALUES (2, 180);
INSERT INTO passenger_capacity (aircraft_id, capacity) VALUES (3, 200);

-- Realistic data for aircraft_assignment
INSERT INTO aircraft_assignment (airport_id, number_of_aircraft) VALUES (1, 3);
INSERT INTO aircraft_assignment (airport_id, number_of_aircraft) VALUES (2, 5);
INSERT INTO aircraft_assignment (airport_id, number_of_aircraft) VALUES (3, 7);
```

## 4. Mathematical Optimization Formulation

#### Decision Variables
- Let \( x_{ij} \) be the number of aircraft of type \( i \) assigned to airport \( j \).

#### Objective Function
Maximize the total number of passengers transported:
\[ \text{Maximize } Z = \sum_{i} \sum_{j} \text{capacity}_i \times x_{ij} \]

Where:
- \(\text{capacity}_i\) is the passenger capacity of aircraft type \( i \).

#### Constraints

1. **Aircraft Capacity Constraint**: Ensure that the number of passengers transported by any aircraft does not exceed its capacity.
   \[
   \sum_{j} x_{ij} \leq \text{number\_of\_aircraft}_j \quad \forall i
   \]

2. **Airport Movement Constraint**: The total number of aircraft movements at each airport cannot exceed the specified limit.
   \[
   \sum_{i} x_{ij} \leq \text{movement\_limit}_j \quad \forall j
   \]

3. **Non-negativity and Integer Constraints**: 
   \[
   x_{ij} \geq 0 \quad \text{and integer} \quad \forall i, j
   \]

Data Source Verification:
- \(\text{capacity}_i\) comes from `passenger_capacity.capacity` for each `aircraft_id`.
- \(\text{number\_of\_aircraft}_j\) comes from `aircraft_assignment.number_of_aircraft` for each `airport_id`.
- \(\text{movement\_limit}_j\) is a business configuration parameter specifying the maximum allowable aircraft movements at each airport.

This formulation provides a linear optimization model that can be solved using standard linear programming or mixed-integer programming techniques to determine the optimal allocation of aircraft to maximize passenger transport while respecting all operational constraints.

## 5. Gurobipy Implementation

```python
# 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()
```

### Execution Results
**Status**: OPTIMAL
**Optimal Value**: 2750.0
**Execution Time**: 0.51 seconds
**Reliability**: high
**Analysis**: Gurobipy found an optimal solution quickly with the shortest execution time, indicating efficient performance and reliability.

## 6. DOCplex Implementation

```python
# Complete DOCPLEX implementation

from docplex.mp.model import Model

def optimize_aircraft_allocation():
    """Optimize aircraft allocation to maximize passenger transport"""
    
    # 1. MODEL & DATA SETUP
    mdl = Model(name="aircraft_allocation")
    
    # Data: Passenger capacities and aircraft assignments
    passenger_capacities = [150, 180, 200]  # Example capacities for aircraft types
    aircraft_assignments = [3, 5, 7]  # Example number of aircraft assigned to airports
    movement_limits = [10, 12, 15]  # Example movement limits for airports
    
    # CRITICAL: Validate array lengths to prevent IndexError
    assert len(passenger_capacities) == len(aircraft_assignments) == len(movement_limits), "Array length mismatch"
    safe_range = range(min(len(passenger_capacities), len(aircraft_assignments), len(movement_limits)))  # Safe indexing
    
    # 2. VARIABLES
    # Decision variables: number of aircraft of type i assigned to airport j
    x = {(i, j): mdl.integer_var(name=f"x_{i}_{j}", lb=0) for i in safe_range for j in safe_range}
    
    # 3. OBJECTIVE FUNCTION
    # Maximize total number of passengers transported
    objective = mdl.sum(passenger_capacities[i] * x[i, j] for i in safe_range for j in safe_range)
    mdl.maximize(objective)
    
    # 4. CONSTRAINTS - CORRECT SYNTAX PATTERNS
    
    # Aircraft Capacity Constraint
    for i in safe_range:
        mdl.add_constraint(mdl.sum(x[i, j] for j in safe_range) <= aircraft_assignments[i], ctname=f"aircraft_capacity_{i}")
    
    # Airport Movement Constraint
    for j in safe_range:
        mdl.add_constraint(mdl.sum(x[i, j] for i in safe_range) <= movement_limits[j], ctname=f"airport_movement_{j}")
    
    # 5. SOLVING & RESULTS
    solution = mdl.solve()
    
    if solution:
        print(f"Optimal value: {solution.objective_value}")
        for i in safe_range:
            for j in safe_range:
                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_aircraft_allocation()
```

### Execution Results
**Status**: OPTIMAL
**Optimal Value**: 2750.0
**Execution Time**: 3.34 seconds
**Reliability**: high
**Analysis**: DOCplex also found an optimal solution, albeit with a longer execution time compared to Gurobipy, but still reliable.

## 7. Pyomo Implementation

```python
# Complete PYOMO implementation

import pyomo.environ as pyo
from pyomo.opt import SolverFactory

def aircraft_optimization():
    """Optimize aircraft allocation to maximize passenger transport"""

    # 1. MODEL CREATION
    model = pyo.ConcreteModel()

    # 2. DATA SETUP
    aircraft_ids = [1, 2, 3]
    airport_ids = [1, 2, 3]
    capacities = {1: 150, 2: 180, 3: 200}
    number_of_aircraft = {1: 3, 2: 5, 3: 7}
    movement_limits = {1: 10, 2: 15, 3: 20}

    # CRITICAL: Validate array lengths before indexing
    assert len(capacities) == len(aircraft_ids), "Capacity data length mismatch"
    assert len(number_of_aircraft) == len(airport_ids), "Aircraft data length mismatch"
    assert len(movement_limits) == len(airport_ids), "Movement limit data length mismatch"

    # 3. SETS
    model.I = pyo.Set(initialize=aircraft_ids)
    model.J = pyo.Set(initialize=airport_ids)

    # 4. PARAMETERS
    model.capacity = pyo.Param(model.I, initialize=capacities)
    model.number_of_aircraft = pyo.Param(model.J, initialize=number_of_aircraft)
    model.movement_limit = pyo.Param(model.J, initialize=movement_limits)

    # 5. VARIABLES
    model.x = pyo.Var(model.I, model.J, within=pyo.NonNegativeIntegers)

    # 6. OBJECTIVE FUNCTION
    def obj_rule(model):
        return sum(model.capacity[i] * model.x[i, j] for i in model.I for j in model.J)
    model.objective = pyo.Objective(rule=obj_rule, sense=pyo.maximize)

    # 7. CONSTRAINTS

    # Aircraft Capacity Constraint
    def aircraft_capacity_rule(model, i):
        return sum(model.x[i, j] for j in model.J) <= model.number_of_aircraft[i]
    model.aircraft_capacity_constraint = pyo.Constraint(model.I, rule=aircraft_capacity_rule)

    # Airport Movement Constraint
    def airport_movement_rule(model, j):
        return sum(model.x[i, j] for i in model.I) <= model.movement_limit[j]
    model.airport_movement_constraint = pyo.Constraint(model.J, rule=airport_movement_rule)

    # 8. SOLVING WITH GUROBI
    solver = SolverFactory('gurobi')

    # Optional: Set solver options
    solver.options['TimeLimit'] = 300  # 5 minutes
    solver.options['MIPGap'] = 0.01    # 1% gap

    # Solve the model
    results = solver.solve(model, tee=True)

    # 9. RESULT PROCESSING
    if results.solver.termination_condition == pyo.TerminationCondition.optimal:
        print("Optimal solution found!")
        print(f"Optimal value: {pyo.value(model.objective)}")

        # Extract variable values
        print("\nVariable values:")
        for i in model.I:
            for j in model.J:
                x_val = pyo.value(model.x[i, j])
                if x_val > 1e-6:  # Only print non-zero values
                    print(f"x[{i},{j}] = {x_val:.3f}")

    elif results.solver.termination_condition == pyo.TerminationCondition.infeasible:
        print("Problem is infeasible")
    elif results.solver.termination_condition == pyo.TerminationCondition.unbounded:
        print("Problem is unbounded")
    else:
        print(f"Solver terminated with condition: {results.solver.termination_condition}")

    return model

# Run the optimization
aircraft_optimization()
```

### Execution Results
**Status**: OPTIMAL
**Optimal Value**: 2750.0
**Execution Time**: 1.86 seconds
**Reliability**: high
**Analysis**: Pyomo achieved an optimal solution with a moderate execution time, demonstrating reliability and consistency with other solvers.

## 8. Cross-Solver Analysis and Final Recommendation

### Solver Results Comparison

| Solver | Status | Optimal Value | Execution Time | Decision Variables | Retry Attempt |
|--------|--------|---------------|----------------|-------------------|---------------|
| Gurobipy | OPTIMAL | 2750.00 | 0.51s | N/A | N/A |
| Docplex | OPTIMAL | 2750.00 | 3.34s | N/A | N/A |
| Pyomo | OPTIMAL | 2750.00 | 1.86s | N/A | N/A |

### Solver Consistency Analysis
**Result**: All solvers produced consistent results ✓
**Consistent Solvers**: gurobipy, docplex, pyomo
**Majority Vote Optimal Value**: 2750.0

### Final Recommendation
**Recommended Optimal Value**: 2750.0
**Confidence Level**: HIGH
**Preferred Solver(s)**: gurobipy
**Reasoning**: Gurobipy is recommended due to its fastest execution time and high reliability, making it suitable for real-time or large-scale applications.

### Business Interpretation
**Overall Strategy**: The optimal allocation of aircraft maximizes passenger transport capacity, ensuring efficient use of resources.
**Objective Value Meaning**: The optimal objective value of 2750.0 represents the maximum number of passengers that can be transported given the constraints.
**Resource Allocation Summary**: Aircraft should be allocated to airports in a manner that maximizes passenger capacity while adhering to movement and capacity constraints.
**Implementation Recommendations**: Implement the solution by adjusting aircraft assignments according to the solver's output, ensuring compliance with operational constraints and maximizing efficiency.