## 4. Mathematical Optimization Formulation

#### Decision Variables
- Let \( x_i \) be the amount of resources allocated to location \( i \). These are continuous decision variables representing the allocation of resources to each location.

#### Objective Function
- Minimize the total number of casualties, which is the sum of killed and injured individuals at each location, weighted by the resources allocated:
  \[
  \text{Minimize } Z = \sum_{i=1}^{3} ( \text{Killed}_i + \text{Injured}_i ) \times x_i
  \]
  Using the data provided:
  \[
  Z = (10 + 50) \times x_1 + (5 + 30) \times x_2 + (20 + 100) \times x_3
  \]
  \[
  Z = 60x_1 + 35x_2 + 120x_3
  \]

#### Constraints
1. Budget Constraint: The total cost of resources allocated must not exceed the total budget.
   \[
   \sum_{i=1}^{3} \text{Cost}_i \times x_i \leq \text{Total Budget}
   \]
   Using the data provided:
   \[
   2000x_1 + 1500x_2 + 2500x_3 \leq \text{Total Budget}
   \]

2. Non-negativity Constraints: The amount of resources allocated to each location must be non-negative.
   \[
   x_1 \geq 0, \quad x_2 \geq 0, \quad x_3 \geq 0
   \]

Data Source Verification:
- Coefficients for the objective function (Killed and Injured) are sourced from the `perpetrator` table.
- Coefficients for the budget constraint (Cost) are sourced from the `LocationCosts` table.
- The decision variables \( x_i \) correspond to the `ResourceAllocation.amount` for each `location_id`.

This linear model can be solved using standard linear programming techniques to determine the optimal allocation of resources that minimizes the total number of casualties while adhering to the budget constraint.

## 5. Gurobipy Implementation

```python
# Complete GUROBIPY implementation

import gurobipy as gp
from gurobipy import GRB

def optimize_resource_allocation():
    """Optimize resource allocation to minimize casualties within budget constraints."""
    
    # 1. MODEL & DATA SETUP
    model = gp.Model("resource_allocation")
    
    # Data from the problem statement
    killed = [10, 5, 20]
    injured = [50, 30, 100]
    costs = [2000, 1500, 2500]
    total_budget = 1000000  # Example budget value
    
    # Validate array lengths
    n_locations = len(killed)
    assert len(injured) == len(costs) == n_locations, "Array length mismatch"
    
    # 2. VARIABLES
    # Decision variables for resource allocation
    x = {i: model.addVar(vtype=GRB.CONTINUOUS, name=f"x_{i}", lb=0) 
         for i in range(n_locations)}
    
    # 3. OBJECTIVE FUNCTION
    # Minimize total casualties
    model.setObjective(gp.quicksum((killed[i] + injured[i]) * x[i] for i in range(n_locations)), GRB.MINIMIZE)
    
    # 4. CONSTRAINTS
    # Budget constraint
    model.addConstr(gp.quicksum(costs[i] * x[i] for i in range(n_locations)) <= total_budget, name="budget_constraint")
    
    # Non-negativity constraints are implicitly handled by the variable lower bounds
    
    # 5. SOLVING & RESULTS
    model.optimize()
    
    if model.status == GRB.OPTIMAL:
        print(f"Optimal value: {model.objVal}")
        for i in range(n_locations):
            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_resource_allocation()
```

### Execution Results
**Status**: OPTIMAL
**Optimal Value**: 0.0
**Execution Time**: 2.13 seconds
**Reliability**: high
**Analysis**: Gurobipy found an optimal solution with zero casualties, indicating no resources were allocated. This suggests that the budget constraint may be too restrictive or the cost coefficients are too high relative to the objective coefficients.

## 6. DOCplex Implementation

```python
# Complete DOCPLEX implementation

from docplex.mp.model import Model

def optimize_resource_allocation(total_budget):
    """Optimize resource allocation to minimize casualties within budget constraints."""
    
    # 1. MODEL & DATA SETUP
    mdl = Model(name="resource_allocation")
    
    # Data from the problem context
    killed = [10, 5, 20]
    injured = [50, 30, 100]
    costs = [2000, 1500, 2500]
    
    # CRITICAL: Validate array lengths to prevent IndexError
    assert len(killed) == len(injured) == len(costs) == 3, "Array length mismatch"
    safe_range = range(min(len(killed), len(injured), len(costs)))  # Safe indexing
    
    # 2. VARIABLES
    x = {i: mdl.continuous_var(name=f"x_{i}", lb=0) for i in safe_range}
    
    # 3. OBJECTIVE FUNCTION
    # Minimize the total number of casualties
    objective = mdl.sum((killed[i] + injured[i]) * x[i] for i in safe_range)
    mdl.minimize(objective)
    
    # 4. CONSTRAINTS
    # Budget constraint
    budget_constraint = mdl.sum(costs[i] * x[i] for i in safe_range)
    mdl.add_constraint(budget_constraint <= total_budget, ctname="budget_constraint")
    
    # 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

# Example usage
total_budget = 1000000  # Example budget
optimize_resource_allocation(total_budget)
```

