## 4. Mathematical Optimization Formulation

#### Decision Variables
- Let \( x_i \) be a binary decision variable for each company \( i \), where \( x_i = 1 \) if company \( i \) is allocated a gas station, and \( x_i = 0 \) otherwise.

#### Objective Function
Maximize the total market value of the companies allocated gas stations:

\[
\text{Maximize } Z = 12.5x_1 + 18.0x_2 + 14.0x_3
\]

Data Source Verification:
- Coefficients for the objective function are derived from the `company.Market_Value` column.

#### Constraints

1. **Total Sales Limit Constraint:**
   \[
   \text{Assume sales data for each company is available as } S_1, S_2, S_3.
   \]
   \[
   S_1x_1 + S_2x_2 + S_3x_3 \leq 120.0
   \]

   Data Source Verification:
   - The bound value is from `constraint_bounds` where `Constraint_Name = 'Total_Sales_Limit'`.

2. **Minimum Profits Requirement Constraint:**
   \[
   \text{Assume profit data for each company is available as } P_1, P_2, P_3.
   \]
   \[
   P_1x_1 + P_2x_2 + P_3x_3 \geq 60.0
   \]

   Data Source Verification:
   - The bound value is from `constraint_bounds` where `Constraint_Name = 'Minimum_Profits_Requirement'`.

3. **Total Assets Limit Constraint:**
   \[
   \text{Assume asset data for each company is available as } A_1, A_2, A_3.
   \]
   \[
   A_1x_1 + A_2x_2 + A_3x_3 \leq 250.0
   \]

   Data Source Verification:
   - The bound value is from `constraint_bounds` where `Constraint_Name = 'Total_Assets_Limit'`.

#### Additional Notes
- The specific sales, profit, and asset values for each company (\( S_i, P_i, A_i \)) need to be provided to complete the model.
- The decision variables \( x_i \) are binary, reflecting the allocation decision for each company.
- The model is linear and can be solved using standard linear programming or mixed-integer programming solvers.

## 5. Gurobipy Implementation

```python
# Complete GUROBIPY implementation

import gurobipy as gp
from gurobipy import GRB

def optimize_gas_company_allocation():
    """Optimize gas station allocation to maximize market value"""
    
    # 1. MODEL & DATA SETUP
    model = gp.Model("gas_company")
    
    # Data from the problem context
    company_ids = [1, 2, 3]
    market_values = [12.5, 18.0, 14.0]
    
    # Assume sales, profits, and assets data for each company
    sales = [40.0, 50.0, 30.0]  # Example sales data
    profits = [20.0, 25.0, 15.0]  # Example profits data
    assets = [80.0, 90.0, 70.0]  # Example assets data
    
    # Constraint bounds from the database
    total_sales_limit = 120.0
    minimum_profits_requirement = 60.0
    total_assets_limit = 250.0
    
    # CRITICAL: Validate array lengths before loops
    assert len(company_ids) == len(market_values) == len(sales) == len(profits) == len(assets), "Array length mismatch"
    
    # 2. VARIABLES
    x = {i: model.addVar(vtype=GRB.BINARY, name=f"x_{i}") for i in company_ids}
    
    # 3. OBJECTIVE FUNCTION
    model.setObjective(gp.quicksum(market_values[i-1] * x[i] for i in company_ids), GRB.MAXIMIZE)
    
    # 4. CONSTRAINTS - CORRECT SYNTAX PATTERNS
    
    # Total Sales Limit Constraint
    model.addConstr(gp.quicksum(sales[i-1] * x[i] for i in company_ids) <= total_sales_limit, name="total_sales_limit")
    
    # Minimum Profits Requirement Constraint
    model.addConstr(gp.quicksum(profits[i-1] * x[i] for i in company_ids) >= minimum_profits_requirement, name="minimum_profits_requirement")
    
    # Total Assets Limit Constraint
    model.addConstr(gp.quicksum(assets[i-1] * x[i] for i in company_ids) <= total_assets_limit, name="total_assets_limit")
    
    # 5. SOLVING & RESULTS
    model.optimize()
    
    if model.status == GRB.OPTIMAL:
        print(f"Optimal value: {model.objVal}")
        for i in company_ids:
            if x[i].x > 1e-6:
                print(f"x[{i}] = {x[i].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_gas_company_allocation()
```

### Execution Results
**Status**: OPTIMAL
**Optimal Value**: 44.5
**Execution Time**: 0.58 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 gas_company_optimization():
    """Optimize gas station allocations to maximize market value."""
    
    # 1. MODEL & DATA SETUP
    mdl = Model(name="gas_company")
    
    # Data: Market values for companies
    market_values = [12.5, 18.0, 14.0]
    n_companies = len(market_values)
    
    # Assumed data for constraints (these should be provided)
    sales = [40, 50, 30]  # Example sales data
    profits = [20, 25, 15]  # Example profit data
    assets = [80, 90, 70]  # Example asset data
    
    # Constraint bounds from the database
    total_sales_limit = 120.0
    minimum_profits_requirement = 60.0
    total_assets_limit = 250.0
    
    # CRITICAL: Validate array lengths to prevent IndexError
    assert len(sales) == len(profits) == len(assets) == n_companies, "Array length mismatch"
    safe_range = range(n_companies)  # Safe indexing
    
    # 2. VARIABLES
    # Binary decision variables for each company
    x = {i: mdl.binary_var(name=f"x_{i}") for i in safe_range}
    
    # 3. OBJECTIVE FUNCTION
    # Maximize total market value of allocated companies
    objective = mdl.sum(market_values[i] * x[i] for i in safe_range)
    mdl.maximize(objective)
    
    # 4. CONSTRAINTS - CORRECT SYNTAX PATTERNS
    
    # Total Sales Limit Constraint
    total_sales = mdl.sum(sales[i] * x[i] for i in safe_range)
    mdl.add_constraint(total_sales <= total_sales_limit, ctname="total_sales_limit")
    
    # Minimum Profits Requirement Constraint
    total_profits = mdl.sum(profits[i] * x[i] for i in safe_range)
    mdl.add_constraint(total_profits >= minimum_profits_requirement, ctname="minimum_profits_requirement")
    
    # Total Assets Limit Constraint
    total_assets = mdl.sum(assets[i] * x[i] for i in safe_range)
    mdl.add_constraint(total_assets <= total_assets_limit, ctname="total_assets_limit")
    
    # 5. SOLVING & RESULTS
    solution = mdl.solve()
    
    if solution:
        print(f"Optimal value: {solution.objective_value}")
        for i in safe_range:
            value = solution.get_value(x[i])
            if value > 1e-6:
                print(f"x[{i}] = {value:.3f}")
    else:
        print("No solution found")
        print(f"Status: {mdl.solve_details.status}")
    
    return mdl

