# Complete Optimization Problem and Solution: tvshow

## 1. Problem Context and Goals

### Context  
A TV network is tasked with maximizing viewer engagement by strategically allocating airtime to its series and cartoons. The network must decide how many episodes of each show to air, considering the show's viewer ratings, the channel's total available airtime, and the need for content diversity. Each show has a minimum and maximum number of episodes that must be aired to ensure visibility and avoid over-saturation. Additionally, the network must maintain a minimum level of diversity across the aired shows to cater to a broad audience. The total airtime allocated to all shows combined cannot exceed the channel's capacity, which is set at 1200 units. The network aims to balance these factors to achieve the highest possible viewer ratings while adhering to operational constraints.

### Goals  
The primary goal is to maximize the total viewer ratings across all aired episodes. This is achieved by determining the optimal number of episodes to air for each show, weighted by its individual rating. Success is measured by the sum of the ratings of all aired episodes, ensuring that the network's programming appeals to the largest possible audience. The decision-making process is guided by linear relationships, ensuring that the solution is both practical and efficient.

## 2. Constraints    

1. **Total Airtime Constraint**: The combined airtime of all aired episodes must not exceed the channel's total available airtime of 1200 units. This ensures that the network operates within its capacity.  
2. **Episode Bounds Constraint**: Each show must air a minimum of 1 episode and a maximum of 10 episodes. This ensures that no show is overlooked or overexposed.  
3. **Diversity Constraint**: The total diversity score of all aired shows must meet or exceed the minimum required diversity score of 50. This ensures a balanced mix of content that appeals to a wide audience.  

These constraints are designed to align with linear mathematical relationships, ensuring that the optimization problem remains straightforward and solvable using linear methods.

## 3. Available Data  

### Database Schema  
```sql
-- Iteration 1 Database Schema
-- Objective: Schema changes include creating new tables for missing optimization requirements, modifying existing tables to better map to optimization variables, and adding business configuration logic for scalar parameters and formulas.

CREATE TABLE TV_series (
  Rating FLOAT,
  Min_Episodes INTEGER,
  Max_Episodes INTEGER,
  Episodes_Aired INTEGER
);

CREATE TABLE Cartoon (
  Rating FLOAT,
  Min_Episodes INTEGER,
  Max_Episodes INTEGER,
  Episodes_Aired INTEGER
);

CREATE TABLE Show_Diversity (
  Diversity_Score INTEGER
);


```

### Data Dictionary  
- **TV_series**: Stores information about TV series, including their ratings, minimum and maximum episode limits, and the number of episodes aired.  
  - **Rating**: The viewer rating of the TV series, used to determine its contribution to the total viewer engagement.  
  - **Min_Episodes**: The minimum number of episodes that must be aired for the series to maintain visibility.  
  - **Max_Episodes**: The maximum number of episodes that can be aired to avoid over-saturation.  
  - **Episodes_Aired**: The decision variable representing the number of episodes aired for the series.  

- **Cartoon**: Stores information about cartoons, including their ratings, minimum and maximum episode limits, and the number of episodes aired.  
  - **Rating**: The viewer rating of the cartoon, used to determine its contribution to the total viewer engagement.  
  - **Min_Episodes**: The minimum number of episodes that must be aired for the cartoon to maintain visibility.  
  - **Max_Episodes**: The maximum number of episodes that can be aired to avoid over-saturation.  
  - **Episodes_Aired**: The decision variable representing the number of episodes aired for the cartoon.  

- **Show_Diversity**: Stores diversity scores for shows, ensuring a balanced mix of content.  
  - **Diversity_Score**: The diversity score of the show, used to ensure that the total diversity of aired shows meets the minimum requirement.  

### Current Stored Values  
```sql
-- Iteration 1 Realistic Data
-- Generated by triple expert (business + data + optimization)
-- Values were determined based on typical TV network operations, considering viewer ratings, airtime constraints, and content diversity requirements. The data ensures a balanced mix of popular and diverse shows while respecting the channel's capacity.

-- Realistic data for TV_series
INSERT INTO TV_series (Rating, Min_Episodes, Max_Episodes, Episodes_Aired) VALUES (4.8, 2, 8, 5);
INSERT INTO TV_series (Rating, Min_Episodes, Max_Episodes, Episodes_Aired) VALUES (4.3, 1, 6, 3);
INSERT INTO TV_series (Rating, Min_Episodes, Max_Episodes, Episodes_Aired) VALUES (4.6, 3, 7, 4);

-- Realistic data for Cartoon
INSERT INTO Cartoon (Rating, Min_Episodes, Max_Episodes, Episodes_Aired) VALUES (4.5, 1, 5, 3);
INSERT INTO Cartoon (Rating, Min_Episodes, Max_Episodes, Episodes_Aired) VALUES (4.1, 2, 4, 2);
INSERT INTO Cartoon (Rating, Min_Episodes, Max_Episodes, Episodes_Aired) VALUES (4.4, 1, 6, 4);

-- Realistic data for Show_Diversity
INSERT INTO Show_Diversity (Diversity_Score) VALUES (15);
INSERT INTO Show_Diversity (Diversity_Score) VALUES (10);
INSERT INTO Show_Diversity (Diversity_Score) VALUES (20);


```

