示例#1
0
def test_simulate_A():
    """
    `simulate_until_max_t`
    Feature A: simulating until the time cap.
    """
    predecessor_node_lists, truth_tables = build_predecessor_nodes_lists_and_truth_tables(
        UPDATE_RULES_A)
    initial_state = [False, True, True, False, False]
    perturbed_nodes_by_t = dict()
    # Test for {not reaching attractor, reaching attractor}.
    max_t_1 = 3
    max_t_2 = 20
    expected_simulation_states_1 = \
        [initial_state, [False, False, True, False, True], [True, False, False, False, True],
         [True, True, False, True, True]]
    expected_simulation_states_2 = \
        4 * [initial_state, [False, False, True, False, True], [True, False, False, False, True],
             [True, True, False, True, True], [True, True, True, True, False]] + \
        [initial_state]

    for max_t, expected_simulation_states in zip(
        [max_t_1, max_t_2],
        [expected_simulation_states_1, expected_simulation_states_2]):
        _, _simulate_until_attractor_or_target_substate_or_max_t = \
            configure_encode_and_simulate(max_t=max_t)
        simulation_states = simulate_until_max_t(
            max_t, _simulate_until_attractor_or_target_substate_or_max_t,
            initial_state, perturbed_nodes_by_t, predecessor_node_lists,
            truth_tables)

        test_description = generate_test_description(locals(), 'max_t')
        assert expected_simulation_states == simulation_states, test_description
示例#2
0
def test_simulate_n_steps_A():
    """
    `simulate_n_steps`
    Feature A: evaluating next n states.
    """
    predecessor_nodes_lists, truth_tables = \
        build_predecessor_nodes_lists_and_truth_tables(UPDATE_RULES_B)
    initial_state = [False, False, False, False, False, False]
    n_steps = 3
    # Test for {no perturbations, perturbations}.
    perturbed_nodes_by_t_1 = dict()
    perturbed_nodes_by_t_2 = {1: {1: True}}

    for perturbed_nodes_by_t in [
            perturbed_nodes_by_t_1, perturbed_nodes_by_t_2
    ]:
        expected_states = [
            initial_state,
            [True, bool(perturbed_nodes_by_t), False, False, True, False],
            [True, True, False, False, False, True],
            [False, True, False, False, False, False]
        ]

        states = simulate_n_steps(initial_state, perturbed_nodes_by_t,
                                  predecessor_nodes_lists, truth_tables,
                                  n_steps)

        test_description = generate_test_description(locals(),
                                                     'perturbed_nodes_by_t')
        assert expected_states == states
def test_find_node_correlations_A():
    """
    `find_node_correlations`
    Feature A: correctly terminating if insufficient attractors found.
    """
    # Test for {no attractors found, one attractor found, two attractors found}.
    aggregated_attractors_1 = dict()
    aggregated_attractors_2 = {
        1: construct_aggregated_attractor(attractor_states_1, 10, 1, 0)
    }
    aggregated_attractors_3 = {
        1: construct_aggregated_attractor(attractor_states_1, 1, 1, 0),
        8: construct_aggregated_attractor(attractor_states_2, 1, 1, 0)
    }
    for aggregated_attractors in [
            aggregated_attractors_1, aggregated_attractors_2,
            aggregated_attractors_3
    ]:
        db_conn = ZODB.connection(None)
        init_attractor_db_structure(db_conn)
        for key, aggregated_attractor in aggregated_attractors.items():
            db_conn.root.aggregated_attractors[key] = aggregated_attractor
            db_conn.root.n_aggregated_attractors.change(1)
            db_conn.root.total_frequency.change(aggregated_attractor.frequency)

        node_correlations = find_node_correlations(db_conn, None, True)

        test_description = generate_test_description(locals(),
                                                     'aggregated_attractors')
        assert node_correlations is None, test_description
示例#4
0
def test_simulate_until_target_substate_or_max_t_C():
    """
    `simulate_until_target_substate_or_max_t`
    Feature C: not finding target substate if time cap is violated.
    """
    predecessor_node_lists, truth_tables = \
        build_predecessor_nodes_lists_and_truth_tables(UPDATE_RULES_B)
    initial_state = [False, False, False, False, False, False]
    substate_node_set = {0, 1, 2, 3, 4, 5}
    _encode_state, _ = configure_encode_and_simulate(
        substate_node_set=substate_node_set)
    _, target_substate_code = _encode_state(
        [True, True, False, False, False, True])
    max_t = 1
    _, _simulate_until_attractor_or_target_substate_or_max_t = \
        configure_encode_and_simulate(max_t=max_t, substate_node_set=substate_node_set,
                                      target_substate_code=target_substate_code)
    # Test for {no perturbations, perturbations}.
    perturbed_nodes_by_t_1 = dict()
    perturbed_nodes_by_t_2 = {1: {3: False}}

    for perturbed_nodes_by_t in [
            perturbed_nodes_by_t_1, perturbed_nodes_by_t_2
    ]:
        simulation_states = simulate_until_target_substate_or_max_t(
            _simulate_until_attractor_or_target_substate_or_max_t,
            initial_state, perturbed_nodes_by_t, predecessor_node_lists,
            truth_tables)

        test_description = generate_test_description(locals(), 'max_t',
                                                     'perturbed_nodes_by_t')
        assert simulation_states is None
示例#5
0
def test_simulate_time_step_A():
    """
    `simulate_time_step`
    Feature A: evaluating next state.
    """
    predecessor_nodes_lists, truth_tables = \
        build_predecessor_nodes_lists_and_truth_tables(UPDATE_RULES_B)

    current_state = [False, False, False, False, False, False]
    # Test for {no perturbations, perturbations}.
    current_perturbations_1 = dict()
    current_perturbations_2 = {1: True}

    for current_perturbations in [
            current_perturbations_1, current_perturbations_2
    ]:
        expected_next_state = [
            True, bool(current_perturbations), False, False, True, False
        ]

        next_state = simulate_step(current_state, predecessor_nodes_lists,
                                   truth_tables, current_perturbations)

        test_description = generate_test_description(locals(),
                                                     'current_perturbations')
        assert expected_next_state == next_state
