## 4. Mathematical Optimization Formulation

#### Decision Variables
- Let \( x_i \) be a binary decision variable where:
  - \( x_i = 1 \) if submission \( i \) is accepted,
  - \( x_i = 0 \) if submission \( i \) is rejected.

#### Objective Function
Maximize the total quality score of accepted submissions:
\[
\text{Maximize} \quad \sum_{i} s_i \cdot x_i
\]
where \( s_i \) is the score of submission \( i \).

#### Constraints
1. **Workshop Capacity Constraint**: The total number of accepted submissions for each workshop \( j \) must not exceed its capacity \( C_j \):
\[
\sum_{i \in W_j} x_i \leq C_j \quad \forall j
\]
where \( W_j \) is the set of submissions assigned to workshop \( j \).

2. **Binary Decision Constraint**: Each submission must be either accepted or rejected:
\[
x_i \in \{0, 1\} \quad \forall i
\]

#### Data Source Verification
- **Objective Function Coefficient \( s_i \)**: `submission_scores.score`
- **Workshop Capacity \( C_j \)**: `workshop_capacity.capacity`
- **Submission-Workshop Mapping \( W_j \)**: `submission_workshop_mapping.workshop_id`

### Complete Numerical Model
Using the provided data:

#### Decision Variables
- \( x_1 \): Decision for submission 1
- \( x_2 \): Decision for submission 2
- \( x_3 \): Decision for submission 3

#### Objective Function
\[
\text{Maximize} \quad 8.7x_1 + 7.5x_2 + 9.2x_3
\]

#### Constraints
1. **Workshop Capacity Constraints**:
   - Workshop 1: \( x_1 \leq 12 \)
   - Workshop 2: \( x_2 \leq 15 \)
   - Workshop 3: \( x_3 \leq 10 \)

2. **Binary Decision Constraints**:
   - \( x_1 \in \{0, 1\} \)
   - \( x_2 \in \{0, 1\} \)
   - \( x_3 \in \{0, 1\} \)

This is a complete, immediately solvable Linear Programming (LP) model with all numerical coefficients derived from the provided data.

## 5. Gurobipy Implementation

```python
#!/usr/bin/env python3
"""
Gurobipy implementation for workshop paper selection optimization
"""

import gurobipy as gp
from gurobipy import GRB

def optimize_workshop_selection():
    """Optimize the selection of workshop submissions to maximize quality scores."""
    
    # 1. MODEL & DATA SETUP
    model = gp.Model("workshop_paper_selection")
    
    # Data from the problem
    workshop_capacity = {1: 12, 2: 15, 3: 10}
    submission_scores = {1: 8.7, 2: 7.5, 3: 9.2}
    submission_workshop_mapping = {1: 1, 2: 2, 3: 3}
    
    # Validate array lengths
    assert len(submission_scores) == len(submission_workshop_mapping), "Array length mismatch"
    
    # 2. VARIABLES
    # Binary decision variables for each submission
    x = {i: model.addVar(vtype=GRB.BINARY, name=f"x_{i}") for i in submission_scores.keys()}
    
    # 3. OBJECTIVE FUNCTION
    # Maximize the total quality score of accepted submissions
    model.setObjective(gp.quicksum(submission_scores[i] * x[i] for i in submission_scores.keys()), GRB.MAXIMIZE)
    
    # 4. CONSTRAINTS
    
    # Workshop Capacity Constraints
    for workshop_id, capacity in workshop_capacity.items():
        # Get submissions assigned to this workshop
        submissions_in_workshop = [i for i, w_id in submission_workshop_mapping.items() if w_id == workshop_id]
        model.addConstr(gp.quicksum(x[i] for i in submissions_in_workshop) <= capacity, name=f"capacity_{workshop_id}")
    
    # 5. SOLVING & RESULTS
    model.optimize()
    
    if model.status == GRB.OPTIMAL:
        print(f"Optimal value: {model.objVal}")
        for i in submission_scores.keys():
            if x[i].x > 0.5:
                print(f"Submission {i} is accepted")
            else:
                print(f"Submission {i} is rejected")
    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__":
    optimize_workshop_selection()
```

### Execution Results
**Status**: OPTIMAL
**Optimal Value**: 25.4
**Execution Time**: 0.20 seconds
**Reliability**: high
**Analysis**: Gurobipy found the optimal solution quickly with the lowest execution time.

## 6. DOCplex Implementation

