## 4. Mathematical Optimization Formulation

#### Decision Variables
- Let \( x_i \) be the number of resources allocated to location \( i \), where \( i \in \{1, 2, 3\} \).  
  (Controllable decision: resources_allocated in ResourceAllocation table)

#### Objective Function
Minimize the total number of casualties across all locations:  
\[
\text{Minimize } Z = 5x_1 + 25x_1 + 3x_2 + 15x_2 + 1x_3 + 10x_3
\]  
Simplified:  
\[
\text{Minimize } Z = 30x_1 + 18x_2 + 11x_3
\]  
(Objective coefficients: killed and injured from Casualties table)

#### Constraints
1. **Total Resource Constraint**: The sum of resources allocated to all locations must not exceed the total available resources (assume total resources = 45):  
\[
x_1 + x_2 + x_3 \leq 45
\]  
(Constraint coefficient: 1 for each \( x_i \), constant: total resources available)

2. **Maximum Casualties Constraint**: For each location, the sum of killed and injured individuals must not exceed the maximum allowed casualties (assume maximum casualties per location = 30):  
\[
30x_1 \leq 30  
18x_2 \leq 30  
11x_3 \leq 30
\]  
(Constraint coefficients: 30, 18, 11 from objective function, constant: maximum allowed casualties)

#### Data Source Verification
- **Objective Function Coefficients**:  
  - \( 30x_1 \): Sum of killed (5) and injured (25) for location 1 (Casualties table).  
  - \( 18x_2 \): Sum of killed (3) and injured (15) for location 2 (Casualties table).  
  - \( 11x_3 \): Sum of killed (1) and injured (10) for location 3 (Casualties table).  

- **Total Resource Constraint**:  
  - Total resources available = 45 (business configuration parameter).  

- **Maximum Casualties Constraint**:  
  - Maximum allowed casualties per location = 30 (business configuration parameter).  

This is a complete, immediately solvable LINEAR mathematical model with all numerical coefficients derived from the provided data.

## 5. Gurobipy Implementation

```python
#!/usr/bin/env python3
"""
Gurobipy Implementation for Security Agency Resource Allocation Problem
"""

import gurobipy as gp
from gurobipy import GRB

def optimize_resource_allocation():
    """Optimize resource allocation to minimize casualties across locations."""
    
    # 1. MODEL & DATA SETUP
    model = gp.Model("ResourceAllocation")
    
    # Data from the problem
    locations = [1, 2, 3]
    casualties_coeff = {1: 30, 2: 18, 3: 11}  # Sum of killed and injured per location
    total_resources = 45
    max_casualties = 30
    
    # CRITICAL: Validate array lengths before loops
    assert len(locations) == len(casualties_coeff), "Array length mismatch"
    
    # 2. VARIABLES
    x = {i: model.addVar(vtype=GRB.CONTINUOUS, name=f"x_{i}", lb=0) for i in locations}
    
    # 3. OBJECTIVE FUNCTION
    model.setObjective(gp.quicksum(casualties_coeff[i] * x[i] for i in locations), GRB.MINIMIZE)
    
    # 4. CONSTRAINTS
    
    # Total Resource Constraint
    model.addConstr(gp.quicksum(x[i] for i in locations) <= total_resources, name="total_resources")
    
    # Maximum Casualties Constraint
    for i in locations:
        model.addConstr(casualties_coeff[i] * x[i] <= max_casualties, name=f"max_casualties_{i}")
    
    # 5. SOLVING & RESULTS
    model.optimize()
    
    if model.status == GRB.OPTIMAL:
        print(f"Optimal value: {model.objVal}")
        for i in locations:
            if x[i].x > 1e-6:
                print(f"Resources allocated to location {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

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

### Execution Results
**Status**: OPTIMAL
**Optimal Value**: 0.0
**Execution Time**: 0.18 seconds
**Reliability**: high
**Analysis**: Gurobipy found an optimal solution with zero casualties, indicating no resources need to be allocated. This aligns with the constraints and objective function.

## 6. DOCplex Implementation

```python
#!/usr/bin/env python3
"""
DOCplex 2.29.245 Implementation for Security Agency Resource Allocation Problem
"""

from docplex.mp.model import Model

def optimize_resource_allocation():
    """Optimize resource allocation to minimize total casualties."""
    
    # 1. MODEL & DATA SETUP
    mdl = Model(name="Resource_Allocation")
    
    # Data from the problem
    locations = [1, 2, 3]
    casualties_coeff = {1: 30, 2: 18, 3: 11}  # Sum of killed and injured per location
    total_resources = 45
    max_casualties_per_location = 30
    
    # CRITICAL: Validate array lengths to prevent IndexError
    assert len(locations) == len(casualties_coeff), "Array length mismatch"
    safe_range = range(min(len(locations), len(casualties_coeff)))  # Safe indexing
    
    # 2. VARIABLES
    # Decision variables: resources allocated to each location
    x = {i: mdl.continuous_var(name=f"x_{i}", lb=0) for i in locations}
    
    # 3. OBJECTIVE FUNCTION
    # Minimize total casualties: Z = 30x1 + 18x2 + 11x3
    objective = mdl.sum(casualties_coeff[i] * x[i] for i in locations)
    mdl.minimize(objective)
    
    # 4. CONSTRAINTS
    
    # Total Resource Constraint: x1 + x2 + x3 <= 45
    total_resource_usage = mdl.sum(x[i] for i in locations)
    mdl.add_constraint(total_resource_usage <= total_resources, ctname="total_resources")
    
    # Maximum Casualties Constraint: 30x1 <= 30, 18x2 <= 30, 11x3 <= 30
    for i in locations:
        mdl.add_constraint(casualties_coeff[i] * x[i] <= max_casualties_per_location, ctname=f"max_casualties_{i}")
    
    # 5. SOLVING & RESULTS
    solution = mdl.solve()
    
    if solution:
        print(f"Optimal value: {solution.objective_value}")
        for i in locations:
            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

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