## 4. Mathematical Optimization Formulation

#### Decision Variables
- Let \( x_i \) be the number of episodes aired for TV series \( i \) (where \( i = 1, 2, 3 \)).
- Let \( y_j \) be the number of episodes aired for cartoon \( j \) (where \( j = 1, 2, 3 \)).

#### Objective Function
Maximize the total viewer ratings:
\[
\text{Maximize } Z = 4.8x_1 + 4.3x_2 + 4.6x_3 + 4.5y_1 + 4.1y_2 + 4.4y_3
\]

#### Constraints
1. **Total Airtime Constraint**:
   \[
   x_1 + x_2 + x_3 + y_1 + y_2 + y_3 \leq 1200
   \]
2. **Episode Bounds Constraint**:
   - For TV series:
     \[
     2 \leq x_1 \leq 8, \quad 1 \leq x_2 \leq 6, \quad 3 \leq x_3 \leq 7
     \]
   - For cartoons:
     \[
     1 \leq y_1 \leq 5, \quad 2 \leq y_2 \leq 4, \quad 1 \leq y_3 \leq 6
     \]
3. **Diversity Constraint**:
   \[
   15x_1 + 10x_2 + 20x_3 + 15y_1 + 10y_2 + 20y_3 \geq 50
   \]

#### Data Source Verification
- **Objective Function Coefficients**:
  - \( 4.8, 4.3, 4.6 \) from `TV_series.Rating`.
  - \( 4.5, 4.1, 4.4 \) from `Cartoon.Rating`.
- **Episode Bounds Constraints**:
  - \( 2, 1, 3 \) from `TV_series.Min_Episodes`.
  - \( 8, 6, 7 \) from `TV_series.Max_Episodes`.
  - \( 1, 2, 1 \) from `Cartoon.Min_Episodes`.
  - \( 5, 4, 6 \) from `Cartoon.Max_Episodes`.
- **Diversity Constraint Coefficients**:
  - \( 15, 10, 20 \) from `Show_Diversity.Diversity_Score` for TV series.
  - \( 15, 10, 20 \) from `Show_Diversity.Diversity_Score` for cartoons.

This formulation provides a complete, immediately solvable LINEAR mathematical model with all numerical coefficients derived from the provided data.

## 5. Gurobipy Implementation

