def test_factor_get_level(): assert color.get_level(get_level_from_name( color, "red").internal_name).external_name == "red" assert color_repeats_factor.get_level( get_level_from_name(color_repeats_factor, "yes").internal_name) == color_repeats_level assert color.get_level("bogus") == None
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_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
def test_exclude(): f = Exclude(color, get_level_from_name(color, "red")) backend_request = BackendRequest(0) f.apply(block, backend_request) assert backend_request.cnfs == [And([-1, -7, -13, -19])] f = Exclude(con_factor, get_level_from_name(con_factor, "con")) backend_request = BackendRequest(0) f.apply(block, backend_request) assert backend_request.cnfs == [And([-5, -11, -17, -23])]
def test_correct_solution_count_with_repeated_color_and_text_factors_and_constrained(design): crossing = [[color, text], [mix, text]] constraints = [ at_most_k_in_a_row(1, (repeated_color_factor, get_level_from_name(repeated_color_factor, "yes"))), at_most_k_in_a_row(1, (repeated_text_factor, get_level_from_name(repeated_text_factor, "yes"))) ] block = multiple_cross_block(design, crossing, constraints) experiments = synthesize_trials_non_uniform(block, 100) assert len(experiments) == 96
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"))
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_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_correct_solution_count_with_repeated_color_factor_and_no_repetition_allowed(design): crossing = [[color, text], [mix, text]] constraints = [exclude(repeated_color_factor, get_level_from_name(repeated_color_factor, "yes"))] block = multiple_cross_block(design, crossing, constraints) experiments = synthesize_trials_non_uniform(block, 100) assert len(experiments) == 32
def test_nomorethankinarow_sugar(): backend_request = __run_kinarow( NoMoreThanKInARow(1, (color, get_level_from_name(color, "red")))) assert backend_request.ll_requests == [ LowLevelRequest("LT", 2, [1, 7]), LowLevelRequest("LT", 2, [7, 13]), LowLevelRequest("LT", 2, [13, 19]) ]
def test_correct_solution_count_with_congruence_factor_and_constrained(design): crossing = [[color, text], [text, mix]] constraints = [at_most_k_in_a_row(1, (con_factor, get_level_from_name(con_factor, "con")))] block = multiple_cross_block(design, crossing, constraints) experiments = synthesize_trials_non_uniform(block, 100) assert len(experiments) == 48
def test_exclude_with_transition(): block = fully_cross_block([color, text, color_repeats_factor], [color, text], []) c = Exclude(color_repeats_factor, get_level_from_name(color_repeats_factor, "yes")) backend_request = BackendRequest(0) c.apply(block, backend_request) assert backend_request.cnfs == [And([-17, -19, -21])]
def test_exclude_with_general_window(): block = fully_cross_block([color, text, congruent_bookend], [color, text], []) c = Exclude(congruent_bookend, get_level_from_name(congruent_bookend, "yes")) backend_request = BackendRequest(0) c.apply(block, backend_request) assert backend_request.cnfs == [And([-17, -19])]
def test_correct_solution_count_with_repeated_color_factor_and_constrained(design): crossing = [[color, text], [mix, text]] constraints = [at_most_k_in_a_row(1, (repeated_color_factor, get_level_from_name(repeated_color_factor, "yes")))] block = multiple_cross_block(design, crossing, constraints) experiments = synthesize_trials_non_uniform(block, 100) # With only two colors, there can never be two color repetitons anyways, # so the total should still be the same. assert len(experiments) == 96
def test_atmostkinarow(): backend_request = __run_kinarow(AtMostKInARow(3, color)) assert backend_request.ll_requests == [ LowLevelRequest("LT", 4, [1, 7, 13, 19]), LowLevelRequest("LT", 4, [2, 8, 14, 20]) ] backend_request = __run_kinarow( AtMostKInARow(1, (color, get_level_from_name(color, "red")))) assert backend_request.ll_requests == [ LowLevelRequest("LT", 2, [1, 7]), LowLevelRequest("LT", 2, [7, 13]), LowLevelRequest("LT", 2, [13, 19]) ] backend_request = __run_kinarow( AtMostKInARow(2, (color, get_level_from_name(color, "red")))) assert backend_request.ll_requests == [ LowLevelRequest("LT", 3, [1, 7, 13]), LowLevelRequest("LT", 3, [7, 13, 19]) ] backend_request = __run_kinarow( AtMostKInARow(1, (color, get_level_from_name(color, "blue")))) assert backend_request.ll_requests == [ LowLevelRequest("LT", 2, [2, 8]), LowLevelRequest("LT", 2, [8, 14]), LowLevelRequest("LT", 2, [14, 20]) ] backend_request = __run_kinarow( AtMostKInARow(2, (color, get_level_from_name(color, "blue")))) assert backend_request.ll_requests == [ LowLevelRequest("LT", 3, [2, 8, 14]), LowLevelRequest("LT", 3, [8, 14, 20]) ] backend_request = __run_kinarow( AtMostKInARow(3, (con_factor, get_level_from_name(con_factor, "con")))) assert backend_request.ll_requests == [ LowLevelRequest("LT", 4, [5, 11, 17, 23]) ]
def test_atmostkinarow_with_transition(design): block = fully_cross_block(design, [color, text], []) backend_request = __run_kinarow( AtMostKInARow(1, (color_repeats_factor, get_level_from_name(color_repeats_factor, "yes"))), block) assert backend_request.ll_requests == [ LowLevelRequest("LT", 2, [17, 19]), LowLevelRequest("LT", 2, [19, 21]) ] backend_request = __run_kinarow( AtMostKInARow(1, (color_repeats_factor, get_level_from_name(color_repeats_factor, "no"))), block) assert backend_request.ll_requests == [ LowLevelRequest("LT", 2, [18, 20]), LowLevelRequest("LT", 2, [20, 22]) ]
def test_correct_solution_count_when_transition_in_crossing_and_constrained( design): crossing = [direction, repeated_color_factor] constraints = [ at_most_k_in_a_row(1, (color, get_level_from_name(color, "red"))) ] block = fully_cross_block(design, crossing, constraints) experiments = synthesize_trials_non_uniform(block, 100) assert len(experiments) == 32
def test_atmostkinarow_with_multiple_transitions(): block = fully_cross_block( [color, text, color_repeats_factor, text_repeats_factor], [color, text], []) backend_request = __run_kinarow( AtMostKInARow(1, (text_repeats_factor, get_level_from_name(text_repeats_factor, "yes"))), block) assert backend_request.ll_requests == [ LowLevelRequest("LT", 2, [23, 25]), LowLevelRequest("LT", 2, [25, 27]) ] backend_request = __run_kinarow( AtMostKInARow(1, (text_repeats_factor, get_level_from_name(text_repeats_factor, "no"))), block) assert backend_request.ll_requests == [ LowLevelRequest("LT", 2, [24, 26]), LowLevelRequest("LT", 2, [26, 28]) ]
def test_correct_solution_count_with_congruence_factor_and_constrained_cnf(design=[color, text, mix, con_factor]): crossing = [[color, text], [text, mix]] constraints = [at_most_k_in_a_row(1, (con_factor, get_level_from_name(con_factor, "con")))] block = multiple_cross_block(design, crossing, constraints) cnf = build_cnf(block) # with open(path_to_cnf_files+'/test_correct_solution_count_with_congruence_factor_and_constrained.cnf', 'w') as f: # f.write(cnf.as_unigen_string()) with open(path_to_cnf_files+'/test_correct_solution_count_with_congruence_factor_and_constrained.cnf', 'r') as f: old_cnf = f.read() assert old_cnf == cnf.as_unigen_string()
def test_correct_solution_count_with_repeated_color_factor_and_no_repetition_allowed_cnf(design=[color, text, mix, repeated_color_factor]): crossing = [[color, text], [mix, text]] constraints = [exclude(repeated_color_factor, get_level_from_name(repeated_color_factor, "yes"))] block = multiple_cross_block(design, crossing, constraints) cnf = build_cnf(block) # with open(path_to_cnf_files+'/test_correct_solution_count_with_repeated_color_factor_and_no_repetition_allowed.cnf', 'w') as f: # f.write(cnf.as_unigen_string()) with open(path_to_cnf_files+'/test_correct_solution_count_with_repeated_color_factor_and_no_repetition_allowed.cnf', 'r') as f: old_cnf = f.read() assert old_cnf == cnf.as_unigen_string()
def test_correct_solution_count_when_bookends_must_not_be_congruent(design): crossing = [color, text] # Require both bookends to not be congruent. constraints = [ exclude(congruent_bookend, get_level_from_name(congruent_bookend, "yes")) ] block = fully_cross_block(design, crossing, constraints) experiments = synthesize_trials_non_uniform(block, 100) assert len(experiments) == 4
def test_exactlykinarow(): backend_request = __run_kinarow( ExactlyKInARow(1, (color, get_level_from_name(color, "red")))) (expected_cnf, expected_fresh) = to_cnf_tseitin( And([ If(1, Not(7)), If(And([Not(1), 7]), Not(13)), If(And([Not(7), 13]), Not(19)) ]), 25) assert backend_request.fresh == expected_fresh assert backend_request.cnfs == [expected_cnf] backend_request = __run_kinarow( ExactlyKInARow(2, (color, get_level_from_name(color, "red")))) (expected_cnf, expected_fresh) = to_cnf_tseitin( And([ If(1, And([7, Not(13)])), If(And([Not(1), 7]), And([13, Not(19)])), If(And([Not(7), 13]), 19), If(19, 13) ]), 25) assert backend_request.fresh == expected_fresh assert backend_request.cnfs == [expected_cnf] backend_request = __run_kinarow( ExactlyKInARow(3, (color, get_level_from_name(color, "red")))) (expected_cnf, expected_fresh) = to_cnf_tseitin( And([ If(1, And([7, 13, Not(19)])), If(And([Not(1), 7]), And([13, 19])), If(19, 13), If(13, 7) ]), 25) assert backend_request.fresh == expected_fresh assert backend_request.cnfs == [expected_cnf]
def test_correct_solution_count_with_override_flag_and_multiple_trials_excluded( ): # With this constraint, there should only be ONE allowed crossing, and therefore one solution. constraints = [ exclude(stimulus_configuration, get_level_from_name(stimulus_configuration, "legal")) ] block = fully_cross_block(design, crossing, constraints, require_complete_crossing=False) experiments = synthesize_trials_non_uniform(block, 500) assert block.crossing_size() == 1 assert len(experiments) == 1 assert_no_repetition(experiments)
def test_fully_cross_block_should_copy_input_lists(): # FullyCrossBlock should copy the input lists, so as not to break if the # user modifies the original list. design = [color, text, con_factor] crossing = [color, text] constraints = [Exclude(con_factor, get_level_from_name(con_factor, "con"))] block = FullyCrossBlock(design, [crossing], constraints) design.clear() assert len(block.design) == 3 crossing.clear() assert len(block.crossing[0]) == 2 constraints.clear() assert len(block.constraints) == 1
def test_correct_solution_count_when_transition_in_crossing_and_constrained_cnf( design=[direction, color, repeated_color_factor]): crossing = [direction, repeated_color_factor] constraints = [ at_most_k_in_a_row(1, (color, get_level_from_name(color, "red"))) ] block = fully_cross_block(design, crossing, constraints) cnf = build_cnf(block) # with open(path_to_cnf_files+'/test_correct_solution_count_when_transition_in_crossing_and_constrained.cnf', 'w') as f: # f.write(cnf.as_unigen_string()) with open( path_to_cnf_files + '/test_correct_solution_count_when_transition_in_crossing_and_constrained.cnf', 'r') as f: old_cnf = f.read() assert old_cnf == cnf.as_unigen_string()
def test_correct_solution_count_with_override_flag_and_multiple_trials_excluded_cnf( ): # With this constraint, there should only be ONE allowed crossing, and therefore one solution. constraints = [ exclude(stimulus_configuration, get_level_from_name(stimulus_configuration, "legal")) ] block = fully_cross_block(design, crossing, constraints, require_complete_crossing=False) cnf = build_cnf(block) # with open(path_to_cnf_files+'/test_correct_solution_count_with_override_flag_and_multiple_trials_excluded.cnf', 'w') as f: # f.write(cnf.as_unigen_string()) with open( path_to_cnf_files + '/test_correct_solution_count_with_override_flag_and_multiple_trials_excluded.cnf', 'r') as f: old_cnf = f.read() assert old_cnf == cnf.as_unigen_string() # FIXME
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])]
import glob import operator as op import os import pytest import re from sweetpea import fully_cross_block from sweetpea.primitives import Factor, DerivedLevel, WithinTrial, Transition, Window from sweetpea.constraints import Exclude, ExactlyKInARow, NoMoreThanKInARow from sweetpea.sampling_strategies.uniform_combinatoric import UniformCombinatoricSamplingStrategy, UCSolutionEnumerator from sweetpea.tests.test_utils import get_level_from_name color = Factor("color", ["red", "blue"]) text = Factor("text", ["red", "blue"]) red_color = get_level_from_name(color, "red") blue_color = get_level_from_name(color, "blue") red_text = get_level_from_name(text, "red") blue_text = get_level_from_name(text, "blue") con_factor_within_trial = Factor("congruent?", [ DerivedLevel("con", WithinTrial(op.eq, [color, text])), DerivedLevel("inc", WithinTrial(op.ne, [color, text])) ]) con_factor_window = Factor("congruent?", [ DerivedLevel("con", Window(op.eq, [color, text], 1, 1)), DerivedLevel("inc", Window(op.ne, [color, text], 1, 1)) ]) color_repeats_factor = Factor("repeated color?", [
def test_exactlykinarow_disallows_k_of_zero(): with pytest.raises(ValueError): ExactlyKInARow(0, (color, get_level_from_name(color, "red")))