def test_frequency_pearsonr_A():
    """
    `compute_frequency_pearsonr`
    Feature A: properly calculating correlations and p-values.
    """
    frequencies = np.array([2, 4, 1, 3, 2])
    # Test for {p-value < 0.05, p-value >= 0.05}.
    raw_data_1 = [[1, 0, 1, 0, 1], [.67, .25, .75, .2, .6]]
    raw_data_2 = [[.67, .25, .75, .2, .6], [.1, .3, .8, .3, .2]]
    for raw_data in [raw_data_1, raw_data_2]:
        # Columns are variables and rows are observations, whose
        # frequencies are specified.
        data = np.array(raw_data).T
        # Same data, but with observations (rows) actually repeated
        # instead of their frequencies being specified.
        expanded_data = np.repeat(data.T, frequencies, axis=1)

        expected_r, expected_p = stats.pearsonr(*expanded_data)
        expected_R = np.array([[1, expected_r], [expected_r, 1]])
        expected_P = np.array([[0, expected_p], [expected_p, 0]])

        R, P = compute_frequency_pearsonr(data, frequencies)

        test_description = generate_test_description(locals(), 'raw_data')
        assert np.allclose(expected_R, R, equal_nan=True), test_description
        assert np.allclose(expected_P, P, equal_nan=True), test_description
示例#7
0
def test_calculate_increment_for_chunking_simulation_problems_B():
    """
    `calculate_increment_for_chunking_simulation_problems`
    Feature B: sampling step is > 1 whenever
    the # of simulation problems > the # of chunks.
    """
    n_simulation_problems = 12
    # Test for the # of chunks in {even & 0 mod 3, even & 1 mod 3,
    # even & 2 mod 3, odd & 0 mod 3, odd & 1 mod 3, odd & 2 mod 3}.
    n_chunks_1 = 6
    n_chunks_2 = 10
    n_chunks_3 = 8
    n_chunks_4 = 9
    n_chunks_5 = 7
    n_chunks_6 = 5

    for n_chunks in [
            n_chunks_1, n_chunks_2, n_chunks_3, n_chunks_4, n_chunks_5,
            n_chunks_6
    ]:
        sampling_step = calculate_increment_for_chunking_simulation_problems(
            n_simulation_problems, n_chunks)

        test_description = generate_test_description(locals(), 'n_chunks',
                                                     'n_simulation_problems',
                                                     'sampling_step')
        assert sampling_step > 1, test_description
示例#8
0
def test_adjust_update_rules_to_fixed_nodes_A():
    """
    `adjust_update_rules_to_fixed_nodes`
    Feature A: properly adjusting truth tables for fixed nodes.
    """
    update_rule_dict = {'A': 'not A'}
    predecessor_nodes_lists, truth_tables = \
        build_predecessor_nodes_lists_and_truth_tables(update_rule_dict)
    fixed_node_state_1 = False
    fixed_node_state_2 = False

    expected_adjusted_predecessor_node_lists = [[]]

    for fixed_node_state in [fixed_node_state_1, fixed_node_state_2]:
        fixed_nodes = {0: fixed_node_state}

        expected_adjusted_truth_tables = [{(): fixed_node_state}]

        adjusted_predecessor_node_lists, adjusted_truth_tables = \
            adjust_update_rules_for_fixed_nodes(predecessor_nodes_lists, truth_tables, fixed_nodes)

        test_description = generate_test_description(locals(),
                                                     'fixed_node_state')
        assert expected_adjusted_predecessor_node_lists == adjusted_predecessor_node_lists, \
            test_description
        assert expected_adjusted_truth_tables == adjusted_truth_tables, test_description
示例#9
0
def test_simulate_until_max_t_or_attractor_or_target_substate_G():
    """
    `simulate_until_attractor_or_target_substate_or_max_t`
    Feature G: recognizing target substate in initial state.
    """
    predecessor_nodes_lists, truth_tables = \
        build_predecessor_nodes_lists_and_truth_tables(UPDATE_RULES_B)
    initial_state = [False, False, False, False, False, False]
    perturbed_nodes_by_t = dict()
    max_t = inf
    target_node_set = {1, 2, 4, 5}
    _encode_state = partial(encode_state, target_node_set)
    _, target_substate_code = _encode_state(initial_state)
    # Test for {not storing all states, storing all states}.
    storing_all_states_1 = False
    storing_all_states_2 = True

    for storing_all_states in [storing_all_states_1, storing_all_states_2]:
        _, _, t, *_ = simulate_until_attractor_or_target_substate_or_max_t(
            storing_all_states, max_t, _encode_state, target_substate_code,
            initial_state, perturbed_nodes_by_t, predecessor_nodes_lists,
            truth_tables)

        test_description = generate_test_description(locals(),
                                                     'storing_all_states')
        assert t == 0, test_description
示例#10
0
def test_simulate_until_max_t_or_attractor_or_target_substate_F():
    """
    `simulate_until_attractor_or_target_substate_or_max_t`
    Feature F: ignoring target substates before last perturbation.
    """
    predecessor_nodes_lists, truth_tables = \
        build_predecessor_nodes_lists_and_truth_tables(UPDATE_RULES_B)
    initial_state = [False, False, False, False, False, False]
    perturbed_nodes_by_t = {2: {1: True}}
    max_t = inf
    target_node_set = {0, 1, 2, 3, 4, 5}
    target_state = [True, False, False, False, True, False]
    _encode_state = partial(encode_state, target_node_set)
    _, target_substate_code = _encode_state(target_state)
    # Test for {not storing all states, storing all states}.
    storing_all_states_1 = False
    storing_all_states_2 = True

    for storing_all_states in [storing_all_states_1, storing_all_states_2]:
        _, _, t, *_ = simulate_until_attractor_or_target_substate_or_max_t(
            storing_all_states, max_t, _encode_state, target_substate_code,
            initial_state, perturbed_nodes_by_t, predecessor_nodes_lists,
            truth_tables)

        test_description = generate_test_description(locals(),
                                                     'storing_all_states')
        assert t >= 2, test_description
示例#11
0
def test_simulate_until_attractor_or_max_t_storing_all_states_B():
    """
    `simulate_until_attractor_or_max_t_storing_all_states`
    Feature B: not finding attractor if time cap is violated.
    """
    initial_state = [False, False, True, False, False, False]
    max_t = 3
    # Test for {no length constraint, length constraint}.
    max_attractor_l_1 = inf
    max_attractor_l_2 = 100
    # Test for {no perturbations, perturbations}.
    perturbed_nodes_by_t_1 = dict()
    perturbed_nodes_by_t_2 = {1: {3: False}}

    for max_attractor_l, perturbed_nodes_by_t in product(
        [max_attractor_l_1, max_attractor_l_2],
        [perturbed_nodes_by_t_1, perturbed_nodes_by_t_2]):
        predecessor_node_lists, truth_tables = \
            build_predecessor_nodes_lists_and_truth_tables(UPDATE_RULES_B)
        _, _simulate_until_attractor_or_target_substate_or_max_t = \
            configure_encode_and_simulate(max_t=max_t)

        attractor = simulate_until_attractor_or_max_t_storing_all_states(
            max_attractor_l,
            _simulate_until_attractor_or_target_substate_or_max_t,
            initial_state, perturbed_nodes_by_t, predecessor_node_lists,
            truth_tables)

        test_description = generate_test_description(locals(),
                                                     'max_attractor_l',
                                                     'perturbed_nodes_by_t')
        assert attractor is None, test_description
