# Complete Optimization Problem and Solution: browser_web

## 1. Problem Context and Goals

### Context  
A company is focused on optimizing the selection of web client accelerators to ensure maximum compatibility with the most widely used browsers. The decision-making process involves determining which accelerators are compatible with which browsers, with the goal of maximizing the overall market share of compatible browsers. The company has a limited number of accelerators it can feasibly implement and maintain, as defined by a maximum number of accelerators that can be selected. This limit is a key operational constraint.  

The compatibility between accelerators and browsers is evaluated using a compatibility score, which is calculated based on the market share of the browser and a predefined weighting formula. This score ensures that the selection process prioritizes browsers with higher market shares, aligning with the company’s goal of maximizing user coverage.  

The business configuration includes a scalar parameter that defines the maximum number of accelerators that can be selected, currently set to three. Additionally, the compatibility score formula incorporates the market share of the browser and a compatibility weight, divided by a total weight, to determine the final score. This formula ensures that the decision variables are calculated in a way that supports linear optimization.  

### Goals  
The primary goal of this optimization problem is to maximize the total market share of browsers that are compatible with the selected accelerators. This is achieved by selecting accelerators that are compatible with the most widely used browsers, as measured by their market share. Success is measured by the extent to which the selected accelerators cover the highest possible market share of browsers, ensuring broad user compatibility.  

## 2. Constraints  

The optimization problem is subject to two key constraints:  
1. **Maximum Accelerators Constraint**: The total number of accelerators selected cannot exceed the predefined maximum number of accelerators, which is currently set to three. This ensures that the company does not exceed its operational capacity for implementing and maintaining accelerators.  
2. **Minimum Compatibility Constraint**: Each selected accelerator must be compatible with at least one browser. This ensures that no accelerator is selected without providing compatibility benefits to at least one browser.  

These constraints are designed to align with the company’s operational limitations and ensure that the optimization process remains feasible and practical.  

## 3. Available Data  

### Database Schema  
```sql
-- Iteration 1 Database Schema
-- Objective: Schema changes include adding a max_accelerators parameter to business_configuration_logic.json, enhancing the accelerator_compatible_browser table with additional attributes, and ensuring all tables meet the 3-row minimum rule. Configuration logic updates include scalar parameters and formulas for optimization constraints and metrics.

CREATE TABLE browser (
  browser_id INTEGER,
  market_share FLOAT
);

CREATE TABLE accelerator_compatible_browser (
  accelerator_id INTEGER,
  browser_id INTEGER,
  compatibility_score FLOAT,
  last_updated_date DATE
);
```

### Data Dictionary  
- **browser**:  
  - **Business Purpose**: Stores browser market share data, which is critical for determining the optimization objective.  
  - **Optimization Role**: Provides the coefficients for the objective function, ensuring that the optimization process prioritizes browsers with higher market shares.  
  - **Columns**:  
    - **browser_id**: Unique identifier for each browser, used to index the objective coefficients.  
    - **market_share**: Percentage of the market share for each browser, used as the coefficient in the objective function.  

- **accelerator_compatible_browser**:  
  - **Business Purpose**: Stores compatibility data between accelerators and browsers, which is essential for determining the decision variables.  
  - **Optimization Role**: Provides the data used to calculate the decision variables, ensuring that the optimization process selects accelerators that are compatible with the most widely used browsers.  
  - **Columns**:  
    - **accelerator_id**: Unique identifier for each accelerator, used to index the decision variables.  
    - **browser_id**: Unique identifier for each browser, used to index the decision variables.  
    - **compatibility_score**: Score indicating the compatibility between an accelerator and a browser, used in the calculation of the decision variables.  
    - **last_updated_date**: Ensures that the compatibility data is current and reliable.  

