## 4. Mathematical Optimization Formulation

#### Decision Variables
- Let \( x_1 \) be the weight lifted in the Snatch event for a bodybuilder.
- Let \( x_2 \) be the weight lifted in the Clean & Jerk event for a bodybuilder.

#### Objective Function
Maximize the total weight lifted:
\[ \text{Maximize } Z = x_1 + x_2 \]

#### Constraints
For each bodybuilder, we have the following constraints:

1. **Performance Target Constraint**: The total weight lifted should not exceed the performance target for each bodybuilder.
   - For Bodybuilder 1: 
     \[ x_1 + x_2 \leq 300.0 \]
   - For Bodybuilder 2: 
     \[ x_1 + x_2 \leq 320.0 \]
   - For Bodybuilder 3: 
     \[ x_1 + x_2 \leq 340.0 \]

2. **Training Impact Constraints**: These constraints ensure that the training impact coefficients are considered in the optimization.
   - For Bodybuilder 1:
     \[ 1.2 \times x_1 + 1.5 \times x_2 \leq 190.0 \]
   - For Bodybuilder 2:
     \[ 1.3 \times x_1 + 1.6 \times x_2 \leq 210.0 \]
   - For Bodybuilder 3:
     \[ 1.1 \times x_1 + 1.4 \times x_2 \leq 220.0 \]

3. **Non-negativity Constraints**: The weights lifted must be non-negative.
   \[ x_1 \geq 0 \]
   \[ x_2 \geq 0 \]

Data Source Verification:
- The coefficients for the objective function and constraints are derived from the `body_builder` table:
  - Snatch and Clean & Jerk weights are decision variables.
  - Snatch_Impact and Clean_Jerk_Impact are used in the training impact constraints.
- The performance targets are derived from the `bodybuilder_performance` table:
  - Performance_Target is used in the performance target constraints.

## 5. Gurobipy Implementation

```python
# Complete GUROBIPY implementation

import gurobipy as gp
from gurobipy import GRB

def optimize_bodybuilder_performance():
    """Optimize the total weight lifted by bodybuilders in Snatch and Clean & Jerk events."""
    
    # 1. MODEL & DATA SETUP
    model = gp.Model("body_builder_optimization")
    
    # Data from the database
    snatch_impact = [1.2, 1.3, 1.1]
    clean_jerk_impact = [1.5, 1.6, 1.4]
    performance_targets = [300.0, 320.0, 340.0]
    training_limits = [190.0, 210.0, 220.0]
    
    n_bodybuilders = len(performance_targets)
    
    # CRITICAL: Validate array lengths before loops
    assert len(snatch_impact) == len(clean_jerk_impact) == len(training_limits) == n_bodybuilders, "Array length mismatch"
    
    # 2. VARIABLES
    # Variables for weights lifted in Snatch and Clean & Jerk
    x_snatch = {i: model.addVar(vtype=GRB.CONTINUOUS, name=f"x_snatch_{i}", lb=0) 
                for i in range(n_bodybuilders)}
    x_clean_jerk = {i: model.addVar(vtype=GRB.CONTINUOUS, name=f"x_clean_jerk_{i}", lb=0) 
                    for i in range(n_bodybuilders)}
    
    # 3. OBJECTIVE FUNCTION
    # Maximize the total weight lifted
    model.setObjective(gp.quicksum(x_snatch[i] + x_clean_jerk[i] for i in range(n_bodybuilders)), GRB.MAXIMIZE)
    
    # 4. CONSTRAINTS - CORRECT SYNTAX PATTERNS
    
    # Performance Target Constraints
    for i in range(n_bodybuilders):
        model.addConstr(x_snatch[i] + x_clean_jerk[i] <= performance_targets[i], name=f"performance_target_{i}")
    
    # Training Impact Constraints
    for i in range(n_bodybuilders):
        model.addConstr(snatch_impact[i] * x_snatch[i] + clean_jerk_impact[i] * x_clean_jerk[i] <= training_limits[i], 
                        name=f"training_impact_{i}")
    
    # 5. SOLVING & RESULTS
    model.optimize()
    
    if model.status == GRB.OPTIMAL:
        print(f"Optimal value: {model.objVal}")
        for i in range(n_bodybuilders):
            print(f"Bodybuilder {i+1}: Snatch = {x_snatch[i].x:.3f}, Clean & Jerk = {x_clean_jerk[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_bodybuilder_performance()
```

