예제 #1
0
def __get_response_transition() -> Factor:
    color = Factor("color", ["red", "blue", "green"])
    motion = Factor("motion", ["up", "down"])
    task = Factor("task", ["color", "motion"])

    # Response Definition
    def response_left(task, color, motion):
        return (task == "color"  and color  == "red") or \
            (task == "motion" and motion == "up")

    def response_right(task, color, motion):
        return not response_left(task, color, motion)

    response = Factor("response", [
        DerivedLevel("left", WithinTrial(response_left,
                                         [task, color, motion])),
        DerivedLevel("right", WithinTrial(response_right,
                                          [task, color, motion]))
    ])

    return Factor("response transition", [
        DerivedLevel(
            "repeat",
            Transition(lambda responses: responses[0] == responses[1],
                       [response])),
        DerivedLevel(
            "switch",
            Transition(lambda responses: responses[0] != responses[1],
                       [response]))
    ])
예제 #2
0
def test_fully_cross_block_crossing_size_with_overlapping_exclude():
    # How about with two overlapping exclude constraints? Initial crossing size
    # should be 3 x 3 = 9.
    # Excluding congruent pairs will reduce that to 9 - 3 = 6
    # Then excluding red and green on top of that should make it 5.
    color = Factor("color", ["red", "blue", "green"])
    text = Factor("text", ["red", "blue", "green"])

    congruent_factor = Factor("congruent?", [
        DerivedLevel("congruent", WithinTrial(op.eq, [color, text])),
        DerivedLevel("incongruent", WithinTrial(op.ne, [color, text])),
    ])

    def illegal(color, text):
        return (color == "red" and text == "green") or color == text

    def legal(color, text):
        return not illegal(color, text)

    legal_factor = Factor("legal", [
        DerivedLevel("yes", WithinTrial(legal, [color, text])),
        DerivedLevel("no", WithinTrial(illegal, [color, text]))
    ])

    assert FullyCrossBlock(
        [color, text, congruent_factor, legal_factor],
        [[color, text]],
        [
            Exclude(congruent_factor,
                    get_level_from_name(congruent_factor,
                                        "congruent")),  # Excludes 3
            Exclude(legal_factor, get_level_from_name(legal_factor, "no"))
        ],  # Exludes 4, but 3 were already excluded
        require_complete_crossing=False).crossing_size() == 5
예제 #3
0
def test_generate_encoding_diagram_with_window_with_stride():
    congruent_bookend = Factor("congruent bookend?", [
        DerivedLevel("yes", Window(lambda colors, texts: colors[0] == texts[0], [color, text], 1, 3)),
        DerivedLevel("no",  Window(lambda colors, texts: colors[0] != texts[0], [color, text], 1, 3))
    ])

    block = fully_cross_block([color, text, congruent_bookend], [color, text], [])

    assert __generate_encoding_diagram(block) == "\
------------------------------------------------------\n\
|   Trial |  color   |   text   | congruent bookend? |\n\
|       # | red blue | red blue |    yes       no    |\n\
------------------------------------------------------\n\
|       1 |  1   2   |  3   4   |    17        18    |\n\
|       2 |  5   6   |  7   8   |                    |\n\
|       3 |  9   10  | 11   12  |                    |\n\
|       4 | 13   14  | 15   16  |    19        20    |\n\
------------------------------------------------------\n"

    congruent_bookend = Factor("congruent bookend?", [
        DerivedLevel("yes", Window(lambda colors, texts: colors[0] == texts[0], [color, text], 2, 2)),
        DerivedLevel("no",  Window(lambda colors, texts: colors[0] != texts[0], [color, text], 2, 2))
    ])

    block = fully_cross_block([color, text, congruent_bookend], [color, text], [])

    assert __generate_encoding_diagram(block) == "\
예제 #4
0
def test_consistency_with_transition_first_and_uneven_level_lengths():
    color3 = Factor("color3", ["red", "blue", "green"])

    yes_fn = lambda colors: colors[0] == colors[1] == colors[2]
    no_fn = lambda colors: not yes_fn(colors)
    color3_repeats_factor = Factor("color3 repeats?", [
        DerivedLevel("yes", Window(yes_fn, [color3], 3, 1)),
        DerivedLevel("no", Window(no_fn, [color3], 3, 1))
    ])

    block = fully_cross_block([color3_repeats_factor, color3, text],
                              [color3, text], [])

    backend_request = BackendRequest(0)
    Consistency.apply(block, backend_request)

    assert backend_request.ll_requests == [
        LowLevelRequest("EQ", 1, [1, 2, 3]),
        LowLevelRequest("EQ", 1, [4, 5]),
        LowLevelRequest("EQ", 1, [6, 7, 8]),
        LowLevelRequest("EQ", 1, [9, 10]),
        LowLevelRequest("EQ", 1, [11, 12, 13]),
        LowLevelRequest("EQ", 1, [14, 15]),
        LowLevelRequest("EQ", 1, [16, 17, 18]),
        LowLevelRequest("EQ", 1, [19, 20]),
        LowLevelRequest("EQ", 1, [21, 22, 23]),
        LowLevelRequest("EQ", 1, [24, 25]),
        LowLevelRequest("EQ", 1, [26, 27, 28]),
        LowLevelRequest("EQ", 1, [29, 30]),
        LowLevelRequest("EQ", 1, [31, 32]),
        LowLevelRequest("EQ", 1, [33, 34]),
        LowLevelRequest("EQ", 1, [35, 36]),
        LowLevelRequest("EQ", 1, [37, 38])
    ]
