# Complete Optimization Problem and Solution: manufacturer

## 1. Problem Context and Goals

### Context  
A furniture manufacturer is tasked with determining the optimal number of units to produce for each furniture type to maximize profit. The decision involves balancing production costs, market rates, and resource limitations. The manufacturer operates under two key constraints: the total production capacity across all factories is limited to 1,000 units, and the total budget available for production is capped at $50,000.  

The profit for each furniture type is calculated as the difference between its market rate and its production cost. The manufacturer aims to allocate production quantities in a way that maximizes total profit while staying within the factory capacity and budget limits. This problem is formulated as a linear optimization model, ensuring that all relationships and constraints are linear and directly tied to operational parameters.  

### Goals  
The primary goal is to maximize the total profit from furniture production. This is achieved by optimizing the number of units produced for each furniture type, considering the difference between the market rate and the production cost for each item. Success is measured by the total profit generated, which is directly influenced by the production quantities and the operational parameters of market rates, production costs, and resource constraints.  

## 2. Constraints  

The manufacturer must adhere to the following constraints:  
1. **Total Production Capacity**: The sum of units produced across all furniture types must not exceed the total factory capacity of 1,000 units. This ensures that production does not surpass the manufacturer's operational capabilities.  
2. **Budget Limit**: The total cost of production, calculated as the sum of the production cost multiplied by the number of units produced for each furniture type, must not exceed the available budget of $50,000. This ensures that production remains financially feasible.  

These constraints are linear and directly tied to the manufacturer's operational limitations, ensuring a realistic and feasible optimization problem.  

## 3. Available Data  

### Database Schema  
```sql
-- Iteration 2 Database Schema
-- Objective: Schema changes include creating tables for objective coefficients (Market_Rate and Price_in_Dollar) and updating business configuration logic to include scalar parameters and formulas for missing optimization requirements.

CREATE TABLE production_plan (
  Furniture_ID INTEGER,
  Quantity_Produced INTEGER
);

CREATE TABLE furniture_market_rates (
  Furniture_ID INTEGER,
  Market_Rate FLOAT
);

CREATE TABLE furniture_production_costs (
  Furniture_ID INTEGER,
  Price_in_Dollar FLOAT
);
```

### Data Dictionary  
- **production_plan**:  
  - **Furniture_ID**: Unique identifier for each furniture type.  
  - **Quantity_Produced**: Number of units to produce for each furniture type. This is the decision variable in the optimization model.  

- **furniture_market_rates**:  
  - **Furniture_ID**: Unique identifier for each furniture type.  
  - **Market_Rate**: Market rate for each furniture type. This is used as an objective coefficient in the optimization model.  

- **furniture_production_costs**:  
  - **Furniture_ID**: Unique identifier for each furniture type.  
  - **Price_in_Dollar**: Production cost for each furniture type. This is used as an objective coefficient in the optimization model.  

### Current Stored Values  
```sql
-- Iteration 2 Realistic Data
-- Generated by triple expert (business + data + optimization)
-- Values were determined based on typical furniture manufacturing scenarios, considering production costs, market rates, and factory capacities. The data ensures a balanced optimization problem with feasible constraints.

-- Realistic data for production_plan
INSERT INTO production_plan (Furniture_ID, Quantity_Produced) VALUES (1, 0);
INSERT INTO production_plan (Furniture_ID, Quantity_Produced) VALUES (2, 0);
INSERT INTO production_plan (Furniture_ID, Quantity_Produced) VALUES (3, 0);

-- Realistic data for furniture_market_rates
INSERT INTO furniture_market_rates (Furniture_ID, Market_Rate) VALUES (1, 120.0);
INSERT INTO furniture_market_rates (Furniture_ID, Market_Rate) VALUES (2, 180.0);
INSERT INTO furniture_market_rates (Furniture_ID, Market_Rate) VALUES (3, 250.0);

-- Realistic data for furniture_production_costs
INSERT INTO furniture_production_costs (Furniture_ID, Price_in_Dollar) VALUES (1, 60.0);
INSERT INTO furniture_production_costs (Furniture_ID, Price_in_Dollar) VALUES (2, 90.0);
INSERT INTO furniture_production_costs (Furniture_ID, Price_in_Dollar) VALUES (3, 130.0);
```

## 4. Mathematical Optimization Formulation

#### Decision Variables
- Let \( x_i \) be the number of units produced for furniture type \( i \), where \( i \in \{1, 2, 3\} \).  
  (Source: `production_plan.Quantity_Produced`)

#### Objective Function
Maximize the total profit:  
\[
\text{Maximize } Z = \sum_{i=1}^{3} ( \text{Market\_Rate}_i - \text{Price\_in\_Dollar}_i ) \times x_i
\]  
Substituting the values:  
\[
\text{Maximize } Z = (120 - 60) \times x_1 + (180 - 90) \times x_2 + (250 - 130) \times x_3
\]  
\[
\text{Maximize } Z = 60x_1 + 90x_2 + 120x_3
\]  
(Source: `furniture_market_rates.Market_Rate` and `furniture_production_costs.Price_in_Dollar`)