def test_assign_frequency_ranks_A():
    """
    `assign_frequency_ranks`
    Feature A: properly calculating "averaged" ranks.
    """
    # Test for {no repeated values, repeated values}.
    data_1 = np.array([.67, .25, .75, .2, .6])
    data_2 = np.array([1, 0, 1, 0, 1])
    # Test for {no frequencies > 1, frequencies > 1}.
    frequencies_1 = np.array([1, 1, 1, 1, 1])
    frequencies_2 = np.array([2, 4, 1, 3, 2])

    expected_ranks_list = [
        np.array([4, 2, 5, 1, 3]),
        np.array([10.5, 5.5, 12, 2, 8.5]),
        np.array([4, 1.5, 4, 1.5, 4]),
        np.array([10, 4, 10, 4, 10])
    ]

    for (data, frequencies), expected_ranks in zip(
            product([data_1, data_2], [frequencies_1, frequencies_2]),
            expected_ranks_list):
        ranks = assign_frequency_ranks(data, frequencies)

        test_description = generate_test_description(locals(), 'data',
                                                     'frequencies')
        assert np.array_equal(expected_ranks, ranks), test_description
示例#13
0
def test_calculate_increment_for_chunking_simulation_problems_A():
    """
    `calculate_increment_for_chunking_simulation_problems`
    Feature A: sampling step is coprime to # of simulation problems.
    """
    # Test for the # of chunks in {1, 2, 3, > 3 & even & 0 mod 3,
    # > 3 & even & 1 mod 3, > 3 & even & 2 mod 3, > 3 & odd & 0 mod 3,
    # > 3 & odd & 1 mod 3, > 3 & odd & 2 mod 3}.
    n_chunks_1 = 1
    n_chunks_2 = 2
    n_chunks_3 = 3
    n_chunks_4 = 6
    n_chunks_5 = 10
    n_chunks_6 = 8
    n_chunks_7 = 9
    n_chunks_8 = 7
    n_chunks_9 = 5
    # Test for the # of simulation problems in {less than the # of
    # chunks (if possible), no less than the # of chunks}.
    n_simulation_problems_1 = 1
    n_simulation_problems_2 = 24

    for n_chunks, n_simulation_problems in product([
            n_chunks_1, n_chunks_2, n_chunks_3, n_chunks_4, n_chunks_5,
            n_chunks_6, n_chunks_7, n_chunks_8, n_chunks_9
    ], [n_simulation_problems_1, n_simulation_problems_2]):
        sampling_step = calculate_increment_for_chunking_simulation_problems(
            n_simulation_problems, n_chunks)
        gcd = math.gcd(sampling_step, n_simulation_problems)

        test_description = generate_test_description(locals(), 'n_chunks',
                                                     'n_simulation_problems')
        assert gcd == 1, test_description
示例#14
0
def test_simulate_master_A():
    """
    `simulate_master`
    Feature A: performing simulations irrespectively of performance tuning.
    """
    predecessor_node_lists, truth_tables = build_predecessor_nodes_lists_and_truth_tables(
        UPDATE_RULES_B)
    initial_state = [False, False, True, False, False, False]
    fixed_nodes = dict()
    perturbed_nodes_by_t = dict()
    max_t = 101
    initial_state_variations = []
    fixed_nodes_variations = []
    perturbed_nodes_by_t_variations = [(40, 0, NodeStateRange.MAYBE_TRUE)]
    n_simulation_problems = count_simulation_problems(
        initial_state_variations, fixed_nodes_variations,
        perturbed_nodes_by_t_variations)
    # Test for {single batch per process, multiple batches per process}.
    n_simulation_problem_batches_per_process_1 = 1
    n_simulation_problem_batches_per_process_2 = 5

    expected_simulation_states_1 = \
        [initial_state] + 25 * [[True, False, False, True, True, False],
                                [True, True, False, False, True, True],
                                [False, True, False, False, False, True],
                                [False, False, True, False, False, False]] + \
        [[True, False, False, True, True, False]]
    expected_simulation_1 = Simulation(expected_simulation_states_1, dict(),
                                       dict())
    expected_simulation_states_2 = \
        expected_simulation_states_1[:40] + [[True, False, True, False, False, False],
                                             [True, True, False, True, False, False]] + \
        60 * [[True, True, False, False, False, False]]
    expected_simulation_2 = Simulation(expected_simulation_states_2, dict(),
                                       {40: {
                                           0: True
                                       }})
    expected_simulations = [expected_simulation_1, expected_simulation_2]

    for n_simulation_problem_batches_per_process in [
            n_simulation_problem_batches_per_process_1,
            n_simulation_problem_batches_per_process_2
    ]:
        db_conn = ZODB.connection(None)
        init_simulation_db_structure(db_conn)
        simulate_master(MPICommWrapper(),
                        n_simulation_problem_batches_per_process,
                        (initial_state, fixed_nodes, perturbed_nodes_by_t),
                        (initial_state_variations, fixed_nodes_variations,
                         perturbed_nodes_by_t_variations),
                        predecessor_node_lists, truth_tables, max_t,
                        n_simulation_problems, db_conn, None)

        test_description = generate_test_description(
            locals(), 'n_simulation_problem_batches_per_process')
        assert list(db_conn.root.simulations.values()
                    ) == expected_simulations, test_description
        assert db_conn.root.n_simulations() == len(
            expected_simulations), test_description
