def test_search_one_backward_step_3(self, cfg): # given gs = GoalSequenceSearcher() start = "01111111" goal = "10111111" gs.forward_perceptions.append(Perception(start)) gs.backward_perceptions.append(Perception(goal)) reliable_classifiers = ClassifiersList( Classifier(condition="#1######", action=1, effect="#0######", cfg=cfg), Classifier(condition="0#######", action=1, effect="1#######", cfg=cfg)) forward_size = 1 forward_point = 0 # when act_seq, size = gs._search_one_backward_step(reliable_classifiers, forward_size, forward_point) # then assert act_seq is None assert len(gs.backward_classifiers) == 2
def unexpected_case(cl: Classifier, p0: Perception, p1: Perception, time: int) -> Optional[Classifier]: """ Controls the unexpected case of the classifier. :param cl: :param p0: :param p1: :param time: :return: specialized classifier if generation was possible, None otherwise """ cl.decrease_quality() cl.set_mark(p0) # Return if the effect is not specializable if not cl.effect.is_specializable(p0, p1): return None child = cl.copy_from(cl, time) if cl.cfg.do_pee: # Probability-Enhanced attributes cannot appear in the effect part # if we leave already specialized attributes unchanged. # Therefore don't leave specialized. child.specialize(p0, p1, leave_specialized=False) else: child.specialize(p0, p1, leave_specialized=True) if child.q < 0.5: child.q = 0.5 return child
def test_form_sequence_backwards_5(self, cfg): # given gs = GoalSequenceSearcher() cl0 = Classifier(condition="01010101", action=2, effect="0000000", cfg=cfg) cl1 = Classifier(condition="11111111", action=0, effect="0000000", cfg=cfg) cl2 = Classifier(condition="11111111", action=1, effect="0000000", cfg=cfg) gs.backward_classifiers = [ ClassifiersList(cl0), ClassifiersList(cl0, cl1) ] i = 2 idx = 0 # when seq = gs._form_sequence_backwards(i, idx, cl2) # then assert len(seq) == 3 assert cl0.action in seq assert cl1.action in seq assert cl2.action in seq assert seq == [cl2.action, cl0.action, cl1.action]
def test_should_form_match_set_backwards(self, cfg): # given population = ClassifiersList() situation = Perception('11110000') # C1 - general condition c1 = Classifier(cfg=cfg) # C2 - matching c2 = Classifier(condition='0##0####', effect='1##1####', cfg=cfg) # C3 - non-matching c3 = Classifier(condition='0###1###', effect='1######0', cfg=cfg) # C4 - non-matching c4 = Classifier(condition='0###0###', effect='1###1###', cfg=cfg) population.append(c1) population.append(c2) population.append(c3) population.append(c4) # when match_set = ClassifiersList.form_match_set_backwards( population, situation) # then assert 2 == len(match_set) assert c1 in match_set assert c2 in match_set
def unexpected_case(cl: Classifier, p0: Perception, p1: Perception, time: int) -> Optional[Classifier]: """ Controls the unexpected case of the classifier. :param cl: :param p0: :param p1: :param time: :return: specialized classifier if generation was possible, None otherwise """ cl.decrease_quality() cl.set_mark(p0) # Return if the effect is not specializable if not cl.effect.is_specializable(p0, p1): return None child = cl.copy_from(cl, time) child.specialize(p0, p1, leave_specialized=True) if child.q < 0.5: child.q = 0.5 return child
def test_find_subsumer_finds_single_subsumer_among_nonsubsumers(self, cfg): # given subsumer = Classifier(condition='###0####', action=3, effect='##1#####', quality=0.93, reward=1.35, experience=23, cfg=cfg) nonsubsumer = Classifier(cfg=cfg) classifier = Classifier(condition='1##0####', action=3, effect='##1#####', quality=0.5, reward=0.35, experience=1, cfg=cfg) classifiers_list = ClassifiersList( *[nonsubsumer, subsumer, nonsubsumer], cfg=cfg) # when actual_subsumer = classifiers_list.find_subsumer( classifier, choice_func=lambda l: l[0]) # then assert actual_subsumer == subsumer
def test_equality(self, _c1, _a1, _e1, _c2, _a2, _e2, _result, cfg): # given cl1 = Classifier(condition=_c1, action=_a1, effect=_e1, cfg=cfg) cl2 = Classifier(condition=_c2, action=_a2, effect=_e2, cfg=cfg) # then assert (cl1 == cl2) is _result
def test_should_return_latest_action(self, cfg): # given all_actions = cfg.number_of_possible_actions population = ClassifiersList() c0 = Classifier(action=0, cfg=cfg) c0.talp = 1 # when population.append(c0) # Should return first action with no classifiers assert 1 == choose_latest_action(population, all_actions) # Add rest of classifiers population.append(Classifier(action=3, cfg=cfg)) population.append(Classifier(action=7, cfg=cfg)) population.append(Classifier(action=5, cfg=cfg)) population.append(Classifier(action=1, cfg=cfg)) population.append(Classifier(action=4, cfg=cfg)) population.append(Classifier(action=2, cfg=cfg)) population.append(Classifier(action=6, cfg=cfg)) # Assign each classifier random talp from certain range for cl in population: cl.talp = randint(70, 100) # But third classifier (action 7) will be the executed long time ago population[2].talp = randint(10, 20) # then assert choose_latest_action(population, all_actions) == 7
def test_get_quality_classifiers_list(self, cfg): # given population = ClassifiersList() # C1 - matching c1 = Classifier(quality=0.9, cfg=cfg) # C2 - matching c2 = Classifier(quality=0.7, cfg=cfg) # C3 - non-matching c3 = Classifier(quality=0.5, cfg=cfg) # C4 - non-matching c4 = Classifier(quality=0.1, cfg=cfg) population.append(c1) population.append(c2) population.append(c3) population.append(c4) # when match_set = get_quality_classifiers_list(population, 0.5) # then assert 2 == len(match_set) assert c1 in match_set assert c2 in match_set
def test_quality_and_numerosity_influence_parent_selection(self, cfg): # given population = ClassifiersList(cfg=cfg) c0 = Classifier(condition='######00', quality=1, numerosity=1, cfg=cfg) c1 = Classifier(condition='######01', cfg=cfg) c2 = Classifier(condition='######10', cfg=cfg) population.append(c0) # q3num = 1 population.append(c1) # q3num = 0.0625 population.append(c2) # q3num = 0.0625 # when p1, p2 = roulette_wheel_parents_selection(population, randomfunc=(RandomMock( [0.888, 0.999]))) # then assert c1 == p1 assert c2 == p2 # when p1, p2 = roulette_wheel_parents_selection(population, randomfunc=(RandomMock( [0.888, 0.777]))) # then assert c0 == p1 assert c1 == p2
def test_should_copy_classifier(self, cfg): # given operation_time = 123 original_cl = Classifier(condition='1###1011', action=1, effect='10####1#', reward=50, quality=0.7, cfg=cfg) # when copied_cl = Classifier.copy_from(original_cl, operation_time) # Assert that we are dealing with different object assert original_cl is not copied_cl # Assert that condition is equal but points to another object assert original_cl.condition == copied_cl.condition assert original_cl.condition is not copied_cl.condition # Assert that action is equal assert original_cl.action == copied_cl.action # Assert that effect is equal but points to another object assert original_cl.effect == copied_cl.effect assert original_cl.effect is not copied_cl.effect # Assert that other properties were set accordingly assert copied_cl.is_marked() is False assert 50 == copied_cl.r assert 0.7 == copied_cl.q assert operation_time == copied_cl.tga assert operation_time == copied_cl.talp
def test_copy_from_and_mutate_does_not_influence_another_condition( self, cfg): """ Verify that not just reference to Condition copied (changing which will change the original - definitily not original C++ code did). """ # given s = cfg.mu * 0.5 # less then MU b = 1 - (1 - cfg.mu) * 0.5 # more then MU operation_time = 123 original_cl = Classifier(condition='1###1011', cfg=cfg) copied_cl = Classifier.copy_from(original_cl, operation_time) # when mutate(copied_cl, cfg.mu, RandomMock([s, b, b, b, b])) # then assert Condition('####1011') == copied_cl.condition assert Condition('1###1011') == original_cl.condition # when mutate(original_cl, cfg.mu, RandomMock([b, s, b, b, b])) # then assert Condition('1####011') == original_cl.condition assert Condition('####1011') == copied_cl.condition
def test_should_return_best_fitness_action(self, cfg): # given population = ClassifiersList(cfg=cfg) # when & then # C1 - does not anticipate change c1 = Classifier(action=1, cfg=cfg) population.append(c1) # Some random action should be selected here best_action = exploit(population) assert best_action is not None # when & then # C2 - does anticipate some change c2 = Classifier(action=2, effect='1###0###', reward=0.25, cfg=cfg) population.append(c2) # Here C2 action should be selected best_action = exploit(population) assert 2 == best_action # when & then # C3 - does anticipate change and is quite good c3 = Classifier(action=3, effect='1#######', quality=0.8, reward=5, cfg=cfg) population.append(c3) # Here C3 has the biggest fitness score best_action = exploit(population) assert 3 == best_action
def test_should_set_mark_from_condition_4(self, cfg): # given p0 = Perception('01100000') cls = Classifier(condition='###0###0', cfg=cfg) # when cls.set_mark(p0) # then assert 1 == len(cls.mark[0]) assert '0' in cls.mark[0] assert 1 == len(cls.mark[1]) assert '1' in cls.mark[1] assert 1 == len(cls.mark[2]) assert '1' in cls.mark[2] assert 1 == len(cls.mark[4]) assert '0' in cls.mark[4] assert 1 == len(cls.mark[5]) assert '0' in cls.mark[5] assert 1 == len(cls.mark[6]) assert '0' in cls.mark[6]
def test_should_anticipate_correctly(self, cfg): # given cls = Classifier(effect='#1####0#', cfg=cfg) p0 = Perception('00001111') p1 = Perception('01001101') # then assert cls.does_anticipate_correctly(p0, p1) is True
def test_should_increase_quality(self, cfg): # given cls = Classifier(quality=0.5, cfg=cfg) # when cls.increase_quality() # then assert 0.525 == cls.q
def test_should_increase_experience(self, cfg): # given cls = Classifier(experience=5, cfg=cfg) # when cls.increase_experience() # then assert 6 == cls.exp
def test_should_update_intermediate_reward(self, _ir0, _ir1, _p, cfg): # given cls = Classifier(intermediate_reward=_ir0, cfg=cfg) # when cls.update_intermediate_reward(_p) # then assert cls.ir == _ir1
def test_should_decrease_quality(self, cfg): # given cls = Classifier(quality=0.47, cfg=cfg) # when cls.decrease_quality() # then assert abs(0.45 - cls.q) < 0.01
def test_should_update_reward(self, _r0, _r1, _p, cfg): # given cls = Classifier(reward=_r0, cfg=cfg) # when cls.update_reward(_p) # then assert cls.r == _r1
def test_should_update_intermediate_reward(self, cfg): # given cls = Classifier(cfg=cfg) # when cls.update_intermediate_reward(1000) # then assert 50.0 == cls.ir
def test_does_match_backwards(self, cfg, _e, _result): # given percept = Perception('11111111') c1 = Classifier(condition='#####0#0', effect=_e, cfg=cfg) # when result1 = c1.does_match_backwards(percept) # then assert result1 is _result
def test_get_backwards_anticipation(self, cfg, _c, _e, _result): # given p0 = Perception(['0', '1', '1', '1', '1', '0', '1', '0']) c0 = Classifier(condition=_c, effect=_e, cfg=cfg) # when result0 = c0.get_backwards_anticipation(p0) # then assert result0 == _result
def test_should_detect_more_general_classifier(self, _c1_condition, _c2_condition, _result, cfg): # given c1 = Classifier(condition=_c1_condition, cfg=cfg) c2 = Classifier(condition=_c2_condition, cfg=cfg) # when & then assert c1.is_more_general(c2) is _result
def test_get_best_anticipation(self, cfg, _p0, _result): # given p0 = Perception(_p0) classifier = Classifier(effect='##0##0##', cfg=cfg) # when result0 = classifier.get_best_anticipation(p0) # then assert result0 == _result
def test_should_anticipate_change(self, cfg): # given cls = Classifier(cfg=cfg) assert cls.does_anticipate_change() is False # when cls.effect[1] = '1' # then assert cls.does_anticipate_change() is True
def test_crossover_allows_to_change_last_element(self, cfg): # given cl1 = Classifier(condition='0##10###', cfg=cfg) cl2 = Classifier(condition='#10##011', cfg=cfg) # when two_point_crossover(cl1, cl2, samplefunc=SampleMock([5, 8])) # then assert Condition('0##10011') == cl1.condition assert Condition('#10#####') == cl2.condition
def test_other_not_preferred_to_delete_if_significantly_better(self, cfg): # given cl = Classifier(quality=0.8, cfg=cfg) cl_del = Classifier(quality=0.5, cfg=cfg) # when selected_cl = ClassifiersList(cfg=cfg)\ .select_preferred_to_delete(cl, cl_del) # then assert cl_del == selected_cl
def test_crossover(self, cfg): # given cl1 = Classifier(condition='0##10###', cfg=cfg) cl2 = Classifier(condition='#10##0##', cfg=cfg) # when two_point_crossover(cl1, cl2, samplefunc=SampleMock([1, 4])) # then assert Condition('010#0###') == cl1.condition assert Condition('###1#0##') == cl2.condition
def test_should_detect_correct_anticipation_1(self, cfg): # Classifier is not predicting any change, all pass-through effect # should predict correctly # given cls = Classifier(effect=Effect('########'), cfg=cfg) p0 = Perception('00001111') p1 = Perception('00001111') # then assert cls.does_anticipate_correctly(p0, p1) is True