예제 #5
0
def test_consistency():
    # From standard example
    # [ LowLevelRequest("EQ", 1, [1, 2]), LowLevelRequest("EQ", 1, [3, 4]), ...]
    backend_request = BackendRequest(0)

    Consistency.apply(block, backend_request)
    assert backend_request.ll_requests == \
        list(map(lambda x: LowLevelRequest("EQ", 1, [x, x+1]), range(1, 24, 2)))

    # Different case
    backend_request = BackendRequest(0)
    f = Factor("a", ["b", "c", "d", "e"])
    f_block = fully_cross_block([f], [f], [])

    Consistency.apply(f_block, backend_request)
    assert backend_request.ll_requests == \
        list(map(lambda x: LowLevelRequest("EQ", 1, [x, x+1, x+2, x+3]), range(1, 16, 4)))

    # Varied level lengths
    backend_request = BackendRequest(0)
    f1 = Factor("a", ["b", "c", "d"])
    f2 = Factor("e", ["f"])
    f_block = fully_cross_block([f1, f2], [f1, f2], [])

    Consistency.apply(f_block, backend_request)
    assert backend_request.ll_requests == [
        LowLevelRequest("EQ", 1, [1, 2, 3]),
        LowLevelRequest("EQ", 1, [4]),
        LowLevelRequest("EQ", 1, [5, 6, 7]),
        LowLevelRequest("EQ", 1, [8]),
        LowLevelRequest("EQ", 1, [9, 10, 11]),
        LowLevelRequest("EQ", 1, [12])
    ]
def test_generate_derivations_within_trial():
    assert DerivationProcessor.generate_derivations(blk) == [
        Derivation(4, [[0, 2], [1, 3]], con_factor),
        Derivation(5, [[0, 3], [1, 2]], con_factor)
    ]

    integer = Factor("integer", ["1", "2"])
    numeral = Factor("numeral", ["I", "II"])
    text = Factor("text", ["one", "two"])

    twoConLevel = DerivedLevel("twoCon",
                               WithinTrial(two_con, [integer, numeral, text]))
    twoNotConLevel = DerivedLevel(
        "twoNotCon", WithinTrial(two_not_con, [integer, numeral, text]))
    two_con_factor = Factor("twoCon?", [twoConLevel, twoNotConLevel])

    one_two_design = [integer, numeral, text, two_con_factor]
    one_two_crossing = [integer, numeral, text]

    assert DerivationProcessor.generate_derivations(
        fully_cross_block(one_two_design, one_two_crossing, [])) == [
            Derivation(6,
                       [[0, 2, 5], [0, 3, 4], [0, 3, 5], [1, 2, 4], [1, 2, 5],
                        [1, 3, 4]], two_con_factor),
            Derivation(7, [[0, 2, 4], [1, 3, 5]], two_con_factor)
        ]
