# Complete Optimization Problem and Solution: phone_1

## 1. Problem Context and Goals

### Context  
A phone manufacturer is tasked with optimizing the production of phones to minimize total costs while meeting specific hardware and accreditation requirements. The manufacturer must decide how many phones to produce for each combination of chip model and screen mode. Each chip model has an associated cost, RAM capacity, and ROM capacity, while each screen mode has an associated cost and accreditation level. The goal is to determine the optimal number of phones to produce for each chip model and screen mode combination, ensuring that the total RAM, ROM, and accreditation levels across all produced phones meet or exceed the minimum requirements set by the business.  

The business has established the following minimum requirements for all phones produced:  
- **Total RAM Required**: 8,000 MiB  
- **Total ROM Required**: 128,000 MiB  
- **Total Accreditation Level Required**: 5  

These requirements ensure that the phones meet production targets and quality standards. The manufacturer must balance the costs of chip models and screen modes while adhering to these constraints.  

### Goals  
The primary goal of this optimization problem is to minimize the total cost of producing phones. This cost is determined by the sum of the costs of the chip models and screen modes used in each phone, multiplied by the number of phones produced for each combination. Success is measured by achieving the lowest possible total cost while ensuring that the minimum RAM, ROM, and accreditation level requirements are met.  

## 2. Constraints  

The optimization problem must adhere to the following constraints:  
1. **Total RAM Constraint**: The combined RAM capacity of all phones produced must meet or exceed the minimum total RAM requirement of 8,000 MiB. This is calculated by summing the RAM capacity of each chip model multiplied by the number of phones produced with that chip model.  
2. **Total ROM Constraint**: The combined ROM capacity of all phones produced must meet or exceed the minimum total ROM requirement of 128,000 MiB. This is calculated by summing the ROM capacity of each chip model multiplied by the number of phones produced with that chip model.  
3. **Total Accreditation Level Constraint**: The combined accreditation level of all phones produced must meet or exceed the minimum total accreditation level requirement of 5. This is calculated by summing the accreditation level of each screen mode multiplied by the number of phones produced with that screen mode.  

These constraints ensure that the phones produced meet the necessary hardware and quality standards while minimizing production costs.  

## 3. Available Data  

### Database Schema  
```sql
-- Iteration 1 Database Schema
-- Objective: Schema changes and configuration logic updates implemented to address missing optimization data requirements and mapping gaps identified by the OR expert.

CREATE TABLE chip_models (
  chip_model_id INTEGER,
  cost FLOAT,
  RAM_MiB INTEGER,
  ROM_MiB INTEGER
);

CREATE TABLE screen_modes (
  screen_mode_id INTEGER,
  cost FLOAT,
  Accreditation_level INTEGER
);

CREATE TABLE phone_production (
  chip_model_id INTEGER,
  screen_mode_id INTEGER,
  quantity INTEGER
);
```

### Data Dictionary  
- **chip_models**:  
  - **chip_model_id**: Unique identifier for each chip model.  
  - **cost**: The cost associated with using the chip model in phone production.  
  - **RAM_MiB**: The RAM capacity of the chip model, measured in MiB.  
  - **ROM_MiB**: The ROM capacity of the chip model, measured in MiB.  

- **screen_modes**:  
  - **screen_mode_id**: Unique identifier for each screen mode.  
  - **cost**: The cost associated with using the screen mode in phone production.  
  - **Accreditation_level**: The accreditation level of the screen mode, indicating its quality standard.  

- **phone_production**:  
  - **chip_model_id**: The chip model used in the production of a specific phone.  
  - **screen_mode_id**: The screen mode used in the production of a specific phone.  
  - **quantity**: The number of phones produced with the specified chip model and screen mode combination.  

