# Complete DOCPLEX implementation - Retry Attempt 4

from docplex.mp.model import Model

def program_share_optimization():
    # 1. MODEL & DATA SETUP
    mdl = Model(name="program_share_optimization")
    
    # Data from the database
    channels = [1, 2, 3]
    programs = [1, 2, 3]
    time_slots = [1, 2, 3]
    
    program_shares = {
        (1, 1): 60,
        (2, 2): 70,
        (3, 3): 50
    }
    
    channel_ratings = {
        1: 75,
        2: 85,
        3: 80
    }
    
    program_origins = {
        1: 'Local',
        2: 'International',
        3: 'Local'
    }
    
    # CRITICAL: Validate array lengths to prevent IndexError
    assert len(program_shares) == len(programs) * len(channels), "Program shares length mismatch"
    
    # 2. VARIABLES
    x = {(c, p, t): mdl.binary_var(name=f"x_{c}_{p}_{t}") 
         for c in channels 
         for p in programs 
         for t in time_slots}
    
    # 3. OBJECTIVE FUNCTION
    objective = mdl.sum(program_shares[(c, p)] * channel_ratings[c] * x[(c, p, t)] 
                        for c in channels 
                        for p in programs 
                        for t in time_slots)
    mdl.maximize(objective)
    
    # 4. CONSTRAINTS
    
    # Program Uniqueness: Each program can be broadcast at most once
    for p in programs:
        mdl.add_constraint(mdl.sum(x[(c, p, t)] for c in channels for t in time_slots) <= 1, 
                           ctname=f"program_uniqueness_{p}")
    
    # Channel Time Slot Limit: Each channel can use at most 5 time slots
    for c in channels:
        mdl.add_constraint(mdl.sum(x[(c, p, t)] for p in programs for t in time_slots) <= 5, 
                           ctname=f"time_slot_limit_{c}")
    
    # Local Program Requirement: Each channel must broadcast at least 2 local programs
    for c in channels:
        mdl.add_constraint(mdl.sum(x[(c, p, t)] for p in programs if program_origins[p] == 'Local' for t in time_slots) >= 2, 
                           ctname=f"local_program_requirement_{c}")
    
    # 5. SOLVING & RESULTS
    solution = mdl.solve()
    
    if solution:
        print(f"Optimal value: {solution.objective_value}")
        for c in channels:
            for p in programs:
                for t in time_slots:
                    if solution.get_value(x[(c, p, t)]) > 0.5:
                        print(f"Channel {c} broadcasts Program {p} at Time Slot {t}")
    else:
        print("No solution found")
        print(f"Status: {mdl.solve_details.status}")
    
    return mdl

# Execute the optimization
program_share_optimization()