### Execution Results
**Status**: OPTIMAL
**Optimal Value**: 519.8717948717948
**Execution Time**: 1.21 seconds
**Reliability**: high
**Analysis**: Gurobipy found an optimal solution quickly with a precise optimal value. It is known for its efficiency and reliability in solving linear programming problems.

## 6. DOCplex Implementation

```python
# Complete DOCPLEX implementation

from docplex.mp.model import Model

def optimize_bodybuilder_performance():
    """Optimize the total weight lifted by bodybuilders in Snatch and Clean & Jerk events."""
    
    # 1. MODEL & DATA SETUP
    mdl = Model(name="body_builder_optimization")
    
    # Data from the database
    snatch_impact = [1.2, 1.3, 1.1]
    clean_jerk_impact = [1.5, 1.6, 1.4]
    performance_targets = [300.0, 320.0, 340.0]
    total_limits = [190.0, 210.0, 220.0]
    
    # CRITICAL: Validate array lengths to prevent IndexError
    assert len(snatch_impact) == len(clean_jerk_impact) == len(performance_targets) == len(total_limits), "Array length mismatch"
    safe_range = range(min(len(snatch_impact), len(clean_jerk_impact), len(performance_targets), len(total_limits)))  # Safe indexing
    
    # 2. VARIABLES
    x1 = {i: mdl.continuous_var(name=f"x1_{i}", lb=0) for i in safe_range}
    x2 = {i: mdl.continuous_var(name=f"x2_{i}", lb=0) for i in safe_range}
    
    # 3. OBJECTIVE FUNCTION
    # Maximize the total weight lifted
    objective = mdl.sum(x1[i] + x2[i] for i in safe_range)
    mdl.maximize(objective)
    
    # 4. CONSTRAINTS - CORRECT SYNTAX PATTERNS
    
    # Performance Target Constraints
    for i in safe_range:
        mdl.add_constraint(x1[i] + x2[i] <= performance_targets[i], ctname=f"performance_target_{i}")
    
    # Training Impact Constraints
    for i in safe_range:
        mdl.add_constraint(snatch_impact[i] * x1[i] + clean_jerk_impact[i] * x2[i] <= total_limits[i], ctname=f"training_impact_{i}")
    
    # 5. SOLVING & RESULTS
    solution = mdl.solve()
    
    if solution:
        print(f"Optimal value: {solution.objective_value}")
        for i in safe_range:
            x1_value = solution.get_value(x1[i])
            x2_value = solution.get_value(x2[i])
            if x1_value > 1e-6 or x2_value > 1e-6:
                print(f"x1[{i}] = {x1_value:.3f}, x2[{i}] = {x2_value:.3f}")
    else:
        print("No solution found")
        print(f"Status: {mdl.solve_details.status}")
    
    return mdl

# Run the optimization
optimize_bodybuilder_performance()
```

### Execution Results
**Status**: OPTIMAL
**Optimal Value**: 519.8717948717949
**Execution Time**: 6.89 seconds
**Reliability**: high
**Analysis**: DOCplex also found an optimal solution, albeit with a slightly longer execution time. The optimal value is consistent with Gurobipy's result within a very small tolerance.

## 7. Pyomo Implementation

