#!/usr/bin/env python3
"""
DOCplex 2.29.245 Implementation for Office Space Allocation Optimization
"""

from docplex.mp.model import Model

def optimize_office_allocation():
    """Optimize the allocation of office spaces across multiple buildings to minimize total leasing cost."""
    
    # 1. MODEL & DATA SETUP
    mdl = Model(name="office_space_allocation")
    
    # Data from the problem
    buildings = [1, 2, 3]
    companies = [1, 2, 3]
    
    cost_per_sqft = {
        1: 55.0,
        2: 65.0,
        3: 45.0
    }
    
    required_space = {
        1: 1200,
        2: 1800,
        3: 900
    }
    
    available_space = {
        1: 6000,
        2: 7000,
        3: 5000
    }
    
    # CRITICAL: Validate array lengths to prevent IndexError
    assert len(buildings) == len(cost_per_sqft) == len(available_space), "Building data length mismatch"
    assert len(companies) == len(required_space), "Company data length mismatch"
    
    # 2. VARIABLES
    # Decision variables: x_{ij} = space allocated to company i in building j
    x = {(i, j): mdl.continuous_var(name=f"x_{i}_{j}", lb=0) for i in companies for j in buildings}
    
    # 3. OBJECTIVE FUNCTION
    # Minimize total leasing cost
    objective = mdl.sum(cost_per_sqft[j] * x[(i, j)] for i in companies for j in buildings)
    mdl.minimize(objective)
    
    # 4. CONSTRAINTS
    
    # Minimum Space Requirement for each company
    for i in companies:
        total_space = mdl.sum(x[(i, j)] for j in buildings)
        mdl.add_constraint(total_space >= required_space[i], ctname=f"min_space_{i}")
    
    # Building Capacity for each building
    for j in buildings:
        total_allocated = mdl.sum(x[(i, j)] for i in companies)
        mdl.add_constraint(total_allocated <= available_space[j], ctname=f"capacity_{j}")
    
    # Non-Negative Allocation is already handled by lb=0 in variable definition
    
    # 5. SOLVING & RESULTS
    solution = mdl.solve()
    
    if solution:
        print(f"Optimal value: {solution.objective_value}")
        for i in companies:
            for j in buildings:
                value = solution.get_value(x[(i, j)])
                if value > 1e-6:
                    print(f"Space allocated to Company {i} in Building {j}: {value:.3f}")
    else:
        print("No solution found")
        print(f"Status: {mdl.solve_details.status}")
    
    return mdl

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