# Complete PYOMO implementation - Retry Attempt 1

import pyomo.environ as pyo
from pyomo.opt import SolverFactory

def movie_recommendation_optimization():
    # 1. MODEL CREATION
    model = pyo.ConcreteModel()
    
    # 2. DATA SETUP
    # Define sets for reviewers and movies
    reviewers = [1, 2, 3]
    movies = [1, 2, 3]
    
    # Define star ratings
    star_ratings = {
        (1, 1): 5,
        (2, 2): 4,
        (3, 3): 3
    }
    
    # Define maximum recommendations for movies
    movie_max_recommendations = {
        1: 10,
        2: 7,
        3: 5
    }
    
    # Define maximum recommendations for reviewers
    reviewer_max_recommendations = {
        1: 5,
        2: 4,
        3: 3
    }
    
    # 3. SETS
    model.reviewers = pyo.Set(initialize=reviewers)
    model.movies = pyo.Set(initialize=movies)
    
    # 4. PARAMETERS
    model.star_ratings = pyo.Param(model.reviewers, model.movies, initialize=star_ratings, default=0)
    model.movie_max_recommendations = pyo.Param(model.movies, initialize=movie_max_recommendations)
    model.reviewer_max_recommendations = pyo.Param(model.reviewers, initialize=reviewer_max_recommendations)
    
    # 5. VARIABLES
    model.x = pyo.Var(model.reviewers, model.movies, within=pyo.NonNegativeIntegers)
    
    # 6. OBJECTIVE FUNCTION
    def obj_rule(model):
        return sum(model.star_ratings[i, j] * model.x[i, j] for i in model.reviewers for j in model.movies)
    model.objective = pyo.Objective(rule=obj_rule, sense=pyo.maximize)
    
    # 7. CONSTRAINTS
    # Movie Recommendation Limits
    def movie_limit_rule(model, j):
        return sum(model.x[i, j] for i in model.reviewers) <= model.movie_max_recommendations[j]
    model.movie_limit_constraint = pyo.Constraint(model.movies, rule=movie_limit_rule)
    
    # Reviewer Recommendation Limits
    def reviewer_limit_rule(model, i):
        return sum(model.x[i, j] for j in model.movies) <= model.reviewer_max_recommendations[i]
    model.reviewer_limit_constraint = pyo.Constraint(model.reviewers, rule=reviewer_limit_rule)
    
    # 8. SOLVING WITH GUROBI
    solver = SolverFactory('gurobi')
    results = solver.solve(model, tee=True)
    
    # 9. RESULT PROCESSING
    if results.solver.termination_condition == pyo.TerminationCondition.optimal:
        print(f"Optimal value: {pyo.value(model.objective)}")
    elif results.solver.termination_condition == pyo.TerminationCondition.infeasible:
        print("Problem is infeasible")
    elif results.solver.termination_condition == pyo.TerminationCondition.unbounded:
        print("Problem is unbounded")
    else:
        print(f"Solver terminated with condition: {results.solver.termination_condition}")

# Execute the optimization
movie_recommendation_optimization()