示例#15
0
def test_simulate_until_max_t_or_attractor_or_target_substate_B():
    """
    `simulate_until_attractor_or_target_substate_or_max_t`
    Feature B: finding attractor at expected time step.
    """
    predecessor_nodes_lists, truth_tables = \
        build_predecessor_nodes_lists_and_truth_tables(UPDATE_RULES_B)
    initial_state = [False, False, False, False, False, False]
    perturbed_nodes_by_t = dict()
    # Test for {not storing all states, storing all states}.
    storing_all_states_1 = False
    storing_all_states_2 = True
    # Test for {no time cap, not reaching time cap, reaching time cap}.
    n_steps_before_max_t_1 = inf
    n_steps_before_max_t_2 = 1
    n_steps_before_max_t_3 = 0
    # Test for {no target substate, target substate}.
    target_node_set_1 = set()
    target_node_set_2 = {0, 1, 2, 3, 4, 5}

    expected_attractor_is_found = True
    expected_target_substate_is_reached = False

    for storing_all_states, n_steps_before_max_t, target_node_set in product(
        [storing_all_states_1, storing_all_states_2], [
            n_steps_before_max_t_1, n_steps_before_max_t_2,
            n_steps_before_max_t_3
        ], [target_node_set_1, target_node_set_2]):
        if storing_all_states:
            update_rules = UPDATE_RULES_B
            initial_state = [False, False, False, False, False, False]
            target_state = [True, True, False, False, True, False]
        else:
            update_rules = UPDATE_RULES_A
            initial_state = [False, True, True, False, False]
            target_state = [True, True, True, True, True]

        predecessor_nodes_lists, truth_tables = \
            build_predecessor_nodes_lists_and_truth_tables(update_rules)
        _encode_state = partial(encode_state, target_node_set)
        _, target_substate_code = _encode_state(target_state)
        target_substate_code = target_substate_code or None

        expected_t = 7 if storing_all_states else 11

        max_t = expected_t + n_steps_before_max_t
        _, _, t, attractor_is_found, target_substate_is_reached, _ = \
            simulate_until_attractor_or_target_substate_or_max_t(
                storing_all_states, max_t, _encode_state, target_substate_code, initial_state,
                perturbed_nodes_by_t, predecessor_nodes_lists, truth_tables)

        test_description = generate_test_description(locals(),
                                                     'storing_all_states',
                                                     'n_steps_before_max_t',
                                                     'target_node_set')
        assert expected_t == t, test_description
        assert expected_attractor_is_found == attractor_is_found, test_description
        assert expected_target_substate_is_reached == target_substate_is_reached, test_description
示例#16
0
def test_attract_master_A():
    """
    `attract_master`
    Feature A: finding attractors irrespectively of performance tuning.
    """
    predecessor_node_lists, truth_tables = build_predecessor_nodes_lists_and_truth_tables(
        UPDATE_RULES_A)
    initial_state = [False, False, False, False, False]
    max_t = inf
    max_attractor_l = inf
    initial_state_variations = [0, 1, 2, 3, 4]
    fixed_nodes_variations = []
    perturbed_nodes_by_t_variations = []
    fixed_nodes = {2: True}
    perturbed_nodes_by_t = {5: {2: True}, 1000: {2: False}}
    n_simulation_problems = count_simulation_problems(
        initial_state_variations, fixed_nodes_variations,
        perturbed_nodes_by_t_variations)
    # Test for {single batch per process, multiple batches per process}.
    n_simulation_problem_batches_per_process_1 = 1
    n_simulation_problem_batches_per_process_2 = 5
    # Test for {not storing all states, storing all states}.
    storing_all_states_1 = False
    storing_all_states_2 = True
    # Test for {not packing DB, packing DB}.
    packing_db_1 = False
    packing_db_2 = True

    expected_attractors = \
        {(-32, 23): construct_aggregated_attractor([[True, True, True, False, True]], 32, 1005, 0)}
    expected_total_frequency = sum(
        attractor.frequency for attractor in expected_attractors.values())

    for n_simulation_problem_batches_per_process, storing_all_states, packing_db in product(
        [
            n_simulation_problem_batches_per_process_1,
            n_simulation_problem_batches_per_process_2
        ], [storing_all_states_1, storing_all_states_2],
        [packing_db_1, packing_db_2]):
        db_conn = ZODB.connection(None)
        init_attractor_db_structure(db_conn)
        attract_master(MPICommWrapper(),
                       n_simulation_problem_batches_per_process,
                       (initial_state, fixed_nodes, perturbed_nodes_by_t),
                       (initial_state_variations, [], []),
                       predecessor_node_lists, truth_tables, max_t,
                       max_attractor_l, n_simulation_problems,
                       storing_all_states, db_conn, packing_db, None)

        test_description = generate_test_description(
            locals(), 'n_simulation_problem_batches_per_process',
            'storing_all_states')
        assert dict(db_conn.root.aggregated_attractors.items()) == expected_attractors, \
            test_description
        assert db_conn.root.n_aggregated_attractors() == len(
            expected_attractors), test_description
        assert db_conn.root.total_frequency(
        ) == expected_total_frequency, test_description
示例#17
0
def test_target_master_B():
    """
    `target_master`
    Feature B: finding no more than requested number of simulations
    reaching target state.
    """
    predecessor_node_lists, truth_tables = build_predecessor_nodes_lists_and_truth_tables(
        UPDATE_RULES_B)
    initial_state = [False, False, False, False, False, False]
    substate_node_set = {0, 1, 2, 3, 4, 5}
    _encode_state, _ = configure_encode_and_simulate(
        substate_node_set=substate_node_set)
    _, target_substate_code = _encode_state(
        [True, True, False, False, False, True])
    max_t = inf
    n_simulations_to_reach_target_substate = 1
    initial_state_variations = [0, 1, 2, 3, 4, 5]
    fixed_nodes_variations = []
    perturbed_nodes_by_t_variations = []
    fixed_nodes = {0: True, 1: True, 2: False, 3: False, 4: False, 5: True}
    perturbed_nodes_by_t = dict()
    n_simulation_problems = count_simulation_problems(
        initial_state_variations, fixed_nodes_variations,
        perturbed_nodes_by_t_variations)
    # Test for {single batch per process, multiple batches per process}.
    n_simulation_problem_batches_per_process_1 = 1
    n_simulation_problem_batches_per_process_2 = 5

    expected_simulations = [
        Simulation([initial_state] + [[True, True, False, False, False, True]],
                   fixed_nodes, perturbed_nodes_by_t)
    ]

    for n_simulation_problem_batches_per_process in [
            n_simulation_problem_batches_per_process_1,
            n_simulation_problem_batches_per_process_2
    ]:
        db_conn = ZODB.connection(None)
        init_simulation_db_structure(db_conn)
        target_master(MPICommWrapper(),
                      n_simulation_problem_batches_per_process,
                      (initial_state, fixed_nodes, perturbed_nodes_by_t),
                      (initial_state_variations, fixed_nodes_variations,
                       perturbed_nodes_by_t_variations), target_substate_code,
                      substate_node_set, predecessor_node_lists, truth_tables,
                      n_simulations_to_reach_target_substate, max_t,
                      n_simulation_problems, db_conn, None)

        test_description = generate_test_description(
            locals(), 'n_simulation_problem_batches_per_process')
        assert list(db_conn.root.simulations.values()
                    ) == expected_simulations, test_description
        assert db_conn.root.n_simulations() == len(
            expected_simulations), test_description
