# Complete Optimization Problem and Solution: election_representative

## 1. Problem Context and Goals

### Context  
A political party is focused on maximizing the total number of seats won across multiple elections by strategically allocating campaign resources to its representatives in different states. The party must make decisions on how much campaign resources to allocate to each representative, ensuring that these allocations adhere to a total budget limit, provide a minimum level of support to each representative, and respect state-specific resource caps. The total budget available for campaign resources is set at one million units, ensuring that the party can cover all necessary allocations without exceeding its financial capacity. Each representative must receive at least one thousand units of resources to ensure a baseline level of campaign support. Additionally, the total resources allocated to representatives within any single state cannot exceed fifty thousand units, ensuring a fair distribution of resources across states. These operational parameters are designed to support a linear optimization approach, where the relationships between resource allocations and outcomes are straightforward and proportional.

### Goals  
The primary goal of this optimization problem is to maximize the total number of seats won by the party across all elections. This is achieved by strategically allocating campaign resources to representatives in a way that directly increases the likelihood of winning seats. The success of this strategy is measured by the total seats won, which is calculated as the sum of the seats won by each representative multiplied by the amount of resources allocated to them. The optimization process ensures that the party’s resource allocation decisions are aligned with its objective of maximizing electoral success while adhering to all operational constraints.

## 2. Constraints    

The optimization problem is subject to three key constraints, each designed to ensure that resource allocations are both effective and feasible. First, the total amount of resources allocated to all representatives combined must not exceed the total budget of one million units. This ensures that the party does not overspend its available financial resources. Second, each representative must receive at least one thousand units of resources, guaranteeing that every candidate receives a minimum level of campaign support. Third, the total resources allocated to representatives within any single state must not exceed fifty thousand units, ensuring that no state receives an disproportionate share of resources. These constraints are designed to be linear and proportional, supporting a straightforward optimization approach.

## 3. Available Data  

### Database Schema  
```sql
-- Iteration 1 Database Schema
-- Objective: Schema changes include creating tables for decision variables and constraint bounds, moving scalar parameters to business configuration logic, and updating the data dictionary to reflect optimization mappings.

CREATE TABLE election (
  Seats INTEGER
);

CREATE TABLE resource_allocation (
  Resource_Amount FLOAT
);

CREATE TABLE state_resource_limits (
  Maximum_Resource_Allocation INTEGER
);
```

### Data Dictionary  
The database schema includes three key tables, each with a specific role in the optimization process. The `election` table stores the number of seats won by each representative, which serves as the coefficient in the objective function. The `resource_allocation` table tracks the amount of campaign resources allocated to each representative, representing the decision variables in the optimization model. The `state_resource_limits` table contains the maximum amount of resources that can be allocated to representatives within each state, serving as a constraint bound in the optimization model. Together, these tables provide the necessary data to support the linear optimization of campaign resource allocations.

### Current Stored Values  
```sql
-- Iteration 1 Realistic Data
-- Generated by triple expert (business + data + optimization)
-- Values were determined based on realistic campaign budgets, resource allocation limits, and election outcomes, ensuring they align with the business context and optimization requirements.

-- Realistic data for election
INSERT INTO election (Seats) VALUES (1);
INSERT INTO election (Seats) VALUES (2);
INSERT INTO election (Seats) VALUES (3);

-- Realistic data for resource_allocation
INSERT INTO resource_allocation (Resource_Amount) VALUES (1000.0);
INSERT INTO resource_allocation (Resource_Amount) VALUES (2000.0);
INSERT INTO resource_allocation (Resource_Amount) VALUES (3000.0);

-- Realistic data for state_resource_limits
INSERT INTO state_resource_limits (Maximum_Resource_Allocation) VALUES (50000);
INSERT INTO state_resource_limits (Maximum_Resource_Allocation) VALUES (60000);
INSERT INTO state_resource_limits (Maximum_Resource_Allocation) VALUES (70000);
```

## 4. Mathematical Optimization Formulation

#### Decision Variables
Let \( x_i \) represent the amount of campaign resources allocated to the \( i \)-th representative, where \( i = 1, 2, 3 \).

#### Objective Function
Maximize the total number of seats won by the party:
\[
\text{Maximize } Z = 1 \cdot x_1 + 2 \cdot x_2 + 3 \cdot x_3
\]
**Data Source Verification**: The coefficients \( 1, 2, 3 \) are from the `election.Seats` table.

#### Constraints
1. **Total Budget Constraint**: The total resources allocated to all representatives must not exceed one million units.
\[
x_1 + x_2 + x_3 \leq 1000000
\]
**Data Source Verification**: The constant \( 1000000 \) is from the business configuration (total budget).

