# Complete Optimization Problem and Solution: voter_2

## 1. Problem Context and Goals

### Context  
The university is focused on optimizing the election of student representatives to various leadership positions. The aim is to maximize student satisfaction by ensuring that the most popular candidates, as determined by voting records, are elected. The decision-making process involves selecting students for the roles of President, Vice President, Secretary, Treasurer, Class President, and Class Senator. Each of these roles is represented by a binary decision variable, indicating whether a student is elected to that position. The operational goal is to maximize the total number of votes received by the elected representatives. This is achieved by summing the votes for each position, weighted by whether the student is elected. The business logic ensures that exactly one student is elected to each position and that no student holds more than one position. This approach aligns with linear optimization principles, focusing on clear, linear relationships without involving complex mathematical operations like products or divisions. The constraints are designed to ensure that each position is filled by exactly one student and that each student can hold only one position, reflecting the university's commitment to fair and efficient representation.

### Goals  
The primary goal of this optimization problem is to maximize the total number of votes received by the elected student representatives. This involves selecting candidates who have received the highest number of votes for each position, thereby ensuring that the elected representatives reflect the preferences of the student body. The success of this optimization is measured by the total votes accumulated across all positions, with the objective being to maximize this total. The linear nature of this goal is emphasized by the straightforward summation of votes, weighted by the binary decision variables indicating election outcomes.

## 2. Constraints    

The constraints for this optimization problem are designed to ensure a fair and efficient election process. Each position must be filled by exactly one student, which means that the sum of the binary decision variables for each position must equal one. Additionally, each student can hold only one position, ensuring that the sum of the decision variables for all positions for a single student does not exceed one. These constraints are expressed in a linear form, aligning with the principles of linear optimization and ensuring that the election process is both fair and efficient.

## 3. Available Data  

### Database Schema  
```sql
-- Iteration 1 Database Schema
-- Objective: Schema changes include creating tables for decision variables and constraint bounds, and updating business configuration logic for scalar parameters and formulas.

CREATE TABLE Voting_record (
  President_Vote INTEGER,
  Vice_President_Vote INTEGER,
  Secretary_Vote INTEGER,
  Treasurer_Vote INTEGER,
  Class_President_Vote INTEGER,
  Class_Senator_Vote INTEGER
);

CREATE TABLE Decision_Variables (
  President BOOLEAN,
  Vice_President BOOLEAN,
  Secretary BOOLEAN,
  Treasurer BOOLEAN,
  Class_President BOOLEAN,
  Class_Senator BOOLEAN
);

CREATE TABLE Constraint_Bounds (
  Position_Filled STRING,
  Student_Position_Limit STRING
);
```

### Data Dictionary  
The data dictionary provides a comprehensive overview of the tables and columns used in this optimization problem, mapping them to their business purposes and optimization roles. 

- **Voting_record**: This table stores the number of votes each student received for each position. It plays a crucial role in the optimization process by providing the coefficients for the objective function. Each column represents a different position, with the values indicating the number of votes received by a student.

- **Decision_Variables**: This table contains binary decision variables that indicate whether a student is elected to a specific position. Each column corresponds to a different position, and the values are either true or false, representing the election outcome.

- **Constraint_Bounds**: This table stores the constraints that ensure each position is filled by exactly one student and that each student holds at most one position. The constraints are expressed in a linear form, aligning with the optimization model's requirements.

### Current Stored Values  
```sql
-- Iteration 1 Realistic Data
-- Generated by triple expert (business + data + optimization)
-- Values were determined based on typical voting scenarios in a university setting, ensuring a diverse distribution of votes across different positions to reflect realistic election outcomes.

-- Realistic data for Voting_record
INSERT INTO Voting_record (President_Vote, Vice_President_Vote, Secretary_Vote, Treasurer_Vote, Class_President_Vote, Class_Senator_Vote) VALUES (25, 18, 22, 15, 30, 20);
INSERT INTO Voting_record (President_Vote, Vice_President_Vote, Secretary_Vote, Treasurer_Vote, Class_President_Vote, Class_Senator_Vote) VALUES (30, 25, 20, 18, 28, 22);
INSERT INTO Voting_record (President_Vote, Vice_President_Vote, Secretary_Vote, Treasurer_Vote, Class_President_Vote, Class_Senator_Vote) VALUES (20, 30, 25, 22, 18, 25);

-- Realistic data for Decision_Variables
INSERT INTO Decision_Variables (President, Vice_President, Secretary, Treasurer, Class_President, Class_Senator) VALUES (True, False, False, False, False, False);
INSERT INTO Decision_Variables (President, Vice_President, Secretary, Treasurer, Class_President, Class_Senator) VALUES (False, True, False, False, False, False);
INSERT INTO Decision_Variables (President, Vice_President, Secretary, Treasurer, Class_President, Class_Senator) VALUES (False, False, True, False, False, False);

-- Realistic data for Constraint_Bounds
INSERT INTO Constraint_Bounds (Position_Filled, Student_Position_Limit) VALUES ('sum(x[i] for all i) = 1', 'x[i] + y[i] + z[i] + w[i] + u[i] + v[i] <= 1');
```