#### Constraints
1. **Total Production Capacity**:  
\[
x_1 + x_2 + x_3 \leq 1000
\]  
(Source: Business constraint on total factory capacity)

2. **Budget Limit**:  
\[
60x_1 + 90x_2 + 130x_3 \leq 50000
\]  
(Source: `furniture_production_costs.Price_in_Dollar` and business budget limit)

3. **Non-Negativity**:  
\[
x_1 \geq 0, \quad x_2 \geq 0, \quad x_3 \geq 0
\]  
(Source: Logical constraint to ensure non-negative production quantities)

#### Data Source Verification
- **Objective Function Coefficients**:  
  - \( 60 \): `furniture_market_rates.Market_Rate` for Furniture_ID = 1 minus `furniture_production_costs.Price_in_Dollar` for Furniture_ID = 1.  
  - \( 90 \): `furniture_market_rates.Market_Rate` for Furniture_ID = 2 minus `furniture_production_costs.Price_in_Dollar` for Furniture_ID = 2.  
  - \( 120 \): `furniture_market_rates.Market_Rate` for Furniture_ID = 3 minus `furniture_production_costs.Price_in_Dollar` for Furniture_ID = 3.  

- **Constraint Coefficients**:  
  - \( 60, 90, 130 \): `furniture_production_costs.Price_in_Dollar` for Furniture_ID = 1, 2, 3 respectively.  
  - \( 1000 \): Business constraint on total factory capacity.  
  - \( 50000 \): Business constraint on total budget.  

