# Complete DOCPLEX implementation - Retry Attempt 4

from docplex.mp.model import Model

def music_festival_optimization():
    # 1. MODEL & DATA SETUP
    mdl = Model(name="music_festival_optimization")
    
    # Sample data
    songs = ['S1', 'S2', 'S3', 'S4', 'S5']
    artists = ['A1', 'A2', 'A3', 'A4', 'A5']
    weeks_on_top = {'S1': 5, 'S2': 10, 'S3': 15, 'S4': 3, 'S5': 8}
    artist_songs = {'A1': ['S1', 'S2'], 'A2': ['S3'], 'A3': ['S4'], 'A4': ['S5'], 'A5': []}
    
    # Validate array lengths
    assert len(songs) == len(weeks_on_top), "Mismatch in songs and weeks_on_top data"
    
    # 2. VARIABLES
    x = {song: mdl.binary_var(name=f"x_{song}") for song in songs}
    y = {artist: mdl.binary_var(name=f"y_{artist}") for artist in artists}
    
    # 3. OBJECTIVE FUNCTION
    objective = mdl.sum(weeks_on_top[song] * x[song] for song in songs)
    mdl.maximize(objective)
    
    # 4. CONSTRAINTS
    # Total Song Capacity
    mdl.add_constraint(mdl.sum(x[song] for song in songs) <= 50, ctname="total_song_capacity")
    
    # Maximum Songs Per Artist
    for artist in artists:
        if artist_songs[artist]:  # Ensure artist has songs
            mdl.add_constraint(mdl.sum(x[song] for song in artist_songs[artist]) <= 3, ctname=f"max_songs_{artist}")
    
    # Minimum Number of Artists
    for artist in artists:
        if artist_songs[artist]:  # Ensure artist has songs
            mdl.add_constraint(y[artist] <= mdl.sum(x[song] for song in artist_songs[artist]), ctname=f"artist_selection_lower_{artist}")
            for song in artist_songs[artist]:
                mdl.add_constraint(y[artist] >= x[song], ctname=f"artist_selection_upper_{artist}_{song}")
    
    mdl.add_constraint(mdl.sum(y[artist] for artist in artists) >= 10, ctname="min_artists")
    
    # 5. SOLVING & RESULTS
    solution = mdl.solve()
    
    if solution:
        print(f"Optimal value: {solution.objective_value}")
        for song in songs:
            if solution.get_value(x[song]) > 0:
                print(f"Selected song: {song}, Weeks on Top: {weeks_on_top[song]}")
    else:
        print("No solution found")
        print(f"Status: {mdl.solve_details.status}")
    
    return mdl

# Execute the optimization
music_festival_optimization()