예제 #7
0
def test_exclude_with_three_derived_levels():
    color_list = ["red", "green", "blue"]
    color = Factor("color", color_list)
    text = Factor("text", color_list)

    def count_diff(colors, texts):
        changes = 0
        if (colors[0] != colors[1]): changes += 1
        if (texts[0] != texts[1]): changes += 1
        return changes

    def make_k_diff_level(k):
        def k_diff(colors, texts):
            return count_diff(colors, texts) == k

        return DerivedLevel(str(k), Transition(k_diff, [color, text]))

    changed = Factor(
        "changed",
        [make_k_diff_level(0),
         make_k_diff_level(1),
         make_k_diff_level(2)])

    exclude_constraint = Exclude(changed, get_level_from_name(changed, "2"))

    design = [color, text, changed]
    crossing = [color, text]
    block = fully_cross_block(design, crossing, [exclude_constraint])

    backend_request = BackendRequest(0)
    exclude_constraint.apply(block, backend_request)
    assert backend_request.cnfs == [
        And([-57, -60, -63, -66, -69, -72, -75, -78])
    ]
예제 #8
0
def __build_stroop_block(color_count):
    color = Factor("color", color_list[:color_count])
    text = Factor("text", color_list[:color_count])

    congruent = Factor("congruent?", [
        DerivedLevel("yes", WithinTrial(op.eq, [color, text])),
        DerivedLevel("no",  WithinTrial(op.ne, [color, text]))
    ])

    constraints = [AtMostKInARow(1, ("congruent?", "yes"))]

    return fully_cross_block([color, text, congruent], [color, text], constraints)
예제 #9
0
def test_generate_encoding_diagram_with_windows():
    color3 = Factor("color3", ["red", "blue", "green"])

    yes_fn = lambda colors: colors[0] == colors[1] == colors[2]
    no_fn = lambda colors: not yes_fn(colors)
    color3_repeats_factor = Factor("color3 repeats?", [
        DerivedLevel("yes", Window(yes_fn, [color3], 3, 1)),
        DerivedLevel("no",  Window(no_fn, [color3], 3, 1))
    ])

    block = fully_cross_block([color3_repeats_factor, color3, text], [color3, text], [])

    assert __generate_encoding_diagram(block) == "\
def test_generate_sample_basic_stroop_uneven_colors(sequence_number, expected_solution):
    text = Factor("text", ["red", "blue", "green"])
    congruency = Factor("congruency", [
        DerivedLevel("congruent",   WithinTrial(op.eq, [color, text])),
        DerivedLevel("incongruent", WithinTrial(op.ne, [color, text]))
    ])

    block = fully_cross_block([color, text, congruency],
                              [color, congruency],
                              [])
    enumerator = UCSolutionEnumerator(block)
    print(enumerator.generate_sample(sequence_number))
    assert enumerator.generate_sample(sequence_number) == expected_solution
예제 #11
0
def test_decode():
    solution = [-1,   2,  -3,   4,   5,  -6,
                -7,   8,   9, -10, -11,  12,
                13, -14, -15,  16, -17,  18,
                19, -20,  21, -22,  23, -24]
    shuffle(solution)

    assert SamplingStrategy.decode(blk, solution) == {
        'color':      ['blue', 'blue', 'red',  'red'],
        'text':       ['blue', 'red',  'blue', 'red'],
        'congruent?': ['con',  'inc',  'inc',  'con']
    }

    solution = [ -1,   2, -3,   4,   5,  -6,
                  7,  -8, -9,  10, -11,  12,
                 13, -14, 15, -16,  17, -18,
                -19,  20, 21, -22, -23,  24]
    shuffle(solution)

    assert SamplingStrategy.decode(blk, solution) == {
        'color':      ['blue', 'red',  'red', 'blue'],
        'text':       ['blue', 'blue', 'red', 'red'],
        'congruent?': ['con',  'inc',  'con', 'inc']
    }

    solution = [-1,   2,   3,  -4,  -5,   6,
                -7,   8,  -9,  10,  11, -12,
                13, -14,  15, -16,  17, -18,
                19, -20, -21,  22, -23,  24]
    shuffle(solution)

    assert SamplingStrategy.decode(blk, solution) == {
        'color':      ['blue', 'blue', 'red', 'red'],
        'text':       ['red',  'blue', 'red', 'blue'],
        'congruent?': ['inc',  'con',  'con', 'inc']
    }

    f1 = Factor("a", ["b", "c", "d"])
    f2 = Factor("e", ["f"])
    f_blk = fully_cross_block([f1, f2], [f1, f2], [])
    solution = [-1,   2,  -3, 4,
                -5,  -6,   7, 8,
                 9, -10  -11, 12]
    shuffle(solution)

    assert SamplingStrategy.decode(f_blk, solution) == {
        'a': ['c', 'd', 'b'],
        'e': ['f', 'f', 'f']
    }