### Current Stored Values  
```sql
-- Iteration 1 Realistic Data
-- Generated by triple expert (business + data + optimization)
-- Values were determined based on realistic market share data for browsers, compatibility scores reflecting real-world scenarios, and a maximum number of accelerators that aligns with business constraints.

-- Realistic data for browser
INSERT INTO browser (browser_id, market_share) VALUES (1, 0.35);
INSERT INTO browser (browser_id, market_share) VALUES (2, 0.25);
INSERT INTO browser (browser_id, market_share) VALUES (3, 0.15);

-- Realistic data for accelerator_compatible_browser
INSERT INTO accelerator_compatible_browser (accelerator_id, browser_id, compatibility_score, last_updated_date) VALUES (1, 1, 0.9, 2023-10-01);
INSERT INTO accelerator_compatible_browser (accelerator_id, browser_id, compatibility_score, last_updated_date) VALUES (1, 2, 0.8, 2023-10-01);
INSERT INTO accelerator_compatible_browser (accelerator_id, browser_id, compatibility_score, last_updated_date) VALUES (2, 1, 0.85, 2023-10-02);
INSERT INTO accelerator_compatible_browser (accelerator_id, browser_id, compatibility_score, last_updated_date) VALUES (2, 3, 0.7, 2023-10-02);
INSERT INTO accelerator_compatible_browser (accelerator_id, browser_id, compatibility_score, last_updated_date) VALUES (3, 2, 0.75, 2023-10-03);
INSERT INTO accelerator_compatible_browser (accelerator_id, browser_id, compatibility_score, last_updated_date) VALUES (3, 3, 0.65, 2023-10-03);
```

## 4. Mathematical Optimization Formulation

#### Decision Variables
- \( x_i \): Binary decision variable indicating whether accelerator \( i \) is selected (1 if selected, 0 otherwise).  
  \( i \in \{1, 2, 3\} \)  
- \( y_j \): Binary decision variable indicating whether browser \( j \) is compatible with at least one selected accelerator (1 if compatible, 0 otherwise).  
  \( j \in \{1, 2, 3\} \)  

#### Objective Function
Maximize the total market share of compatible browsers:  
\[
\text{Maximize} \quad Z = \sum_{j=1}^{3} \text{market\_share}_j \cdot y_j
\]  
**Coefficients**:  
- \( \text{market\_share}_j \): From `browser.market_share`  

#### Constraints
1. **Maximum Accelerators Constraint**: The total number of selected accelerators cannot exceed 3.  
\[
\sum_{i=1}^{3} x_i \leq 3
\]  
**Coefficients**:  
- Constant 3: From business configuration parameter `max_accelerators`  

2. **Minimum Compatibility Constraint**: Each selected accelerator must be compatible with at least one browser.  
\[
\sum_{j=1}^{3} \text{compatibility\_score}_{ij} \cdot y_j \geq x_i \quad \forall i \in \{1, 2, 3\}
\]  
**Coefficients**:  
- \( \text{compatibility\_score}_{ij} \): From `accelerator_compatible_browser.compatibility_score`  

3. **Browser Compatibility Constraint**: A browser \( j \) is considered compatible (\( y_j = 1 \)) if at least one selected accelerator is compatible with it.  
\[
y_j \leq \sum_{i=1}^{3} \text{compatibility\_score}_{ij} \cdot x_i \quad \forall j \in \{1, 2, 3\}
\]  
**Coefficients**:  
- \( \text{compatibility\_score}_{ij} \): From `accelerator_compatible_browser.compatibility_score`  

4. **Binary Decision Variables**:  
\[
x_i \in \{0, 1\} \quad \forall i \in \{1, 2, 3\}  
\]  
\[
y_j \in \{0, 1\} \quad \forall j \in \{1, 2, 3\}
\]  

#### Data Source Verification
- **Objective Function Coefficients**: `browser.market_share`  
- **Maximum Accelerators Constraint**: Business configuration parameter `max_accelerators`  
- **Compatibility Constraints**: `accelerator_compatible_browser.compatibility_score`  

This formulation is a complete, immediately solvable Mixed-Integer Linear Programming (MILP) model with all numerical coefficients derived from the provided data.

## 5. Gurobipy Implementation