示例#18
0
def test_simulate_until_attractor_or_max_t_storing_all_states_A():
    """
    `simulate_until_attractor_or_max_t_storing_all_states`
    Feature A: finding attractor.
    """
    initial_state = [False, False, True, False, False, False]
    # Test for {no time cap, time cap}.
    max_t_1 = inf
    max_t_2 = 10
    # Test for {no length constraint, length constraint}.
    max_attractor_l_1 = inf
    max_attractor_l_2 = 10
    # Test for {no perturbations, perturbations}.
    perturbed_nodes_by_t_1 = dict()
    perturbed_nodes_by_t_2 = {1: {3: False}}

    attractor_states_1 = [[True, False, False, True, True, False],
                          [True, True, False, False, True, True],
                          [False, True, False, False, False, True],
                          [False, False, True, False, False, False]]
    attractor_states_2 = [[True, True, False, False, False, False]]
    expected_attractor_states_list = [attractor_states_1, attractor_states_2
                                      ] * 4
    expected_trajectory_l_list = [0, 6] * 4

    for (max_t, max_attractor_l, perturbed_nodes_by_t), \
        (expected_attractor_states, expected_trajectory_l) in zip(
            product([max_t_1, max_t_2],
                    [max_attractor_l_1, max_attractor_l_2],
                    [perturbed_nodes_by_t_1, perturbed_nodes_by_t_2]),
        zip(expected_attractor_states_list, expected_trajectory_l_list)):

        predecessor_node_lists, truth_tables = \
            build_predecessor_nodes_lists_and_truth_tables(UPDATE_RULES_B)
        _, _simulate_until_attractor_or_target_substate_or_max_t = \
                configure_encode_and_simulate(max_t=max_t)
        expected_attractor_state_codes = \
            [encode_state(set(), state)[0] for state in expected_attractor_states]
        expected_attractor_key = min(expected_attractor_state_codes)

        attractor_key, attractor_state_codes, attractor_states, trajectory_l = \
            simulate_until_attractor_or_max_t_storing_all_states(
                max_attractor_l, _simulate_until_attractor_or_target_substate_or_max_t,
                initial_state, perturbed_nodes_by_t, predecessor_node_lists, truth_tables)

        test_description = generate_test_description(locals(), 'max_t',
                                                     'max_attractor_l',
                                                     'perturbed_nodes_by_t')
        assert expected_attractor_key == attractor_key, test_description
        assert expected_attractor_state_codes == attractor_state_codes, test_description
        assert expected_attractor_states == attractor_states, test_description
        assert expected_trajectory_l == trajectory_l, test_description
def test_find_node_correlations_B():
    """
    `find_node_correlations`
    Feature B: calculating node correlations if sufficient attractors found.
    """
    # Test for {two attractors found, more than two attractors found}.
    aggregated_attractors_1 = {
        2: construct_aggregated_attractor(attractor_states_1, 1, 1, 0),
        3: construct_aggregated_attractor(attractor_states_2, 2, 2, 1)
    }
    aggregated_attractors_2 = {
        1: construct_aggregated_attractor(attractor_states_1, 10, 1, 0),
        8: construct_aggregated_attractor(attractor_states_2, 2, 2, 1),
        18: construct_aggregated_attractor(attractor_states_3, 20, 5, 4)
    }

    expected_Rhos = [
        np.array([[1, -1, np.nan, -1], [-1, 1, np.nan, 1],
                  [np.nan, np.nan, np.nan, np.nan], [-1, 1, np.nan, 1]]),
        np.array([[1, -0.77777778, np.nan, -0.49236596],
                  [-0.77777778, 1, np.nan, -0.16412199],
                  [np.nan, np.nan, np.nan, np.nan],
                  [-0.49236596, -0.16412199, np.nan, 1]])
    ]
    expected_Ps = [
        np.array([[0, 0, np.nan, 0], [0, 0, np.nan, 0],
                  [np.nan, np.nan, np.nan, np.nan], [0, 0, np.nan, 0]]),
        np.array([[0, 1.62331867e-07, np.nan, 4.20171535e-03],
                  [1.62331867e-07, 0, np.nan, 3.69407243e-01],
                  [np.nan, np.nan, np.nan, np.nan],
                  [4.20171535e-03, 3.69407243e-01, np.nan, 0]])
    ]
    for aggregated_attractors, (expected_Rho, expected_P) in zip(
        [aggregated_attractors_1, aggregated_attractors_2],
            zip(expected_Rhos, expected_Ps)):
        db_conn = ZODB.connection(None)
        init_attractor_db_structure(db_conn)
        for key, aggregated_attractor in aggregated_attractors.items():
            db_conn.root.aggregated_attractors[key] = aggregated_attractor
            db_conn.root.n_aggregated_attractors.change(1)
            db_conn.root.total_frequency.change(aggregated_attractor.frequency)

        Rho, P = find_node_correlations(db_conn, None, True)

        test_description = generate_test_description(locals(),
                                                     'aggregated_attractors')
        assert np.allclose(expected_Rho, Rho, equal_nan=True), test_description
        assert np.allclose(expected_P, P, equal_nan=True), test_description
示例#20
0
def test_simulate_until_max_t_or_attractor_or_target_substate_D():
    """
     `simulate_until_attractor_or_target_substate_or_max_t`
    Feature D: simulating expected states.
    """
    predecessor_nodes_lists, truth_tables = build_predecessor_nodes_lists_and_truth_tables(
        UPDATE_RULES_A)
    initial_state = [False, True, True, False, False]
    max_t = 1
    target_node_set = set()
    _encode_state = partial(encode_state, target_node_set)
    target_substate_code = None
    # Test for {not storing all states, storing all states}.
    storing_all_states_1 = False
    storing_all_states_2 = True
    # Test for {stopping at last perturbation, stopping not at last
    # perturbation}.
    perturbed_nodes_by_t_1 = {1: {1: True}}
    perturbed_nodes_by_t_2 = dict()

    for storing_all_states, perturbed_nodes_by_t in product(
        [storing_all_states_1, storing_all_states_2],
        [perturbed_nodes_by_t_1, perturbed_nodes_by_t_2]):
        expected_last_state = [
            False, bool(perturbed_nodes_by_t), True, False, True
        ]
        expected_states = [initial_state, expected_last_state]
        expected_state_codes_since_last_perturbation = \
            [_encode_state(state)[0]
             for state in expected_states[int(bool(perturbed_nodes_by_t)):]]
        if storing_all_states:
            expected_attractor_reference_points = None
        elif not perturbed_nodes_by_t:
            expected_states.insert(1, None)
            expected_state_codes_since_last_perturbation.insert(1, None)

        states, state_codes_since_last_perturbation, *_ = \
            simulate_until_attractor_or_target_substate_or_max_t(
                storing_all_states, max_t, _encode_state, target_substate_code, initial_state,
                perturbed_nodes_by_t, predecessor_nodes_lists, truth_tables)

        test_description = generate_test_description(locals(),
                                                     'storing_all_states',
                                                     'perturbed_nodes_by_t')
        assert expected_states == states, test_description
        assert expected_state_codes_since_last_perturbation == state_codes_since_last_perturbation, \
            test_description