```python
#!/usr/bin/env python3
"""
DOCplex implementation for workshop paper selection optimization
"""

from docplex.mp.model import Model

def workshop_paper_optimization():
    """Optimize the selection of workshop submissions to maximize quality scores"""
    
    # 1. MODEL & DATA SETUP
    mdl = Model(name="workshop_paper_selection")
    
    # Data from the database
    workshop_capacity = {1: 12, 2: 15, 3: 10}
    submission_scores = {1: 8.7, 2: 7.5, 3: 9.2}
    submission_workshop_mapping = {1: 1, 2: 2, 3: 3}
    
    # CRITICAL: Validate array lengths to prevent IndexError
    assert len(submission_scores) == len(submission_workshop_mapping), "Array length mismatch"
    safe_range = range(min(len(submission_scores), len(submission_workshop_mapping)))  # Safe indexing
    
    # 2. VARIABLES
    # Binary decision variables for each submission
    x = {i: mdl.binary_var(name=f"x_{i}") for i in safe_range}
    
    # 3. OBJECTIVE FUNCTION
    # Maximize the total quality score of accepted submissions
    objective = mdl.sum(submission_scores[i+1] * x[i] for i in safe_range)
    mdl.maximize(objective)
    
    # 4. CONSTRAINTS
    
    # Workshop Capacity Constraints
    # Group submissions by workshop
    workshop_submissions = {j: [i for i in safe_range if submission_workshop_mapping[i+1] == j] for j in workshop_capacity}
    
    for j, submissions in workshop_submissions.items():
        mdl.add_constraint(mdl.sum(x[i] for i in submissions) <= workshop_capacity[j], ctname=f"workshop_capacity_{j}")
    
    # Binary Decision Constraints are inherently handled by the binary_var type
    
    # 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])
            print(f"x[{i+1}] = {value}")
    else:
        print("No solution found")
        print(f"Status: {mdl.solve_details.status}")
    
    return mdl

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

### Execution Results
**Status**: OPTIMAL
**Optimal Value**: 25.4
**Execution Time**: 1.16 seconds
**Reliability**: high
**Analysis**: DOCplex also found the optimal solution but took longer compared to Gurobipy.

## 7. Pyomo Implementation

```python
#!/usr/bin/env python3
"""
Pyomo 6.9.2 Implementation for Workshop Paper Selection Optimization
"""

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

def workshop_paper_optimization():
    """Optimize the selection of workshop submissions to maximize quality scores."""
    
    # 1. MODEL CREATION
    model = pyo.ConcreteModel()
    
    # 2. DATA SETUP
    # Workshop capacities
    workshop_capacity_data = {
        1: 12,
        2: 15,
        3: 10
    }
    
    # Submission scores
    submission_scores_data = {
        1: 8.7,
        2: 7.5,
        3: 9.2
    }
    
    # Submission to workshop mapping
    submission_workshop_mapping_data = {
        1: 1,
        2: 2,
        3: 3
    }
    
    # Validate data consistency
    submission_ids = set(submission_scores_data.keys())
    workshop_ids = set(workshop_capacity_data.keys())
    mapped_submissions = set(submission_workshop_mapping_data.keys())
    mapped_workshops = set(submission_workshop_mapping_data.values())
    
    assert submission_ids == mapped_submissions, "Submission IDs mismatch in mapping"
    assert mapped_workshops.issubset(workshop_ids), "Workshop IDs mismatch in mapping"
    
    # 3. SETS
    model.SUBMISSIONS = pyo.Set(initialize=submission_ids)
    model.WORKSHOPS = pyo.Set(initialize=workshop_ids)
    
    # 4. PARAMETERS
    model.scores = pyo.Param(model.SUBMISSIONS, initialize=submission_scores_data)
    model.capacities = pyo.Param(model.WORKSHOPS, initialize=workshop_capacity_data)
    model.mapping = pyo.Param(model.SUBMISSIONS, initialize=submission_workshop_mapping_data)
    
    # 5. VARIABLES
    model.accept = pyo.Var(model.SUBMISSIONS, within=pyo.Binary)
    
    # 6. OBJECTIVE FUNCTION
    def obj_rule(model):
        return sum(model.scores[i] * model.accept[i] for i in model.SUBMISSIONS)
    model.objective = pyo.Objective(rule=obj_rule, sense=pyo.maximize)
    
    # 7. CONSTRAINTS
    # Workshop capacity constraints
    def capacity_rule(model, j):
        return sum(model.accept[i] for i in model.SUBMISSIONS if model.mapping[i] == j) <= model.capacities[j]
    model.capacity_constraint = pyo.Constraint(model.WORKSHOPS, rule=capacity_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(f"Optimal value: {pyo.value(model.objective)}")
        
        # Extract variable values
        print("\nAccepted submissions:")
        for i in model.SUBMISSIONS:
            if pyo.value(model.accept[i]) > 0.5:
                print(f"Submission {i} accepted (Score: {model.scores[i]})")
        
    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
if __name__ == "__main__":
    workshop_paper_optimization()
```

### Execution Results
**Status**: OPTIMAL
**Optimal Value**: 25.4
**Execution Time**: 0.93 seconds
**Reliability**: high
**Analysis**: Pyomo found the optimal solution with an execution time between 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 | 25.40 | 0.20s | N/A | N/A |
| Docplex | OPTIMAL | 25.40 | 1.16s | N/A | N/A |
| Pyomo | OPTIMAL | 25.40 | 0.93s | N/A | N/A |

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

### Final Recommendation
**Recommended Optimal Value**: 25.4
**Confidence Level**: HIGH
**Preferred Solver(s)**: gurobipy
**Reasoning**: Gurobipy provided the optimal solution with the fastest execution time, making it the most efficient choice.

### Optimal Decision Variables
- **x_1** = 1.000
  - *Business Meaning*: Submission 1 is accepted, contributing 8.7 to the total quality score.
- **x_2** = 1.000
  - *Business Meaning*: Submission 2 is accepted, contributing 7.5 to the total quality score.
- **x_3** = 1.000
  - *Business Meaning*: Submission 3 is accepted, contributing 9.2 to the total quality score.

### Business Interpretation
**Overall Strategy**: All three submissions should be accepted to maximize the total quality score, as they all fit within the workshop capacities.
**Objective Value Meaning**: The total quality score of 25.4 is the highest achievable given the workshop capacities.
**Resource Allocation Summary**: All workshops have sufficient capacity to accept their assigned submissions.
**Implementation Recommendations**: Proceed with accepting all three submissions and ensure that the workshops are prepared to accommodate them.