### Current Stored Values  
```sql
-- Iteration 1 Realistic Data
-- Generated by triple expert (business + data + optimization)
-- Values were determined based on industry standards for phone manufacturing, ensuring realistic costs, capacities, and accreditation levels. The data was designed to create a meaningful optimization problem by balancing costs and constraints.

-- Realistic data for chip_models
INSERT INTO chip_models (chip_model_id, cost, RAM_MiB, ROM_MiB) VALUES (1, 50.0, 2048, 32768);
INSERT INTO chip_models (chip_model_id, cost, RAM_MiB, ROM_MiB) VALUES (2, 75.0, 4096, 65536);
INSERT INTO chip_models (chip_model_id, cost, RAM_MiB, ROM_MiB) VALUES (3, 100.0, 8192, 131072);

-- Realistic data for screen_modes
INSERT INTO screen_modes (screen_mode_id, cost, Accreditation_level) VALUES (1, 30.0, 3);
INSERT INTO screen_modes (screen_mode_id, cost, Accreditation_level) VALUES (2, 45.0, 4);
INSERT INTO screen_modes (screen_mode_id, cost, Accreditation_level) VALUES (3, 60.0, 5);

-- Realistic data for phone_production
INSERT INTO phone_production (chip_model_id, screen_mode_id, quantity) VALUES (1, 1, 10);
INSERT INTO phone_production (chip_model_id, screen_mode_id, quantity) VALUES (2, 2, 20);
INSERT INTO phone_production (chip_model_id, screen_mode_id, quantity) VALUES (3, 3, 30);
```

## 4. Mathematical Optimization Formulation

#### Decision Variables
Let \( x_{i,j} \) be the number of phones produced with chip model \( i \) and screen mode \( j \), where:
- \( i \in \{1, 2, 3\} \) (chip models)
- \( j \in \{1, 2, 3\} \) (screen modes)

#### Objective Function
Minimize the total cost of production:
\[
\text{Minimize } \sum_{i=1}^{3} \sum_{j=1}^{3} (c_i + s_j) \cdot x_{i,j}
\]
where:
- \( c_i \) is the cost of chip model \( i \) (from `chip_models.cost`)
- \( s_j \) is the cost of screen mode \( j \) (from `screen_modes.cost`)

#### Constraints
1. **Total RAM Constraint**:
\[
\sum_{i=1}^{3} \sum_{j=1}^{3} r_i \cdot x_{i,j} \geq 8000
\]
where \( r_i \) is the RAM capacity of chip model \( i \) (from `chip_models.RAM_MiB`).

2. **Total ROM Constraint**:
\[
\sum_{i=1}^{3} \sum_{j=1}^{3} o_i \cdot x_{i,j} \geq 128000
\]
where \( o_i \) is the ROM capacity of chip model \( i \) (from `chip_models.ROM_MiB`).

3. **Total Accreditation Level Constraint**:
\[
\sum_{i=1}^{3} \sum_{j=1}^{3} a_j \cdot x_{i,j} \geq 5
\]
where \( a_j \) is the accreditation level of screen mode \( j \) (from `screen_modes.Accreditation_level`).

4. **Non-Negativity Constraint**:
\[
x_{i,j} \geq 0 \quad \forall i, j
\]

#### Data Source Verification
- \( c_i \): `chip_models.cost`
- \( s_j \): `screen_modes.cost`
- \( r_i \): `chip_models.RAM_MiB`
- \( o_i \): `chip_models.ROM_MiB`
- \( a_j \): `screen_modes.Accreditation_level`

#### Numerical Coefficients
Based on the provided data:
- \( c_1 = 50.0 \), \( c_2 = 75.0 \), \( c_3 = 100.0 \)
- \( s_1 = 30.0 \), \( s_2 = 45.0 \), \( s_3 = 60.0 \)
- \( r_1 = 2048 \), \( r_2 = 4096 \), \( r_3 = 8192 \)
- \( o_1 = 32768 \), \( o_2 = 65536 \), \( o_3 = 131072 \)
- \( a_1 = 3 \), \( a_2 = 4 \), \( a_3 = 5 \)

This formulation provides a complete, immediately solvable LINEAR mathematical model for the optimization problem.

## 5. Gurobipy Implementation