示例#21
0
def test_simulate_until_target_substate_or_max_t_B():
    """
    `simulate_until_target_substate_or_max_t`
    Feature B: finding target substate that is part of attractor.
    """
    predecessor_node_lists, truth_tables = \
        build_predecessor_nodes_lists_and_truth_tables(UPDATE_RULES_B)
    initial_state = [False, False, False, False, False, False]
    substate_node_set = {0, 1, 2, 3, 4, 5}
    _encode_state, _ = configure_encode_and_simulate(
        substate_node_set=substate_node_set)
    _, target_substate_code = _encode_state(
        [True, True, False, False, False, False])
    # Test for {no time cap, time cap}.
    max_t_1 = inf
    max_t_2 = 10
    # Test for {no perturbations, perturbations}.
    perturbed_nodes_by_t_1 = dict()
    perturbed_nodes_by_t_2 = {1: {3: False}}

    expected_simulation_states = [initial_state] + [[
        True, False, False, False, True, False
    ], [True, True, False, False, False, True
        ], [False, True, False, False, False, False
            ], [True, False, True, False, False, False
                ], [True, True, False, True, False, False
                    ], [True, True, False, False, False, False]]

    for max_t, perturbed_nodes_by_t in product(
        [max_t_1, max_t_2], [perturbed_nodes_by_t_1, perturbed_nodes_by_t_2]):
        _, _simulate_until_attractor_or_target_substate_or_max_t = \
            configure_encode_and_simulate(max_t=max_t, substate_node_set=substate_node_set,
                                          target_substate_code=target_substate_code)

        simulation_states = simulate_until_target_substate_or_max_t(
            _simulate_until_attractor_or_target_substate_or_max_t,
            initial_state, perturbed_nodes_by_t, predecessor_node_lists,
            truth_tables)

        test_description = generate_test_description(locals(), 'max_t',
                                                     'perturbed_nodes_by_t')
        assert expected_simulation_states == simulation_states
示例#22
0
def test_simulate_until_max_t_or_attractor_or_target_substate_H():
    """
    `simulate_until_attractor_or_target_substate_or_max_t`
    Feature H: storing expected reference points when looking for
    attractors.
    """
    perturbed_nodes_by_t = dict()
    max_t = inf
    target_node_set = set()
    _encode_state = partial(encode_state, target_node_set)
    target_substate_code = None
    storing_all_states = False
    # Test for {attractor detected at a reference point, attractor
    # detected not at a reference point}.
    update_rules_1 = UPDATE_RULES_A
    initial_state_1 = [True, True, True, True, True]
    expected_attractor_reference_points_dict_1 = \
        {0: initial_state_1, 3: [True, False, True, False, True],
         6: [True, True, True, False, False]}
    update_rules_2 = {'A': 'A'}
    initial_state_2 = [False]
    expected_attractor_reference_points_dict_2 = {0: initial_state_2}

    for update_rules, initial_state, expected_attractor_reference_points_dict in zip(
        [update_rules_1, update_rules_2], [initial_state_1, initial_state_2], [
            expected_attractor_reference_points_dict_1,
            expected_attractor_reference_points_dict_2
        ]):
        expected_attractor_reference_points = \
            [(t, state, _encode_state(state)[0])
             for t, state in sorted(expected_attractor_reference_points_dict.items())]

        predecessor_nodes_lists, truth_tables = \
            build_predecessor_nodes_lists_and_truth_tables(update_rules)
        *_, attractor_reference_points = simulate_until_attractor_or_target_substate_or_max_t(
            storing_all_states, max_t, _encode_state, target_substate_code,
            initial_state, perturbed_nodes_by_t, predecessor_nodes_lists,
            truth_tables)

        test_description = generate_test_description(locals(), 'update_rules',
                                                     'initial_state')
        assert expected_attractor_reference_points == attractor_reference_points, test_description
示例#23
0
def test_count_simulation_problem_batches_A():
    """
    `count_simulation_problem_batches`
    Feature A: counting simulation problem batches to be generated.
    """
    n_simulation_problems = 100
    n_chunks = 10
    # Test for {no zero-sized batches, zero-sized batches}.
    batches_per_chunk_1 = 10
    batches_per_chunk_2 = 11

    expected_n_simulation_problem_batches = 100

    for batches_per_chunk in [batches_per_chunk_1, batches_per_chunk_2]:
        n_simulation_problem_batches = count_simulation_problem_batches(
            n_chunks, n_simulation_problems, batches_per_chunk)

        test_description = generate_test_description(locals(),
                                                     'batches_per_chunk')
        assert expected_n_simulation_problem_batches == n_simulation_problem_batches
示例#24
0
def test_majority_A():
    """
    `majority`
    Feature A: evaluating output correctly.
    """
    arguments_1 = [False, True, False]
    arguments_2 = [False, True, True]
    arguments_3 = [False, True]

    expected_outcome_1 = False
    expected_outcome_2 = True
    expected_outcome_3 = False

    for arguments, expected_outcome in zip(
        [arguments_1, arguments_2, arguments_3],
        [expected_outcome_1, expected_outcome_2, expected_outcome_3]):
        outcome = majority(*arguments)

        test_description = generate_test_description(locals(), 'arguments')
        assert expected_outcome == outcome, test_description
示例#25
0
def test_convert_number_to_variational_representation_A():
    """
    `convert_number_to_variational_representation()`
    Feature A: decomposing number into multibase representation.
    COMPLETE.
    """
    # Test for {bases of 2 only, bases of 3 only, mixed bases}.
    number_1 = 10
    decomposition_bases_1 = [2, 2, 2, 2]
    decomposition_place_values_1 = [1, 2, 4, 8]
    number_2 = 41
    decomposition_bases_2 = [3, 3, 3, 3]
    decomposition_place_values_2 = [1, 3, 9, 27]
    number_3 = 30
    decomposition_bases_3 = [2, 3, 2, 3]
    decomposition_place_values_3 = [1, 2, 6, 12]

    expected_decomposition_1 = [0, 1, 0, 1]
    expected_decomposition_2 = [2, 1, 1, 1]
    expected_decomposition_3 = [0, 0, 1, 2]

    for number, decomposition_bases, decomposition_place_values, expected_decomposition in zip(
        [number_1, number_2, number_3],
        [decomposition_bases_1, decomposition_bases_2, decomposition_bases_3],
        [
            decomposition_place_values_1, decomposition_place_values_2,
            decomposition_place_values_3
        ], [
            expected_decomposition_1, expected_decomposition_2,
            expected_decomposition_3
        ]):

        decomposition = convert_number_to_variational_representation(
            number, decomposition_bases, decomposition_place_values)

        test_description = generate_test_description(
            locals(), 'number', 'decomposition_bases',
            'decomposition_place_values')
        assert expected_decomposition == decomposition, test_description
