# Complete DOCPLEX implementation

from docplex.mp.model import Model

def swimming_optimization():
    """Optimize swimmer-event assignments to maximize performance score."""
    
    # 1. MODEL & DATA SETUP
    mdl = Model(name="swimming_optimization")
    
    # Example data based on the provided schema and realistic data
    performance_scores = {
        (1, 101): 9.5,
        (2, 102): 8.7,
        (3, 103): 9.0
    }
    
    stadium_capacities = {
        101: 500,
        102: 1000,
        103: 1500
    }
    
    max_events_per_swimmer = 2  # Example constraint
    
    # Extract unique swimmers and events
    swimmers = {i for i, _ in performance_scores.keys()}
    events = {j for _, j in performance_scores.keys()}
    
    # CRITICAL: Validate array lengths to prevent IndexError
    assert len(performance_scores) > 0, "Performance scores data is empty"
    assert len(stadium_capacities) > 0, "Stadium capacities data is empty"
    
    # 2. VARIABLES
    # Binary decision variables for swimmer-event assignments
    x = {(i, j): mdl.binary_var(name=f"x_{i}_{j}") for i, j in performance_scores.keys()}
    
    # 3. OBJECTIVE FUNCTION
    # Maximize the total performance score
    objective = mdl.sum(performance_scores[i, j] * x[i, j] for i, j in performance_scores.keys())
    mdl.maximize(objective)
    
    # 4. CONSTRAINTS
    
    # Maximum events per swimmer constraint
    for i in swimmers:
        mdl.add_constraint(mdl.sum(x[i, j] for j in events if (i, j) in x) <= max_events_per_swimmer, ctname=f"max_events_swimmer_{i}")
    
    # Stadium capacity constraint
    for j in events:
        mdl.add_constraint(mdl.sum(x[i, j] for i in swimmers if (i, j) in x) <= stadium_capacities[j], ctname=f"stadium_capacity_{j}")
    
    # 5. SOLVING & RESULTS
    solution = mdl.solve()
    
    if solution:
        print(f"Optimal value: {solution.objective_value}")
        for (i, j) in x.keys():
            value = solution.get_value(x[i, j])
            if value > 1e-6:
                print(f"x[{i},{j}] = {value:.3f}")
    else:
        print("No solution found")
        print(f"Status: {mdl.solve_details.status}")
    
    return mdl

# Run the optimization
swimming_optimization()