#!/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()