示例#26
0
def test_add_variational_representations_A():
    """
    `add_variational_representations`
    Feature A: adding two multibase representations.
    """
    first_decomposition = [1, 0, 1]
    # Test for {bases of 2 only, bases of 3 only, mixed bases}.
    bases_1 = [2] * 3
    bases_2 = [3] * 3
    bases_3 = [3] * 2 + [2] * 1
    # Test for {no overflows, overflows but not in the most
    # significant digit, overflow in the most significant digit}.
    digit_to_increase_1 = 1
    digit_to_increase_2 = 2
    digit_to_increase_3 = 0

    for bases, digit_to_increase in product(
        [bases_1, bases_2, bases_3],
        [digit_to_increase_1, digit_to_increase_2, digit_to_increase_3]):
        digit_increase = bases[digit_to_increase] - 1
        second_decomposition = \
            [digit_increase if digit == digit_to_increase else 0 for digit in range(3)]

        expected_decomposition = first_decomposition.copy()
        overflow, expected_decomposition[digit_to_increase] = divmod(
            digit_increase + first_decomposition[digit_to_increase],
            bases[digit_to_increase])
        if overflow > 0 and digit_to_increase < 2:
            expected_decomposition[digit_to_increase + 1] = overflow

        decomposition = add_variational_representations(
            first_decomposition, second_decomposition, bases)

        test_description = generate_test_description(locals(), 'bases',
                                                     'second_decomposition')
        assert expected_decomposition == decomposition, test_description
示例#27
0
def test_simulate_until_max_t_or_attractor_or_target_substate_A():
    """
    `simulate_until_attractor_or_target_substate_or_max_t`
    Feature A: stopping at the time cap.
    """
    predecessor_nodes_lists, truth_tables = \
        build_predecessor_nodes_lists_and_truth_tables(UPDATE_RULES_B)
    initial_state = [False, False, False, False, False, False]
    perturbed_nodes_by_t = dict()
    max_t = 6
    # Test for {not storing all states, storing all states}.
    storing_all_states_1 = False
    storing_all_states_2 = True
    # Test for {no target substate, target substate}.
    target_node_set_1 = set()
    target_node_set_2 = {0, 1, 2, 3, 4, 5}

    expected_t = 6

    for storing_all_states, target_node_set in product(
        [storing_all_states_1, storing_all_states_2],
        [target_node_set_1, target_node_set_2]):
        _encode_state = partial(encode_state, target_node_set)
        _, target_substate_code = _encode_state(
            [True, True, True, True, True, True])
        target_substate_code = target_substate_code or None

        _, _, t, *_ = simulate_until_attractor_or_target_substate_or_max_t(
            storing_all_states, max_t, _encode_state, target_substate_code,
            initial_state, perturbed_nodes_by_t, predecessor_nodes_lists,
            truth_tables)

        test_description = generate_test_description(locals(),
                                                     'storing_all_states',
                                                     'target_node_set')
        assert expected_t == t, test_description
示例#28
0
def test_output_node_correlations_A():
    """
    `output_node_correlations`
    Feature A: successful output.
    """
    output_dirpath = "Test output of node correlations"
    n_nodes = 10
    node_names = [('${}$' if i % 2 else '{}').format('node{}'.format(i))
                  for i in range(n_nodes)]
    p_value = 0.05
    # Test for {no single repeated averaged node states, single
    # repeated averaged node states}.
    repeated_state_nodes_1 = []
    repeated_state_nodes_2 = [5]
    # Test for {valid p-values, insufficient frequencies for valid
    # p-values}.
    invalid_p_value_nodes_1 = []
    invalid_p_value_nodes_2 = [7]
    # Test for {no PDF format, PDF format}.
    to_pdf_1 = False
    to_pdf_2 = True
    # Test for {no image formats, all image formats}.
    image_formats_and_dpis_1 = []
    image_formats_and_dpis_2 = [('svg', None), ('png', 300), ('tiff', 150)]
    # Test for {no CSV format, CSV format}.
    to_csv_1 = False
    to_csv_2 = True

    for repeated_state_nodes, invalid_p_value_nodes in product(
        [repeated_state_nodes_1, repeated_state_nodes_2],
        [invalid_p_value_nodes_1, invalid_p_value_nodes_2]):
        Rho = np.random.uniform(low=-1, high=1, size=(n_nodes, n_nodes))
        P = np.random.uniform(low=0, high=1, size=(n_nodes, n_nodes))
        Rho[np.diag_indices_from(Rho)] = 1
        P[np.diag_indices_from(P)] = 0
        Rho = np.tril(Rho) + np.tril(Rho, -1).T
        P = np.tril(P) + np.tril(P, -1).T
        for i in repeated_state_nodes:
            Rho[i, :].fill(np.nan)
            Rho[:, i].fill(np.nan)
        for i in invalid_p_value_nodes:
            P[i, :].fill(np.nan)
            P[:, i].fill(np.nan)
            Rho[i, :].fill(np.nan)
            Rho[:, i].fill(np.nan)

        for to_pdf, image_formats_and_dpis, to_csv in product(
            [to_pdf_1, to_pdf_2],
            [image_formats_and_dpis_1, image_formats_and_dpis_2],
            [to_csv_1, to_csv_2]):

            if not to_pdf and not image_formats_and_dpis and not to_csv:
                continue

            os.makedirs(output_dirpath, exist_ok=True)
            test_description = generate_test_description(
                locals(), 'repeated_state_nodes', 'invalid_p_value_nodes',
                'to_pdf', 'image_formats_and_dpis', 'to_csv')
            try:
                output_node_correlations(Rho, P, p_value, node_names,
                                         output_dirpath, to_pdf,
                                         image_formats_and_dpis, to_csv)
            except Exception as e:
                pytest.fail(test_description)
            finally:
                shutil.rmtree(output_dirpath)
