# Complete DOCPLEX implementation

from docplex.mp.model import Model

def real_estate_optimization():
    """Optimization model for selecting real estate properties to maximize profit."""
    
    # 1. MODEL & DATA SETUP
    mdl = Model(name="real_estate_properties")
    
    # Data from the problem statement
    agreed_selling_prices = [120000.0, 180000.0, 250000.0, 95000.0, 130000.0]
    vendor_requested_prices = [110000.0, 170000.0, 240000.0, 90000.0, 125000.0]
    room_counts = [3, 4, 5, 2, 3]
    features = ['desired_feature', 'other_feature', 'desired_feature', 'desired_feature', 'other_feature']
    
    # Constraint bounds
    max_properties_to_sell = 3
    max_total_rooms = 12
    min_desired_features = 2
    
    # CRITICAL: Validate array lengths to prevent IndexError
    n_properties = len(agreed_selling_prices)
    assert len(vendor_requested_prices) == len(room_counts) == len(features) == n_properties, "Array length mismatch"
    safe_range = range(n_properties)  # Safe indexing
    
    # 2. VARIABLES
    x = {i: mdl.binary_var(name=f"x_{i}") for i in safe_range}
    
    # 3. OBJECTIVE FUNCTION
    profits = [agreed_selling_prices[i] - vendor_requested_prices[i] for i in safe_range]
    objective = mdl.sum(profits[i] * x[i] for i in safe_range)
    mdl.maximize(objective)
    
    # 4. CONSTRAINTS
    
    # Maximum number of properties to sell
    mdl.add_constraint(mdl.sum(x[i] for i in safe_range) <= max_properties_to_sell, ctname="max_properties")
    
    # Maximum total number of rooms
    mdl.add_constraint(mdl.sum(room_counts[i] * x[i] for i in safe_range) <= max_total_rooms, ctname="max_rooms")
    
    # Minimum number of properties with desired feature
    desired_feature_indices = [i for i in safe_range if features[i] == 'desired_feature']
    mdl.add_constraint(mdl.sum(x[i] for i in desired_feature_indices) >= min_desired_features, ctname="min_desired_features")
    
    # 5. SOLVING & RESULTS
    solution = mdl.solve()
    
    if solution:
        print(f"Optimal value: {solution.objective_value}")
        for i in safe_range:
            value = solution.get_value(x[i])
            if value > 1e-6:
                print(f"x[{i}] = {value:.3f}")
    else:
        print("No solution found")
        print(f"Status: {mdl.solve_details.status}")
    
    return mdl

# Run the optimization
real_estate_optimization()