# Complete Optimization Problem and Solution: wine_1

## 1. Problem Context and Goals

### Context  
The winery is focused on optimizing its production strategy to maximize revenue from wine sales. The primary decision involves determining the number of cases to produce for each type of wine. This decision is guided by the winery's total production capacity and the market demand for each wine. The goal is to ensure that production decisions align with these constraints while maximizing revenue. The winery operates under a total production capacity, which serves as a critical constraint, ensuring that production does not exceed operational capabilities. The business configuration includes this total production capacity as a scalar parameter, reflecting the realistic production limits of a small to medium-sized winery. The winery's operational parameters are structured to align with a linear objective, focusing on maximizing total revenue by considering the price per case of each wine and the number of cases produced.

### Goals  
The primary goal of the winery is to maximize its total revenue from wine sales. This involves optimizing the number of cases produced for each wine type, with the objective of maximizing the sum of the revenue generated from each wine. The success of this optimization is measured by the total revenue, which is calculated by multiplying the price per case by the number of cases produced for each wine. The winery aims to achieve this goal by adhering to linear optimization principles, ensuring that the production strategy is both efficient and aligned with market demands.

## 2. Constraints    

The winery's production strategy is subject to several constraints that ensure operational feasibility and market alignment. The first constraint is the total production capacity, which limits the sum of all cases produced to not exceed the winery's operational capacity. This ensures that the production remains within the realistic limits of the winery's capabilities. Additionally, each wine's production is constrained by its market demand, ensuring that the number of cases produced does not exceed what the market can absorb. These constraints are designed to naturally lead to linear mathematical forms, focusing on maintaining a balance between production capacity and market demand without involving complex variable interactions.

## 3. Available Data  

### Database Schema  
```sql
-- Iteration 1 Database Schema
-- Objective: Schema changes include adding tables for missing data requirements and updating existing tables to address mapping gaps. Configuration logic updated for scalar parameters and formulas.

CREATE TABLE wine (
  Price FLOAT,
  Cases INTEGER
);

CREATE TABLE market_demand (
  demand INTEGER
);


```

### Data Dictionary  
The data dictionary provides a comprehensive overview of the business purposes and optimization roles of the tables and columns involved in the winery's production strategy. The "wine" table stores information about different wines, with columns for the price per case and the number of cases to produce. The price per case serves as an objective coefficient in the revenue maximization goal, while the number of cases represents the decision variable in the optimization process. The "market_demand" table captures the market demand for each wine, serving as a constraint bound in the optimization model. This structure ensures that all data elements are aligned with the linear mathematical formulation of the optimization problem.

### Current Stored Values  
```sql
-- Iteration 1 Realistic Data
-- Generated by triple expert (business + data + optimization)
-- Values were determined based on typical market prices and demands for wine, ensuring that production capacity constraints are realistic and allow for a meaningful optimization problem.

-- Realistic data for wine
INSERT INTO wine (Price, Cases) VALUES (12.0, 150);
INSERT INTO wine (Price, Cases) VALUES (18.0, 250);
INSERT INTO wine (Price, Cases) VALUES (22.0, 100);

-- Realistic data for market_demand
INSERT INTO market_demand (demand) VALUES (500);
INSERT INTO market_demand (demand) VALUES (800);
INSERT INTO market_demand (demand) VALUES (300);


```

## 4. Mathematical Optimization Formulation

#### Decision Variables
Let \( x_1, x_2, x_3 \) be the number of cases produced for each type of wine. These are the decision variables representing the controllable production quantities for each wine type.

#### Objective Function
Maximize total revenue:
\[ \text{Maximize } Z = 12x_1 + 18x_2 + 22x_3 \]

Data Source Verification:
- Coefficients 12, 18, and 22 are from `wine.Price`.

#### Constraints

1. **Total Production Capacity Constraint:**
   \[ x_1 + x_2 + x_3 \leq 500 \]

   Data Source Verification:
   - The total production capacity of 500 is a business configuration parameter reflecting the winery's operational capacity.

2. **Market Demand Constraints:**
   \[ x_1 \leq 500 \]
   \[ x_2 \leq 800 \]
   \[ x_3 \leq 300 \]

   Data Source Verification:
   - The demand constraints 500, 800, and 300 are from `market_demand.demand`.

