# Complete DOCPLEX implementation

from docplex.mp.model import Model

def candidate_poll_optimization():
    """Optimization for candidate poll resource allocation"""

    # 1. MODEL & DATA SETUP
    mdl = Model(name="candidate_poll")
    
    # Data from the problem context
    poll_sources = [1, 2, 3]
    support_rates = [0.55, 0.75, 0.6]
    min_efforts = [5.0, 10.0, 7.5]
    max_efforts = [20.0, 30.0, 25.0]
    total_budget = 50.0  # Example budget constraint

    # CRITICAL: Validate array lengths to prevent IndexError
    assert len(poll_sources) == len(support_rates) == len(min_efforts) == len(max_efforts), "Array length mismatch"
    safe_range = range(len(poll_sources))  # Safe indexing

    # 2. VARIABLES
    effort = {i: mdl.continuous_var(name=f"effort_{poll_sources[i]}", lb=min_efforts[i], ub=max_efforts[i]) for i in safe_range}

    # 3. OBJECTIVE FUNCTION
    # Maximize the total support rate
    objective = mdl.sum(support_rates[i] * effort[i] for i in safe_range)
    mdl.maximize(objective)

    # 4. CONSTRAINTS - CORRECT SYNTAX PATTERNS

    # Total effort constraint (budget constraint)
    total_effort = mdl.sum(effort[i] for i in safe_range)
    mdl.add_constraint(total_effort <= total_budget, ctname="total_budget")

    # 5. SOLVING & RESULTS
    solution = mdl.solve()

    if solution:
        print(f"Optimal value: {solution.objective_value}")
        for i in safe_range:
            value = solution.get_value(effort[i])
            print(f"effort[{poll_sources[i]}] = {value:.3f}")
    else:
        print("No solution found")
        print(f"Status: {mdl.solve_details.status}")

    return mdl

# Run the optimization
candidate_poll_optimization()