#!/usr/bin/env python3
"""
Gurobipy implementation for concert singer optimization problem
"""

import gurobipy as gp
from gurobipy import GRB

def optimize_concert_singer():
    # 1. MODEL & DATA SETUP
    model = gp.Model("concert_singer_optimization")
    
    # Data from the problem
    stadium_capacities = [10000, 20000, 30000]
    singer_assignments = [0, 1, 0, 1, 0]
    L = 2  # Maximum number of concerts a singer can participate in
    
    # Number of singers and stadiums
    n_singers = len(singer_assignments)
    n_stadiums = len(stadium_capacities)
    
    # CRITICAL: Validate array lengths before loops
    assert len(stadium_capacities) == n_stadiums, "Stadium capacities array length mismatch"
    assert len(singer_assignments) == n_singers, "Singer assignments array length mismatch"
    
    # 2. VARIABLES
    # Decision variables: x_ij (binary)
    x = model.addVars(n_singers, n_stadiums, vtype=GRB.BINARY, name="x")
    
    # 3. OBJECTIVE FUNCTION
    # Maximize total audience capacity
    model.setObjective(
        gp.quicksum(stadium_capacities[j] * x[i, j] for i in range(n_singers) for j in range(n_stadiums)),
        GRB.MAXIMIZE
    )
    
    # 4. CONSTRAINTS
    
    # Singer Assignment Limit: Each singer can participate in at most L concerts
    for i in range(n_singers):
        model.addConstr(
            gp.quicksum(x[i, j] for j in range(n_stadiums)) <= L,
            name=f"singer_limit_{i}"
        )
    
    # Stadium Capacity Limit: Each concert in stadium j cannot exceed the stadium's capacity
    for j in range(n_stadiums):
        model.addConstr(
            gp.quicksum(x[i, j] for i in range(n_singers)) <= stadium_capacities[j],
            name=f"stadium_capacity_{j}"
        )
    
    # 5. SOLVING & RESULTS
    model.optimize()
    
    if model.status == GRB.OPTIMAL:
        print(f"Optimal value: {model.objVal}")
        for i in range(n_singers):
            for j in range(n_stadiums):
                if x[i, j].x > 1e-6:
                    print(f"Singer {i} assigned to stadium {j}: {x[i, j].x:.0f}")
    elif model.status == GRB.INFEASIBLE:
        print("Problem is infeasible")
    elif model.status == GRB.UNBOUNDED:
        print("Problem is unbounded")
    
    return model

# Execute the optimization
if __name__ == "__main__":
    optimize_concert_singer()