예제 #1
0
    def test_should_specialize(self, _p0, _p1, _init_cond, _init_effect,
                               _res_cond, _res_effect, cfg):
        # given
        cls = Classifier(condition=Condition(_init_cond),
                         effect=Effect(_init_effect),
                         cfg=cfg)
        p0 = Perception(_p0)
        p1 = Perception(_p1)

        # when
        cls.specialize(p0, p1, leave_specialized=False)

        # then
        assert cls.condition == Condition(_res_cond)
        assert cls.effect == Effect(_res_effect)
예제 #2
0
    def test_should_handle_unexpected_case_2(self, cfg):
        # given
        cls = Classifier(condition='#######0', action=4, quality=0.4, cfg=cfg)
        cls.mark[0].update([0, 1])
        cls.mark[1].update([0, 1])
        cls.mark[2].update([0, 1])
        cls.mark[3].update([0, 1])
        cls.mark[4].update([1])
        cls.mark[5].update([0, 1])
        cls.mark[6].update([0, 1])

        p0 = Perception('11101010')
        p1 = Perception('10011101')
        time = 94

        # when
        new_cl = unexpected_case(cls, p0, p1, time)

        # then
        assert new_cl.condition == Condition('#110#010')
        assert new_cl.effect == Effect('#001#101')
        assert new_cl.is_marked() is False
        assert time == new_cl.tga
        assert time == new_cl.talp
        assert abs(cls.q - 0.38) < 0.01
예제 #3
0
    def get_differences(self, p0: Perception) -> Condition:
        """
        Determines the strongest differences in between the mark
        and current perception.

        :param: perception
        :return: condition that specifies all the differences.
        """
        diff = Condition.empty(length=self.cfg.classifier_length)

        nr1, nr2 = 0, 0

        # Count difference types
        for idx, item in enumerate(self):
            if len(item) > 0 and p0[idx] not in item:
                nr1 += 1
            elif len(item) > 1:
                nr2 += 1

        if nr1 > 0:
            possible_idx = [pi for pi, p in enumerate(p0) if
                            p not in self[pi] and len(self[pi]) > 0]
            rand_idx = random.choice(possible_idx)
            diff[rand_idx] = p0[rand_idx]
        elif nr2 > 0:
            for idx, item in enumerate(self):
                if len(item) > 1:
                    diff[idx] = p0[idx]

        return diff
예제 #4
0
    def test_should_get_differences_1(self, _p0, cfg):
        # given
        generic_condition = Condition.empty(length=cfg.classifier_length)
        p0 = Perception(_p0)
        mark = PMark(cfg)

        # when
        diff = mark.get_differences(p0)

        # then
        assert diff == generic_condition
예제 #5
0
    def test_should_build_initial_population(self, cfg):
        agent = ACS(cfg)

        assert len(agent.population) == 4

        actions = [cl.action for cl in agent.population]
        assert actions == [0, 1, 2, 3]

        for cl in agent.population:
            assert cl.condition == Condition("####")
            assert cl.effect == Effect("####")
예제 #6
0
    def test_should_generalize_second_unchanging_attribute(self, cfg):
        # given
        cls = Classifier(condition='#####0#0', effect='########', cfg=cfg)

        assert len(cls.specified_unchanging_attributes) == 2

        # when
        generalized = cls.generalize_unchanging_condition_attribute(
            lambda x: 7)

        # then
        assert generalized is True
        assert len(cls.specified_unchanging_attributes) == 1
        assert Condition('#####0##') == cls.condition
예제 #7
0
    def test_should_construct_correct_classifier(self, cfg):
        cl = Classifier(condition="000#", effect="000#", quality=0.2, cfg=cfg)
        p0 = Perception("0000")
        p1 = Perception("0001")
        assert cl.does_match(p0)

        new_cl = Classifier.build_corrected(cl, p0, p1)

        assert new_cl is not cl
        assert new_cl.condition is not cl.condition
        assert new_cl.effect is not cl.effect
        assert new_cl.condition == Condition("0000")
        assert new_cl.action == cl.action
        assert new_cl.effect == Effect("0001")
        assert new_cl.q == 0.5
        assert new_cl.does_match(p0)
예제 #8
0
    def test_should_handle_unexpected_case_1(self, cfg):
        # given
        cls = Classifier(action=2, cfg=cfg)

        p0 = Perception('01100000')
        p1 = Perception('10100010')
        time = 14

        new_cls = unexpected_case(cls, p0, p1, time)

        # Quality should be decreased
        assert 0.475 == cls.q

        # Should be marked with previous perception
        for mark_attrib in cls.mark:
            assert 1 == len(mark_attrib)

        assert '0' in cls.mark[0]
        assert '1' in cls.mark[1]
        assert '1' in cls.mark[2]
        assert '0' in cls.mark[3]
        assert '0' in cls.mark[4]
        assert '0' in cls.mark[5]
        assert '0' in cls.mark[6]
        assert '0' in cls.mark[7]

        # New classifier should not be the same object
        assert cls is not new_cls

        # Check attributes of a new classifier
        assert Condition('01####0#') == new_cls.condition
        assert 2 == new_cls.action
        assert Effect('10####1#') == new_cls.effect

        # There should be no mark
        for mark_attrib in new_cls.mark:
            assert 0 == len(mark_attrib)

        assert 0.5 == new_cls.q
        assert cls.r == new_cls.r
        assert time == new_cls.tga
        assert time == new_cls.talp