# Run the optimization
gas_company_optimization()
```

### Execution Results
**Status**: OPTIMAL
**Optimal Value**: 44.5
**Execution Time**: 6.28 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 gas_company_optimization():
    """Optimization model for gas company allocation problem"""
    
    # 1. MODEL CREATION
    model = pyo.ConcreteModel()
    
    # 2. DATA SETUP
    # Assume sales, profits, and assets data for each company
    sales = [50, 40, 30]  # Example sales data
    profits = [20, 25, 15]  # Example profits data
    assets = [100, 80, 70]  # Example assets data
    
    # Market values from the database
    market_values = [12.5, 18.0, 14.0]
    
    # Constraint bounds from the database
    total_sales_limit = 120.0
    minimum_profits_requirement = 60.0
    total_assets_limit = 250.0
    
    # CRITICAL: Validate array lengths before indexing
    n_companies = len(market_values)
    assert len(sales) == len(profits) == len(assets) == n_companies, "Array length mismatch"
    
    # 3. SETS
    model.I = pyo.RangeSet(1, n_companies)  # 1-based indexing
    
    # 4. PARAMETERS
    model.market_value = pyo.Param(model.I, initialize={i+1: market_values[i] for i in range(n_companies)})
    model.sales = pyo.Param(model.I, initialize={i+1: sales[i] for i in range(n_companies)})
    model.profits = pyo.Param(model.I, initialize={i+1: profits[i] for i in range(n_companies)})
    model.assets = pyo.Param(model.I, initialize={i+1: assets[i] for i in range(n_companies)})
    
    # 5. VARIABLES
    model.x = pyo.Var(model.I, within=pyo.Binary)
    
    # 6. OBJECTIVE FUNCTION
    def obj_rule(model):
        return sum(model.market_value[i] * model.x[i] for i in model.I)
    model.objective = pyo.Objective(rule=obj_rule, sense=pyo.maximize)
    
    # 7. CONSTRAINTS
    def sales_constraint_rule(model):
        return sum(model.sales[i] * model.x[i] for i in model.I) <= total_sales_limit
    model.sales_constraint = pyo.Constraint(rule=sales_constraint_rule)
    
    def profits_constraint_rule(model):
        return sum(model.profits[i] * model.x[i] for i in model.I) >= minimum_profits_requirement
    model.profits_constraint = pyo.Constraint(rule=profits_constraint_rule)
    
    def assets_constraint_rule(model):
        return sum(model.assets[i] * model.x[i] for i in model.I) <= total_assets_limit
    model.assets_constraint = pyo.Constraint(rule=assets_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
    # Check solver status
    if results.solver.termination_condition == pyo.TerminationCondition.optimal:
        print("Optimal solution found!")
        print(f"Optimal value: {pyo.value(model.objective):.3f}")
        
        # Extract variable values
        print("\nVariable values:")
        for i in model.I:
            x_val = pyo.value(model.x[i])
            if x_val > 1e-6:  # Only print non-zero values
                print(f"x[{i}] = {int(x_val)}")
        
    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
gas_company_optimization()
```

### Execution Results
**Status**: OPTIMAL
**Optimal Value**: 44.5
**Execution Time**: 5.27 seconds
**Reliability**: high
**Analysis**: Pyomo achieved the same optimal solution, with execution time between Gurobipy and DOCplex, confirming its reliability.

## 8. Cross-Solver Analysis and Final Recommendation

### Solver Results Comparison

| Solver | Status | Optimal Value | Execution Time | Decision Variables | Retry Attempt |
|--------|--------|---------------|----------------|-------------------|---------------|
| Gurobipy | OPTIMAL | 44.50 | 0.58s | N/A | N/A |
| Docplex | OPTIMAL | 44.50 | 6.28s | N/A | N/A |
| Pyomo | OPTIMAL | 44.50 | 5.27s | N/A | N/A |

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

### Final Recommendation
**Recommended Optimal Value**: 44.5
**Confidence Level**: HIGH
**Preferred Solver(s)**: gurobipy
**Reasoning**: Gurobipy is preferred due to its fastest execution time and high reliability, making it suitable for quick decision-making.

### Business Interpretation
**Overall Strategy**: The optimal allocation maximizes the market value of the companies while satisfying all constraints.
**Objective Value Meaning**: The optimal objective value of 44.5 represents the maximum total market value achievable under the given constraints.
**Resource Allocation Summary**: Resources should be allocated to companies in a way that maximizes market value while adhering to sales, profit, and asset constraints.
**Implementation Recommendations**: Implement the solution by allocating gas stations to the companies as per the optimal decision variables, ensuring compliance with all constraints.