# Complete PYOMO implementation - Retry Attempt 1

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

def ship_mission_optimization():
    # 1. MODEL CREATION
    model = pyo.ConcreteModel()
    
    # 2. DATA SETUP
    missions = [
        {'mission_id': 1, 'min_tonnage': 5000, 'min_speed': 20, 'required_nationality': 'USA'},
        {'mission_id': 2, 'min_tonnage': 6000, 'min_speed': 25, 'required_nationality': 'UK'},
        {'mission_id': 3, 'min_tonnage': 7000, 'min_speed': 30, 'required_nationality': 'Canada'}
    ]
    
    ships = [
        {'ship_id': 1, 'tonnage': 5500, 'speed_knots': 22, 'nationality': 'USA'},
        {'ship_id': 2, 'tonnage': 6500, 'speed_knots': 27, 'nationality': 'UK'},
        {'ship_id': 3, 'tonnage': 7500, 'speed_knots': 32, 'nationality': 'Canada'}
    ]
    
    # 3. SETS
    model.MISSIONS = pyo.Set(initialize=[m['mission_id'] for m in missions])
    model.SHIPS = pyo.Set(initialize=[s['ship_id'] for s in ships])
    
    # 4. PARAMETERS
    model.min_tonnage = pyo.Param(model.MISSIONS, initialize={m['mission_id']: m['min_tonnage'] for m in missions})
    model.min_speed = pyo.Param(model.MISSIONS, initialize={m['mission_id']: m['min_speed'] for m in missions})
    model.required_nationality = pyo.Param(model.MISSIONS, initialize={m['mission_id']: m['required_nationality'] for m in missions})
    
    model.tonnage = pyo.Param(model.SHIPS, initialize={s['ship_id']: s['tonnage'] for s in ships})
    model.speed = pyo.Param(model.SHIPS, initialize={s['ship_id']: s['speed_knots'] for s in ships})
    model.nationality = pyo.Param(model.SHIPS, initialize={s['ship_id']: s['nationality'] for s in ships})
    
    # 5. VARIABLES
    model.x = pyo.Var(model.SHIPS, model.MISSIONS, within=pyo.Binary)
    
    # 6. OBJECTIVE FUNCTION
    def obj_rule(model):
        return sum((model.tonnage[i] + model.speed[i]) * model.x[i, j] for i in model.SHIPS for j in model.MISSIONS)
    model.objective = pyo.Objective(rule=obj_rule, sense=pyo.minimize)
    
    # 7. CONSTRAINTS
    def mission_assignment_rule(model, j):
        return sum(model.x[i, j] for i in model.SHIPS) == 1
    model.mission_assignment = pyo.Constraint(model.MISSIONS, rule=mission_assignment_rule)
    
    def ship_assignment_rule(model, i):
        return sum(model.x[i, j] for j in model.MISSIONS) <= 1
    model.ship_assignment = pyo.Constraint(model.SHIPS, rule=ship_assignment_rule)
    
    def tonnage_requirement_rule(model, i, j):
        return model.tonnage[i] * model.x[i, j] >= model.min_tonnage[j] * model.x[i, j]
    model.tonnage_requirement = pyo.Constraint(model.SHIPS, model.MISSIONS, rule=tonnage_requirement_rule)
    
    def speed_requirement_rule(model, i, j):
        return model.speed[i] * model.x[i, j] >= model.min_speed[j] * model.x[i, j]
    model.speed_requirement = pyo.Constraint(model.SHIPS, model.MISSIONS, rule=speed_requirement_rule)
    
    def nationality_requirement_rule(model, i, j):
        return model.nationality[i] == model.required_nationality[j] if model.x[i, j].value == 1 else pyo.Constraint.Skip
    model.nationality_requirement = pyo.Constraint(model.SHIPS, model.MISSIONS, rule=nationality_requirement_rule)
    
    # 8. SOLVING WITH GUROBI
    solver = SolverFactory('gurobi')
    results = solver.solve(model, tee=True)
    
    # 9. RESULT PROCESSING
    if results.solver.termination_condition == pyo.TerminationCondition.optimal:
        print(f"Optimal value: {pyo.value(model.objective)}")
    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}")

# Execute the optimization
ship_mission_optimization()