3. **Non-negativity Constraints:**
   \[ x_1 \geq 0, \quad x_2 \geq 0, \quad x_3 \geq 0 \]

This linear programming model is designed to maximize the winery's revenue while adhering to production capacity and market demand constraints. The decision variables \( x_1, x_2, x_3 \) represent the number of cases produced for each wine type, and the objective function coefficients are derived from the price per case for each wine.

## 5. Gurobipy Implementation

```python
# Complete GUROBIPY implementation

import gurobipy as gp
from gurobipy import GRB

def optimize_wine_production():
    """Optimize wine production to maximize revenue"""
    
    # 1. MODEL & DATA SETUP
    model = gp.Model("wine_optimization")
    
    # Data from the problem context
    prices = [12.0, 18.0, 22.0]
    market_demands = [500, 800, 300]
    total_capacity = 500
    
    # Validate array lengths
    n_wines = len(prices)
    assert len(market_demands) == n_wines, "Array length mismatch"
    
    # 2. VARIABLES
    # Decision variables for the number of cases to produce for each wine
    x = {i: model.addVar(vtype=GRB.CONTINUOUS, name=f"x_{i}", lb=0) 
         for i in range(n_wines)}
    
    # 3. OBJECTIVE FUNCTION
    # Maximize total revenue
    model.setObjective(gp.quicksum(prices[i] * x[i] for i in range(n_wines)), GRB.MAXIMIZE)
    
    # 4. CONSTRAINTS
    
    # Total production capacity constraint
    model.addConstr(gp.quicksum(x[i] for i in range(n_wines)) <= total_capacity, name="total_capacity")
    
    # Market demand constraints
    for i in range(n_wines):
        model.addConstr(x[i] <= market_demands[i], name=f"market_demand_{i}")
    
    # 5. SOLVING & RESULTS
    model.optimize()
    
    if model.status == GRB.OPTIMAL:
        print(f"Optimal value: {model.objVal}")
        for i in range(n_wines):
            if x[i].x > 1e-6:
                print(f"x[{i}] = {x[i].x:.3f}")
    elif model.status == GRB.INFEASIBLE:
        print("Problem is infeasible")
    elif model.status == GRB.UNBOUNDED:
        print("Problem is unbounded")
    
    return model

# Run the optimization
optimize_wine_production()
```

### Execution Results
**Status**: OPTIMAL
**Optimal Value**: 10200.0
**Execution Time**: 1.02 seconds
**Reliability**: high
**Analysis**: Gurobipy found an optimal solution quickly with a reliable status and no errors.

## 6. DOCplex Implementation

```python
# Complete DOCPLEX implementation

from docplex.mp.model import Model

def optimize_wine_production():
    """Optimize wine production to maximize revenue"""

    # 1. MODEL & DATA SETUP
    mdl = Model(name="wine_optimization")
    
    # Data from the problem statement
    prices = [12.0, 18.0, 22.0]
    market_demands = [500, 800, 300]
    total_production_capacity = 500
    
    # CRITICAL: Validate array lengths to prevent IndexError
    assert len(prices) == len(market_demands), "Array length mismatch"
    safe_range = range(min(len(prices), len(market_demands)))  # Safe indexing
    
    # 2. VARIABLES
    # Variable dictionaries (most common)
    x = {i: mdl.continuous_var(name=f"x_{i}", lb=0) for i in safe_range}
    
    # 3. OBJECTIVE FUNCTION
    # Use mdl.sum() for summations (DOCplex specific)
    objective = mdl.sum(prices[i] * x[i] for i in safe_range)
    mdl.maximize(objective)
    
    # 4. CONSTRAINTS - CORRECT SYNTAX PATTERNS
    
    # Total production capacity constraint
    total_production = mdl.sum(x[i] for i in safe_range)
    mdl.add_constraint(total_production <= total_production_capacity, ctname="total_capacity")
    
    # Market demand constraints
    for i in safe_range:
        mdl.add_constraint(x[i] <= market_demands[i], ctname=f"market_demand_{i}")
    
    # 5. SOLVING & RESULTS
    solution = mdl.solve()
    
    if solution:
        print(f"Optimal value: {solution.objective_value}")
        for i in safe_range:
            value = solution.get_value(x[i])
            if value > 1e-6:
                print(f"x[{i}] = {value:.3f}")
    else:
        print("No solution found")
        print(f"Status: {mdl.solve_details.status}")
    
    return mdl

# Run the optimization
optimize_wine_production()
```

