# Complete GUROBIPY implementation

import gurobipy as gp
from gurobipy import GRB

def optimize_weddings():
    """Optimize the allocation of weddings to churches."""
    
    # 1. MODEL & DATA SETUP
    model = gp.Model("wedding_optimization")
    
    # Data: Church capacities and participant constraints
    church_ids = [1, 2, 3]
    male_ids = [101, 102, 103]
    female_ids = [201, 202, 203]
    capacities = {1: 100, 2: 150, 3: 200}
    
    # Validate data lengths
    assert len(church_ids) == len(capacities), "Church data length mismatch"
    assert len(male_ids) == len(female_ids), "Participant data length mismatch"
    
    # 2. VARIABLES
    # Decision variables: x[i,j,k] = 1 if wedding with male j and female k is held at church i
    x = model.addVars(church_ids, male_ids, female_ids, vtype=GRB.BINARY, name="x")
    
    # 3. OBJECTIVE FUNCTION
    # Maximize the total number of weddings
    model.setObjective(gp.quicksum(x[i, j, k] for i in church_ids for j in male_ids for k in female_ids), GRB.MAXIMIZE)
    
    # 4. CONSTRAINTS
    
    # Church capacity constraints
    model.addConstrs((gp.quicksum(x[i, j, k] for j in male_ids for k in female_ids) <= capacities[i] for i in church_ids), name="church_capacity")
    
    # Unique male participation
    model.addConstrs((gp.quicksum(x[i, j, k] for i in church_ids for k in female_ids) <= 1 for j in male_ids), name="unique_male")
    
    # Unique female participation
    model.addConstrs((gp.quicksum(x[i, j, k] for i in church_ids for j in male_ids) <= 1 for k in female_ids), name="unique_female")
    
    # 5. SOLVING & RESULTS
    model.optimize()
    
    if model.status == GRB.OPTIMAL:
        print(f"Optimal value: {model.objVal}")
        for i in church_ids:
            for j in male_ids:
                for k in female_ids:
                    if x[i, j, k].x > 1e-6:
                        print(f"Wedding at Church {i} with Male {j} and Female {k}")
    elif model.status == GRB.INFEASIBLE:
        print("Problem is infeasible")
    elif model.status == GRB.UNBOUNDED:
        print("Problem is unbounded")
    
    return model

# Run the optimization
optimize_weddings()