# Complete GUROBIPY implementation - Retry Attempt 3

import gurobipy as gp
from gurobipy import GRB

def optimize_device_allocation():
    # 1. MODEL & DATA SETUP
    model = gp.Model("device_allocation")
    
    # Data from the problem statement
    shop_ids = [1, 2, 3]
    device_ids = [101, 102, 103]
    
    # Potential sales data
    potential_sales = {
        (1, 101): 600.0,
        (2, 102): 850.0,
        (3, 103): 950.0
    }
    
    # Shop capacity data
    shop_capacity = {
        1: 120,
        2: 180,
        3: 220
    }
    
    # Validate data lengths
    assert len(potential_sales) == len(shop_ids) == len(device_ids), "Data length mismatch"
    
    # 2. VARIABLES
    # Decision variables: number of devices allocated to each shop
    x = model.addVars(shop_ids, device_ids, vtype=GRB.INTEGER, name="x", lb=0)
    
    # 3. OBJECTIVE FUNCTION
    # Maximize total potential sales
    model.setObjective(
        gp.quicksum(potential_sales[i, j] * x[i, j] for i in shop_ids for j in device_ids if (i, j) in potential_sales),
        GRB.MAXIMIZE
    )
    
    # 4. CONSTRAINTS
    # Shop capacity constraints
    for i in shop_ids:
        model.addConstr(
            gp.quicksum(x[i, j] for j in device_ids if (i, j) in potential_sales) <= shop_capacity[i],
            name=f"capacity_{i}"
        )
    
    # 5. SOLVING & RESULTS
    model.optimize()
    
    if model.status == GRB.OPTIMAL:
        print(f"Optimal value: {model.objVal}")
        for i in shop_ids:
            for j in device_ids:
                if (i, j) in potential_sales and x[i, j].x > 1e-6:
                    print(f"x[{i},{j}] = {x[i, j].x:.3f}")
    elif model.status == GRB.INFEASIBLE:
        print("Problem is infeasible")
    elif model.status == GRB.UNBOUNDED:
        print("Problem is unbounded")

# Run the optimization
optimize_device_allocation()