#!/usr/bin/env python3
"""
Gurobipy 12.0.2 Implementation for Singer Promotion Optimization
"""

import gurobipy as gp
from gurobipy import GRB

def singer_promotion_optimization():
    """Optimize singer selection to maximize song sales within budget and promotional capacity constraints."""
    
    # 1. MODEL & DATA SETUP
    model = gp.Model("singer_promotion")
    
    # Data from the problem
    singers = [1, 2, 3]
    sales = {1: 1500, 2: 2500, 3: 1000}
    net_worth = {1: 200000, 2: 300000, 3: 150000}  # Placeholder values for net worth
    total_budget = 500000
    max_singers = 3
    
    # CRITICAL: Validate array lengths before loops
    assert len(singers) == len(sales) == len(net_worth), "Array length mismatch"
    
    # 2. VARIABLES
    x = {i: model.addVar(vtype=GRB.BINARY, name=f"x_{i}") for i in singers}
    
    # 3. OBJECTIVE FUNCTION
    model.setObjective(gp.quicksum(sales[i] * x[i] for i in singers), GRB.MAXIMIZE)
    
    # 4. CONSTRAINTS
    # Budget Constraint
    model.addConstr(gp.quicksum(net_worth[i] * x[i] for i in singers) <= total_budget, name="budget_constraint")
    
    # Promotional Capacity Constraint
    model.addConstr(gp.quicksum(x[i] for i in singers) <= max_singers, name="promotional_capacity_constraint")
    
    # 5. SOLVING & RESULTS
    model.optimize()
    
    if model.status == GRB.OPTIMAL:
        print(f"Optimal value: {model.objVal}")
        for i in singers:
            if x[i].x > 1e-6:
                print(f"Singer {i} is selected for promotion.")
    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__":
    singer_promotion_optimization()