def test_host_on_highest_dependent_agent(self): d1 = VariableDomain('d1', '', [1, 2, 3, 5]) v1 = Variable('v1', d1) v2 = Variable('v2', d1) v3 = Variable('v3', d1) f1 = relation_from_str('f1', 'v1 + v2', [v1, v2]) f2 = relation_from_str('f2', 'v1 - v2 + v3', [v1, v2, v3]) cv1 = VariableComputationNode(v1, ['f1', 'f2']) cv2 = VariableComputationNode(v2, ['f1', 'f2']) cv3 = VariableComputationNode(v3, ['f2']) cf1 = FactorComputationNode(f1) cf2 = FactorComputationNode(f2) cg = ComputationsFactorGraph([cv1, cv2, cv3], [cf1, cf2]) hints = DistributionHints(must_host={'a1': ['v1'], 'a2': ['v2', 'v3']}) # we must set the capacity to make sure that a2 cannot take f1 agents = [AgentDef('a{}'.format(i), capacity=41) for i in range(1, 11)] agent_mapping = distribute(cg, agents, hints, computation_memory=lambda x: 10) print(agent_mapping) self.assertEqual(agent_mapping.agent_for('f1'), 'a1') self.assertEqual(agent_mapping.agent_for('f2'), 'a2') self.assertTrue(is_all_hosted(cg, agent_mapping))
def test_respect_must_host_all_computation_fixed(self): f1 = relation_from_str('f1', 'v1 * 0.5 + v2', [v1, v2]) cv1 = VariableComputationNode(v1, ['f1']) cv2 = VariableComputationNode(v2, []) cf1 = FactorComputationNode(f1) cg = ComputationsFactorGraph([cv1, cv2], [cf1]) a1 = AgentDef("a1", capacity=200, default_hosting_cost=1, hosting_costs={ "f1": 0, "v1": 0 }) a2 = AgentDef("a2", capacity=200, default_hosting_cost=1, hosting_costs={"v2": 0}) agent_mapping = distribute(cg, [a1, a2], hints=None, computation_memory=ms.computation_memory, communication_load=ms.communication_load) self.assertEqual(agent_mapping.agent_for('f1'), 'a1') self.assertEqual(agent_mapping.agent_for('v1'), 'a1') self.assertEqual(agent_mapping.agent_for('v2'), 'a2')
def test_respect_must_host_all_computation_invalid(self): f1 = relation_from_str('f1', 'v1 * 0.5', [v1]) cv1 = VariableComputationNode(v1, ['f1']) cf1 = FactorComputationNode(f1) cg = ComputationsFactorGraph([cv1], [cf1]) a1 = AgentDef("a1", capacity=200, default_hosting_cost=1, hosting_costs={ "f1": 0, "v1": 0 }) a2 = AgentDef("a2", capacity=200, default_hosting_cost=1) # These hints lead to an impossible distribution, as ilp-fgdp requires # each agent to host at least one computation. Here Both # computations are hosted on a1 and there is no computation # available for a2 ! self.assertRaises(ImpossibleDistributionException, distribute, cg, [a1, a2], hints=None, computation_memory=ms.computation_memory, communication_load=ms.communication_load)
def test_comm(self): f1 = relation_from_str('f1', 'v1 * 0.5 + v2 + v3', [v1, v2, v3]) cv1 = VariableComputationNode(v1, ['f1']) cv2 = VariableComputationNode(v2, ['f1']) cv3 = VariableComputationNode(v3, ['f1']) cf1 = FactorComputationNode(f1) cg = ComputationsFactorGraph([cv1, cv2, cv3], [cf1]) a1 = AgentDef("a1", capacity=200, default_hosting_cost=1, hosting_costs={ "v1": 0, "v2": 0 }) a2 = AgentDef("a2", capacity=200, default_hosting_cost=1) a1.capacity = 1000 agent_mapping = distribute(cg, [a1, a2], hints=None, computation_memory=ms.computation_memory, communication_load=ms.communication_load) # As there is enough capacity on a1, factor f1 must go there (where # most of its variable are already hosted) while v3 must go on a2 to # make sure that all agents are used self.assertEqual(agent_mapping.agent_for('f1'), 'a1') self.assertEqual(agent_mapping.agent_for('v3'), 'a2')
def test_comm_not_enough_place(self): f1 = relation_from_str('f1', 'v1 * 0.5 + v2 + v3', [v1, v2, v3]) cv1 = VariableComputationNode(v1, ['f1']) cv2 = VariableComputationNode(v2, ['f1']) cv3 = VariableComputationNode(v3, ['f1']) cf1 = FactorComputationNode(f1) cg = ComputationsFactorGraph([cv1, cv2, cv3], [cf1]) a1 = AgentDef("a1", capacity=200, default_hosting_cost=1, hosting_costs={ "v1": 0, "v2": 0 }) a2 = AgentDef("a2", capacity=200, default_hosting_cost=1) a1.capacity = 15 agent_mapping = distribute(cg, [a1, a2], hints=None, computation_memory=ms.computation_memory, communication_load=ms.communication_load) # As there is enough not capacity on a1, factor f1 and variable v3 # must go on a2 self.assertEqual(agent_mapping.agent_for('f1'), 'a2') self.assertEqual(agent_mapping.agent_for('v3'), 'a2')
def test_raises_if_methods_not_given(self): f1 = relation_from_str('f1', 'v1 * 0.5', [v1]) cv1 = VariableComputationNode(v1, ['f1']) cf1 = FactorComputationNode(f1) cg = ComputationsFactorGraph([cv1], [cf1]) self.assertRaises(ImpossibleDistributionException, distribute, cg, [Agent('a1'), Agent('a2')], hints=None)
def _create_ising_constraint(i, j, i1, j1, domain_size, variables): target = floor(domain_size * random.random()) v = 'v{}_{}'.format(i, j) v1 = 'v{}_{}'.format(i1, j1) c = relation_from_str('c_{}_{}_{}_{}'.format(i, j, i1, j1), '{} + {} - {}'.format(v, v1, target), [variables[(i, j)], variables[i1, j1]]) return c
def test_factor_memory_one_neighbor(self): d1 = VariableDomain("d1", "", [1, 2, 3, 5]) v1 = Variable("v1", d1) f1 = relation_from_str("f1", "v1 * 0.5", [v1]) cv1 = VariableComputationNode(v1, ["f1"]) cf1 = FactorComputationNode(f1) self.assertEqual(computation_memory(cf1), FACTOR_UNIT_SIZE * 4)
def test_factor_memory_one_neighbor(self): d1 = VariableDomain('d1', '', [1, 2, 3, 5]) v1 = Variable('v1', d1) f1 = relation_from_str('f1', 'v1 * 0.5', [v1]) cv1 = VariableComputationNode(v1, ['f1']) cf1 = FactorComputationNode(f1) self.assertEqual(computation_memory(cf1), FACTOR_UNIT_SIZE * 4)
def test_build_alphaijk_one_var_two_fac(self): f1 = relation_from_str('f1', 'v1 * 0.5', [v1]) f2 = relation_from_str('f2', 'v1 * 0.5', [v1]) cv1 = VariableComputationNode(v1, ['f1', 'f2']) cf1 = FactorComputationNode(f1) cf2 = FactorComputationNode(f2) cg = ComputationsFactorGraph([cv1], [cf1, cf2]) agents_names = ['a1', 'a2'] alphas = _build_alphaijk_binvars(cg, agents_names) self.assertEqual(len(alphas), 4) self.assertIn((('v1', 'f1'), 'a1'), alphas) self.assertIn((('v1', 'f2'), 'a1'), alphas) self.assertIn((('v1', 'f1'), 'a2'), alphas) self.assertIn((('v1', 'f2'), 'a2'), alphas) print(alphas)
def test_fac_2var(self): f1 = relation_from_str('f1', 'v1 * 0.5+v2', [v1, v2]) cv1 = VariableComputationNode(v1, ['f1']) cv2 = VariableComputationNode(v2, ['f1']) cf1 = FactorComputationNode(f1) cg = ComputationsFactorGraph([cv1, cv2], [cf1]) # size of the domain of v1 + size domain v2 self.assertEqual( _computation_memory_in_cg('f1', cg, computation_memory), 8)
def test_var_fac_nolink(self): f1 = relation_from_str('f1', '0.5', []) cv1 = VariableComputationNode(v1, []) cf1 = FactorComputationNode(f1) cg = ComputationsFactorGraph([cv1], [cf1]) self.assertEqual( _computation_memory_in_cg('v1', cg, computation_memory), 0) self.assertEqual( _computation_memory_in_cg('f1', cg, computation_memory), 0)
def test_footprint_on_computation_object(): v1 = Variable('v1', [0, 1, 2, 3, 4]) v2 = Variable('v2', [0, 1, 2, 3, 4]) c1 = relation_from_str('c1', '0 if v1 == v2 else 1', [v1, v2]) n1 = VariableComputationNode(v1, [c1]) n2 = VariableComputationNode(v2, [c1]) comp_def = ComputationDef(n1, AlgoDef('dsa', mode='min')) c = build_computation(comp_def) assert c.footprint() == 5
def setUp(self): d1 = VariableDomain('d1', '', [1, 2, 3, 5]) # An secp made of 2 lights, one model and two rule v1 = Variable('v1', d1) v2 = Variable('v2', d1) v3 = Variable('v3', d1) m1 = Variable('m1', d1) mf1 = relation_from_str('mf1', 'v1 + v2 == m1', [v1, v2, m1]) r1 = relation_from_str('r1', 'm1 - v2', [m1, v2]) r2 = relation_from_str('r2', 'v3', [v3]) cv1 = VariableComputationNode(v1, ['mf1']) cv2 = VariableComputationNode(v2, ['mf1', 'r1']) cv3 = VariableComputationNode(v3, ['r2']) cm1 = VariableComputationNode(m1, ['mf1', 'r1']) cmf1 = FactorComputationNode(mf1) cr1 = FactorComputationNode(r1) cr2 = FactorComputationNode(r2) self.cg = ComputationsFactorGraph([cv1, cv2, cv3, cm1], [cmf1, cr1, cr2])
def test_factor_memory_two_neighbor(self): d1 = VariableDomain("d1", "", [1, 2, 3, 4, 5]) v1 = Variable("v1", d1) d2 = VariableDomain("d1", "", [1, 2, 3]) v2 = Variable("v2", d2) f1 = relation_from_str("f1", "v1 * 0.5 + v2", [v1, v2]) cv1 = VariableComputationNode(v1, ["f1"]) cv2 = VariableComputationNode(v2, ["f1"]) cf1 = FactorComputationNode(f1) self.assertEqual(computation_memory(cf1), FACTOR_UNIT_SIZE * (5 + 3))
def test_no_hints(self): d1 = VariableDomain('d1', '', [1, 2, 3, 5]) v1 = Variable('v1', d1) f1 = relation_from_str('f1', 'v1 * 0.5', [v1]) cv1 = VariableComputationNode(v1, ['f1']) cf1 = FactorComputationNode(f1) cg = ComputationsFactorGraph([cv1], [cf1]) agents = [AgentDef('a1', capacity=100), AgentDef('a2', capacity=100)] agent_mapping = distribute(cg, agents, hints=None, computation_memory=lambda x: 10) self.assertTrue(agent_mapping.is_hosted(['v1', 'f1']))
def test_density_two_var_one_factor(self): dcop = DCOP('test', 'min') d1 = VariableDomain('d1', '--', [1, 2, 3]) v1 = Variable('v1', d1) v2 = Variable('v2', d1) c1 = relation_from_str('c1', '0.5 * v1 + v2', [v1, v2]) dcop.add_constraint(c1) g = build_computation_graph(dcop) self.assertEqual(g.density(), 2 / 2)
def test_var_fac_link(self): f1 = relation_from_str('f1', 'v1 * 0.5', [v1]) cv1 = VariableComputationNode(v1, ['f1']) cf1 = FactorComputationNode(f1) cg = ComputationsFactorGraph([cv1], [cf1]) # size of the domain of v1 self.assertEqual( _computation_memory_in_cg('v1', cg, computation_memory), 4 * VARIABLE_UNIT_SIZE) self.assertEqual( _computation_memory_in_cg('f1', cg, computation_memory), 4)
def test_raise_when_not_enough_agents(self): d1 = VariableDomain('d1', '', [1, 2, 3, 5]) v1 = Variable('v1', d1) f1 = relation_from_str('f1', 'v1 * 0.5', [v1]) cv1 = VariableComputationNode(v1, ['f1']) cf1 = FactorComputationNode(f1) cg = ComputationsFactorGraph([cv1], [cf1]) self.assertRaises(ImpossibleDistributionException, distribute, cg, [AgentDef('a1')])
def test_factor_memory_two_neighbor(self): d1 = VariableDomain('d1', '', [1, 2, 3, 4, 5]) v1 = Variable('v1', d1) d2 = VariableDomain('d1', '', [1, 2, 3]) v2 = Variable('v2', d2) f1 = relation_from_str('f1', 'v1 * 0.5 + v2', [v1, v2]) cv1 = VariableComputationNode(v1, ['f1']) cv2 = VariableComputationNode(v2, ['f1']) cf1 = FactorComputationNode(f1) self.assertEqual(computation_memory(cf1), FACTOR_UNIT_SIZE * (5 + 3))
def test_obj_function(self): f1 = relation_from_str('f1', 'v1 * 0.5', [v1]) cv1 = VariableComputationNode(v1, ['f1']) cf1 = FactorComputationNode(f1) cg = ComputationsFactorGraph([cv1], [cf1]) agents_names = ['a1', 'a2'] alphas = _build_alphaijk_binvars(cg, agents_names) obj = _objective_function(cg, communication_load, alphas, agents_names) # In that case, the objective function must depend on two variables: self.assertEqual(len(obj.sorted_keys()), 2)
def test_variable_one_neighbors(self): d1 = VariableDomain("d1", "", [1, 2, 3, 5]) v1 = Variable("v1", d1) f1 = relation_from_str("f1", "v1 * 0.5", [v1]) cv1 = VariableComputationNode(v1, ["f1"]) cf1 = FactorComputationNode(f1) # If a variable has no neighbors, it does not need to keep any cost # and thus requires no memory self.assertEqual(communication_load(cv1, "f1"), HEADER_SIZE + UNIT_SIZE * len(v1.domain)) self.assertEqual(communication_load(cf1, "v1"), HEADER_SIZE + UNIT_SIZE * len(v1.domain))
def test_respect_must_host_for_var(self): f1 = relation_from_str('f1', 'v1 * 0.5', [v1]) cv1 = VariableComputationNode(v1, ['f1']) cf1 = FactorComputationNode(f1) cg = ComputationsFactorGraph([cv1], [cf1]) hints = DistributionHints(must_host={'a1': ['v1']}) agent_mapping = distribute(cg, [a1, a2], hints=hints, computation_memory=ms.computation_memory, communication_load=ms.communication_load) self.assertEqual(agent_mapping.agent_for('v1'), 'a1')
def test_build_two_var(self): v1 = Variable('v1', [1, 2, 3]) v2 = Variable('v2', [1, 2, 3]) c1 = relation_from_str('c1', 'v1 + v2 ', [v1, v2]) dcop = DCOP('test', 'min') dcop.add_constraint(c1) cg = build_computation_graph(dcop) self.assertEqual(len(cg.nodes), 2) self.assertEqual(cg.computation('v1').variable, v1) self.assertEqual(cg.computation('v2').variable, v2) # one parent link, one children link self.assertEqual(len(cg.links), 2)
def test_must_host_one(self): d1 = VariableDomain('d1', '', [1, 2, 3, 5]) v1 = Variable('v1', d1) f1 = relation_from_str('f1', 'v1 * 0.5', [v1]) cv1 = VariableComputationNode(v1, ['f1']) cf1 = FactorComputationNode(f1) cg = ComputationsFactorGraph([cv1], [cf1]) hints = DistributionHints({'a1': ['v1']}, None) agents = [AgentDef('a1', capacity=100), AgentDef('a2', capacity=100)] agent_mapping = distribute(cg, agents, hints, computation_memory=lambda x: 10) self.assertIn('v1', agent_mapping.computations_hosted('a1')) self.assertTrue(is_all_hosted(cg, agent_mapping))
def test_footprint_on_computation_object(): v1 = Variable('v1', [0, 1, 2, 3, 4]) v2 = Variable('v2', [0, 1, 2, 3, 4]) c1 = relation_from_str('c1', '0 if v1 == v2 else 1', [v1, v2]) n1 = VariableComputationNode(v1, [c1]) n2 = VariableComputationNode(v2, [c1]) comp_def = ComputationDef( n1, AlgorithmDef.build_with_default_param('dsa', mode='min')) c = DsaComputation(comp_def) # Must fix unit size otherwise the tests fails when we change the default # value dsa.UNIT_SIZE = 1 footprint = c.footprint() assert footprint == 1
def test_respect_must_host_all_computation_invalid(self): f1 = relation_from_str('f1', 'v1 * 0.5', [v1]) cv1 = VariableComputationNode(v1, ['f1']) cf1 = FactorComputationNode(f1) cg = ComputationsFactorGraph([cv1], [cf1]) hints = DistributionHints(must_host={'a1': ['f1', 'v1']}) # These hints lead to an impossible distribution, as ilp-fgdp requires # each agent to host at least one computation. Here Both # computations are hosted on a1 and there is no computation # available for a2 ! self.assertRaises(ImpossibleDistributionException, distribute, cg, [a1, a2], hints=hints, computation_memory=ms.computation_memory, communication_load=ms.communication_load)
def test_simple_fg(self): d1 = VariableDomain('d1', '', [1, 2, 3, 5]) v1 = Variable('v1', d1) f1 = relation_from_str('f1', 'v1 * 0.5', [v1]) cv1 = VariableComputationNode(v1, ['f1']) cf1 = FactorComputationNode(f1) cg = ComputationsFactorGraph([cv1], [cf1]) agents= [AgentDef('a1'), AgentDef('a2')] distribution = distribute(cg, agents) self.assertEqual(len(distribution.agents), 2) self.assertEqual(len(distribution.computations), 2) self.assertEqual(len(distribution.computations_hosted('a1')), 1) self.assertEqual(len(distribution.computations_hosted('a2')), 1) self.assertNotEqual(distribution.computations_hosted('a2'), distribution.computations_hosted('a1'))
def test_comm_not_enough_place(self): f1 = relation_from_str('f1', 'v1 * 0.5 + v2 + v3', [v1, v2, v3]) cv1 = VariableComputationNode(v1, ['f1']) cv2 = VariableComputationNode(v2, ['f1']) cv3 = VariableComputationNode(v3, ['f1']) cf1 = FactorComputationNode(f1) cg = ComputationsFactorGraph([cv1, cv2, cv3], [cf1]) hints = DistributionHints(must_host={'a1': ['v1', 'v2']}) a1.capacity = 10 agent_mapping = distribute(cg, [a1, a2], hints=hints, computation_memory=ms.computation_memory, communication_load=ms.communication_load) # As there is enough not capacity on a1, factor f1 and variable v3 # must go on a2 self.assertEqual(agent_mapping.agent_for('f1'), 'a2') self.assertEqual(agent_mapping.agent_for('v3'), 'a2')
def test_host_with(self): d1 = VariableDomain('d1', '', [1, 2, 3, 5]) v1 = Variable('v1', d1) v2 = Variable('v2', d1) f1 = relation_from_str('f1', 'v1 * 0.5', [v1]) cv1 = VariableComputationNode(v1, ['f1']) cv2 = VariableComputationNode(v2, []) cf1 = FactorComputationNode(f1) cg = ComputationsFactorGraph([cv1, cv2], [cf1]) hints = DistributionHints(None, {'v1': ['f1']}) agents = [AgentDef('a{}'.format(i), capacity=100) for i in range(1, 11)] agent_mapping = distribute(cg, agents, hints, computation_memory=lambda x: 10) self.assertEqual(agent_mapping.agent_for('v1'), agent_mapping.agent_for('f1')) self.assertTrue(is_all_hosted(cg, agent_mapping))