```python
#!/usr/bin/env python3
"""
Gurobipy 12.0.2 Implementation for TV Show Optimization Problem
"""

import gurobipy as gp
from gurobipy import GRB

def tvshow_optimization():
    """Optimize TV show and cartoon airtime allocation to maximize viewer ratings."""
    
    # 1. MODEL & DATA SETUP
    model = gp.Model("tvshow_optimization")
    
    # Data from the problem
    tv_series_ratings = [4.8, 4.3, 4.6]
    cartoon_ratings = [4.5, 4.1, 4.4]
    
    tv_series_min_episodes = [2, 1, 3]
    tv_series_max_episodes = [8, 6, 7]
    
    cartoon_min_episodes = [1, 2, 1]
    cartoon_max_episodes = [5, 4, 6]
    
    diversity_scores = [15, 10, 20]
    
    total_airtime = 1200
    min_diversity = 50
    
    # CRITICAL: Validate array lengths before loops
    assert len(tv_series_ratings) == len(tv_series_min_episodes) == len(tv_series_max_episodes) == 3, "TV series data length mismatch"
    assert len(cartoon_ratings) == len(cartoon_min_episodes) == len(cartoon_max_episodes) == 3, "Cartoon data length mismatch"
    assert len(diversity_scores) == 3, "Diversity scores length mismatch"
    
    # 2. VARIABLES
    # Decision variables for TV series and cartoons
    x = {i: model.addVar(vtype=GRB.INTEGER, name=f"x_{i}", lb=tv_series_min_episodes[i], ub=tv_series_max_episodes[i]) 
         for i in range(3)}
    
    y = {i: model.addVar(vtype=GRB.INTEGER, name=f"y_{i}", lb=cartoon_min_episodes[i], ub=cartoon_max_episodes[i]) 
         for i in range(3)}
    
    # 3. OBJECTIVE FUNCTION
    # Maximize total viewer ratings
    model.setObjective(
        gp.quicksum(tv_series_ratings[i] * x[i] for i in range(3)) +
        gp.quicksum(cartoon_ratings[i] * y[i] for i in range(3)),
        GRB.MAXIMIZE
    )
    
    # 4. CONSTRAINTS
    
    # Total Airtime Constraint
    model.addConstr(
        gp.quicksum(x[i] for i in range(3)) + gp.quicksum(y[i] for i in range(3)) <= total_airtime,
        name="total_airtime"
    )
    
    # Diversity Constraint
    model.addConstr(
        gp.quicksum(diversity_scores[i] * x[i] for i in range(3)) +
        gp.quicksum(diversity_scores[i] * y[i] for i in range(3)) >= min_diversity,
        name="min_diversity"
    )
    
    # 5. SOLVING & RESULTS
    model.optimize()
    
    if model.status == GRB.OPTIMAL:
        print(f"Optimal value: {model.objVal}")
        for i in range(3):
            print(f"TV Series {i+1} episodes aired: {x[i].x}")
        for i in range(3):
            print(f"Cartoon {i+1} episodes aired: {y[i].x}")
    elif model.status == GRB.INFEASIBLE:
        print("Problem is infeasible")
    elif model.status == GRB.UNBOUNDED:
        print("Problem is unbounded")
    
    return model

# Run the optimization
if __name__ == "__main__":
    tvshow_optimization()
```

### Execution Results
**Status**: OPTIMAL
**Optimal Value**: 161.7
**Execution Time**: 0.21 seconds
**Reliability**: high
**Analysis**: Gurobipy achieved the optimal solution efficiently with the fastest execution time.

## 6. DOCplex Implementation

```python
#!/usr/bin/env python3
"""
DOCplex implementation for TV show optimization problem
"""

from docplex.mp.model import Model

def tvshow_optimization():
    """Optimize TV show and cartoon airtime allocation to maximize viewer ratings."""
    
    # 1. MODEL & DATA SETUP
    mdl = Model(name="tvshow_optimization")
    
    # Data from the problem statement
    tv_series_ratings = [4.8, 4.3, 4.6]
    cartoon_ratings = [4.5, 4.1, 4.4]
    
    tv_series_min_episodes = [2, 1, 3]
    tv_series_max_episodes = [8, 6, 7]
    
    cartoon_min_episodes = [1, 2, 1]
    cartoon_max_episodes = [5, 4, 6]
    
    diversity_scores = [15, 10, 20]
    
    total_airtime = 1200
    min_diversity = 50
    
    # CRITICAL: Validate array lengths to prevent IndexError
    assert len(tv_series_ratings) == len(tv_series_min_episodes) == len(tv_series_max_episodes) == len(diversity_scores), "TV series array length mismatch"
    assert len(cartoon_ratings) == len(cartoon_min_episodes) == len(cartoon_max_episodes) == len(diversity_scores), "Cartoon array length mismatch"
    
    safe_range_tv = range(len(tv_series_ratings))
    safe_range_cartoon = range(len(cartoon_ratings))
    
    # 2. VARIABLES
    x = {i: mdl.integer_var(name=f"x_{i}", lb=tv_series_min_episodes[i], ub=tv_series_max_episodes[i]) for i in safe_range_tv}
    y = {i: mdl.integer_var(name=f"y_{i}", lb=cartoon_min_episodes[i], ub=cartoon_max_episodes[i]) for i in safe_range_cartoon}
    
    # 3. OBJECTIVE FUNCTION
    objective = mdl.sum(tv_series_ratings[i] * x[i] for i in safe_range_tv) + \
               mdl.sum(cartoon_ratings[i] * y[i] for i in safe_range_cartoon)
    mdl.maximize(objective)
    
    # 4. CONSTRAINTS
    
    # Total Airtime Constraint
    total_airtime_expr = mdl.sum(x[i] for i in safe_range_tv) + \
                         mdl.sum(y[i] for i in safe_range_cartoon)
    mdl.add_constraint(total_airtime_expr <= total_airtime, ctname="total_airtime")
    
    # Diversity Constraint
    diversity_expr = mdl.sum(diversity_scores[i] * x[i] for i in safe_range_tv) + \
                     mdl.sum(diversity_scores[i] * y[i] for i in safe_range_cartoon)
    mdl.add_constraint(diversity_expr >= min_diversity, ctname="diversity")
    
    # 5. SOLVING & RESULTS
    solution = mdl.solve()
    
    if solution:
        print(f"Optimal value: {solution.objective_value}")
        for i in safe_range_tv:
            value = solution.get_value(x[i])
            print(f"TV Series {i+1} episodes aired: {value}")
        for i in safe_range_cartoon:
            value = solution.get_value(y[i])
            print(f"Cartoon {i+1} episodes aired: {value}")
    else:
        print("No solution found")
        print(f"Status: {mdl.solve_details.status}")
    
    return mdl

# Run the optimization
if __name__ == "__main__":
    tvshow_optimization()
```

