def test_constraint_violation(): are_constraints_violated = UniformCombinatoricSamplingStrategy._UniformCombinatoricSamplingStrategy__are_constraints_violated block = fully_cross_block([color, text, con_factor_within_trial], [color, text], [ExactlyKInARow(2, (color, red_color))]) assert are_constraints_violated( block, {color: [red_color, red_color, blue_color, blue_color]}) == False assert are_constraints_violated( block, {color: [red_color, blue_color, red_color, blue_color]}) == True block = fully_cross_block([color, text, con_factor_within_trial], [color, text], [NoMoreThanKInARow(2, (color, red_color))]) assert are_constraints_violated( block, {color: [red_color, blue_color, blue_color, blue_color]}) == False assert are_constraints_violated( block, {color: [red_color, red_color, blue_color, blue_color]}) == False assert are_constraints_violated( block, {color: [red_color, red_color, red_color, blue_color]}) == True assert are_constraints_violated( block, {color: [blue_color, red_color, red_color, red_color]}) == True
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_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"))) ])
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) == "\
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], [])
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"
def test_validate_accepts_derived_factors_with_simple_windows(): block = fully_cross_block([color, text, con_factor_within_trial], [color, text], []) UniformCombinatoricSamplingStrategy._UniformCombinatoricSamplingStrategy__validate( block) block = fully_cross_block([color, text, con_factor_window], [color, text], []) UniformCombinatoricSamplingStrategy._UniformCombinatoricSamplingStrategy__validate( block)
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], [])
def test_generate_derivations_with_window(): block = fully_cross_block([color, text, congruent_bookend], [color, text], []) assert DerivationProcessor.generate_derivations(block) == [ Derivation(16, [[0, 2], [1, 3]], congruent_bookend), Derivation(17, [[0, 3], [1, 2]], congruent_bookend) ]
def test_generate_derivations_transition(design): block = fully_cross_block(design, [color, text], []) assert DerivationProcessor.generate_derivations(block) == [ Derivation(16, [[0, 4], [1, 5]], color_repeats_factor), Derivation(17, [[0, 5], [1, 4]], color_repeats_factor) ]
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]) ]
def test_build_variable_list_for_simple_factors(): block = fully_cross_block([color, text, con_factor], [color, text], []) assert block.build_variable_list((color, red_color)) == [1, 7, 13, 19] assert block.build_variable_list( (con_factor, get_level_from_name(con_factor, "con"))) == [5, 11, 17, 23]
def test_fully_cross_block_decode_variable_with_transition_first(): block = fully_cross_block( [text_repeats_factor, text, color, color_repeats_factor], [color, text], []) assert block.decode_variable(1) == (text, red_text) assert block.decode_variable(2) == (text, blue_text) assert block.decode_variable(5) == (text, red_text) assert block.decode_variable(14) == (text, blue_text) assert block.decode_variable(3) == (color, red_color) assert block.decode_variable(4) == (color, blue_color) assert block.decode_variable(15) == (color, red_color) assert block.decode_variable(12) == (color, blue_color) assert block.decode_variable(17) == (text_repeats_factor, yes_text_repeats) assert block.decode_variable(18) == (text_repeats_factor, no_text_repeats) assert block.decode_variable(19) == (text_repeats_factor, yes_text_repeats) assert block.decode_variable(22) == (text_repeats_factor, no_text_repeats) assert block.decode_variable(23) == (color_repeats_factor, yes_color_repeats) assert block.decode_variable(24) == (color_repeats_factor, no_color_repeats) assert block.decode_variable(27) == (color_repeats_factor, yes_color_repeats) assert block.decode_variable(28) == (color_repeats_factor, no_color_repeats)
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) ]
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]
def test_generate_sample_basic_stroop_variation(sequence_number, expected_solution): 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
def test_generate_encoding_diagram_with_constraint_and_multiple_transitions_in_different_order( ): block = fully_cross_block( [text_repeats_factor, color, color_repeats_factor, text, con_factor], [color, text], []) assert __generate_encoding_diagram(block) == "\
def test_fully_cross_with_transition_in_design(design): block = fully_cross_block(design, [color, text], []) backend_request = BackendRequest(23) FullyCross.apply(block, backend_request) (expected_cnf, _) = to_cnf_tseitin( And([ Iff(23, And([1, 3])), Iff(24, And([1, 4])), Iff(25, And([2, 3])), Iff(26, And([2, 4])), Iff(27, And([5, 7])), Iff(28, And([5, 8])), Iff(29, And([6, 7])), Iff(30, And([6, 8])), Iff(31, And([9, 11])), Iff(32, And([9, 12])), Iff(33, And([10, 11])), Iff(34, And([10, 12])), Iff(35, And([13, 15])), Iff(36, And([13, 16])), Iff(37, And([14, 15])), Iff(38, And([14, 16])) ]), 39) assert backend_request.fresh == 72 assert backend_request.cnfs == [expected_cnf] assert backend_request.ll_requests == [ LowLevelRequest("GT", 0, [23, 27, 31, 35]), LowLevelRequest("GT", 0, [24, 28, 32, 36]), LowLevelRequest("GT", 0, [25, 29, 33, 37]), LowLevelRequest("GT", 0, [26, 30, 34, 38]) ]
def test_fully_cross_simple(): block = fully_cross_block([color, text], [color, text], []) (expected_cnf, _) = to_cnf_tseitin( And([ Iff(17, And([1, 3])), Iff(18, And([1, 4])), Iff(19, And([2, 3])), Iff(20, And([2, 4])), Iff(21, And([5, 7])), Iff(22, And([5, 8])), Iff(23, And([6, 7])), Iff(24, And([6, 8])), Iff(25, And([9, 11])), Iff(26, And([9, 12])), Iff(27, And([10, 11])), Iff(28, And([10, 12])), Iff(29, And([13, 15])), Iff(30, And([13, 16])), Iff(31, And([14, 15])), Iff(32, And([14, 16])) ]), 33) backend_request = BackendRequest(17) FullyCross.apply(block, backend_request) assert backend_request.fresh == 66 assert backend_request.cnfs == [expected_cnf] assert backend_request.ll_requests == [ LowLevelRequest("GT", 0, [17, 21, 25, 29]), LowLevelRequest("GT", 0, [18, 22, 26, 30]), LowLevelRequest("GT", 0, [19, 23, 27, 31]), LowLevelRequest("GT", 0, [20, 24, 28, 32]) ]
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]) ]
def test_derivation_with_multiple_transitions(): block = fully_cross_block( [color, text, color_repeats_factor, text_repeats_factor], [color, text], []) # Text repeats derivation d = Derivation(22, [[2, 6], [3, 7]], text_repeats_factor) backend_request = BackendRequest(29) d.apply(block, backend_request) (expected_cnf, expected_fresh) = to_cnf_tseitin( And([ Iff(23, Or([And([3, 7]), And([4, 8])])), Iff(25, Or([And([7, 11]), And([8, 12])])), Iff(27, Or([And([11, 15]), And([12, 16])])) ]), 29) assert backend_request.fresh == expected_fresh assert backend_request.cnfs == [expected_cnf] # Text does not repeat derivation d = Derivation(23, [[2, 7], [3, 6]], text_repeats_factor) backend_request = BackendRequest(29) d.apply(block, backend_request) (expected_cnf, expected_fresh) = to_cnf_tseitin( And([ Iff(24, Or([And([3, 8]), And([4, 7])])), Iff(26, Or([And([7, 12]), And([8, 11])])), Iff(28, Or([And([11, 16]), And([12, 15])])) ]), 29) assert backend_request.fresh == expected_fresh assert backend_request.cnfs == [expected_cnf]
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]) ]
def test_no_solutions_without_override_flag(): block = fully_cross_block(design, crossing, constraints) experiments = synthesize_trials_non_uniform(block, 500) assert block.crossing_size() == 6 assert len(experiments) == 0 assert_no_repetition(experiments)
def test_decode_with_transition(): block = fully_cross_block([color, text, color_repeats_factor], [color, text], []) solution = [ 1, -2, 3, -4, 5, -6, -7, 8, # 17, -18 -9, 10, 11, -12, # -19, 20 -13, 14, -15, 16, # 21, -22 17, -18, -19, 20, 21, -22] # color_repeats_factor decoded = __decode(block, solution) assert decoded['color'] == ['red', 'red', 'blue', 'blue'] assert decoded['text'] == ['red', 'blue', 'red', 'blue'] assert decoded['color repeats?'] == ['', 'yes', 'no', 'yes' ] solution = [ 1, -2, -3, 4, -5, 6, 7, -8, -9, 10, -11, 12, 13, -14, 15, -16, -17, 18, 19, -20, -21, 22] decoded = __decode(block, solution) assert decoded['color'] == ['red', 'blue', 'blue', 'red'] assert decoded['text'] == ['blue', 'red', 'blue', 'red'] assert decoded['color repeats?'] == ['', 'no', 'yes', 'no' ]
def test_derivation_with_transition(): block = fully_cross_block([color, text, color_repeats_factor], [color, text], []) # Color repeats derivation d = Derivation(16, [[0, 4], [1, 5]], color_repeats_factor) backend_request = BackendRequest(23) d.apply(block, backend_request) (expected_cnf, expected_fresh) = to_cnf_tseitin( And([ Iff(17, Or([And([1, 5]), And([2, 6])])), Iff(19, Or([And([5, 9]), And([6, 10])])), Iff(21, Or([And([9, 13]), And([10, 14])])) ]), 23) assert backend_request.fresh == expected_fresh assert backend_request.cnfs == [expected_cnf] # Color does not repeat derivation d = Derivation(17, [[0, 5], [1, 4]], color_repeats_factor) backend_request = BackendRequest(23) d.apply(block, backend_request) (expected_cnf, expected_fresh) = to_cnf_tseitin( And([ Iff(18, Or([And([1, 6]), And([2, 5])])), Iff(20, Or([And([5, 10]), And([6, 9])])), Iff(22, Or([And([9, 14]), And([10, 13])])) ]), 23) assert backend_request.fresh == expected_fresh assert backend_request.cnfs == [expected_cnf]
def test_generate_derivations_when_derived_factor_precedes_dependencies(): block = fully_cross_block([congruency, motion, color, task], [color, motion, task], []) derivations = DerivationProcessor.generate_derivations(block) assert Derivation(0, [[4, 2], [5, 3]], congruency) in derivations assert Derivation(1, [[4, 3], [5, 2]], congruency) in derivations
def test_derivation_with_general_window(): block = fully_cross_block([color, text, congruent_bookend], [color, text], []) # congruent bookend - yes d = Derivation(16, [[0, 2], [1, 3]], congruent_bookend) backend_request = BackendRequest(19) d.apply(block, backend_request) (expected_cnf, expected_fresh) = to_cnf_tseitin( And([ Iff(17, Or([And([1, 3]), And([2, 4])])), Iff(19, Or([And([13, 15]), And([14, 16])])) ]), 19) assert backend_request.fresh == expected_fresh assert backend_request.cnfs == [expected_cnf] # congruent bookend - no d = Derivation(17, [[0, 3], [1, 2]], congruent_bookend) backend_request = BackendRequest(19) d.apply(block, backend_request) (expected_cnf, expected_fresh) = to_cnf_tseitin( And([ Iff(18, Or([And([1, 4]), And([2, 3])])), Iff(20, Or([And([13, 16]), And([14, 15])])) ]), 19) assert backend_request.fresh == expected_fresh assert backend_request.cnfs == [expected_cnf]
def test_validate_rejects_exclude_constraints(): block = fully_cross_block([color, text, con_factor_within_trial], [color, text], [Exclude(color, red_color)]) with pytest.raises(ValueError): UniformCombinatoricSamplingStrategy._UniformCombinatoricSamplingStrategy__validate( block)
def test_correct_solution_count_when_unconstrained(design): crossing = [color, text] constraints = [] block = fully_cross_block(design, crossing, constraints) experiments = synthesize_trials_non_uniform(block, 100) assert len(experiments) == 24
def test_consistency_with_multiple_transitions(design): block = fully_cross_block(design, [color, text], []) 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, 28, 2)))