This is 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 Furniture Manufacturer Optimization Problem
"""

import gurobipy as gp
from gurobipy import GRB

def optimize_furniture_production():
    """Optimize the number of units to produce for each furniture type to maximize profit."""
    
    # 1. MODEL & DATA SETUP
    model = gp.Model("furniture_production")
    
    # Data from the problem
    furniture_ids = [1, 2, 3]
    market_rates = {1: 120.0, 2: 180.0, 3: 250.0}
    production_costs = {1: 60.0, 2: 90.0, 3: 130.0}
    
    # Validate array lengths before loops
    assert len(furniture_ids) == len(market_rates) == len(production_costs), "Array length mismatch"
    
    # 2. VARIABLES
    x = {i: model.addVar(vtype=GRB.CONTINUOUS, name=f"x_{i}", lb=0) for i in furniture_ids}
    
    # 3. OBJECTIVE FUNCTION
    # Maximize total profit: Z = sum((Market_Rate_i - Price_in_Dollar_i) * x_i)
    model.setObjective(
        gp.quicksum((market_rates[i] - production_costs[i]) * x[i] for i in furniture_ids),
        GRB.MAXIMIZE
    )
    
    # 4. CONSTRAINTS
    
    # Total Production Capacity: sum(x_i) <= 1000
    model.addConstr(
        gp.quicksum(x[i] for i in furniture_ids) <= 1000,
        name="total_production_capacity"
    )
    
    # Budget Limit: sum(Price_in_Dollar_i * x_i) <= 50000
    model.addConstr(
        gp.quicksum(production_costs[i] * x[i] for i in furniture_ids) <= 50000,
        name="budget_limit"
    )
    
    # 5. SOLVING & RESULTS
    model.optimize()
    
    if model.status == GRB.OPTIMAL:
        print(f"Optimal value: {model.objVal}")
        for i in furniture_ids:
            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

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

### Execution Results
**Status**: OPTIMAL
**Optimal Value**: 50000.0
**Execution Time**: 0.16 seconds
**Reliability**: high
**Analysis**: Gurobipy found the optimal solution quickly with the lowest execution time, indicating high efficiency and reliability.

## 6. DOCplex Implementation

```python
#!/usr/bin/env python3
"""
DOCPLEX Implementation for Furniture Manufacturer Optimization Problem
"""

from docplex.mp.model import Model

def furniture_optimization():
    """Optimize furniture production to maximize profit."""
    
    # 1. MODEL & DATA SETUP
    mdl = Model(name="furniture_optimization")
    
    # Data from the problem
    furniture_ids = [1, 2, 3]
    market_rates = [120.0, 180.0, 250.0]
    production_costs = [60.0, 90.0, 130.0]
    
    # CRITICAL: Validate array lengths to prevent IndexError
    assert len(furniture_ids) == len(market_rates) == len(production_costs), "Array length mismatch"
    safe_range = range(min(len(furniture_ids), len(market_rates), len(production_costs)))  # Safe indexing
    
    # 2. VARIABLES
    # Decision variables: Number of units produced for each furniture type
    x = {i: mdl.continuous_var(name=f"x_{furniture_ids[i]}", lb=0) for i in safe_range}
    
    # 3. OBJECTIVE FUNCTION
    # Maximize total profit: sum((Market_Rate - Price_in_Dollar) * Quantity_Produced)
    profit_coefficients = [market_rates[i] - production_costs[i] for i in safe_range]
    objective = mdl.sum(profit_coefficients[i] * x[i] for i in safe_range)
    mdl.maximize(objective)
    
    # 4. CONSTRAINTS
    
    # Total Production Capacity: sum(Quantity_Produced) <= 1000
    total_production = mdl.sum(x[i] for i in safe_range)
    mdl.add_constraint(total_production <= 1000, ctname="total_production_capacity")
    
    # Budget Limit: sum(Price_in_Dollar * Quantity_Produced) <= 50000
    total_cost = mdl.sum(production_costs[i] * x[i] for i in safe_range)
    mdl.add_constraint(total_cost <= 50000, ctname="budget_limit")
    
    # 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[{furniture_ids[i]}] = {value:.3f}")
    else:
        print("No solution found")
        print(f"Status: {mdl.solve_details.status}")
    
    return mdl

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

### Execution Results
**Status**: OPTIMAL
**Optimal Value**: 50000.0
**Execution Time**: 1.09 seconds
**Reliability**: high
**Analysis**: DOCplex also found the optimal solution but took longer than Gurobipy, suggesting slightly lower efficiency.

## 7. Pyomo Implementation

```python
# Complete PYOMO implementation

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

def furniture_optimization():
    """Pyomo implementation for furniture manufacturer optimization problem."""
    
    # 1. MODEL CREATION
    model = pyo.ConcreteModel()
    
    # 2. DATA SETUP
    furniture_ids = [1, 2, 3]
    market_rates = {1: 120.0, 2: 180.0, 3: 250.0}
    production_costs = {1: 60.0, 2: 90.0, 3: 130.0}
    
    # CRITICAL: Validate array lengths before indexing
    assert len(furniture_ids) == len(market_rates) == len(production_costs), "Array length mismatch"
    
    # 3. SETS (Pyomo way to define indices)
    model.I = pyo.Set(initialize=furniture_ids)  # Furniture types
    
    # 4. PARAMETERS (data containers)
    model.market_rate = pyo.Param(model.I, initialize=market_rates)
    model.production_cost = pyo.Param(model.I, initialize=production_costs)
    
    # 5. VARIABLES
    model.x = pyo.Var(model.I, within=pyo.NonNegativeReals)  # Units produced
    
    # 6. OBJECTIVE FUNCTION
    def obj_rule(model):
        return sum((model.market_rate[i] - model.production_cost[i]) * model.x[i] for i in model.I)
    model.objective = pyo.Objective(rule=obj_rule, sense=pyo.maximize)
    
    # 7. CONSTRAINTS
    # Total Production Capacity
    def capacity_rule(model):
        return sum(model.x[i] for i in model.I) <= 1000
    model.capacity_constraint = pyo.Constraint(rule=capacity_rule)
    
    # Budget Limit
    def budget_rule(model):
        return sum(model.production_cost[i] * model.x[i] for i in model.I) <= 50000
    model.budget_constraint = pyo.Constraint(rule=budget_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("\nProduction quantities:")
        for i in model.I:
            x_val = pyo.value(model.x[i])
            if x_val > 1e-6:  # Only print non-zero values
                print(f"Furniture {i}: {x_val:.0f} units")
        
    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__":
    furniture_optimization()
```

### Execution Results
**Status**: OPTIMAL
**Optimal Value**: 50000.0
**Execution Time**: 0.93 seconds
**Reliability**: high
**Analysis**: Pyomo found the optimal solution but had the longest execution time, indicating lower efficiency compared to Gurobipy and DOCplex.

## 8. Cross-Solver Analysis and Final Recommendation

### Solver Results Comparison

| Solver | Status | Optimal Value | Execution Time | Decision Variables | Retry Attempt |
|--------|--------|---------------|----------------|-------------------|---------------|
| Gurobipy | OPTIMAL | 50000.00 | 0.16s | N/A | N/A |
| Docplex | OPTIMAL | 50000.00 | 1.09s | N/A | N/A |
| Pyomo | OPTIMAL | 50000.00 | 0.93s | N/A | N/A |

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

### Final Recommendation
**Recommended Optimal Value**: 50000.0
**Confidence Level**: HIGH
**Preferred Solver(s)**: gurobipy
**Reasoning**: Gurobipy is recommended due to its fastest execution time and high reliability, making it the most efficient solver for this problem.

### Business Interpretation
**Overall Strategy**: The optimal solution maximizes profit by fully utilizing the budget and production capacity, ensuring efficient resource allocation.
**Objective Value Meaning**: The optimal objective value of 50000 represents the maximum achievable profit given the constraints on production capacity and budget.
**Resource Allocation Summary**: Resources should be allocated to maximize the production of furniture types with the highest profit margins while staying within the budget and production capacity limits.
**Implementation Recommendations**: Focus on producing Furniture Type 3 due to its highest profit margin, followed by Types 2 and 1, ensuring the total production does not exceed 1000 units and the budget does not exceed $50,000.