예제 #12
0
def test_fully_cross_with_uncrossed_simple_factors():
    other = Factor('other', ['l1', 'l2'])
    block = fully_cross_block([color, text, other], [color, text], [])

    backend_request = BackendRequest(25)
    FullyCross.apply(block, backend_request)

    (expected_cnf, _) = to_cnf_tseitin(
        And([
            Iff(25, And([1, 3])),
            Iff(26, And([1, 4])),
            Iff(27, And([2, 3])),
            Iff(28, And([2, 4])),
            Iff(29, And([7, 9])),
            Iff(30, And([7, 10])),
            Iff(31, And([8, 9])),
            Iff(32, And([8, 10])),
            Iff(33, And([13, 15])),
            Iff(34, And([13, 16])),
            Iff(35, And([14, 15])),
            Iff(36, And([14, 16])),
            Iff(37, And([19, 21])),
            Iff(38, And([19, 22])),
            Iff(39, And([20, 21])),
            Iff(40, And([20, 22]))
        ]), 41)

    assert backend_request.fresh == 74
    assert backend_request.cnfs == [expected_cnf]
    assert backend_request.ll_requests == [
        LowLevelRequest("GT", 0, [25, 29, 33, 37]),
        LowLevelRequest("GT", 0, [26, 30, 34, 38]),
        LowLevelRequest("GT", 0, [27, 31, 35, 39]),
        LowLevelRequest("GT", 0, [28, 32, 36, 40])
    ]
예제 #13
0
def test_build_variable_list_for_three_derived_levels():
    def count_diff(colors, texts):
        changes = 0
        if (colors[0] != colors[1]): changes += 1
        if (texts[0] != texts[1]): changes += 1
        return changes

    def make_k_diff_level(k):
        def k_diff(colors, texts):
            return count_diff(colors, texts) == k

        return DerivedLevel(str(k), Transition(k_diff, [color, text]))

    changed = Factor(
        "changed",
        [make_k_diff_level(0),
         make_k_diff_level(1),
         make_k_diff_level(2)])

    block = fully_cross_block([color, text, changed], [color, text], [])

    assert block.build_variable_list(
        (changed, get_level_from_name(changed, "0"))) == [17, 20, 23]
    assert block.build_variable_list(
        (changed, get_level_from_name(changed, "1"))) == [18, 21, 24]
    assert block.build_variable_list(
        (changed, get_level_from_name(changed, "2"))) == [19, 22, 25]
예제 #14
0
def test_kinarow_with_bad_factor():
    bogus_factor = Factor("f", ["a", "b", "c"])
    with pytest.raises(ValueError):
        fully_cross_block(design, crossing, [
            ExactlyKInARow(
                2, (bogus_factor, get_level_from_name(bogus_factor, "a")))
        ])
예제 #15
0
    def factor_variables_for_trial(self, f: Factor, t: int) -> List[int]:
        if not f.applies_to_trial(t):
            raise ValueError('Factor does not apply to trial #' + str(t) +
                             ' f=' + str(f))

        previous_trials = sum(
            map(lambda trial: 1 if f.applies_to_trial(trial + 1) else 0,
                range(t))) - 1
        initial_sequence = list(
            map(lambda l: self.first_variable_for_level(f, l),
                list(filter(lambda l: (f, l) not in self.exclude, f.levels))))
        offset = 0
        if f.has_complex_window():
            offset = len(f.levels) * previous_trials
        else:
            offset = self.variables_per_trial() * previous_trials
        return list(map(lambda n: n + offset + 1, initial_sequence))
