# Complete DOCPLEX implementation - Retry Attempt 4

from docplex.mp.model import Model

def optimize_battle_death():
    # 1. MODEL & DATA SETUP
    mdl = Model(name="battle_death_optimization")
    
    # Data from the database
    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 to prevent IndexError
    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 = {(s, b): mdl.binary_var(name=f"x_{s}_{b}") for s in ships for b in battles}
    
    # 3. OBJECTIVE FUNCTION
    total_casualties = mdl.sum((death_data[(s, b)]['killed'] + death_data[(s, b)]['injured']) * x[(s, b)] for s in ships for b in battles)
    mdl.minimize(total_casualties)
    
    # 4. CONSTRAINTS
    
    # Tonnage Constraint
    for b in battles:
        mdl.add_constraint(mdl.sum(ship_tonnage[s] * x[(s, b)] for s in ships) <= battle_constraints[b], ctname=f"tonnage_{b}")
    
    # Single Deployment Constraint
    for s in ships:
        mdl.add_constraint(mdl.sum(x[(s, b)] for b in battles) <= 1, ctname=f"single_deployment_{s}")
    
    # 5. SOLVING & RESULTS
    solution = mdl.solve()
    
    if solution:
        print(f"Optimal value: {solution.objective_value}")
        for s in ships:
            for b in battles:
                if solution.get_value(x[(s, b)]) > 0.5:
                    print(f"Ship {s} deployed to Battle {b}")
    else:
        print("No solution found")
        print(f"Status: {mdl.solve_details.status}")
    
    return mdl

# Execute the optimization
optimize_battle_death()