```python
#!/usr/bin/env python3
"""
Gurobipy 12.0.2 Implementation for Browser Web Accelerator Optimization
"""

import gurobipy as gp
from gurobipy import GRB

def optimize_browser_accelerators():
    """Optimize the selection of web client accelerators to maximize browser compatibility."""
    
    # 1. MODEL & DATA SETUP
    model = gp.Model("browser_web_optimization")
    
    # Data from the problem
    browsers = {
        1: {"market_share": 0.35},
        2: {"market_share": 0.25},
        3: {"market_share": 0.15}
    }
    
    accelerator_compatibility = [
        {"accelerator_id": 1, "browser_id": 1, "compatibility_score": 0.9},
        {"accelerator_id": 1, "browser_id": 2, "compatibility_score": 0.8},
        {"accelerator_id": 2, "browser_id": 1, "compatibility_score": 0.85},
        {"accelerator_id": 2, "browser_id": 3, "compatibility_score": 0.7},
        {"accelerator_id": 3, "browser_id": 2, "compatibility_score": 0.75},
        {"accelerator_id": 3, "browser_id": 3, "compatibility_score": 0.65}
    ]
    
    max_accelerators = 3
    
    # CRITICAL: Validate array lengths before loops
    assert len(browsers) == 3, "Browser data length mismatch"
    assert len(accelerator_compatibility) == 6, "Compatibility data length mismatch"
    
    # 2. VARIABLES
    # Decision variables for accelerators
    x = {i: model.addVar(vtype=GRB.BINARY, name=f"x_{i}") 
         for i in range(1, 4)}
    
    # Decision variables for browsers
    y = {j: model.addVar(vtype=GRB.BINARY, name=f"y_{j}") 
         for j in range(1, 4)}
    
    # 3. OBJECTIVE FUNCTION
    # Maximize the total market share of compatible browsers
    model.setObjective(
        gp.quicksum(browsers[j]["market_share"] * y[j] for j in range(1, 4)), 
        GRB.MAXIMIZE
    )
    
    # 4. CONSTRAINTS
    
    # Maximum Accelerators Constraint
    model.addConstr(
        gp.quicksum(x[i] for i in range(1, 4)) <= max_accelerators, 
        name="max_accelerators"
    )
    
    # Minimum Compatibility Constraint
    for i in range(1, 4):
        model.addConstr(
            gp.quicksum(
                comp["compatibility_score"] * y[comp["browser_id"]] 
                for comp in accelerator_compatibility 
                if comp["accelerator_id"] == i
            ) >= x[i], 
            name=f"min_compatibility_{i}"
        )
    
    # Browser Compatibility Constraint
    for j in range(1, 4):
        model.addConstr(
            y[j] <= gp.quicksum(
                comp["compatibility_score"] * x[comp["accelerator_id"]] 
                for comp in accelerator_compatibility 
                if comp["browser_id"] == j
            ), 
            name=f"browser_compatibility_{j}"
        )
    
    # 5. SOLVING & RESULTS
    model.optimize()
    
    if model.status == GRB.OPTIMAL:
        print(f"Optimal value: {model.objVal}")
        for i in range(1, 4):
            if x[i].x > 1e-6:
                print(f"Accelerator {i} is selected")
        for j in range(1, 4):
            if y[j].x > 1e-6:
                print(f"Browser {j} is compatible")
    elif model.status == GRB.INFEASIBLE:
        print("Problem is infeasible")
    elif model.status == GRB.UNBOUNDED:
        print("Problem is unbounded")
    
    return model

# Run the optimization
optimize_browser_accelerators()
```

### Execution Results
**Status**: OPTIMAL
**Optimal Value**: 0.75
**Execution Time**: 0.18 seconds
**Reliability**: high
**Analysis**: Gurobipy successfully found an optimal solution with a value of 0.75 in a very short execution time (0.176 seconds). This indicates high reliability and efficiency.

## 6. DOCplex Implementation

