# Complete DOCPLEX implementation

from docplex.mp.model import Model

def optimize_weddings():
    """Optimize the allocation of weddings to churches."""
    
    # 1. MODEL & DATA SETUP
    mdl = Model(name="wedding_optimization")
    
    # Data: Church capacities
    church_ids = [1, 2, 3]
    capacities = [100, 150, 200]
    
    # Data: Participants
    male_ids = [101, 102, 103]
    female_ids = [201, 202, 203]
    
    # CRITICAL: Validate array lengths to prevent IndexError
    assert len(church_ids) == len(capacities), "Array length mismatch for church capacities"
    assert len(male_ids) == len(female_ids), "Array length mismatch for participants"
    
    # Safe indexing
    safe_church_range = range(len(church_ids))
    safe_participant_range = range(len(male_ids))
    
    # 2. VARIABLES
    # Decision variables: x[i][j][k] = 1 if wedding with male j and female k is held at church i
    x = {(i, j, k): mdl.binary_var(name=f"x_{i}_{j}_{k}") for i in safe_church_range for j in safe_participant_range for k in safe_participant_range}
    
    # 3. OBJECTIVE FUNCTION
    # Maximize the total number of weddings
    objective = mdl.sum(x[i, j, k] for i in safe_church_range for j in safe_participant_range for k in safe_participant_range)
    mdl.maximize(objective)
    
    # 4. CONSTRAINTS
    
    # Church capacity constraints
    for i in safe_church_range:
        mdl.add_constraint(mdl.sum(x[i, j, k] for j in safe_participant_range for k in safe_participant_range) <= capacities[i], ctname=f"capacity_{i}")
    
    # Unique male participation
    for j in safe_participant_range:
        mdl.add_constraint(mdl.sum(x[i, j, k] for i in safe_church_range for k in safe_participant_range) <= 1, ctname=f"unique_male_{j}")
    
    # Unique female participation
    for k in safe_participant_range:
        mdl.add_constraint(mdl.sum(x[i, j, k] for i in safe_church_range for j in safe_participant_range) <= 1, ctname=f"unique_female_{k}")
    
    # 5. SOLVING & RESULTS
    solution = mdl.solve()
    
    if solution:
        print(f"Optimal value: {solution.objective_value}")
        for i in safe_church_range:
            for j in safe_participant_range:
                for k in safe_participant_range:
                    value = solution.get_value(x[i, j, k])
                    if value > 1e-6:
                        print(f"x[{i}][{j}][{k}] = {value:.3f}")
    else:
        print("No solution found")
        print(f"Status: {mdl.solve_details.status}")
    
    return mdl

# Run the optimization
optimize_weddings()