def test_set_processing_times(self):
        frame = JobSchedulingFrame([[]])
        frame.set_processing_times(self.processing_times)

        expected_frame = JobSchedulingFrame(self.processing_times)

        tm.assert_js_frame(frame, expected_frame)
def test_cds_create_proc_times():
    processing_times = [[17, 19, 13], [15, 11, 12], [14, 21, 16], [20, 16, 20],
                        [16, 17, 17]]
    frame = JobSchedulingFrame(processing_times)
    johnson_frame = JobSchedulingFrame([[]])

    # sub problem index begin with 1
    processing_times_first = cds_create_proc_times(frame, 1)
    johnson_frame.set_processing_times(processing_times_first)

    assert_js_frame(
        johnson_frame,
        JobSchedulingFrame([[17, 13], [15, 12], [14, 16], [20, 20], [16, 17]]))

    processing_times_second = cds_create_proc_times(frame, 2)
    johnson_frame.set_processing_times(processing_times_second)

    assert_js_frame(
        johnson_frame,
        JobSchedulingFrame([[36, 32], [26, 23], [35, 37], [36, 36], [33, 34]]))
def cds_heuristics(frame: JobSchedulingFrame) -> list:
    """
    Compute approximate solution for instance of Flow Job problem by
    Campbell, Dudek, and Smith (CDS) heuristic.

    Parameters
    ----------
    frame: JobSchedulingFrame

    Returns
    -------
    solution: list
        sequence of job index

    Notes
    -----
    Developed by Campbell, Dudek, and Smith in 1970.

    """
    johnson_frame = JobSchedulingFrame([[]])
    johnson_solutions_with_end_time = []

    # Create `count_machines - 1` sub-problems
    # which will be solved by Johnson's algorithm
    for sub_problem in range(1, frame.count_machines):
        # Create processing times matrix for all jobs on only 2 machines
        proc_times = cds_create_proc_times(frame, sub_problem)
        johnson_frame.set_processing_times(proc_times)
        johnson_solution = johnson_algorithm(johnson_frame)

        # end time compute for the original task, that is `frame`
        end_time = compute_end_time(frame, johnson_solution)
        johnson_solutions_with_end_time.append((johnson_solution, end_time))

    johnson_solutions_with_end_time.sort(key=lambda elem: elem[1])

    # return only solution with minimum makespan (end_time)
    return johnson_solutions_with_end_time[0][0]