예제 #16
0
def test_factor_validation():
    Factor("factor name", ["level 1", "level 2"])

    # Non-string name
    with pytest.raises(ValueError):
        Factor(56, ["level "])

    # Non-list levels
    with pytest.raises(ValueError):
        Factor("name", 42)

    # Empty list
    with pytest.raises(ValueError):
        Factor("name", [])

    # Invalid level type
    with pytest.raises(ValueError):
        Factor("name", [1, 2])

    # Valid level types, but not uniform.
    with pytest.raises(ValueError):
        Factor("name", ["level1", con_level])

    # Derived levels with non-uniform window types
    with pytest.raises(ValueError):
        Factor("name", [
            con_level,
            DerivedLevel(
                "other",
                Transition(lambda colors: colors[0] == colors[1], [color]))
        ])
예제 #17
0
def validate_factor_and_level(block: Block, factor: Factor, level: Union[SimpleLevel, DerivedLevel]) -> None:
    if not block.has_factor(factor):
        raise ValueError(("A factor with name '{}' wasn't found in the design. " +\
            "Are you sure the factor was included, and that the name is spelled " +\
            "correctly?").format(factor.factor_name))

    if not factor.has_level(level):
        raise ValueError(("A level with name '{}' wasn't found in the '{}' factor, " +\
            "Are you sure the level name is spelled correctly?").format(get_internal_level_name(level), factor.factor_name))
def test_generate_derivations_should_raise_error_if_some_factor_matches_multiple_levels(
):
    local_con_factor = Factor("congruent?", [
        DerivedLevel("con", WithinTrial(op.eq, [color, text])),
        DerivedLevel("inc", WithinTrial(op.eq, [color, text]))
    ])

    with pytest.raises(ValueError):
        fully_cross_block([color, text, local_con_factor], [color, text], [])
예제 #19
0
 def __trials_required_for_crossing(self, f: Factor,
                                    crossing_size: int) -> int:
     trial = 0
     counter = 0
     while counter != crossing_size:
         trial += 1
         if f.applies_to_trial(trial):
             counter += 1
     return trial
예제 #20
0
    def factor_variables_for_trial(self, f: Factor, t: int) -> List[int]:
        """Given a factor and a trial number (1-based) this function will
        return a list of the variables representing the levels of the given
        factor for that trial. The variable list is also 1-based.
        """
        if not f.applies_to_trial(t):
            raise ValueError('Factor does not apply to trial #' + str(t) + ' f=' + str(f))

        previous_trials = sum(map(lambda trial: 1 if f.applies_to_trial(trial + 1) else 0, range(t))) - 1
        initial_sequence = list(map(lambda l: self.first_variable_for_level(f, l),
                                    list(filter(lambda l: (f, l) not in self.exclude,
                                                f.levels))))
        offset = 0
        if f.has_complex_window:
            offset = len(f.levels) * previous_trials
        else:
            offset = self.variables_per_trial() * previous_trials
        return list(map(lambda n: n + offset + 1, initial_sequence))
예제 #21
0
def test_factor_validation():
    Factor("factor name", ["level 1", "level 2"])
    Factor("name", [1, 2])

    # Duplicated name
    with pytest.raises(ValueError):
        Factor("name", ["a", "b", "a"])
    with pytest.raises(ValueError):
        Factor("name", [
            DerivedLevel("a", WithinTrial(op.eq, [color, text])),
            ElseLevel("a")
        ])

    # Non-string name
    with pytest.raises(ValueError):
        Factor(56, ["level "])

    # Non-list levels
    with pytest.raises(TypeError):
        Factor("name", 42)

    # Empty list
    with pytest.raises(ValueError):
        Factor("name", [])

    # Valid level types, but not uniform.
    with pytest.raises(ValueError):
        Factor("name", ["level1", con_level])

    # Derived levels with non-uniform window types
    with pytest.raises(ValueError):
        Factor("name", [
            con_level,
            DerivedLevel("other", WithinTrial(lambda color: color, [color]))
        ])

    # Derived levels with different window arguments
    with pytest.raises(ValueError):
        Factor("name", [
            con_level,
            DerivedLevel(
                "other",
                Transition(lambda colors: colors[0] == colors[1], [color]))
        ])
def test_generate_derivations_should_produce_warning_if_some_level_is_unreachable(capsys):
    local_con_factor = Factor("congruent?", [
        DerivedLevel("con", WithinTrial(op.eq, [color, text])),
        DerivedLevel("inc", WithinTrial(op.ne, [color, text])),
        DerivedLevel("dum", WithinTrial(lambda c, t: c=='green', [color, text]))
    ])
    fully_cross_block([color, text, local_con_factor],
                      [color, text],
                      [])
    assert capsys.readouterr().out == "WARNING: There is no assignment that matches factor congruent? with level dum.\n"