### Execution Results
**Status**: OPTIMAL
**Optimal Value**: 161.7
**Execution Time**: 1.05 seconds
**Reliability**: high
**Analysis**: DOCplex also found the optimal solution but with a longer execution time compared to Gurobipy.

## 7. Pyomo Implementation

```python
#!/usr/bin/env python3
"""
Pyomo 6.9.2 Implementation for TV Show Optimization Problem
"""

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

def tvshow_optimization():
    """Optimize TV show episode allocation to maximize viewer ratings."""
    
    # 1. MODEL CREATION
    model = pyo.ConcreteModel()
    
    # 2. DATA SETUP
    # TV Series Data
    tv_series_ratings = [4.8, 4.3, 4.6]
    tv_series_min_episodes = [2, 1, 3]
    tv_series_max_episodes = [8, 6, 7]
    tv_series_diversity_scores = [15, 10, 20]
    
    # Cartoon Data
    cartoon_ratings = [4.5, 4.1, 4.4]
    cartoon_min_episodes = [1, 2, 1]
    cartoon_max_episodes = [5, 4, 6]
    cartoon_diversity_scores = [15, 10, 20]
    
    # Validate array lengths
    assert len(tv_series_ratings) == len(tv_series_min_episodes) == len(tv_series_max_episodes) == len(tv_series_diversity_scores), "TV Series data length mismatch"
    assert len(cartoon_ratings) == len(cartoon_min_episodes) == len(cartoon_max_episodes) == len(cartoon_diversity_scores), "Cartoon data length mismatch"
    
    # 3. SETS
    model.TV = pyo.RangeSet(1, len(tv_series_ratings))  # 1-based indexing for TV series
    model.CARTOON = pyo.RangeSet(1, len(cartoon_ratings))  # 1-based indexing for cartoons
    
    # 4. PARAMETERS
    model.tv_rating = pyo.Param(model.TV, initialize={i+1: tv_series_ratings[i] for i in range(len(tv_series_ratings))})
    model.tv_min_episodes = pyo.Param(model.TV, initialize={i+1: tv_series_min_episodes[i] for i in range(len(tv_series_min_episodes))})
    model.tv_max_episodes = pyo.Param(model.TV, initialize={i+1: tv_series_max_episodes[i] for i in range(len(tv_series_max_episodes))})
    model.tv_diversity = pyo.Param(model.TV, initialize={i+1: tv_series_diversity_scores[i] for i in range(len(tv_series_diversity_scores))})
    
    model.cartoon_rating = pyo.Param(model.CARTOON, initialize={i+1: cartoon_ratings[i] for i in range(len(cartoon_ratings))})
    model.cartoon_min_episodes = pyo.Param(model.CARTOON, initialize={i+1: cartoon_min_episodes[i] for i in range(len(cartoon_min_episodes))})
    model.cartoon_max_episodes = pyo.Param(model.CARTOON, initialize={i+1: cartoon_max_episodes[i] for i in range(len(cartoon_max_episodes))})
    model.cartoon_diversity = pyo.Param(model.CARTOON, initialize={i+1: cartoon_diversity_scores[i] for i in range(len(cartoon_diversity_scores))})
    
    # 5. VARIABLES
    model.tv_episodes = pyo.Var(model.TV, within=pyo.NonNegativeIntegers)
    model.cartoon_episodes = pyo.Var(model.CARTOON, within=pyo.NonNegativeIntegers)
    
    # 6. OBJECTIVE FUNCTION
    def obj_rule(model):
        return sum(model.tv_rating[i] * model.tv_episodes[i] for i in model.TV) + \
               sum(model.cartoon_rating[j] * model.cartoon_episodes[j] for j in model.CARTOON)
    model.objective = pyo.Objective(rule=obj_rule, sense=pyo.maximize)
    
    # 7. CONSTRAINTS
    # Total Airtime Constraint
    def airtime_rule(model):
        return sum(model.tv_episodes[i] for i in model.TV) + \
               sum(model.cartoon_episodes[j] for j in model.CARTOON) <= 1200
    model.airtime_constraint = pyo.Constraint(rule=airtime_rule)
    
    # Episode Bounds Constraint for TV Series
    def tv_episode_bounds_rule(model, i):
        return (model.tv_min_episodes[i], model.tv_episodes[i], model.tv_max_episodes[i])
    model.tv_episode_bounds = pyo.Constraint(model.TV, rule=tv_episode_bounds_rule)
    
    # Episode Bounds Constraint for Cartoons
    def cartoon_episode_bounds_rule(model, j):
        return (model.cartoon_min_episodes[j], model.cartoon_episodes[j], model.cartoon_max_episodes[j])
    model.cartoon_episode_bounds = pyo.Constraint(model.CARTOON, rule=cartoon_episode_bounds_rule)
    
    # Diversity Constraint
    def diversity_rule(model):
        return sum(model.tv_diversity[i] * model.tv_episodes[i] for i in model.TV) + \
               sum(model.cartoon_diversity[j] * model.cartoon_episodes[j] for j in model.CARTOON) >= 50
    model.diversity_constraint = pyo.Constraint(rule=diversity_rule)
    
    # 8. SOLVING WITH GUROBI
    solver = SolverFactory('gurobi')
    
    # Optional: Set solver options
    solver.options['TimeLimit'] = 300  # 5 minutes
    solver.options['MIPGap'] = 0.01    # 1% gap
    
    # Solve the model
    results = solver.solve(model, tee=True)  # tee=True shows solver output
    
    # 9. RESULT PROCESSING
    # Check solver status
    if results.solver.termination_condition == pyo.TerminationCondition.optimal:
        print("Optimal solution found!")
        print(f"Optimal value: {pyo.value(model.objective)}")
        
        # Extract variable values
        print("\nTV Series Episodes:")
        for i in model.TV:
            print(f"TV Series {i}: {pyo.value(model.tv_episodes[i])}")
        
        print("\nCartoon Episodes:")
        for j in model.CARTOON:
            print(f"Cartoon {j}: {pyo.value(model.cartoon_episodes[j])}")
        
    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}")
    
    return model

# Execute the optimization
if __name__ == "__main__":
    tvshow_optimization()
```

