# Complete DOCPLEX implementation - Retry Attempt 4

from docplex.mp.model import Model

def device_distribution_optimization():
    # 1. MODEL & DATA SETUP
    mdl = Model(name="device_distribution_optimization")
    
    # Data from the problem
    devices = [1, 2, 3]
    shops = [101, 102, 103]
    
    # Shipping costs
    shipping_cost = {
        (1, 101): 12.5,
        (2, 102): 18.0,
        (3, 103): 15.0
    }
    
    # Demand
    demand = {
        (1, 101): 60,
        (2, 102): 80,
        (3, 103): 70
    }
    
    # Storage capacity
    storage_capacity = {
        101: 250,
        102: 300,
        103: 200
    }
    
    # CRITICAL: Validate array lengths to prevent IndexError
    assert len(shipping_cost) == len(demand) == len(devices) * len(shops), "Data length mismatch"
    
    # 2. VARIABLES
    x = {(d, s): mdl.continuous_var(name=f"x_{d}_{s}", lb=0) for d in devices for s in shops}
    
    # 3. OBJECTIVE FUNCTION
    objective = mdl.sum(shipping_cost[(d, s)] * x[(d, s)] for d in devices for s in shops)
    mdl.minimize(objective)
    
    # 4. CONSTRAINTS
    # Demand Fulfillment
    for d in devices:
        for s in shops:
            mdl.add_constraint(x[(d, s)] >= demand[(d, s)], ctname=f"demand_{d}_{s}")
    
    # Storage Capacity
    for s in shops:
        mdl.add_constraint(mdl.sum(x[(d, s)] for d in devices) <= storage_capacity[s], ctname=f"capacity_{s}")
    
    # Non-Negative Shipments (already handled by lb=0 in variable definition)
    
    # 5. SOLVING & RESULTS
    solution = mdl.solve()
    
    if solution:
        print(f"Optimal value: {solution.objective_value}")
        for d in devices:
            for s in shops:
                value = solution.get_value(x[(d, s)])
                if value > 1e-6:
                    print(f"x[{d},{s}] = {value:.3f}")
    else:
        print("No solution found")
        print(f"Status: {mdl.solve_details.status}")
    
    return mdl

# Execute the optimization
device_distribution_optimization()