2. **Minimum Resource Allocation Constraint**: Each representative must receive at least one thousand units of resources.
\[
x_1 \geq 1000, \quad x_2 \geq 1000, \quad x_3 \geq 1000
\]
**Data Source Verification**: The constant \( 1000 \) is from the business configuration (minimum resource allocation).

3. **State Resource Limit Constraint**: The total resources allocated to representatives within any single state must not exceed the state-specific resource cap.
\[
x_1 \leq 50000, \quad x_2 \leq 60000, \quad x_3 \leq 70000
\]
**Data Source Verification**: The constants \( 50000, 60000, 70000 \) are from the `state_resource_limits.Maximum_Resource_Allocation` table.

#### Summary of the Complete Linear Programming Model
\[
\text{Maximize } Z = 1 \cdot x_1 + 2 \cdot x_2 + 3 \cdot x_3
\]
Subject to:
\[
x_1 + x_2 + x_3 \leq 1000000
\]
\[
x_1 \geq 1000, \quad x_2 \geq 1000, \quad x_3 \geq 1000
\]
\[
x_1 \leq 50000, \quad x_2 \leq 60000, \quad x_3 \leq 70000
\]

This is a complete, immediately solvable linear programming model with all numerical coefficients derived from the provided data.

## 5. Gurobipy Implementation

```python
#!/usr/bin/env python3
"""
Gurobipy 12.0.2 Implementation for Election Representative Optimization
"""

import gurobipy as gp
from gurobipy import GRB

def election_representative_optimization():
    """Optimize campaign resource allocation to maximize seats won."""
    
    # 1. MODEL & DATA SETUP
    model = gp.Model("election_representative")
    
    # Data from the database
    seats = [1, 2, 3]  # From election.Seats
    resource_allocation = [1000.0, 2000.0, 3000.0]  # From resource_allocation.Resource_Amount
    state_limits = [50000, 60000, 70000]  # From state_resource_limits.Maximum_Resource_Allocation
    
    # Business configuration
    total_budget = 1000000
    min_resource = 1000
    
    # CRITICAL: Validate array lengths before loops
    n_representatives = len(seats)
    assert len(resource_allocation) == n_representatives, "Resource allocation array length mismatch"
    assert len(state_limits) == n_representatives, "State limits array length mismatch"
    
    # 2. VARIABLES
    x = {i: model.addVar(vtype=GRB.CONTINUOUS, name=f"x_{i}", lb=min_resource) 
         for i in range(n_representatives)}
    
    # 3. OBJECTIVE FUNCTION
    model.setObjective(gp.quicksum(seats[i] * x[i] for i in range(n_representatives)), GRB.MAXIMIZE)
    
    # 4. CONSTRAINTS
    
    # Total Budget Constraint
    model.addConstr(gp.quicksum(x[i] for i in range(n_representatives)) <= total_budget, name="total_budget")
    
    # State Resource Limit Constraints
    for i in range(n_representatives):
        model.addConstr(x[i] <= state_limits[i], name=f"state_limit_{i}")
    
    # 5. SOLVING & RESULTS
    model.optimize()
    
    if model.status == GRB.OPTIMAL:
        print(f"Optimal value: {model.objVal}")
        for i in range(n_representatives):
            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__":
    election_representative_optimization()
```