예제 #9
0
    def build_corrected(cls, old: Classifier, p0: Perception,
                        p1: Perception) -> Classifier:
        """
        Constructs the classifier for "correctable case".
        C_new and E_new will be different from the old classifier in the
        non-matching components of p0 and p1.

        There
        - E_new will be equal to p1
        - C_new will be equal to p0
        respectively.

        Parameters
        ----------
        old: Classifier
            Old classifier that will be cloned and changed
        p0: Perception
            previous perception
        p1: Perception
            perception

        Returns
        -------
        Classifier
            new corrected classifier

        """
        assert p0 != p1
        new_c = Condition(old.condition)
        new_e = Effect(old.effect)

        for idx, (ci, ei, p0i, p1i) in \
                enumerate(zip(old.condition, old.effect, p0, p1)):

            if p0i != p1i:
                new_c[idx] = p0i
                new_e[idx] = p1i

        return Classifier(condition=new_c,
                          action=old.action,
                          effect=new_e,
                          cfg=old.cfg)
예제 #10
0
    def test_should_create_new_classifier_using_covering(self, cfg):
        # given
        action = random.randint(0, cfg.number_of_possible_actions)
        time = random.randint(0, 1000)
        p0 = Perception('01001101')
        p1 = Perception('00011111')

        # when
        new_cl = cover(p0, action, p1, time, cfg)

        # then
        assert new_cl.condition == Condition('#1#0##0#')
        assert new_cl.action == action
        assert new_cl.effect == Effect('#0#1##1#')
        assert new_cl.q == .5
        assert new_cl.r == 0
        assert new_cl.ir == 0
        assert new_cl.tav == 0
        assert new_cl.tga == time
        assert new_cl.talp == time
        assert new_cl.num == 1
        assert new_cl.exp == 0
예제 #11
0
    def test_should_handle_unexpected_case_6(self, cfg):
        # given
        cls = Classifier(condition='0#1####1',
                         action=2,
                         effect='1#0####0',
                         quality=0.38505,
                         reward=1.20898,
                         immediate_reward=0,
                         experience=11,
                         tga=95,
                         talp=873,
                         tav=71.3967,
                         cfg=cfg)
        cls.mark[1].update(['1'])
        cls.mark[3].update(['1'])
        cls.mark[4].update(['0', '1'])
        cls.mark[5].update(['1'])
        cls.mark[6].update(['0', '1'])

        p0 = Perception('01111101')
        p1 = Perception('11011110')
        time = 873

        # when
        new_cls = unexpected_case(cls, p0, p1, time)

        # then
        assert new_cls is not None
        assert Condition('0#1###01') == new_cls.condition
        assert Effect('1#0###10') == new_cls.effect
        assert abs(0.5 - new_cls.q) < 0.1
        assert abs(1.20898 - new_cls.r) < 0.1
        assert abs(0 - new_cls.ir) < 0.1
        assert abs(71.3967 - new_cls.tav) < 0.1
        assert 1 == new_cls.exp
        assert 1 == new_cls.num
        assert time == new_cls.tga
        assert time == new_cls.talp
예제 #12
0
    def test_should_handle_unexpected_case_5(self, cfg):
        # given
        cls = Classifier(condition='00####1#',
                         action=2,
                         effect='########',
                         quality=0.129,
                         reward=341.967,
                         immediate_reward=130.369,
                         experience=201,
                         tga=129,
                         talp=9628,
                         tav=25.08,
                         cfg=cfg)
        cls.mark[2].add('2')
        cls.mark[3].add('1')
        cls.mark[4].add('1')
        cls.mark[5].add('0')
        cls.mark[7].add('0')

        p0 = Perception('00211010')
        p1 = Perception('00001110')
        time = 9628

        # when
        new_cls = unexpected_case(cls, p0, p1, time)

        # then
        assert new_cls is not None
        assert Condition('0021#01#') == new_cls.condition
        assert Effect('##00#1##') == new_cls.effect
        assert abs(0.5 - new_cls.q) < 0.1
        assert abs(341.967 - new_cls.r) < 0.1
        assert abs(130.369 - new_cls.ir) < 0.1
        assert abs(25.08 - new_cls.tav) < 0.1
        assert 1 == new_cls.exp
        assert 1 == new_cls.num
        assert time == new_cls.tga
        assert time == new_cls.talp
예제 #13
0
    def test_should_calculate_specificity(self, _condition, _specificity, cfg):

        cls = Classifier(Condition(_condition), cfg=cfg)
        assert cls.specificity == _specificity
예제 #14
0
    def test_distinguish_general_classifier(self, _c, _e, _result, cfg):
        cl = Classifier(condition=Condition(_c), effect=Effect(_e), cfg=cfg)

        assert cl.is_general() == _result
예제 #15
0
    def test_should_create_general_classifier(self, cfg):
        cl = Classifier.general(action=1, cfg=cfg)

        assert cl.condition == Condition("####")
        assert cl.action == 1
        assert cl.condition == Effect("####")
예제 #16
0
    def is_general(self):
        cl_length = self.cfg.classifier_length

        return self.condition == Condition.empty(cl_length) \
            and self.effect == Effect.empty(cl_length)