```python
# Complete PYOMO implementation

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

def bodybuilder_optimization():
    """Optimization for maximizing total weight lifted by bodybuilders"""
    
    # 1. MODEL CREATION
    model = pyo.ConcreteModel()
    
    # 2. DATA SETUP
    # Data from the database
    snatch_impact = [1.2, 1.3, 1.1]
    clean_jerk_impact = [1.5, 1.6, 1.4]
    performance_targets = [300.0, 320.0, 340.0]
    total_limits = [190.0, 210.0, 220.0]
    
    # Validate array lengths
    n_bodybuilders = len(performance_targets)
    assert len(snatch_impact) == len(clean_jerk_impact) == len(total_limits) == n_bodybuilders, "Array length mismatch"
    
    # 3. SETS
    model.I = pyo.RangeSet(1, n_bodybuilders)  # 1-based indexing for bodybuilders
    
    # 4. PARAMETERS
    model.snatch_impact = pyo.Param(model.I, initialize={i+1: snatch_impact[i] for i in range(n_bodybuilders)})
    model.clean_jerk_impact = pyo.Param(model.I, initialize={i+1: clean_jerk_impact[i] for i in range(n_bodybuilders)})
    model.performance_target = pyo.Param(model.I, initialize={i+1: performance_targets[i] for i in range(n_bodybuilders)})
    model.total_limit = pyo.Param(model.I, initialize={i+1: total_limits[i] for i in range(n_bodybuilders)})
    
    # 5. VARIABLES
    model.x1 = pyo.Var(model.I, within=pyo.NonNegativeReals)  # Snatch weights
    model.x2 = pyo.Var(model.I, within=pyo.NonNegativeReals)  # Clean & Jerk weights
    
    # 6. OBJECTIVE FUNCTION
    def obj_rule(model):
        return sum(model.x1[i] + model.x2[i] for i in model.I)
    model.objective = pyo.Objective(rule=obj_rule, sense=pyo.maximize)
    
    # 7. CONSTRAINTS
    
    # Performance Target Constraints
    def performance_target_rule(model, i):
        return model.x1[i] + model.x2[i] <= model.performance_target[i]
    model.performance_target_constraint = pyo.Constraint(model.I, rule=performance_target_rule)
    
    # Training Impact Constraints
    def training_impact_rule(model, i):
        return model.snatch_impact[i] * model.x1[i] + model.clean_jerk_impact[i] * model.x2[i] <= model.total_limit[i]
    model.training_impact_constraint = pyo.Constraint(model.I, rule=training_impact_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)}")
        
        # Extract variable values
        print("\nVariable values:")
        for i in model.I:
            x1_val = pyo.value(model.x1[i])
            x2_val = pyo.value(model.x2[i])
            print(f"Bodybuilder {i}: Snatch = {x1_val:.3f}, Clean & Jerk = {x2_val:.3f}")
        
    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
bodybuilder_optimization()
```

### Execution Results
**Status**: OPTIMAL
**Optimal Value**: 519.8717948717948
**Execution Time**: 6.11 seconds
**Reliability**: high
**Analysis**: Pyomo achieved an optimal solution with an execution time similar to DOCplex. The optimal value matches Gurobipy's result exactly, indicating consistency.

## 8. Cross-Solver Analysis and Final Recommendation

### Solver Results Comparison

| Solver | Status | Optimal Value | Execution Time | Decision Variables | Retry Attempt |
|--------|--------|---------------|----------------|-------------------|---------------|
| Gurobipy | OPTIMAL | 519.87 | 1.21s | N/A | N/A |
| Docplex | OPTIMAL | 519.87 | 6.89s | N/A | N/A |
| Pyomo | OPTIMAL | 519.87 | 6.11s | N/A | N/A |

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

### Final Recommendation
**Recommended Optimal Value**: 519.8717948717948
**Confidence Level**: HIGH
**Preferred Solver(s)**: gurobipy
**Reasoning**: Gurobipy is recommended due to its faster execution time and precise results, making it suitable for time-sensitive applications.

### Business Interpretation
**Overall Strategy**: The optimal solution indicates the maximum total weight that can be lifted by the bodybuilders while respecting all constraints.
**Objective Value Meaning**: The optimal objective value represents the maximum combined weight lifted by the bodybuilders across both events, given the constraints.
**Resource Allocation Summary**: Allocate training resources to ensure bodybuilders can achieve the optimal weights in both events without exceeding performance targets or training impacts.
**Implementation Recommendations**: Focus on optimizing training programs to achieve the recommended weights in both events, ensuring compliance with all constraints.