```python
#!/usr/bin/env python3
"""
DOCplex 2.29.245 Implementation for Browser Web Accelerator Optimization
"""

from docplex.mp.model import Model

def optimize_browser_web_accelerators():
    """Optimize the selection of web client accelerators for maximum browser compatibility."""
    
    # 1. MODEL & DATA SETUP
    mdl = Model(name="browser_web_accelerator_optimization")
    
    # Data from the problem context
    browsers = [
        {"browser_id": 1, "market_share": 0.35},
        {"browser_id": 2, "market_share": 0.25},
        {"browser_id": 3, "market_share": 0.15}
    ]
    
    accelerator_compatibilities = [
        {"accelerator_id": 1, "browser_id": 1, "compatibility_score": 0.9},
        {"accelerator_id": 1, "browser_id": 2, "compatibility_score": 0.8},
        {"accelerator_id": 2, "browser_id": 1, "compatibility_score": 0.85},
        {"accelerator_id": 2, "browser_id": 3, "compatibility_score": 0.7},
        {"accelerator_id": 3, "browser_id": 2, "compatibility_score": 0.75},
        {"accelerator_id": 3, "browser_id": 3, "compatibility_score": 0.65}
    ]
    
    max_accelerators = 3
    
    # Create dictionaries for easy access
    browser_market_share = {b["browser_id"]: b["market_share"] for b in browsers}
    compatibility_scores = {(ac["accelerator_id"], ac["browser_id"]): ac["compatibility_score"] for ac in accelerator_compatibilities}
    
    # Extract unique accelerator and browser IDs
    accelerator_ids = list(set(ac["accelerator_id"] for ac in accelerator_compatibilities))
    browser_ids = list(set(b["browser_id"] for b in browsers))
    
    # CRITICAL: Validate array lengths to prevent IndexError
    assert len(accelerator_ids) == 3, "Expected 3 accelerators"
    assert len(browser_ids) == 3, "Expected 3 browsers"
    
    # 2. VARIABLES
    x = {i: mdl.binary_var(name=f"x_{i}") for i in accelerator_ids}  # Accelerator selection
    y = {j: mdl.binary_var(name=f"y_{j}") for j in browser_ids}     # Browser compatibility
    
    # 3. OBJECTIVE FUNCTION
    objective = mdl.sum(browser_market_share[j] * y[j] for j in browser_ids)
    mdl.maximize(objective)
    
    # 4. CONSTRAINTS
    
    # Maximum Accelerators Constraint
    mdl.add_constraint(mdl.sum(x[i] for i in accelerator_ids) <= max_accelerators, ctname="max_accelerators")
    
    # Minimum Compatibility Constraint
    for i in accelerator_ids:
        mdl.add_constraint(mdl.sum(compatibility_scores[(i, j)] * y[j] for j in browser_ids) >= x[i], ctname=f"min_compat_{i}")
    
    # Browser Compatibility Constraint
    for j in browser_ids:
        mdl.add_constraint(y[j] <= mdl.sum(compatibility_scores[(i, j)] * x[i] for i in accelerator_ids), ctname=f"browser_compat_{j}")
    
    # 5. SOLVING & RESULTS
    solution = mdl.solve()
    
    if solution:
        print(f"Optimal value: {solution.objective_value}")
        for i in accelerator_ids:
            if solution.get_value(x[i]) > 0.5:
                print(f"Accelerator {i} is selected")
        for j in browser_ids:
            if solution.get_value(y[j]) > 0.5:
                print(f"Browser {j} is compatible")
    else:
        print("No solution found")
        print(f"Status: {mdl.solve_details.status}")
    
    return mdl

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

### Execution Results
**Status**: ERROR
**Error**: Traceback (most recent call last):
  File "/tmp/tmpd7dflpdn.py", line 84, in <module>
    optimize_browser_web_accelerators()
  File "/tmp/tmpd7dflpdn.py", line 59, in optimize_browser_web_accelerators
    mdl.add_constraint(mdl.sum(compatibility_scores[(i, j)] * y[j] for j in browser_ids) >= x[i], ctname=f"min_compat_{i}")
  File "/dccstor/nl2opt/miniforge3/envs/nl2opt_optim/lib/python3.10/site-packages/docplex/mp/model.py", line 3342, in sum
    return self._aggregator.sum(args)
  File "/dccstor/nl2opt/miniforge3/envs/nl2opt_optim/lib/python3.10/site-packages/docplex/mp/aggregator.py", line 198, in sum
    sum_res = self._sum_with_iter(sum_args)
  File "/dccstor/nl2opt/miniforge3/envs/nl2opt_optim/lib/python3.10/site-packages/docplex/mp/aggregator.py", line 221, in _sum_with_iter
    for item in args:
  File "/tmp/tmpd7dflpdn.py", line 59, in <genexpr>
    mdl.add_constraint(mdl.sum(compatibility_scores[(i, j)] * y[j] for j in browser_ids) >= x[i], ctname=f"min_compat_{i}")
KeyError: (1, 3)

**Analysis**: DOCplex encountered a KeyError due to a missing key in the compatibility_scores dictionary. This suggests a data preparation or input error rather than a solver issue.

## 7. Pyomo Implementation

```python
# Complete PYOMO implementation

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

