# Complete GUROBIPY implementation - Retry Attempt 4

import gurobipy as gp
from gurobipy import GRB

def optimize_battle_death():
    # 1. MODEL & DATA SETUP
    model = gp.Model("battle_death_optimization")
    
    # Data from the problem
    ships = [1, 2, 3]
    battles = [1, 2, 3]
    
    ship_tonnage = {
        1: 5000,
        2: 7000,
        3: 9000
    }
    
    battle_constraints = {
        1: 10000,
        2: 12000,
        3: 15000
    }
    
    death_data = {
        (1, 1): {'killed': 10, 'injured': 15},
        (2, 2): {'killed': 20, 'injured': 25},
        (3, 3): {'killed': 30, 'injured': 35}
    }
    
    # CRITICAL: Validate array lengths before loops
    assert len(ships) == len(ship_tonnage), "Ship tonnage data length mismatch"
    assert len(battles) == len(battle_constraints), "Battle constraints data length mismatch"
    assert len(death_data) == len(ships) * len(battles), "Casualties data length mismatch"
    
    # 2. VARIABLES
    x = model.addVars(ships, battles, vtype=GRB.BINARY, name="x")
    
    # 3. OBJECTIVE FUNCTION
    model.setObjective(
        gp.quicksum((death_data[(s, b)]['killed'] + death_data[(s, b)]['injured']) * x[s, b] 
                    for s in ships for b in battles), 
        GRB.MINIMIZE
    )
    
    # 4. CONSTRAINTS
    
    # Tonnage Constraint
    for b in battles:
        model.addConstr(
            gp.quicksum(ship_tonnage[s] * x[s, b] for s in ships) <= battle_constraints[b], 
            name=f"tonnage_{b}"
        )
    
    # Single Deployment Constraint
    for s in ships:
        model.addConstr(
            gp.quicksum(x[s, b] for b in battles) <= 1, 
            name=f"single_deployment_{s}"
        )
    
    # 5. SOLVING & RESULTS
    model.optimize()
    
    if model.status == GRB.OPTIMAL:
        print(f"Optimal value: {model.objVal}")
        for s in ships:
            for b in battles:
                if x[s, b].x > 1e-6:
                    print(f"Ship {s} deployed to Battle {b}")
    elif model.status == GRB.INFEASIBLE:
        print("Problem is infeasible")
    elif model.status == GRB.UNBOUNDED:
        print("Problem is unbounded")
    
    return model

# Execute the optimization
optimize_battle_death()