示例#29
0
def test_output_attractors_A():
    """
    `output_attractors`
    Feature A: successful output.
    """
    output_dirpath = "Test output of attractors"
    pdf_page_limit = 1
    is_single_process = True
    packing_db = False
    # Test for {horizontal layout, stacked layout}.
    n_nodes_1 = 2
    n_nodes_2 = 40
    # Test for {no fixed nodes, fixed nodes}.
    fixed_nodes_1 = dict()
    fixed_nodes_2 = {0: False}
    # Test for {attractor found for every simulation problem,
    # attractor not found for some simulation problems}.
    n_simulation_problems_1 = 3
    n_simulation_problems_2 = 4
    # Test for {no time cap, time cap}.
    max_t_1 = inf
    max_t_2 = 10
    # Test for {no attractor length cap, attractor length cap}.
    max_attractor_l_1 = inf
    max_attractor_l_2 = 10
    # Test for {single aggregated attractor batch, multiple
    # aggregated attractor batches}.
    aggregated_attractor_batch_indices_1 = [1, 1]
    aggregated_attractor_batch_indices_2 = [1, 2]
    # Test for {no PDF format, PDF format}.
    to_pdf_1 = False
    to_pdf_2 = True
    # Test for {no image formats, all image formats}.
    image_formats_and_dpis_1 = []
    image_formats_and_dpis_2 = [('svg', None), ('png', 300), ('tiff', 150)]
    # Test for {no CSV format, CSV format}.
    to_csv_1 = False
    to_csv_2 = True

    for n_nodes, fixed_nodes, n_simulation_problems, max_t, max_attractor_l, \
        aggregated_attractor_batch_indices in product(
        [n_nodes_1, n_nodes_2], [fixed_nodes_1, fixed_nodes_2],
        [n_simulation_problems_1, n_simulation_problems_2], [max_t_1, max_t_2],
        [max_attractor_l_1, max_attractor_l_2],
        [aggregated_attractor_batch_indices_1, aggregated_attractor_batch_indices_2]):

        if n_simulation_problems > 3 and max_t == inf and max_attractor_l == inf:
            continue

        node_names = [('${}$' if i % 2 else '{}').format('node{}'.format(i))
                      for i in range(n_nodes)]
        # Fill in attractor database.
        db_conn = ZODB.connection(None)
        init_attractor_db_structure(db_conn)
        aggregated_attractor_1 = construct_aggregated_attractor(
            [[False] * n_nodes], 1, 1, 0)
        aggregated_attractor_2 = construct_aggregated_attractor(
            [[True] * n_nodes] * 2, 2, 1.5, .5)

        for i, (aggregated_attractor_batch_index,
                aggregated_attractor) in enumerate(
                    zip(aggregated_attractor_batch_indices,
                        [aggregated_attractor_1, aggregated_attractor_2])):
            aggregated_attractor_key = i + 1
            aggregated_attractors = {
                aggregated_attractor_key: aggregated_attractor
            }
            write_aggregated_attractors_to_db(
                packing_db, db_conn, aggregated_attractors,
                aggregated_attractor_batch_index)

        for to_pdf, image_formats_and_dpis, to_csv in product(
            [to_pdf_1, to_pdf_2],
            [image_formats_and_dpis_1, image_formats_and_dpis_2],
            [to_csv_1, to_csv_2]):

            if not to_pdf and not image_formats_and_dpis and not to_csv:
                continue

            os.makedirs(output_dirpath, exist_ok=True)
            test_description = generate_test_description(
                locals(), 'n_nodes', 'fixed_nodes', 'n_simulation_problems',
                'max_t', 'max_attractor_l',
                'aggregated_attractor_batch_indices', 'to_pdf',
                'image_formats_and_dpis', 'to_csv')
            try:
                output_attractors(db_conn, fixed_nodes, node_names,
                                  n_simulation_problems, max_attractor_l,
                                  max_t, output_dirpath, is_single_process,
                                  to_pdf, pdf_page_limit,
                                  image_formats_and_dpis, to_csv)
            except:
                pytest.fail(test_description)
            finally:
                shutil.rmtree(output_dirpath)
示例#30
0
def test_output_simulations_A():
    """
    `output_simulations`
    Feature A: successful output.
    """
    output_dirpath = "Test output of simulations"
    pdf_page_limit = 1
    is_single_process = True
    # Test for {horizontal layout, stacked layout}.
    n_nodes_1 = 2
    n_nodes_2 = 40
    # Test for {no fixed nodes, fixed nodes}.
    fixed_nodes_1 = dict()
    fixed_nodes_2 = {0: False}
    # Test for {no perturbations, perturbations}.
    perturbed_nodes_by_t_1 = dict()
    perturbed_nodes_by_t_2 = {1: {0: True}, 2: {0: False}}
    # Test for {single simulation batch, multiple simulation batches}.
    simulation_cutoff_index_for_batches_1 = 1
    simulation_cutoff_index_for_batches_2 = 2
    # Test for {no PDF format, PDF format}.
    to_pdf_1 = False
    to_pdf_2 = True
    # Test for {no image formats, all image formats}.
    image_formats_and_dpis_1 = []
    image_formats_and_dpis_2 = [('svg', None), ('png', 300), ('tiff', 150)]
    # Test for {no CSV format, CSV format}.
    to_csv_1 = False
    to_csv_2 = True

    for n_nodes, fixed_nodes, perturbed_nodes_by_t, simulation_cutoff_index_for_batches in product(
        [n_nodes_1, n_nodes_2], [fixed_nodes_1, fixed_nodes_2],
        [perturbed_nodes_by_t_1, perturbed_nodes_by_t_2], [
            simulation_cutoff_index_for_batches_1,
            simulation_cutoff_index_for_batches_2
        ]):

        node_names = [('${}$' if i % 2 else '{}').format('node{}'.format(i))
                      for i in range(n_nodes)]
        # Fill in simulation database.
        db_conn = ZODB.connection(None)
        init_simulation_db_structure(db_conn)
        simulation_1 = Simulation([[False] * n_nodes], fixed_nodes,
                                  perturbed_nodes_by_t)
        simulation_2 = Simulation([[True] * n_nodes] * 2, fixed_nodes,
                                  perturbed_nodes_by_t)
        simulations = [simulation_1, simulation_2]
        simulation_batch_1 = simulations[:simulation_cutoff_index_for_batches]
        simulation_batch_2 = simulations[simulation_cutoff_index_for_batches:]

        for simulation_batch_index, simulation_batch in enumerate(
            [simulation_batch_1, simulation_batch_2]):
            write_simulations_to_db(db_conn, simulation_batch,
                                    simulation_batch_index)

        for to_pdf, image_formats_and_dpis, to_csv in product(
            [to_pdf_1, to_pdf_2],
            [image_formats_and_dpis_1, image_formats_and_dpis_2],
            [to_csv_1, to_csv_2]):

            if not to_pdf and not image_formats_and_dpis and not to_csv:
                continue

            os.makedirs(output_dirpath, exist_ok=True)
            test_description = generate_test_description(
                locals(), 'n_nodes', 'fixed_nodes', 'perturbed_nodes_by_t',
                'simulation_cutoff_index_for_batches', 'to_pdf',
                'image_formats_and_dpis', 'to_csv')
            try:
                output_simulations(db_conn, node_names, output_dirpath,
                                   is_single_process, to_pdf, pdf_page_limit,
                                   image_formats_and_dpis, to_csv)
            except:
                pytest.fail(test_description)
            finally:
                shutil.rmtree(output_dirpath)