# Complete GUROBIPY implementation - Retry Attempt 4

import gurobipy as gp
from gurobipy import GRB

def program_share_optimization():
    # 1. MODEL & DATA SETUP
    model = gp.Model("program_share_optimization")
    
    # Data from the database
    channels = [1, 2, 3]
    programs = [1, 2, 3]
    time_slots = [1, 2, 3]
    
    # Program shares and channel ratings
    program_shares = {
        (1, 1): 60,
        (2, 2): 70,
        (3, 3): 50
    }
    
    channel_ratings = {
        1: 75,
        2: 85,
        3: 80
    }
    
    # Program origins
    program_origins = {
        1: 'Local',
        2: 'International',
        3: 'Local'
    }
    
    # Validate array lengths before loops
    assert len(program_shares) == len(programs) * len(channels), "Program shares length mismatch"
    assert len(channel_ratings) == len(channels), "Channel ratings length mismatch"
    assert len(program_origins) == len(programs), "Program origins length mismatch"
    
    # 2. VARIABLES
    x = model.addVars(channels, programs, time_slots, vtype=GRB.BINARY, name="x")
    
    # 3. OBJECTIVE FUNCTION
    model.setObjective(
        gp.quicksum(
            program_shares[c, p] * channel_ratings[c] * x[c, p, t]
            for c in channels
            for p in programs
            for t in time_slots
        ),
        GRB.MAXIMIZE
    )
    
    # 4. CONSTRAINTS
    
    # Program Uniqueness: Each program can be broadcast at most once across all channels and time slots
    for p in programs:
        model.addConstr(
            gp.quicksum(x[c, p, t] for c in channels for t in time_slots) <= 1,
            name=f"program_uniqueness_{p}"
        )
    
    # Channel Time Slot Limit: Each channel can use at most 5 time slots
    for c in channels:
        model.addConstr(
            gp.quicksum(x[c, p, t] for p in programs for t in time_slots) <= 5,
            name=f"channel_time_slot_limit_{c}"
        )
    
    # Local Program Requirement: Each channel must broadcast at least 2 local programs
    for c in channels:
        model.addConstr(
            gp.quicksum(x[c, p, t] for p in programs if program_origins[p] == 'Local' for t in time_slots) >= 2,
            name=f"local_program_requirement_{c}"
        )
    
    # 5. SOLVING & RESULTS
    model.optimize()
    
    if model.status == GRB.OPTIMAL:
        print(f"Optimal value: {model.objVal}")
        for c in channels:
            for p in programs:
                for t in time_slots:
                    if x[c, p, t].x > 0.5:
                        print(f"Channel {c} broadcasts Program {p} at Time Slot {t}")
    elif model.status == GRB.INFEASIBLE:
        print("Problem is infeasible")
    elif model.status == GRB.UNBOUNDED:
        print("Problem is unbounded")
    
    return model

# Execute the optimization
program_share_optimization()