# Complete GUROBIPY implementation - Retry Attempt 4

import gurobipy as gp
from gurobipy import GRB

def optimize_friendships():
    # 1. MODEL & DATA SETUP
    model = gp.Model("social_network_friendships")
    
    # Example data
    users = [1, 2, 3, 4, 5]
    age_groups = {1: [1, 2], 2: [1, 3], 3: [2, 3], 4: [1, 3], 5: [2, 3]}
    max_friendships = 15
    min_friendships_per_age_group = 3
    
    # Validate data lengths
    assert len(users) > 0, "No users provided"
    assert all(len(age_groups[u]) > 0 for u in users), "Age groups missing for some users"
    
    # 2. VARIABLES
    friendships = model.addVars([(i, j) for i in users for j in users if i < j], vtype=GRB.BINARY, name="friendship")
    
    # 3. OBJECTIVE FUNCTION
    model.setObjective(gp.quicksum(friendships[(i, j)] for i in users for j in users if i < j), GRB.MAXIMIZE)
    
    # 4. CONSTRAINTS
    # Maximum friendships per person
    for i in users:
        model.addConstr(gp.quicksum(friendships[(i, j)] for j in users if i < j) +
                        gp.quicksum(friendships[(j, i)] for j in users if j < i) <= max_friendships,
                        name=f"max_friendships_{i}")
    
    # Minimum friendships per age group
    for i in users:
        for age_group in set(age_groups[i]):
            model.addConstr(gp.quicksum(friendships[(i, j)] for j in users if j > i and age_group in age_groups[j]) +
                            gp.quicksum(friendships[(j, i)] for j in users if j < i and age_group in age_groups[j]) >= min_friendships_per_age_group,
                            name=f"min_friendships_age_group_{i}_{age_group}")
    
    # Mutual friendships
    for i in users:
        for j in users:
            if i < j:
                model.addConstr(friendships[(i, j)] == friendships[(j, i)], name=f"mutual_friendship_{i}_{j}")
    
    # 5. SOLVING & RESULTS
    model.optimize()
    
    if model.status == GRB.OPTIMAL:
        print(f"Optimal value: {model.objVal}")
        for i in users:
            for j in users:
                if i < j and friendships[(i, j)].x > 0.5:
                    print(f"Friendship between {i} and {j}")
    elif model.status == GRB.INFEASIBLE:
        print("Problem is infeasible")
    elif model.status == GRB.UNBOUNDED:
        print("Problem is unbounded")
    
    return model

# Execute the optimization
optimize_friendships()