```python
#!/usr/bin/env python3
"""
Gurobipy 12.0.2 Implementation for Phone Production Optimization
"""

import gurobipy as gp
from gurobipy import GRB

def phone_production_optimization():
    """Optimize phone production to minimize total cost while meeting hardware and accreditation requirements."""
    
    # 1. MODEL & DATA SETUP
    model = gp.Model("phone_production")
    
    # Chip models data
    chip_models = {
        1: {"cost": 50.0, "RAM_MiB": 2048, "ROM_MiB": 32768},
        2: {"cost": 75.0, "RAM_MiB": 4096, "ROM_MiB": 65536},
        3: {"cost": 100.0, "RAM_MiB": 8192, "ROM_MiB": 131072}
    }
    
    # Screen modes data
    screen_modes = {
        1: {"cost": 30.0, "Accreditation_level": 3},
        2: {"cost": 45.0, "Accreditation_level": 4},
        3: {"cost": 60.0, "Accreditation_level": 5}
    }
    
    # Minimum requirements
    min_RAM = 8000
    min_ROM = 128000
    min_Accreditation = 5
    
    # Validate data lengths
    assert len(chip_models) == 3, "Chip models data length mismatch"
    assert len(screen_modes) == 3, "Screen modes data length mismatch"
    
    # 2. VARIABLES
    x = model.addVars(chip_models.keys(), screen_modes.keys(), vtype=GRB.CONTINUOUS, name="x", lb=0)
    
    # 3. OBJECTIVE FUNCTION
    model.setObjective(
        gp.quicksum((chip_models[i]["cost"] + screen_modes[j]["cost"]) * x[i, j] 
                    for i in chip_models.keys() for j in screen_modes.keys()), 
        GRB.MINIMIZE
    )
    
    # 4. CONSTRAINTS
    
    # Total RAM Constraint
    model.addConstr(
        gp.quicksum(chip_models[i]["RAM_MiB"] * x[i, j] 
                    for i in chip_models.keys() for j in screen_modes.keys()) >= min_RAM, 
        name="total_RAM"
    )
    
    # Total ROM Constraint
    model.addConstr(
        gp.quicksum(chip_models[i]["ROM_MiB"] * x[i, j] 
                    for i in chip_models.keys() for j in screen_modes.keys()) >= min_ROM, 
        name="total_ROM"
    )
    
    # Total Accreditation Level Constraint
    model.addConstr(
        gp.quicksum(screen_modes[j]["Accreditation_level"] * x[i, j] 
                    for i in chip_models.keys() for j in screen_modes.keys()) >= min_Accreditation, 
        name="total_Accreditation"
    )
    
    # 5. SOLVING & RESULTS
    model.optimize()
    
    if model.status == GRB.OPTIMAL:
        print(f"Optimal value: {model.objVal}")
        for i in chip_models.keys():
            for j in screen_modes.keys():
                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
if __name__ == "__main__":
    phone_production_optimization()
```

### Execution Results
**Status**: OPTIMAL
**Optimal Value**: 158.4375
**Execution Time**: 0.18 seconds
**Reliability**: high
**Analysis**: Gurobipy found an optimal solution with the lowest execution time, indicating high efficiency and reliability.

## 6. DOCplex Implementation