### Execution Results
**Status**: OPTIMAL
**Optimal Value**: 10200.0
**Execution Time**: 2.89 seconds
**Reliability**: high
**Analysis**: DOCplex also found an optimal solution, albeit with a slightly longer execution time, but still reliable.

## 7. Pyomo Implementation

```python
# Complete PYOMO implementation

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

def wine_optimization():
    """Optimize wine production to maximize revenue"""
    
    # 1. MODEL CREATION
    model = pyo.ConcreteModel()
    
    # 2. DATA SETUP
    prices = [12.0, 18.0, 22.0]
    market_demands = [500, 800, 300]
    total_capacity = 500
    
    # CRITICAL: Validate array lengths before indexing
    assert len(prices) == len(market_demands), "Array length mismatch"
    
    # 3. SETS
    model.I = pyo.RangeSet(1, len(prices))  # 1-based indexing
    
    # 4. PARAMETERS
    model.price = pyo.Param(model.I, initialize={i+1: prices[i] for i in range(len(prices))})
    model.demand = pyo.Param(model.I, initialize={i+1: market_demands[i] for i in range(len(market_demands))})
    
    # 5. VARIABLES
    model.x = pyo.Var(model.I, within=pyo.NonNegativeReals)
    
    # 6. OBJECTIVE FUNCTION
    def obj_rule(model):
        return sum(model.price[i] * model.x[i] for i in model.I)
    model.objective = pyo.Objective(rule=obj_rule, sense=pyo.maximize)
    
    # 7. CONSTRAINTS
    
    # Total Production Capacity Constraint
    def capacity_rule(model):
        return sum(model.x[i] for i in model.I) <= total_capacity
    model.capacity_constraint = pyo.Constraint(rule=capacity_rule)
    
    # Market Demand Constraints
    def demand_rule(model, i):
        return model.x[i] <= model.demand[i]
    model.demand_constraint = pyo.Constraint(model.I, rule=demand_rule)
    
    # 8. SOLVING WITH GUROBI
    solver = SolverFactory('gurobi')
    
    # Solve the model
    results = solver.solve(model, tee=True)
    
    # 9. RESULT PROCESSING
    if results.solver.termination_condition == pyo.TerminationCondition.optimal:
        print("Optimal solution found!")
        print(f"Optimal value: {pyo.value(model.objective):.2f}")
        
        # Extract variable values
        print("\nVariable values:")
        for i in model.I:
            x_val = pyo.value(model.x[i])
            if x_val > 1e-6:  # Only print non-zero values
                print(f"x[{i}] = {x_val:.2f}")
        
    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

# Run the optimization
wine_optimization()
```

### Execution Results
**Status**: OPTIMAL
**Optimal Value**: 10200.0
**Execution Time**: 2.53 seconds
**Reliability**: high
**Analysis**: Pyomo achieved an optimal solution with a moderate execution time, confirming the reliability of the results.

## 8. Cross-Solver Analysis and Final Recommendation

### Solver Results Comparison

| Solver | Status | Optimal Value | Execution Time | Decision Variables | Retry Attempt |
|--------|--------|---------------|----------------|-------------------|---------------|
| Gurobipy | OPTIMAL | 10200.00 | 1.02s | N/A | N/A |
| Docplex | OPTIMAL | 10200.00 | 2.89s | N/A | N/A |
| Pyomo | OPTIMAL | 10200.00 | 2.53s | N/A | N/A |

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

### Final Recommendation
**Recommended Optimal Value**: 10200.0
**Confidence Level**: HIGH
**Preferred Solver(s)**: multiple
**Reasoning**: All solvers provided consistent and optimal results, indicating robustness and reliability across different platforms.

### Business Interpretation
**Overall Strategy**: The optimal production plan maximizes revenue while respecting all constraints.
**Objective Value Meaning**: The optimal objective value of 10200.0 represents the maximum revenue achievable under the given constraints.
**Resource Allocation Summary**: Allocate production resources to produce a total of 500 cases, distributed optimally among the three wine types.
**Implementation Recommendations**: Implement the production plan by aligning resources to meet the optimal production quantities, ensuring adherence to capacity and demand constraints.