### Execution Results
**Status**: OPTIMAL
**Optimal Value**: 0.0
**Execution Time**: 12.56 seconds
**Reliability**: high
**Analysis**: DOCplex also found an optimal solution with zero casualties, consistent with Gurobipy. This reinforces the possibility of a restrictive budget or high costs.

## 7. Pyomo Implementation

```python
# Complete PYOMO implementation

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

def casualty_minimization():
    """Optimize resource allocation to minimize casualties"""

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

    # 2. DATA SETUP
    # Coefficients for the objective function
    killed = [10, 5, 20]
    injured = [50, 30, 100]
    costs = [2000, 1500, 2500]
    total_budget = 1000000  # Example budget

    # Validate array lengths
    n_locations = len(killed)
    assert len(injured) == len(costs) == n_locations, "Array length mismatch"

    # 3. SETS
    model.Locations = pyo.RangeSet(1, n_locations)

    # 4. PARAMETERS
    model.killed = pyo.Param(model.Locations, initialize={i+1: killed[i] for i in range(n_locations)})
    model.injured = pyo.Param(model.Locations, initialize={i+1: injured[i] for i in range(n_locations)})
    model.cost = pyo.Param(model.Locations, initialize={i+1: costs[i] for i in range(n_locations)})

    # 5. VARIABLES
    model.x = pyo.Var(model.Locations, within=pyo.NonNegativeReals)

    # 6. OBJECTIVE FUNCTION
    def obj_rule(model):
        return sum((model.killed[i] + model.injured[i]) * model.x[i] for i in model.Locations)
    model.objective = pyo.Objective(rule=obj_rule, sense=pyo.minimize)

    # 7. CONSTRAINTS
    def budget_constraint_rule(model):
        return sum(model.cost[i] * model.x[i] for i in model.Locations) <= total_budget
    model.budget_constraint = pyo.Constraint(rule=budget_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)

    # 9. RESULT PROCESSING
    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.Locations:
            x_val = pyo.value(model.x[i])
            if x_val > 1e-6:  # Only print non-zero values
                print(f"x[{i}] = {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
casualty_minimization()
```

### Execution Results
**Status**: OPTIMAL
**Optimal Value**: 0.0
**Execution Time**: 7.50 seconds
**Reliability**: high
**Analysis**: Pyomo's results are consistent with both Gurobipy and DOCplex, suggesting a similar interpretation regarding budget constraints or cost coefficients.

## 8. Cross-Solver Analysis and Final Recommendation

### Solver Results Comparison

| Solver | Status | Optimal Value | Execution Time | Decision Variables | Retry Attempt |
|--------|--------|---------------|----------------|-------------------|---------------|
| Gurobipy | OPTIMAL | 0.00 | 2.13s | N/A | N/A |
| Docplex | OPTIMAL | 0.00 | 12.56s | N/A | N/A |
| Pyomo | OPTIMAL | 0.00 | 7.50s | 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 solvers provided consistent results, indicating a high level of confidence in the solution. The issue likely lies in the model parameters rather than solver performance.

### Optimal Decision Variables
- **x_1** = 0.000
  - *Business Meaning*: Amount of resources allocated to location 2, currently zero due to budget constraints.
- **x_2** = 0.000
  - *Business Meaning*: Amount of resources allocated to location 3, currently zero due to budget constraints.
- **x_3** = 0.000
  - *Business Meaning*: Resource allocation for x_3

### Business Interpretation
**Overall Strategy**: The current budget does not allow for any resource allocation that would reduce casualties. This suggests a need to reassess the budget or cost structure.
**Objective Value Meaning**: An optimal objective value of 0.0 indicates no reduction in casualties, as no resources are allocated.
**Resource Allocation Summary**: No resources are allocated to any location under the current budget constraints.
**Implementation Recommendations**: Re-evaluate the budget and cost coefficients to ensure resources can be allocated effectively. Consider increasing the budget or adjusting cost coefficients to allow for meaningful resource allocation.