# Complete DOCPLEX implementation

from docplex.mp.model import Model

def optimize_roller_coaster_maintenance():
    """Optimize maintenance hours allocation for roller coasters to minimize downtime."""
    
    # 1. MODEL & DATA SETUP
    mdl = Model(name="roller_coaster_maintenance")
    
    # Data from the database
    downtime_coefficients = [0.4, 0.35, 0.25]
    minimum_hours = [3.0, 4.0, 2.5]
    maximum_hours = [10.0, 12.0, 9.0]
    total_available_hours = 22
    
    # CRITICAL: Validate array lengths to prevent IndexError
    assert len(downtime_coefficients) == len(minimum_hours) == len(maximum_hours), "Array length mismatch"
    safe_range = range(len(downtime_coefficients))  # Safe indexing
    
    # 2. VARIABLES
    # Variable dictionaries (most common)
    maintenance_hours = {i: mdl.continuous_var(name=f"x_{i}", lb=0) for i in safe_range}
    
    # 3. OBJECTIVE FUNCTION
    # Minimize total downtime
    objective = mdl.sum(downtime_coefficients[i] * maintenance_hours[i] for i in safe_range)
    mdl.minimize(objective)
    
    # 4. CONSTRAINTS - CORRECT SYNTAX PATTERNS
    
    # Total maintenance hours constraint
    total_usage = mdl.sum(maintenance_hours[i] for i in safe_range)
    mdl.add_constraint(total_usage <= total_available_hours, ctname="total_hours_limit")
    
    # Minimum and maximum maintenance hours constraints
    for i in safe_range:
        mdl.add_constraint(maintenance_hours[i] >= minimum_hours[i], ctname=f"min_hours_{i}")
        mdl.add_constraint(maintenance_hours[i] <= maximum_hours[i], ctname=f"max_hours_{i}")
    
    # 5. SOLVING & RESULTS
    solution = mdl.solve()
    
    if solution:
        print(f"Optimal value: {solution.objective_value:.3f}")
        for i in safe_range:
            value = solution.get_value(maintenance_hours[i])
            print(f"x[{i}] = {value:.3f}")
    else:
        print("No solution found")
        print(f"Status: {mdl.solve_details.status}")
    
    return mdl

# Run the optimization
optimize_roller_coaster_maintenance()