### Execution Results
**Status**: OPTIMAL
**Optimal Value**: 380000.0
**Execution Time**: 0.21 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 election_representative optimization problem
"""

from docplex.mp.model import Model

def election_representative_optimization():
    """Optimize campaign resource allocation to maximize seats won"""
    
    # 1. MODEL & DATA SETUP
    mdl = Model(name="election_representative")
    
    # Data from the problem description
    seats = [1, 2, 3]  # From election.Seats
    min_resource = 1000  # Minimum resource allocation per representative
    total_budget = 1000000  # Total budget constraint
    state_limits = [50000, 60000, 70000]  # From state_resource_limits.Maximum_Resource_Allocation
    
    # CRITICAL: Validate array lengths to prevent IndexError
    n_reps = len(seats)
    assert len(state_limits) == n_reps, "Array length mismatch"
    safe_range = range(min(len(seats), len(state_limits)))  # Safe indexing
    
    # 2. VARIABLES
    # Decision variables: amount of resources allocated to each representative
    x = {i: mdl.continuous_var(name=f"x_{i}", lb=min_resource) for i in safe_range}
    
    # 3. OBJECTIVE FUNCTION
    # Maximize total seats won: sum(seats[i] * x[i])
    objective = mdl.sum(seats[i] * x[i] for i in safe_range)
    mdl.maximize(objective)
    
    # 4. CONSTRAINTS
    
    # Total budget constraint: sum(x[i]) <= total_budget
    total_usage = mdl.sum(x[i] for i in safe_range)
    mdl.add_constraint(total_usage <= total_budget, ctname="total_budget")
    
    # State resource limits: x[i] <= state_limits[i]
    for i in safe_range:
        mdl.add_constraint(x[i] <= state_limits[i], ctname=f"state_limit_{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])
            print(f"x[{i}] = {value:.3f}")
    else:
        print("No solution found")
        print(f"Status: {mdl.solve_details.status}")
    
    return mdl

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

### Execution Results
**Status**: OPTIMAL
**Optimal Value**: 380000.0
**Execution Time**: 1.24 seconds
**Reliability**: high
**Analysis**: DOCplex found the optimal solution but with a longer execution time compared to Gurobipy.

## 7. Pyomo Implementation

```python
# Complete PYOMO implementation

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

def election_representative_optimization():
    """Optimization model for maximizing seats won by allocating campaign resources."""
    
    # 1. MODEL CREATION
    model = pyo.ConcreteModel()
    
    # 2. DATA SETUP
    # Data from the database schema and realistic data
    seats = [1, 2, 3]  # From election.Seats
    min_resource = 1000  # Minimum resource allocation
    total_budget = 1000000  # Total budget
    state_limits = [50000, 60000, 70000]  # From state_resource_limits.Maximum_Resource_Allocation
    
    # CRITICAL: Validate array lengths before indexing
    n_reps = len(seats)
    assert len(state_limits) == n_reps, "Array length mismatch"
    
    # 3. SETS (Pyomo way to define indices)
    model.I = pyo.RangeSet(1, n_reps)  # 1-based indexing for representatives
    
    # 4. PARAMETERS (data containers)
    model.seats = pyo.Param(model.I, initialize={i+1: seats[i] for i in range(n_reps)})
    model.state_limits = pyo.Param(model.I, initialize={i+1: state_limits[i] for i in range(n_reps)})
    
    # 5. VARIABLES
    model.x = pyo.Var(model.I, within=pyo.NonNegativeReals)  # Resource allocation to each representative
    
    # 6. OBJECTIVE FUNCTION
    def obj_rule(model):
        return sum(model.seats[i] * model.x[i] for i in model.I)
    model.objective = pyo.Objective(rule=obj_rule, sense=pyo.maximize)
    
    # 7. CONSTRAINTS
    
    # Total Budget Constraint
    def budget_rule(model):
        return sum(model.x[i] for i in model.I) <= total_budget
    model.budget_constraint = pyo.Constraint(rule=budget_rule)
    
    # Minimum Resource Allocation Constraint
    def min_resource_rule(model, i):
        return model.x[i] >= min_resource
    model.min_resource_constraint = pyo.Constraint(model.I, rule=min_resource_rule)
    
    # State Resource Limit Constraint
    def state_limit_rule(model, i):
        return model.x[i] <= model.state_limits[i]
    model.state_limit_constraint = pyo.Constraint(model.I, rule=state_limit_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("\nResource allocations:")
        for i in model.I:
            x_val = pyo.value(model.x[i])
            print(f"x[{i}] = {x_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

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

### Execution Results
**Status**: OPTIMAL
**Optimal Value**: 380000.0
**Execution Time**: 0.92 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 | 380000.00 | 0.21s | N/A | N/A |
| Docplex | OPTIMAL | 380000.00 | 1.24s | N/A | N/A |
| Pyomo | OPTIMAL | 380000.00 | 0.92s | N/A | N/A |

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

### Final Recommendation
**Recommended Optimal Value**: 380000.0
**Confidence Level**: HIGH
**Preferred Solver(s)**: gurobipy
**Reasoning**: Gurobipy is recommended due to its faster execution time while still providing the same optimal solution as the other solvers.

### Optimal Decision Variables
- **x_1** = 50000.000
  - *Business Meaning*: Allocation of resources to the first representative, capped at 50,000 units.
- **x_2** = 60000.000
  - *Business Meaning*: Allocation of resources to the second representative, capped at 60,000 units.
- **x_3** = 70000.000
  - *Business Meaning*: Allocation of resources to the third representative, capped at 70,000 units.

### Business Interpretation
**Overall Strategy**: The optimal allocation of resources maximizes the number of seats won by the party, ensuring that each representative receives the maximum allowed resources within their state limits.
**Objective Value Meaning**: The optimal objective value of 380,000 represents the maximum number of seats the party can win with the given resource allocation.
**Resource Allocation Summary**: Resources should be allocated as follows: 50,000 units to the first representative, 60,000 units to the second representative, and 70,000 units to the third representative.
**Implementation Recommendations**: Ensure that the resource allocation adheres to the state-specific caps and the total budget constraint. Monitor the execution to confirm that the allocated resources are effectively utilized to maximize seat wins.