### Execution Results
**Status**: OPTIMAL
**Optimal Value**: 0.0
**Execution Time**: 1.08 seconds
**Reliability**: high
**Analysis**: DOCplex also found an optimal solution with zero casualties, consistent with Gurobipy's results. The execution time was longer but still reliable.

## 7. Pyomo Implementation

```python
# Complete PYOMO implementation

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

def optimize_resource_allocation():
    """Optimize resource allocation to minimize casualties across locations."""
    
    # 1. MODEL CREATION
    model = pyo.ConcreteModel()
    
    # 2. DATA SETUP
    locations = [1, 2, 3]
    casualties_coeff = {1: 30, 2: 18, 3: 11}  # Coefficients from objective function
    total_resources = 45
    max_casualties = 30
    
    # CRITICAL: Validate array lengths before indexing
    assert len(locations) == len(casualties_coeff), "Array length mismatch"
    
    # 3. SETS (Pyomo way to define indices)
    model.I = pyo.Set(initialize=locations)  # Set of locations
    
    # 4. PARAMETERS (data containers)
    model.casualties_coeff = pyo.Param(model.I, initialize=casualties_coeff)
    
    # 5. VARIABLES
    model.x = pyo.Var(model.I, within=pyo.NonNegativeReals)  # Resources allocated to each location
    
    # 6. OBJECTIVE FUNCTION
    def obj_rule(model):
        return sum(model.casualties_coeff[i] * model.x[i] for i in model.I)
    model.objective = pyo.Objective(rule=obj_rule, sense=pyo.minimize)
    
    # 7. CONSTRAINTS
    
    # Total Resource Constraint
    def total_resource_rule(model):
        return sum(model.x[i] for i in model.I) <= total_resources
    model.total_resource_constraint = pyo.Constraint(rule=total_resource_rule)
    
    # Maximum Casualties Constraint
    def max_casualties_rule(model, i):
        return model.casualties_coeff[i] * model.x[i] <= max_casualties
    model.max_casualties_constraint = pyo.Constraint(model.I, rule=max_casualties_rule)
    
    # 8. SOLVING WITH GUROBI (your available solver)
    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(f"Optimal value: {pyo.value(model.objective)}")
        
        # Extract variable values
        print("\nResource Allocation:")
        for i in model.I:
            x_val = pyo.value(model.x[i])
            if x_val > 1e-6:  # Only print non-zero values
                print(f"Location {i}: {x_val:.3f} resources")
        
    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

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

### Execution Results
**Status**: OPTIMAL
**Optimal Value**: 0.0
**Execution Time**: 0.91 seconds
**Reliability**: high
**Analysis**: Pyomo confirmed the optimal solution with zero casualties, further validating the results. The execution time was intermediate between Gurobipy and DOCplex.

## 8. Cross-Solver Analysis and Final Recommendation

### Solver Results Comparison

| Solver | Status | Optimal Value | Execution Time | Decision Variables | Retry Attempt |
|--------|--------|---------------|----------------|-------------------|---------------|
| Gurobipy | OPTIMAL | 0.00 | 0.18s | N/A | N/A |
| Docplex | OPTIMAL | 0.00 | 1.08s | N/A | N/A |
| Pyomo | OPTIMAL | 0.00 | 0.91s | N/A | N/A |

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

### Final Recommendation
**Recommended Optimal Value**: 0.0
**Confidence Level**: HIGH
**Preferred Solver(s)**: multiple
**Reasoning**: All three solvers (Gurobipy, DOCplex, Pyomo) consistently found the same optimal solution, indicating high reliability. Gurobipy is preferred for its speed, but the consistency across solvers strengthens confidence in the results.

### Optimal Decision Variables
- **x_1** = 0.000
  - *Business Meaning*: Resources allocated to location 1. Optimal value is 0, meaning no resources are needed here.
- **x_2** = 0.000
  - *Business Meaning*: Resources allocated to location 2. Optimal value is 0, meaning no resources are needed here.
- **x_3** = 0.000
  - *Business Meaning*: Resources allocated to location 3. Optimal value is 0, meaning no resources are needed here.

### Business Interpretation
**Overall Strategy**: The optimal solution suggests that no resources need to be allocated to any location to minimize casualties, as the constraints are already satisfied without any allocation.
**Objective Value Meaning**: The optimal objective value of 0 indicates that no casualties occur when no resources are allocated, as the constraints are inherently satisfied.
**Resource Allocation Summary**: No resources need to be allocated to any location to meet the constraints and minimize casualties.
**Implementation Recommendations**: Verify the constraints and objective function to ensure they accurately reflect the business scenario. If confirmed, implement the solution by not allocating resources to the specified locations.