예제 #23
0
def test_derived_level_get_dependent_cross_product():
    assert [((tup[0][0].factor_name, tup[0][1].external_name),
             (tup[1][0].factor_name, tup[1][1].external_name))
            for tup in con_level.get_dependent_cross_product()
            ] == [(('color', 'red'), ('text', 'red')),
                  (('color', 'red'), ('text', 'blue')),
                  (('color', 'blue'), ('text', 'red')),
                  (('color', 'blue'), ('text', 'blue'))]

    integer = Factor("integer", ["1", "2"])
    numeral = Factor("numeral", ["I", "II"])
    text = Factor("text", ["one", "two"])
    two_con_level = DerivedLevel(
        "twoCon", WithinTrial(lambda x: x, [integer, numeral, text]))
    assert [((tup[0][0].factor_name, tup[0][1].external_name),
             (tup[1][0].factor_name, tup[1][1].external_name),
             (tup[2][0].factor_name, tup[2][1].external_name))
            for tup in two_con_level.get_dependent_cross_product()
            ] == [(('integer', '1'), ('numeral', 'I'), ('text', 'one')),
                  (('integer', '1'), ('numeral', 'I'), ('text', 'two')),
                  (('integer', '1'), ('numeral', 'II'), ('text', 'one')),
                  (('integer', '1'), ('numeral', 'II'), ('text', 'two')),
                  (('integer', '2'), ('numeral', 'I'), ('text', 'one')),
                  (('integer', '2'), ('numeral', 'I'), ('text', 'two')),
                  (('integer', '2'), ('numeral', 'II'), ('text', 'one')),
                  (('integer', '2'), ('numeral', 'II'), ('text', 'two'))]

    mixed_level = DerivedLevel(
        "mixed",
        WithinTrial(lambda x: x, [
            Factor("color", ["red", "blue", "green"]),
            Factor("boolean", ["true", "false"])
        ]))
    assert [((tup[0][0].factor_name, tup[0][1].external_name),
             (tup[1][0].factor_name, tup[1][1].external_name))
            for tup in mixed_level.get_dependent_cross_product()
            ] == [(('color', 'red'), ('boolean', 'true')),
                  (('color', 'red'), ('boolean', 'false')),
                  (('color', 'blue'), ('boolean', 'true')),
                  (('color', 'blue'), ('boolean', 'false')),
                  (('color', 'green'), ('boolean', 'true')),
                  (('color', 'green'), ('boolean', 'false'))]
예제 #24
0
def test_factor_applies_to_trial():
    assert color.applies_to_trial(1) == True
    assert color.applies_to_trial(2) == True
    assert color.applies_to_trial(3) == True
    assert color.applies_to_trial(4) == True

    with pytest.raises(ValueError):
        color.applies_to_trial(0)

    assert color_repeats_factor.applies_to_trial(1) == False
    assert color_repeats_factor.applies_to_trial(2) == True
    assert color_repeats_factor.applies_to_trial(3) == True
    assert color_repeats_factor.applies_to_trial(4) == True

    f = Factor('f', [DerivedLevel('l', Window(op.eq, [color], 2, 2))])
    assert f.applies_to_trial(1) == False
    assert f.applies_to_trial(2) == True
    assert f.applies_to_trial(3) == False
    assert f.applies_to_trial(4) == True

    assert color3.applies_to_trial(1) == True
예제 #25
0
def test_fully_cross_block_trials_per_sample():
    text_single = Factor("text", ["red"])

    assert FullyCrossBlock([], [color, color], []).trials_per_sample() == 4
    assert FullyCrossBlock([], [color, color, color],
                           []).trials_per_sample() == 8
    assert FullyCrossBlock([], [size, text_single],
                           []).trials_per_sample() == 3
    assert FullyCrossBlock([], [size, color], []).trials_per_sample() == 6
    assert FullyCrossBlock([], [text_single], []).trials_per_sample() == 1

    assert FullyCrossBlock([color, text, color_repeats_factor], [color, text],
                           []).trials_per_sample() == 4
