# Complete DOCPLEX implementation

from docplex.mp.model import Model

def conference_scheduling_optimization():
    """Optimize conference paper scheduling to minimize the number of sessions."""
    
    # 1. MODEL & DATA SETUP
    mdl = Model(name="conference_scheduling")
    
    # Data: Papers, Authors, and Author-Paper Associations
    papers = [1, 2, 3]  # Paper IDs
    authors = [1, 2, 3]  # Author IDs
    author_paper_associations = {
        1: [1],  # Author 1 has Paper 1
        2: [2],  # Author 2 has Paper 2
        3: [3]   # Author 3 has Paper 3
    }
    
    max_papers_per_session = 2  # Business configuration parameter
    
    # CRITICAL: Validate array lengths to prevent IndexError
    assert len(papers) == len(authors) == len(author_paper_associations), "Array length mismatch"
    safe_range_papers = range(len(papers))
    safe_range_authors = range(len(authors))
    
    # 2. VARIABLES
    # Decision variables
    x = {(i, j): mdl.binary_var(name=f"x_{i}_{j}") for i in papers for j in papers}
    y = {j: mdl.binary_var(name=f"y_{j}") for j in papers}
    
    # 3. OBJECTIVE FUNCTION
    # Minimize the total number of sessions used
    mdl.minimize(mdl.sum(y[j] for j in papers))
    
    # 4. CONSTRAINTS - CORRECT SYNTAX PATTERNS
    
    # Each paper must be scheduled in exactly one session
    for i in papers:
        mdl.add_constraint(mdl.sum(x[i, j] for j in papers) == 1, ctname=f"one_session_per_paper_{i}")
    
    # The number of papers scheduled in any session cannot exceed the maximum number of papers allowed per session
    for j in papers:
        mdl.add_constraint(mdl.sum(x[i, j] for i in papers) <= max_papers_per_session * y[j], ctname=f"max_papers_per_session_{j}")
    
    # An author cannot present more than one paper in the same session
    for j in papers:
        for k in authors:
            mdl.add_constraint(mdl.sum(x[i, j] for i in author_paper_associations[k]) <= 1, ctname=f"one_paper_per_author_per_session_{j}_{k}")
    
    # Linking sessions to papers
    for i in papers:
        for j in papers:
            mdl.add_constraint(x[i, j] <= y[j], ctname=f"link_sessions_to_papers_{i}_{j}")
    
    # 5. SOLVING & RESULTS
    solution = mdl.solve()
    
    if solution:
        print(f"Optimal value: {solution.objective_value}")
        for i in papers:
            for j in papers:
                value = solution.get_value(x[i, j])
                if value > 1e-6:
                    print(f"x[{i},{j}] = {value:.3f}")
    else:
        print("No solution found")
        print(f"Status: {mdl.solve_details.status}")
    
    return mdl

# Run the optimization
conference_scheduling_optimization()