### Execution Results
**Status**: OPTIMAL
**Optimal Value**: 161.7
**Execution Time**: 1.03 seconds
**Reliability**: high
**Analysis**: Pyomo successfully found the optimal solution, though it took slightly longer than Gurobipy.

## 8. Cross-Solver Analysis and Final Recommendation

### Solver Results Comparison

| Solver | Status | Optimal Value | Execution Time | Decision Variables | Retry Attempt |
|--------|--------|---------------|----------------|-------------------|---------------|
| Gurobipy | OPTIMAL | 161.70 | 0.21s | N/A | N/A |
| Docplex | OPTIMAL | 161.70 | 1.05s | N/A | N/A |
| Pyomo | OPTIMAL | 161.70 | 1.03s | N/A | N/A |

### Solver Consistency Analysis
**Result**: All solvers produced consistent results ✓
**Consistent Solvers**: gurobipy, docplex, pyomo
**Majority Vote Optimal Value**: 161.7

### Final Recommendation
**Recommended Optimal Value**: 161.7
**Confidence Level**: HIGH
**Preferred Solver(s)**: gurobipy
**Reasoning**: Gurobipy is recommended due to its faster execution time while achieving the same optimal solution as the other solvers.

### Business Interpretation
**Overall Strategy**: The optimal solution maximizes total viewer ratings within the given constraints, ensuring efficient use of airtime and diversity requirements.
**Objective Value Meaning**: The optimal objective value of 161.7 represents the maximum total viewer ratings achievable under the given constraints.
**Resource Allocation Summary**: Allocate airtime to TV series and cartoons according to the optimal solution to maximize viewer ratings while adhering to episode bounds and diversity requirements.
**Implementation Recommendations**: Implement the optimal episode counts for each TV series and cartoon, ensuring compliance with airtime and diversity constraints. Monitor viewer ratings post-implementation for validation.