# Complete DOCPLEX implementation - Retry Attempt 4

from docplex.mp.model import Model

def optimize_debate_assignments():
    # 1. MODEL & DATA SETUP
    mdl = Model(name="Debate_Assignment_Optimization")
    
    # Data from the database
    participants = [101, 102, 103]
    debates = [1, 2, 3]
    sides = ['Affirmative', 'Negative']
    
    audience_sizes = {1: 150, 2: 200, 3: 100}
    ages = {101: 25, 102: 30, 103: 35}
    
    # CRITICAL: Validate array lengths to prevent IndexError
    assert len(participants) == len(ages), "Participants and ages length mismatch"
    assert len(debates) == len(audience_sizes), "Debates and audience sizes length mismatch"
    
    # 2. VARIABLES
    x = {(i, j, k): mdl.binary_var(name=f"x_{i}_{j}_{k}") 
         for i in participants 
         for j in debates 
         for k in sides}
    
    # 3. OBJECTIVE FUNCTION
    objective = mdl.sum(audience_sizes[j] * x[i, j, k] 
                        for i in participants 
                        for j in debates 
                        for k in sides)
    mdl.maximize(objective)
    
    # 4. CONSTRAINTS
    
    # Participant Limit: Each participant can be assigned to no more than one debate
    for i in participants:
        mdl.add_constraint(mdl.sum(x[i, j, k] for j in debates for k in sides) <= 1, 
                           ctname=f"participant_limit_{i}")
    
    # Side Balance: For each debate, the number of participants assigned to the Affirmative side must equal the number assigned to the Negative side
    for j in debates:
        mdl.add_constraint(mdl.sum(x[i, j, 'Affirmative'] for i in participants) == 
                           mdl.sum(x[i, j, 'Negative'] for i in participants), 
                           ctname=f"side_balance_{j}")
    
    # Minimum Participation: Each debate must have at least one participant assigned to it
    for j in debates:
        mdl.add_constraint(mdl.sum(x[i, j, k] for i in participants for k in sides) >= 1, 
                           ctname=f"min_participation_{j}")
    
    # Age-Based Constraint: The number of debates a participant can join is limited by their age, specifically by dividing their age by 25
    for i in participants:
        mdl.add_constraint(mdl.sum(x[i, j, k] for j in debates for k in sides) <= (ages[i] // 25), 
                           ctname=f"age_constraint_{i}")
    
    # 5. SOLVING & RESULTS
    solution = mdl.solve()
    
    if solution:
        print(f"Optimal value: {solution.objective_value}")
        for i in participants:
            for j in debates:
                for k in sides:
                    if solution.get_value(x[i, j, k]) > 0:
                        print(f"Participant {i} assigned to Debate {j} on {k} side")
    else:
        print("No solution found")
        print(f"Status: {mdl.solve_details.status}")
    
    return mdl

# Execute the optimization
optimize_debate_assignments()