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_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_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_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_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_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_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])]
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
return (tasks[0] != tasks[2]) and (tasks[0] != tasks[1]) and (tasks[1] != tasks[2]) def other_transition(tasks): return (not (A_B_A(tasks) or A_B_C(tasks))) task_transition = Factor("task transition", [ DerivedLevel("A-B-A", Window(A_B_A, [task], 3, 1)), DerivedLevel("A-B-C", Window(A_B_C, [task], 3, 1)), ]) # DEFINE CONSTRAINTS constraints = [Exclude("object configuration", "illegal")] # DEFINE EXPERIMENT design = [ deviantColorObject, deviantOrientationObject, deviantMovementObject, objectConfiguration, task, task_transition ] crossing = [ deviantColorObject, deviantOrientationObject, deviantMovementObject, task, task_transition ] block = fully_cross_block(design, crossing, constraints, require_complete_crossing=False)
def test_fully_cross_block_crossing_size_with_exclude(): # No congruent excludes 2 trials, 4 - 2 = 2 assert FullyCrossBlock( [color, text, con_factor], [[color, text]], [Exclude(con_factor, con_level)], require_complete_crossing=False).crossing_size() == 2