```python
#!/usr/bin/env python3
"""
DOCplex implementation for phone production optimization problem
"""

from docplex.mp.model import Model

def phone_production_optimization():
    """Optimize phone production to minimize total cost while meeting hardware and accreditation requirements."""
    
    # 1. MODEL & DATA SETUP
    mdl = Model(name="phone_production_optimization")
    
    # Data from the problem
    chip_models = [
        {"id": 1, "cost": 50.0, "RAM_MiB": 2048, "ROM_MiB": 32768},
        {"id": 2, "cost": 75.0, "RAM_MiB": 4096, "ROM_MiB": 65536},
        {"id": 3, "cost": 100.0, "RAM_MiB": 8192, "ROM_MiB": 131072}
    ]
    
    screen_modes = [
        {"id": 1, "cost": 30.0, "Accreditation_level": 3},
        {"id": 2, "cost": 45.0, "Accreditation_level": 4},
        {"id": 3, "cost": 60.0, "Accreditation_level": 5}
    ]
    
    # CRITICAL: Validate array lengths to prevent IndexError
    assert len(chip_models) == 3 and len(screen_modes) == 3, "Array length mismatch"
    safe_range_chip = range(len(chip_models))
    safe_range_screen = range(len(screen_modes))
    
    # 2. VARIABLES
    # Decision variables: x_{i,j} = number of phones produced with chip model i and screen mode j
    x = {(i, j): mdl.continuous_var(name=f"x_{i}_{j}", lb=0) 
         for i in safe_range_chip for j in safe_range_screen}
    
    # 3. OBJECTIVE FUNCTION
    # Minimize total cost: sum_{i,j} (c_i + s_j) * x_{i,j}
    total_cost = mdl.sum((chip_models[i]["cost"] + screen_modes[j]["cost"]) * x[(i, j)] 
                         for i in safe_range_chip for j in safe_range_screen)
    mdl.minimize(total_cost)
    
    # 4. CONSTRAINTS
    
    # Total RAM Constraint: sum_{i,j} r_i * x_{i,j} >= 8000
    total_ram = mdl.sum(chip_models[i]["RAM_MiB"] * x[(i, j)] 
                        for i in safe_range_chip for j in safe_range_screen)
    mdl.add_constraint(total_ram >= 8000, ctname="total_ram")
    
    # Total ROM Constraint: sum_{i,j} o_i * x_{i,j} >= 128000
    total_rom = mdl.sum(chip_models[i]["ROM_MiB"] * x[(i, j)] 
                        for i in safe_range_chip for j in safe_range_screen)
    mdl.add_constraint(total_rom >= 128000, ctname="total_rom")
    
    # Total Accreditation Level Constraint: sum_{i,j} a_j * x_{i,j} >= 5
    total_accreditation = mdl.sum(screen_modes[j]["Accreditation_level"] * x[(i, j)] 
                                  for i in safe_range_chip for j in safe_range_screen)
    mdl.add_constraint(total_accreditation >= 5, ctname="total_accreditation")
    
    # 5. SOLVING & RESULTS
    solution = mdl.solve()
    
    if solution:
        print(f"Optimal value: {solution.objective_value}")
        for i in safe_range_chip:
            for j in safe_range_screen:
                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

# Execute the optimization
if __name__ == "__main__":
    phone_production_optimization()
```

### Execution Results
**Status**: OPTIMAL
**Optimal Value**: 158.4375
**Execution Time**: 1.00 seconds
**Reliability**: high
**Analysis**: DOCplex also found an optimal solution, matching Gurobipy's result, but with a longer execution time.

## 7. Pyomo Implementation