## 4. Mathematical Optimization Formulation

#### Decision Variables
Let:
- \( x_{i,j} \) be a binary decision variable where \( i \) represents the student (1, 2, or 3) and \( j \) represents the position (President, Vice President, Secretary, Treasurer, Class President, Class Senator). \( x_{i,j} = 1 \) if student \( i \) is elected to position \( j \), and \( x_{i,j} = 0 \) otherwise.

#### Objective Function
Maximize the total number of votes received by the elected representatives:

\[
\begin{align*}
\text{Maximize } & \sum_{i=1}^{3} \left( 25x_{i,\text{President}} + 18x_{i,\text{Vice President}} + 22x_{i,\text{Secretary}} + 15x_{i,\text{Treasurer}} + 30x_{i,\text{Class President}} + 20x_{i,\text{Class Senator}} \right) \\
& + \sum_{i=1}^{3} \left( 30x_{i,\text{President}} + 25x_{i,\text{Vice President}} + 20x_{i,\text{Secretary}} + 18x_{i,\text{Treasurer}} + 28x_{i,\text{Class President}} + 22x_{i,\text{Class Senator}} \right) \\
& + \sum_{i=1}^{3} \left( 20x_{i,\text{President}} + 30x_{i,\text{Vice President}} + 25x_{i,\text{Secretary}} + 22x_{i,\text{Treasurer}} + 18x_{i,\text{Class President}} + 25x_{i,\text{Class Senator}} \right)
\end{align*}
\]

#### Constraints
1. Each position must be filled by exactly one student:

\[
\begin{align*}
\sum_{i=1}^{3} x_{i,\text{President}} &= 1 \\
\sum_{i=1}^{3} x_{i,\text{Vice President}} &= 1 \\
\sum_{i=1}^{3} x_{i,\text{Secretary}} &= 1 \\
\sum_{i=1}^{3} x_{i,\text{Treasurer}} &= 1 \\
\sum_{i=1}^{3} x_{i,\text{Class President}} &= 1 \\
\sum_{i=1}^{3} x_{i,\text{Class Senator}} &= 1
\end{align*}
\]

2. Each student can hold at most one position:

\[
\begin{align*}
\sum_{j} x_{1,j} &\leq 1 \\
\sum_{j} x_{2,j} &\leq 1 \\
\sum_{j} x_{3,j} &\leq 1
\end{align*}
\]

Where \( j \) iterates over all positions: President, Vice President, Secretary, Treasurer, Class President, Class Senator.

Data Source Verification:
- Coefficients for the objective function are derived from the `Voting_record` table, specifically from the columns `President_Vote`, `Vice_President_Vote`, `Secretary_Vote`, `Treasurer_Vote`, `Class_President_Vote`, and `Class_Senator_Vote`.
- Constraints are based on the business logic described in the `Constraint_Bounds` table, ensuring each position is filled by exactly one student and each student holds at most one position.

## 5. Gurobipy Implementation