def test_generate_derivations_should_raise_error_if_fn_doesnt_return_a_boolean():
    def local_eq(color, text):
            color == text # Notice the missing return stmt

    local_con_factor = Factor("congruent?", [
        DerivedLevel("con", WithinTrial(local_eq, [color, text])),
        DerivedLevel("inc", WithinTrial(lambda c, t: not local_eq(c, t), [color, text]))
    ])

    with pytest.raises(ValueError):
        fully_cross_block([color, text, local_con_factor],
                          [color, text],
                          [])
예제 #27
0
def test_atmostkinarow_validate():
    color = Factor("color", ["red", "blue"])
    with pytest.raises(ValueError):
        AtMostKInARow(SimpleLevel("yo"), color)

    # Levels must either be a factor/level tuple, or a Factor.
    AtMostKInARow(1, (color, get_level_from_name(color, "red")))
    AtMostKInARow(1, color)

    with pytest.raises(ValueError):
        AtMostKInARow(1, 42)

    with pytest.raises(ValueError):
        AtMostKInARow(1, (color, get_level_from_name(color, "red"), "oops"))
예제 #28
0
def test_derivation_with_three_level_transition():
    f = Factor("f", ["a", "b", "c"])
    f_transition = Factor("transition", [
        DerivedLevel("aa",
                     Transition(lambda c: c[0] == "a" and c[1] == "a", [f])),
        DerivedLevel("ab",
                     Transition(lambda c: c[0] == "a" and c[1] == "b", [f])),
        DerivedLevel("ac",
                     Transition(lambda c: c[0] == "a" and c[1] == "c", [f])),
        DerivedLevel("ba",
                     Transition(lambda c: c[0] == "b" and c[1] == "a", [f])),
        DerivedLevel("bb",
                     Transition(lambda c: c[0] == "b" and c[1] == "b", [f])),
        DerivedLevel("bc",
                     Transition(lambda c: c[0] == "b" and c[1] == "c", [f])),
        DerivedLevel("ca",
                     Transition(lambda c: c[0] == "c" and c[1] == "a", [f])),
        DerivedLevel("cb",
                     Transition(lambda c: c[0] == "c" and c[1] == "b", [f])),
        DerivedLevel("cc",
                     Transition(lambda c: c[0] == "c" and c[1] == "c", [f])),
    ])

    block = fully_cross_block([f, f_transition], [f], [])

    # a-a derivation
    d = Derivation(9, [[0, 3]], f_transition)
    backend_request = BackendRequest(28)
    d.apply(block, backend_request)

    (expected_cnf, expected_fresh) = to_cnf_tseitin(
        And([Iff(10, Or([And([1, 4])])),
             Iff(19, Or([And([4, 7])]))]), 28)

    assert backend_request.fresh == expected_fresh
    assert backend_request.cnfs == [expected_cnf]
예제 #29
0
def test_exclude_with_reduced_crossing():
    color = Factor("color", ["red", "blue", "green"])
    text = Factor("text", ["red", "blue"])

    def illegal_stimulus(color, text):
        return color == "green" and text == "blue"

    def legal_stimulus(color, text):
        return not illegal_stimulus(color, text)

    stimulus_configuration = Factor("stimulus configuration", [
        DerivedLevel("legal", WithinTrial(legal_stimulus, [color, text])),
        DerivedLevel("illegal", WithinTrial(illegal_stimulus, [color, text]))
    ])

    c = Exclude(stimulus_configuration,
                get_level_from_name(stimulus_configuration, "illegal"))
    block = fully_cross_block([color, text, stimulus_configuration],
                              [color, text], [c],
                              require_complete_crossing=False)

    backend_request = BackendRequest(0)
    c.apply(block, backend_request)
    assert backend_request.cnfs == [And([-7, -14, -21, -28, -35])]
예제 #30
0
    def __trials_required_for_crossing(self, f: Factor, crossing_size: int) -> int:
        """Given a factor ``f``, and a crossing size, this function will
        compute the number of trials required to fully cross ``f`` with the
        other factors.

        For example, if ``f`` is a transition, it doesn't apply to trial 1. So
        when the ``crossing_size`` is ``4``, we'd actually need 5 trials to
        fully cross with ``f``.

        This is a helper for :class:`.MultipleCrossBlock.trials_per_sample`.
        """
        trial = 0
        counter = 0
        while counter != crossing_size:
            trial += 1
            if f.applies_to_trial(trial):
                counter += 1
        return trial