```python
# Complete PYOMO implementation

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

def phone_production_optimization():
    """Optimize phone production to minimize total cost while meeting hardware and accreditation requirements."""
    
    # 1. MODEL CREATION
    model = pyo.ConcreteModel()
    
    # 2. DATA SETUP
    # Chip models data
    chip_models_data = {
        1: {'cost': 50.0, 'RAM_MiB': 2048, 'ROM_MiB': 32768},
        2: {'cost': 75.0, 'RAM_MiB': 4096, 'ROM_MiB': 65536},
        3: {'cost': 100.0, 'RAM_MiB': 8192, 'ROM_MiB': 131072}
    }
    
    # Screen modes data
    screen_modes_data = {
        1: {'cost': 30.0, 'Accreditation_level': 3},
        2: {'cost': 45.0, 'Accreditation_level': 4},
        3: {'cost': 60.0, 'Accreditation_level': 5}
    }
    
    # Validate array lengths
    assert len(chip_models_data) == 3, "Chip models data length mismatch"
    assert len(screen_modes_data) == 3, "Screen modes data length mismatch"
    
    # 3. SETS
    model.ChipModels = pyo.Set(initialize=chip_models_data.keys())
    model.ScreenModes = pyo.Set(initialize=screen_modes_data.keys())
    
    # 4. PARAMETERS
    model.chip_cost = pyo.Param(model.ChipModels, initialize={i: chip_models_data[i]['cost'] for i in chip_models_data})
    model.chip_RAM = pyo.Param(model.ChipModels, initialize={i: chip_models_data[i]['RAM_MiB'] for i in chip_models_data})
    model.chip_ROM = pyo.Param(model.ChipModels, initialize={i: chip_models_data[i]['ROM_MiB'] for i in chip_models_data})
    
    model.screen_cost = pyo.Param(model.ScreenModes, initialize={j: screen_modes_data[j]['cost'] for j in screen_modes_data})
    model.screen_accred = pyo.Param(model.ScreenModes, initialize={j: screen_modes_data[j]['Accreditation_level'] for j in screen_modes_data})
    
    # 5. VARIABLES
    model.x = pyo.Var(model.ChipModels, model.ScreenModes, within=pyo.NonNegativeIntegers)
    
    # 6. OBJECTIVE FUNCTION
    def obj_rule(model):
        return sum((model.chip_cost[i] + model.screen_cost[j]) * model.x[i, j] for i in model.ChipModels for j in model.ScreenModes)
    model.objective = pyo.Objective(rule=obj_rule, sense=pyo.minimize)
    
    # 7. CONSTRAINTS
    def ram_constraint_rule(model):
        return sum(model.chip_RAM[i] * model.x[i, j] for i in model.ChipModels for j in model.ScreenModes) >= 8000
    model.ram_constraint = pyo.Constraint(rule=ram_constraint_rule)
    
    def rom_constraint_rule(model):
        return sum(model.chip_ROM[i] * model.x[i, j] for i in model.ChipModels for j in model.ScreenModes) >= 128000
    model.rom_constraint = pyo.Constraint(rule=rom_constraint_rule)
    
    def accred_constraint_rule(model):
        return sum(model.screen_accred[j] * model.x[i, j] for i in model.ChipModels for j in model.ScreenModes) >= 5
    model.accred_constraint = pyo.Constraint(rule=accred_constraint_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)  # tee=True shows solver output
    
    # 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("\nProduction quantities:")
        for i in model.ChipModels:
            for j in model.ScreenModes:
                x_val = pyo.value(model.x[i, j])
                if x_val > 0:
                    print(f"Chip Model {i} with Screen Mode {j}: {int(x_val)} units")
        
    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
if __name__ == "__main__":
    phone_production_optimization()
```

### Execution Results
**Status**: OPTIMAL
**Optimal Value**: 160.0
**Execution Time**: 0.83 seconds
**Reliability**: medium
**Analysis**: Pyomo found an optimal solution, but the objective value is slightly higher than Gurobipy and DOCplex, suggesting potential numerical precision issues.

## 8. Cross-Solver Analysis and Final Recommendation

### Solver Results Comparison

| Solver | Status | Optimal Value | Execution Time | Decision Variables | Retry Attempt |
|--------|--------|---------------|----------------|-------------------|---------------|
| Gurobipy | OPTIMAL | 158.44 | 0.18s | N/A | N/A |
| Docplex | OPTIMAL | 158.44 | 1.00s | N/A | N/A |
| Pyomo | OPTIMAL | 160.00 | 0.83s | N/A | N/A |

### Solver Consistency Analysis
**Result**: Solvers produced inconsistent results
**Consistent Solvers**: gurobipy, docplex
**Inconsistent Solvers**: pyomo
**Potential Issues**:
- Numerical precision differences in Pyomo
- Solver-specific optimization algorithms
**Majority Vote Optimal Value**: 158.4375

### Final Recommendation
**Recommended Optimal Value**: 158.4375
**Confidence Level**: HIGH
**Preferred Solver(s)**: gurobipy
**Reasoning**: Gurobipy is preferred due to its faster execution time and consistent optimal value with DOCplex. Pyomo's slightly higher objective value suggests it may not be as precise.

### Business Interpretation
**Overall Strategy**: The optimal production cost is $158.44, achieved by Gurobipy and DOCplex. This represents the most cost-efficient allocation of resources.
**Objective Value Meaning**: The optimal objective value of $158.44 represents the minimum total production cost while meeting all constraints.
**Resource Allocation Summary**: Resources should be allocated to produce phones with the most cost-effective combination of chip models and screen modes, ensuring RAM, ROM, and accreditation level requirements are met.
**Implementation Recommendations**: Use Gurobipy for solving the optimization problem. Allocate production based on the optimal decision variables to minimize costs while meeting all technical and accreditation requirements.