```python
# Complete GUROBIPY implementation - Retry Attempt 4

import gurobipy as gp
from gurobipy import GRB

def optimize_student_elections():
    # 1. MODEL & DATA SETUP
    model = gp.Model("student_elections")
    
    # Votes data from the Voting_record table
    votes = [
        [25, 18, 22, 15, 30, 20],  # Student 1
        [30, 25, 20, 18, 28, 22],  # Student 2
        [20, 30, 25, 22, 18, 25]   # Student 3
    ]
    
    n_students = len(votes)
    n_positions = len(votes[0])
    
    # Validate array lengths
    assert all(len(vote) == n_positions for vote in votes), "Array length mismatch"
    
    # 2. VARIABLES
    # Binary decision variables: x[i, j] = 1 if student i is elected to position j
    x = model.addVars(n_students, n_positions, vtype=GRB.BINARY, name="x")
    
    # 3. OBJECTIVE FUNCTION
    # Maximize the total number of votes received by the elected representatives
    model.setObjective(
        gp.quicksum(votes[i][j] * x[i, j] for i in range(n_students) for j in range(n_positions)),
        GRB.MAXIMIZE
    )
    
    # 4. CONSTRAINTS
    # Each position must be filled by exactly one student
    model.addConstrs(
        (gp.quicksum(x[i, j] for i in range(n_students)) == 1 for j in range(n_positions)),
        name="position_filled"
    )
    
    # Each student can hold at most one position
    model.addConstrs(
        (gp.quicksum(x[i, j] for j in range(n_positions)) <= 1 for i in range(n_students)),
        name="student_position_limit"
    )
    
    # 5. SOLVING & RESULTS
    model.optimize()
    
    if model.status == GRB.OPTIMAL:
        print(f"Optimal value: {model.objVal}")
        for i in range(n_students):
            for j in range(n_positions):
                if x[i, j].x > 0.5:  # Binary variable, so check if it's 1
                    print(f"Student {i+1} is elected to position {j+1}")
    elif model.status == GRB.INFEASIBLE:
        print("Problem is infeasible")
    elif model.status == GRB.UNBOUNDED:
        print("Problem is unbounded")
    
    return model

# Run the optimization
optimize_student_elections()
```

### Execution Results
**Status**: INFEASIBLE
**Error**: Problem is infeasible
**Analysis**: Gurobipy consistently reports the problem as infeasible, indicating a potential issue with the formulation or constraints.

## 6. DOCplex Implementation

```python
# Complete DOCPLEX implementation - Retry Attempt 4

from docplex.mp.model import Model

def optimize_student_elections():
    # 1. MODEL & DATA SETUP
    mdl = Model(name="student_elections")
    
    # Voting data for each student and position
    votes = [
        [25, 18, 22, 15, 30, 20],  # Student 1
        [30, 25, 20, 18, 28, 22],  # Student 2
        [20, 30, 25, 22, 18, 25]   # Student 3
    ]
    
    n_students = len(votes)
    n_positions = len(votes[0])
    
    # CRITICAL: Validate array lengths to prevent IndexError
    assert all(len(v) == n_positions for v in votes), "Array length mismatch"
    safe_range_students = range(n_students)
    safe_range_positions = range(n_positions)
    
    # 2. VARIABLES
    # Binary decision variables for each student and position
    x = {(i, j): mdl.binary_var(name=f"x_{i}_{j}") for i in safe_range_students for j in safe_range_positions}
    
    # 3. OBJECTIVE FUNCTION
    # Maximize the total number of votes received by the elected representatives
    objective = mdl.sum(votes[i][j] * x[i, j] for i in safe_range_students for j in safe_range_positions)
    mdl.maximize(objective)
    
    # 4. CONSTRAINTS - CORRECT SYNTAX PATTERNS
    
    # Each position must be filled by exactly one student
    for j in safe_range_positions:
        mdl.add_constraint(mdl.sum(x[i, j] for i in safe_range_students) == 1, ctname=f"position_{j}_filled")
    
    # Each student can hold at most one position
    for i in safe_range_students:
        mdl.add_constraint(mdl.sum(x[i, j] for j in safe_range_positions) <= 1, ctname=f"student_{i}_limit")
    
    # 5. SOLVING & RESULTS
    solution = mdl.solve()
    
    if solution:
        print(f"Optimal value: {solution.objective_value}")
        for i in safe_range_students:
            for j in safe_range_positions:
                if solution.get_value(x[i, j]) > 0.5:  # Binary variable, so check > 0.5
                    print(f"Student {i+1} is elected to position {j+1}")
    else:
        print("No solution found")
        print(f"Status: {mdl.solve_details.status}")

    return mdl

# Run the optimization
optimize_student_elections()
```

### Execution Results
**Status**: INFEASIBLE
**Error**: Problem is infeasible
**Analysis**: DOCplex also reports infeasibility, aligning with Gurobipy's results, suggesting a consistent issue across solvers.

