def test_split_in_two_groups_prefa1(self):
        def route(a1, a2):
            if is_same_route((a1, a2), ('a1', 'a2')):
                return 10
            return 1

        def hosting_costa1(a, _):
            if a == 'a1':
                return 0
            return 10

        mapping = lp_model(self.cg,
                           self.agents,
                           footprint=lambda c: 10,
                           capacity=lambda a: 20,
                           route=route,
                           msg_load=lambda c1, c2: 10,
                           hosting_cost=hosting_costa1)

        # Route a1-a2 is costly, either a1 or a2 must be empty
        # as a1 is more attractive, a2 should be empty:
        self.assertTrue(len(mapping['a2']) == 0)

        # And if we make a2 more attractive, a1 is empty:
        mapping = lp_model(self.cg,
                           self.agents,
                           footprint=lambda c: 10,
                           capacity=lambda a: 20,
                           route=route,
                           msg_load=lambda c1, c2: 10,
                           hosting_cost=lambda a, _: 0 if a == 'a2' else 10)

        self.assertTrue(len(mapping['a1']) == 0)
    def test_one_costly_route(self):

        # The route between a1 and a2 is more costly than the other routes
        # so computations should be hosted on a1 and a3 or a3 and a2
        def route(a1, a2):
            if is_same_route((a1, a2), ('a1', 'a2')):
                return 10
            return 1

        # c1 is attracted to a2
        def hosting_cost(a, c):
            if c == 'c1' and a == 'a2':
                return 1
            return 10

        mapping = lp_model(self.cg,
                           self.agents,
                           footprint=lambda c: 10,
                           capacity=lambda a: 10,
                           route=route,
                           msg_load=lambda c1, c2: 10,
                           hosting_cost=hosting_cost)

        # c1 should be hosted on a2 beacause of pref
        # and c2 on a3, to avoid the costly a1-a2 route
        self.assertIn('c1', mapping['a2'])
        self.assertIn('c2', mapping['a3'])
    def test_group_computations(self):

        # No capcity problem : putting all computations on the same agent is
        # the cheapest option.
        mapping = lp_model(self.cg,
                           self.agents,
                           footprint=lambda c: 10,
                           capacity=lambda a: 100,
                           route=lambda a1, a2: 1,
                           msg_load=lambda c1, c2: 10,
                           hosting_cost=lambda c, a: 0)

        self.assertTrue(
            len(mapping['a1']) == 3 or len(mapping['a2']) == 3
            or len(mapping['a3']) == 3)
    def test_sharing_computation(self):

        # given their capcity, each agent must host exactly one of the 3
        # computations
        mapping = lp_model(self.cg,
                           self.agents,
                           footprint=lambda c: 10,
                           capacity=lambda a: 10,
                           route=lambda a1, a2: 1,
                           msg_load=lambda c1, c2: 10,
                           hosting_cost=lambda c, a: 0)

        self.assertEqual(len(mapping['a1']), 1)
        self.assertEqual(len(mapping['a2']), 1)
        self.assertEqual(len(mapping['a3']), 1)
    def test_one_comp_on_each(self):

        # let's use some hardcoded value for footprint, capacity, etc.

        # Each agent can hold exactly one computation, there is only two
        # possible dist
        mapping = lp_model(self.cg,
                           self.agents,
                           footprint=lambda c: 10,
                           capacity=lambda a: 10,
                           route=lambda a1, a2: 10,
                           msg_load=lambda c1, c2: 10,
                           hosting_cost=lambda a, c: 1)

        self.assertEqual(len(mapping['a1']), 1)
        self.assertEqual(len(mapping['a2']), 1)
    def test_split_in_two_groups(self):
        def route(a1, a2):
            if is_same_route((a1, a2), ('a1', 'a2')):
                return 10
            return 1

        mapping = lp_model(self.cg,
                           self.agents,
                           footprint=lambda c: 10,
                           capacity=lambda a: 20,
                           route=route,
                           msg_load=lambda c1, c2: 10,
                           hosting_cost=lambda c, a: 0)

        # route a1-a2 is costly, either a1 or a2 must be empty
        self.assertTrue(len(mapping['a1']) == 0 or len(mapping['a2']) == 0)
    def test_one_comp_on_each_with_pref_competition(self):

        # Both computation are attracted to a2, but c1 is more
        def hosting_cost(a, c):
            if c == 'c1' and a == 'a2':
                return 1
            if c == 'c2' and a == 'a2':
                return 5
            return 10

        mapping = lp_model(self.cg,
                           self.agents,
                           footprint=lambda c: 10,
                           capacity=lambda a: 10,
                           route=lambda a1, a2: 10,
                           msg_load=lambda c1, c2: 10,
                           hosting_cost=hosting_cost)

        self.assertIn('c2', mapping['a1'])
        self.assertIn('c1', mapping['a2'])
    def test_one_comp_on_each_with_hosting_cost(self):

        # This time we introduce a clear preference c1-a2 and c2 - a1
        def hosting_cost(a, c):
            if c == 'c1' and a == 'a2':
                return 0
            if c == 'c2' and a == 'a1':
                return 0
            return 5

        mapping = lp_model(self.cg,
                           self.agents,
                           footprint=lambda c: 10,
                           capacity=lambda a: 10,
                           route=lambda a1, a2: 10,
                           msg_load=lambda c1, c2: 10,
                           hosting_cost=hosting_cost)

        self.assertIn('c2', mapping['a1'])
        self.assertIn('c1', mapping['a2'])
    def test_one_costly_route(self):

        # The route between a1 and a2 is more costly than the other routes
        # so computations should be hosted on a1 and a3 or a3 and a2
        def route(a1, a2):
            if is_same_route((a1, a2), ('a1', 'a2')):
                return 5
            return 1

        mapping = lp_model(self.cg,
                           self.agents,
                           footprint=lambda c: 10,
                           capacity=lambda a: 10,
                           route=route,
                           msg_load=lambda c1, c2: 1,
                           hosting_cost=lambda c, a: 0)

        # hosting on a1 AND a2 is invalid as it would cost more:
        invalid_dist = len(mapping['a1']) == 1 and len(mapping['a2']) == 1
        self.assertFalse(invalid_dist)
    def test_one_comp_on_each_with_pref_competition2(self):

        # Both computation are attrative to a2
        # and a2 has enough capacity for both.
        def hosting_cost(a, c):
            if c == 'c1' and a == 'a2':
                return 5
            if c == 'c2' and a == 'a2':
                return 5
            return 10

        mapping = lp_model(self.cg,
                           self.agents,
                           footprint=lambda c: 10,
                           capacity=lambda a: 20,
                           route=lambda a1, a2: 10,
                           msg_load=lambda c1, c2: 10,
                           hosting_cost=hosting_cost)

        self.assertIn('c2', mapping['a2'])
        self.assertIn('c1', mapping['a2'])
    def test_two_costly_routes(self):

        # The routes a1-a2 and a3-a1 are more costly than the other routes
        # to avoid costly route, computation must be hosted on a2 and a3
        def route(a1, a2):
            if is_same_route((a1, a2), ('a1', 'a2')):
                return 5
            if is_same_route((a1, a2), ('a3', 'a1')):
                return 5
            return 1

        mapping = lp_model(self.cg,
                           self.agents,
                           footprint=lambda c: 10,
                           capacity=lambda a: 10,
                           route=route,
                           msg_load=lambda c1, c2: 1,
                           hosting_cost=lambda c, a: 1)

        # two valid distributions
        valid_dist = ('c1' in mapping['a2'] and 'c2'in mapping['a3']) or \
            ('c1' in mapping['a3'] and 'c2' in mapping['a2'])
        self.assertTrue(valid_dist)