def test_api_cg_creation_dsa(): # creating a computation graph from API, without relying on a full # description of the DCOP. # Two API level # * DCOP : create a dcop # * Computation graph: # DCOP # works when using an orchestrator that can transform a dcop into a # computation graph and distribute the computation on the set of agents. # Efficient and simple solution when there is a single deployement of the # system at startup. # Computation Graph # create the computations directly # Necessary when there is no central place where the full dcop could be # created. Each agent build the computation it will run, for example when # the definition of the dcop changes at run time or when a new dcop must be # created and solve completely dynamically and runtime without relying on a # central element like an orchestrator. # to create a computation instance, one need: # of course, variable(s) and constraint(s) like for the dcop. # but also # an algo_def : given as input # a comp_node : depends of the type of computation graph, requires a # variable and or constraints # Here we define a simple graph coloring problem with 3 variables: d = Domain('color', '', ['R', 'G']) v1 = Variable('v1', d) v2 = Variable('v2', d) v3 = Variable('v3', d) # We need to define all agents first, because we will need their address # when registering neighbors computation agt1 = Agent('a1', InProcessCommunicationLayer()) agt2 = Agent('a2', InProcessCommunicationLayer()) agt3 = Agent('a3', InProcessCommunicationLayer()) # Agent 1 with Variable v1 # Constraints in which v1 is involved cost_v1 = constraint_from_str('cv1', '-0.1 if v1 == "R" else 0.1 ', [v1]) diff_v1_v2 = constraint_from_str('c1', '1 if v1 == v2 else 0', [v1, v2]) # Computation node for the variable with these constraints node_v1 = chg.VariableComputationNode(v1, [cost_v1, diff_v1_v2]) comp_def = ComputationDef(node_v1, AlgorithmDef.build_with_default_param('dsa')) v1_computation = build_computation(comp_def) # and register the computation and the agents for the neighboring # computations. agt1.add_computation(v1_computation) agt1.discovery.register_computation('v2', 'a2', agt2.address) # Agent 2 with Variable v2 cost_v2 = constraint_from_str('cv2', '-0.1 if v2 == "G" else 0.1 ', [v2]) diff_v2_v3 = constraint_from_str('c2', '1 if v2 == v3 else 0', [v2, v3]) node_v2 = chg.VariableComputationNode(v2, [cost_v2, diff_v2_v3, diff_v1_v2]) comp_def_v2 = ComputationDef(node_v2, AlgorithmDef.build_with_default_param('dsa')) v2_computation = build_computation(comp_def_v2) agt2.add_computation(v2_computation) agt2.discovery.register_computation('v1', 'a1', agt1.address) agt2.discovery.register_computation('v3', 'a3', agt3.address) # Agent 3 with Variable v3 cost_v3 = constraint_from_str('cv3', '-0.1 if v3 == "G" else 0.1 ', [v3]) node_v3 = chg.VariableComputationNode(v3, [cost_v3, diff_v2_v3]) comp_def_v3 = ComputationDef(node_v3, AlgorithmDef.build_with_default_param('dsa')) v3_computation = build_computation(comp_def_v3) agt3.add_computation(v3_computation) agt3.discovery.register_computation('v2', 'a2', agt2.address) # Start and run the 3 agents manually: agts = [agt1, agt2, agt3] for a in agts: a.start() for a in agts: a.run() sleep(1) # let the system run for 1 second for a in agts: a.stop() # As we do not have an ochestrator, we need to collect results manually: assert agt1.computation('v1').current_value != \ agt2.computation('v2').current_value assert agt3.computation('v3').current_value != \ agt2.computation('v2').current_value
def test_api_cg_creation_mgm2(): # This time we solve the same graph coloring problem with the MGM2 # algorithm. # As you can see, the only difference is the creation of the AlgorithmDef # instance with 'mgm2' d = Domain('color', '', ['R', 'G']) v1 = Variable('v1', d) v2 = Variable('v2', d) v3 = Variable('v3', d) # We need to define all agents first, because we will need their address # when registering neighbors computation agt1 = Agent('a1', InProcessCommunicationLayer()) agt2 = Agent('a2', InProcessCommunicationLayer()) agt3 = Agent('a3', InProcessCommunicationLayer()) # Agent 1 with Variable v1 cost_v1 = constraint_from_str('cv1', '-0.1 if v1 == "R" else 0.1 ', [v1]) diff_v1_v2 = constraint_from_str('c1', '1 if v1 == v2 else 0', [v1, v2]) node_v1 = chg.VariableComputationNode(v1, [cost_v1, diff_v1_v2]) comp_def = ComputationDef(node_v1, AlgorithmDef.build_with_default_param('mgm2')) v1_computation = build_computation(comp_def) agt1.add_computation(v1_computation) # We need to register manually as we are not using the directory hosted by # the orchestrator. agt1.discovery.register_computation('v2', 'a2', agt2.address) # Agent 2 with Variable v2 cost_v2 = constraint_from_str('cv2', '-0.1 if v2 == "G" else 0.1 ', [v2]) diff_v2_v3 = constraint_from_str('c2', '1 if v2 == v3 else 0', [v2, v3]) node_v2 = chg.VariableComputationNode(v2, [cost_v2, diff_v2_v3, diff_v1_v2]) comp_def_v2 = ComputationDef(node_v2, AlgorithmDef.build_with_default_param('mgm2')) v2_computation = build_computation(comp_def_v2) agt2.add_computation(v2_computation) agt2.discovery.register_computation('v1', 'a1', agt1.address) agt2.discovery.register_computation('v3', 'a3', agt3.address) # Agent 3 with Variable v3 cost_v3 = constraint_from_str('cv3', '-0.1 if v3 == "G" else 0.1 ', [v3]) node_v3 = chg.VariableComputationNode(v3, [cost_v3, diff_v2_v3]) comp_def_v3 = ComputationDef(node_v3, AlgorithmDef.build_with_default_param('mgm2')) v3_computation = build_computation(comp_def_v3) agt3.add_computation(v3_computation) agt3.discovery.register_computation('v2', 'a2', agt2.address) # Start and run the 3 agents manually: agts = [agt1, agt2, agt3] for a in agts: a.start() for a in agts: a.run() sleep(1) # let the system run for 1 second for a in agts: a.stop() # As we do not have an orchestrator, we need to collect results manually. # As with MGM, MGM2 does not necessarily find the optimal solution, # depending on the start affectation (which may require a 3-coordinated # change and thus is not possible with mgm2), so we just check the # hard constraints assert agt1.computation('v1').current_value != \ agt2.computation('v2').current_value assert agt3.computation('v3').current_value != \ agt2.computation('v2').current_value