## 7. Pyomo Implementation

```python
# Complete PYOMO implementation - Retry Attempt 4

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

def voter_2_optimization():
    """Pyomo model for optimizing student representative elections"""
    
    # 1. MODEL CREATION
    model = pyo.ConcreteModel()
    
    # 2. DATA SETUP
    n_students = 3
    positions = ['President', 'Vice President', 'Secretary', 'Treasurer', 'Class President', 'Class Senator']
    
    # Votes received by each student for each position
    votes = {
        (1, 'President'): 25, (1, 'Vice President'): 18, (1, 'Secretary'): 22, (1, 'Treasurer'): 15, (1, 'Class President'): 30, (1, 'Class Senator'): 20,
        (2, 'President'): 30, (2, 'Vice President'): 25, (2, 'Secretary'): 20, (2, 'Treasurer'): 18, (2, 'Class President'): 28, (2, 'Class Senator'): 22,
        (3, 'President'): 20, (3, 'Vice President'): 30, (3, 'Secretary'): 25, (3, 'Treasurer'): 22, (3, 'Class President'): 18, (3, 'Class Senator'): 25
    }
    
    # 3. SETS
    model.I = pyo.RangeSet(1, n_students)  # Students
    model.J = pyo.Set(initialize=positions)  # Positions
    
    # 4. VARIABLES
    model.x = pyo.Var(model.I, model.J, within=pyo.Binary)
    
    # 5. OBJECTIVE FUNCTION
    def obj_rule(model):
        return sum(votes[i, j] * model.x[i, j] for i in model.I for j in model.J)
    model.objective = pyo.Objective(rule=obj_rule, sense=pyo.maximize)
    
    # 6. CONSTRAINTS
    
    # Each position must be filled by exactly one student
    def position_filled_rule(model, j):
        return sum(model.x[i, j] for i in model.I) == 1
    model.position_filled_constraint = pyo.Constraint(model.J, rule=position_filled_rule)
    
    # Each student can hold at most one position
    def student_limit_rule(model, i):
        return sum(model.x[i, j] for j in model.J) <= 1
    model.student_limit_constraint = pyo.Constraint(model.I, rule=student_limit_rule)
    
    # 7. SOLVING WITH GUROBI
    solver = SolverFactory('gurobi')
    
    # Solve the model
    results = solver.solve(model, tee=True)
    
    # 8. 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("\nElection results:")
        for i in model.I:
            for j in model.J:
                if pyo.value(model.x[i, j]) > 0.5:  # Binary variable, check if elected
                    print(f"Student {i} is elected as {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

# Run the optimization
voter_2_optimization()
```

### Execution Results
**Status**: INFEASIBLE
**Error**: Problem is infeasible
**Analysis**: Pyomo confirms the infeasibility, reinforcing the conclusion that the problem setup may be flawed.

## 8. Cross-Solver Analysis and Final Recommendation

### Solver Results Comparison

| Solver | Status | Optimal Value | Execution Time | Decision Variables | Retry Attempt |
|--------|--------|---------------|----------------|-------------------|---------------|
| Gurobipy | INFEASIBLE | N/A | 0.18s | N/A | 4 |
| Docplex | INFEASIBLE | N/A | 2.30s | N/A | 4 |
| Pyomo | INFEASIBLE | N/A | 1.14s | N/A | 4 |

### Solver Consistency Analysis
**Result**: All solvers produced consistent results ✓
**Consistent Solvers**: gurobipy, docplex, pyomo
**Solver Retry Summary**: gurobipy: 4 attempts, docplex: 4 attempts, pyomo: 4 attempts

### Final Recommendation
**Confidence Level**: HIGH
**Preferred Solver(s)**: multiple
**Reasoning**: All solvers consistently report infeasibility, suggesting the issue lies within the problem formulation rather than solver performance.

### Business Interpretation
**Overall Strategy**: The current problem setup does not allow for a feasible solution, indicating a need to revisit the constraints or data inputs.
**Objective Value Meaning**: The objective value represents the total number of votes received by the elected representatives, which cannot be maximized due to infeasibility.
**Resource Allocation Summary**: Currently, no resources can be allocated as no feasible assignment of students to positions exists.
**Implementation Recommendations**: Review and potentially relax constraints, verify data accuracy, and ensure the problem formulation aligns with business requirements.