def optimize_browser_accelerators():
    """Optimize the selection of web client accelerators to maximize browser compatibility."""
    
    # 1. MODEL CREATION
    model = pyo.ConcreteModel()
    
    # 2. DATA SETUP
    # Browser data
    browser_data = {
        1: 0.35,
        2: 0.25,
        3: 0.15
    }
    
    # Accelerator compatibility data
    compatibility_data = {
        (1, 1): 0.9,
        (1, 2): 0.8,
        (2, 1): 0.85,
        (2, 3): 0.7,
        (3, 2): 0.75,
        (3, 3): 0.65
    }
    
    # Maximum number of accelerators
    max_accelerators = 3
    
    # Validate data lengths
    assert len(browser_data) == 3, "Browser data length mismatch"
    assert len(compatibility_data) == 6, "Compatibility data length mismatch"
    
    # 3. SETS
    model.I = pyo.Set(initialize=[1, 2, 3])  # Accelerators
    model.J = pyo.Set(initialize=[1, 2, 3])  # Browsers
    
    # 4. PARAMETERS
    model.market_share = pyo.Param(model.J, initialize=browser_data)
    model.compatibility_score = pyo.Param(model.I, model.J, initialize=compatibility_data, default=0.0)
    
    # 5. VARIABLES
    model.x = pyo.Var(model.I, within=pyo.Binary)  # Accelerator selection
    model.y = pyo.Var(model.J, within=pyo.Binary)  # Browser compatibility
    
    # 6. OBJECTIVE FUNCTION
    def obj_rule(model):
        return sum(model.market_share[j] * model.y[j] for j in model.J)
    model.objective = pyo.Objective(rule=obj_rule, sense=pyo.maximize)
    
    # 7. CONSTRAINTS
    # Maximum Accelerators Constraint
    def max_accelerators_rule(model):
        return sum(model.x[i] for i in model.I) <= max_accelerators
    model.max_accelerators_constraint = pyo.Constraint(rule=max_accelerators_rule)
    
    # Minimum Compatibility Constraint
    def min_compatibility_rule(model, i):
        return sum(model.compatibility_score[i, j] * model.y[j] for j in model.J) >= model.x[i]
    model.min_compatibility_constraint = pyo.Constraint(model.I, rule=min_compatibility_rule)
    
    # Browser Compatibility Constraint
    def browser_compatibility_rule(model, j):
        return model.y[j] <= sum(model.compatibility_score[i, j] * model.x[i] for i in model.I)
    model.browser_compatibility_constraint = pyo.Constraint(model.J, rule=browser_compatibility_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("\nSelected Accelerators:")
        for i in model.I:
            if pyo.value(model.x[i]) > 0.5:
                print(f"Accelerator {i} is selected")
        
        print("\nCompatible Browsers:")
        for j in model.J:
            if pyo.value(model.y[j]) > 0.5:
                print(f"Browser {j} is compatible")
        
    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__":
    optimize_browser_accelerators()
```

### Execution Results
**Status**: OPTIMAL
**Optimal Value**: 0.75
**Execution Time**: 0.93 seconds
**Reliability**: medium
**Analysis**: Pyomo also found an optimal solution with a value of 0.75, but it took significantly longer (0.931 seconds) compared to Gurobipy. This indicates reliability but lower efficiency.

## 8. Cross-Solver Analysis and Final Recommendation

### Solver Results Comparison

| Solver | Status | Optimal Value | Execution Time | Decision Variables | Retry Attempt |
|--------|--------|---------------|----------------|-------------------|---------------|
| Gurobipy | OPTIMAL | 0.75 | 0.18s | N/A | N/A |
| Docplex | ERROR | N/A | 1.05s | N/A | N/A |
| Pyomo | OPTIMAL | 0.75 | 0.93s | N/A | N/A |

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

### Final Recommendation
**Recommended Optimal Value**: 0.75
**Confidence Level**: HIGH
**Preferred Solver(s)**: gurobipy
**Reasoning**: Gurobipy is recommended due to its high reliability, optimal solution, and significantly faster execution time compared to Pyomo. DOCplex is excluded due to its error, which appears to be related to data preparation rather than the solver itself.

### Business Interpretation
**Overall Strategy**: The optimal solution maximizes the market share of compatible browsers, achieving a total market share of 75%. This suggests a strong alignment between selected accelerators and browser compatibility.
**Objective Value Meaning**: The optimal objective value of 0.75 represents the total market share of browsers compatible with the selected accelerators. This is a key metric for maximizing user reach.
**Resource Allocation Summary**: Resources should be allocated to the accelerators identified in the optimal solution to ensure compatibility with the largest possible browser market share.
**Implementation Recommendations**: 1. Verify the compatibility_scores data to ensure accuracy. 2. Select the accelerators as per the optimal solution. 3. Monitor browser compatibility and market share post-implementation to validate results.