def test_dcop_add_agents_from_list(): dcop = DCOP() a1 = AgentDef('a1') a2 = AgentDef('a2') dcop.add_agents([a1, a2]) assert dcop.agent('a1').name == 'a1' assert dcop.agent('a2').name == 'a2'
def generate_ising(args): domain_size = args.range size = args.size d = VariableDomain('d', 'dummy', range(domain_size)) variables = {} constraints = {} for i in range(size): for j in range(size): v = Variable('v{}_{}'.format(i, j), d, floor(domain_size * random.random())) variables[(i, j)] = v for i, j in variables: c = _create_ising_constraint(i, j, i, (j + 1) % size, domain_size, variables) constraints[(i, j, i, (j + 1) % size)] = c c = _create_ising_constraint(i, j, (i + 1) % size, j, domain_size, variables) constraints[(i, j, (i + 1) % size), j] = c dcop = DCOP('radom ising', 'min') #dcop.domains = {'d': d} #dcop.variables = variables dcop._agents_def = {} for c in constraints.values(): dcop.add_constraint(c) if args.output: outputfile = args.output[0] write_in_file(outputfile, dcop_yaml(dcop)) else: print(dcop_yaml(dcop))
def test_build_single_var(self): v1 = Variable('v1', [1, 2, 3]) dcop = DCOP('test', 'min') dcop.variables = {'v1': v1} cg = build_computation_graph(dcop) self.assertEqual(len(cg.nodes), 1) self.assertEqual(cg.computation('v1').variable, v1) self.assertEqual(len(cg.links), 0)
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_dcop_add_constraint_is_enough(): dcop = DCOP() d = VariableDomain('test', 'test', values=range(10)) v1 = Variable('v1', d) v2 = Variable('v2', d) c1 = constraint_from_str('c1', '0 if v1 != v2 else 1000', [v1, v2]) dcop.add_constraint(c1) assert dcop.constraints == {'c1': c1} assert dcop.variables == {'v1': v1, 'v2': v2} assert dcop.domains == {'test': d}
def test_graph_density(): d = Domain('d', 'test', [1, 2, 3]) v1 = Variable('v1', d) v2 = Variable('v2', d) v3 = Variable('v3', d) c1 = constraint_from_str('c1', 'v1 * 0.5 + v2 - v3', [v1, v2, v3]) dcop = DCOP('dcop_test', 'min') dcop.add_constraint(c1) graph = build_computation_graph(dcop) density = graph.density() assert density == 1 / 3
def test_filter_dcop(): dcop = DCOP() d = VariableDomain('test', 'test', values=range(10)) v1 = Variable('v1', d) v2 = Variable('v2', d) v3 = Variable('v3', d) dcop += 'c1', '0 if v1 != v2 else 1000', [v1, v2] dcop.add_variable(v3) assert dcop.variables == {'v1': v1, 'v2': v2, "v3": v3} filtered = filter_dcop(dcop) assert filtered.variables == {'v1': v1, 'v2': v2}
def test_api_dcop_graph_coloring(): # Graph coloring with 3 variables and color preferences dcop = DCOP('test') # Domain and variables d = Domain('color', '', ['R', 'G']) variables = create_variables('v', [1, 2, 3], d) # Creating constraints using the convenience += notation # We could also use the more verbose dcop.add_constraint method. # Variable(s) and domain(s) involved in the constraint are automatically # added to the dcop. # unary constraints for preferences dcop += 'cost_1', '-0.1 if v1 == "R" else 0.1 ', variables dcop += 'cost_2', '-0.1 if v2 == "G" else 0.1 ', variables dcop += 'cost_3', '-0.1 if v3 == "G" else 0.1 ', variables # coloring constraints : v1 != v2 != v3 dcop += 'c1', '1 if v1 == v2 else 0', variables dcop += 'c2', '1 if v3 == v2 else 0', variables # let's check the dcop really has all required domain, variables and # constraints assert len(dcop.variables) == 3 assert 'v1' in dcop.variables assert len(dcop.domains) == 1 assert 'color' in dcop.domains assert len(dcop.constraints) == 5 assert 'cost_3' in dcop.constraints assert 'c2' in dcop.constraints
def test_solve_max(toy_pb): variables, constraints = toy_pb dcop = DCOP(name="toy", variables={v.name: v for v in variables}, constraints={c.name: c for c in constraints}, objective="max") dcop.add_agents(create_agents("a", [1, 2, 3, 4])) assignment = solve(dcop, "syncbb", "oneagent") # Note: this is supposed to be exactly the same pb as bellow assert assignment == {"vA": "G", "vB": "R", "vC": "R", "vD": "G"}
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 generate_ising( row_count: int, col_count: int, bin_range: float, un_range: float, extensive: bool, no_agents: bool, fg_dist: bool, var_dist: bool, ) -> Tuple[DCOP, Dict, Dict]: grid_graph = nx.grid_2d_graph(row_count, col_count, periodic=True) domain = Domain("var_domain", "binary", [0, 1]) variables = generate_binary_variables(grid_graph, domain) constraints = {} unary_constraints = generate_unary_constraints(variables, un_range, extensive) constraints.update(unary_constraints) binary_constraints = generate_binary_constraints( grid_graph, variables, bin_range, extensive ) constraints.update(binary_constraints) agents = {} fg_mapping = defaultdict(lambda: []) var_mapping = defaultdict(lambda: []) for (row, col) in grid_graph.nodes: agent = AgentDef(f"a_{row}_{col}") agents[agent.name] = agent left = (row - 1) % row_count down = (col + 1) % col_count if var_dist: var_mapping[agent.name].append(f"v_{row}_{col}") if fg_dist: fg_mapping[agent.name].append(f"v_{row}_{col}") fg_mapping[agent.name].append(f"cu_v_{row}_{col}") # Sort coordinate to make sure we build the name in the same order as when # creating the constraints: (r1, c1), (r2, c2) = sorted([(row, col), (left, col)]) fg_mapping[agent.name].append(f"cb_v_{r1}_{c1}_v_{r2}_{c2}") (r1, c1), (r2, c2) = sorted([(row, col), (row, down)]) fg_mapping[agent.name].append(f"cb_v_{r1}_{c1}_v_{r2}_{c2}") name = f"Ising_{row_count}_{col_count}_{bin_range}_{un_range}" if no_agents: agents = {} dcop = DCOP( name, domains={"var_domain": domain}, variables={v.name: v for v in variables.values()}, agents=agents, constraints=constraints, ) return dcop, dict(var_mapping), dict(fg_mapping)
def test_solve_min(toy_pb): variables, constraints = toy_pb dcop = DCOP(name="toy", variables={v.name: v for v in variables}, constraints={c.name: c for c in constraints}, objective="min") dcop.add_agents(create_agents("a", [1, 2, 3, 4])) assignment = solve(dcop, "syncbb", "oneagent") # Note: this is exactly the same pb as in the file bellow # dcop = load_dcop_from_file(["/pyDcop/tests/instances/graph_coloring_tuto.yaml"]) assert assignment == {"vA": "G", "vB": "G", "vC": "G", "vD": "G"}
def test_density_two_var_one_factor(): dcop = DCOP('test', 'min') d1 = Domain('d1', '--', [1, 2, 3]) v1 = Variable('v1', d1) v2 = Variable('v2', d1) dcop += 'c1', '0.5 * v1 + v2', [v1, v2] g = build_computation_graph(dcop) assert g.density() == 4 / 6
def test_one_var_one_factor(): dcop = DCOP('test', 'min') d1 = Domain('d1', '--', [1, 2, 3]) v1 = Variable('v1', d1) dcop += 'c1', '0.5 * v1', [v1] g = build_computation_graph(dcop) assert len(g.links) == 1 assert len(g.nodes) == 2
def test_filter_dcop_unary_constraint_accepted(): dcop = DCOP() d = VariableDomain('test', 'test', values=range(10)) v1 = Variable('v1', d) v2 = Variable('v2', d) v3 = Variable('v3', d) v4 = Variable('v4', d) dcop += 'c1', '0 if v1 != v2 else 1000', [v1, v2] # unary constraint on V3 dcop += 'c2', 'v3 * 0.5', [v3] dcop.add_variable(v4) filtered = filter_dcop(dcop, accept_unary=False) # c2 and v3 must stay here, as we accept unary constraints, but v4 must be gone assert "v3" in filtered.variables assert "c2" in filtered.constraints assert "v4" not in filtered.variables
def test_dcop_add_constraint_easy_api(): dcop = DCOP() d = VariableDomain('test', 'test', values=range(10)) v1 = Variable('v1', d) v2 = Variable('v2', d) dcop += 'c1', '0 if v1 != v2 else 1000', [v1, v2] assert 'c1' in dcop.constraints assert dcop.variables == {'v1': v1, 'v2': v2} assert dcop.domains == {'test': d}
def test_3nodes_tree_cycle(self): domain = ['a', 'b', 'c'] x1 = Variable('x1', domain) x2 = Variable('x2', domain) x3 = Variable('x3', domain) variables = [x1, x2, x3] r1 = NAryFunctionRelation(lambda x, y: x + y, [x1, x2], name='r1') r2 = NAryFunctionRelation(lambda x, y: x + y, [x1, x3], name='r2') r3 = NAryFunctionRelation(lambda x, y: x + y, [x2, x3], name='r3') relations = [r1, r2, r3] dcop = DCOP('test', 'min') dcop.add_constraint(r1) dcop.add_constraint(r2) dcop.add_constraint(r3) cg = build_computation_graph(dcop) self.assertEqual(len(cg.nodes), len(variables)) self.assertEqual(len(cg.roots), 1) # All variables have the same number of neighbors, they could all be # root self.assertIn(cg.roots[0].variable, [x1, x2, x3]) self.assertEqual(cg.roots[0].parent, None) root = _generate_dfs_tree(variables, relations, root=x1) self.assertEqual(root.variable, x1) self.assertEqual(root.parent, None)
def test_dcop_add_agents_from_dict(): dcop = DCOP() agts = create_agents('a', [1, 2, 3]) dcop.add_agents(agts) assert dcop.agent('a1').name == 'a1' assert dcop.agent('a2').name == 'a2' assert dcop.agent('a3').name == 'a3'
def create_dcop(): dcop = DCOP('test') # Domain and vraibales d = Domain('color', '', ['R', 'G']) variables = create_variables('v', [1, 2, 3], d) # unary constraints for preferences dcop += 'cost_1', '-0.1 if v1 == "R" else 0.1 ', variables dcop += 'cost_2', '-0.1 if v2 == "G" else 0.1 ', variables dcop += 'cost_3', '-0.1 if v3 == "G" else 0.1 ', variables # coloring constraints : v1 != v2 != v3 dcop += 'c1', '1 if v1 == v2 else 0', variables dcop += 'c2', '1 if v3 == v2 else 0', variables return dcop
def load_dcop(dcop_str: str) -> DCOP: loaded = yaml.load(dcop_str) if 'name' not in loaded: raise ValueError('Missing name in dcop string') if 'objective' not in loaded or loaded['objective'] not in ['min', 'max']: raise ValueError('Objective is mandatory and must be min or max') dcop = DCOP(loaded['name'], loaded['objective'], loaded['description'] if 'description' in loaded else '') dcop.domains = _build_domains(loaded) dcop.variables = _build_variables(loaded, dcop) dcop.external_variables = _build_external_variables(loaded, dcop) dcop._constraints = _build_constraints(loaded, dcop) dcop._agents_def = _build_agents(loaded) dcop.dist_hints = _build_dist_hints(loaded, dcop) return dcop
def generate_secp(args): logger.info("Generate SECP %s", args) light_count = args.lights model_count = args.models rule_count = args.rules capacity = args.capacity max_model_size = args.max_model_size max_rule_size = args.max_rule_size light_domain = Domain("light", "light", range(0, 5)) lights_var, lights_cost = build_lights(light_count, light_domain) models_var, models_constraints = build_models( light_domain, lights_var, max_model_size, model_count ) rules_constraints = build_rules(rule_count, lights_var, models_var, max_rule_size) # Agents : one for each light agents = build_agents(lights_var, lights_cost, capacity) # Force # * each light variable to be hosted on the corresponding agent # * model constraint and var are preferred on the same agent variables = lights_var.copy() variables.update(models_var) constraints = models_constraints.copy() constraints.update(lights_cost) constraints.update(rules_constraints) dcop = DCOP( "graph coloring", "min", domains={"light_domain": light_domain}, variables=variables, agents=agents, constraints=constraints, ) if args.output: outputfile = args.output write_in_file(outputfile, dcop_yaml(dcop)) else: print(dcop_yaml(dcop))
def load_dcop(dcop_str: str) -> DCOP: loaded = yaml.load(dcop_str, Loader=yaml.FullLoader) if "name" not in loaded: raise ValueError("Missing name in dcop string") if "objective" not in loaded or loaded["objective"] not in ["min", "max"]: raise ValueError("Objective is mandatory and must be min or max") dcop = DCOP( loaded["name"], loaded["objective"], loaded["description"] if "description" in loaded else "", ) dcop.domains = _build_domains(loaded) dcop.variables = _build_variables(loaded, dcop) dcop.external_variables = _build_external_variables(loaded, dcop) dcop._constraints = _build_constraints(loaded, dcop) dcop._agents_def = _build_agents(loaded) dcop.dist_hints = _build_dist_hints(loaded, dcop) return dcop
def test_filter_dcop_unary_constraint(): dcop = DCOP() d = VariableDomain('test', 'test', values=range(10)) v1 = Variable('v1', d) v2 = Variable('v2', d) v3 = Variable('v3', d) dcop += 'c1', '0 if v1 != v2 else 1000', [v1, v2] # unary constraint on V3 dcop += 'c2', 'v3 * 0.5', [v3] assert dcop.variables == {'v1': v1, 'v2': v2, "v3": v3} filtered = filter_dcop(dcop) # v3 is only involved in unary constraints c2 => v3 and c2 should be gone assert filtered.variables == {'v1': v1, 'v2': v2} assert "c2" not in filtered.constraints
def test_build_graph_from_dcop(): d = Domain('d', 'test', [1, 2, 3]) v1 = Variable('v1', d) v2 = Variable('v2', d) v3 = Variable('v3', d) dcop = DCOP('dcop_test', 'min') dcop += 'c1', 'v1 * 0.5 + v2 - v3', [v1, v2, v3] c1 = dcop.constraints['c1'] graph = build_computation_graph(dcop) links = list(graph.links) assert 1 == len(links) assert ConstraintLink(c1.name, {'v1', 'v2', 'v3'}) in links nodes = list(graph.nodes) assert 3 == len(nodes) assert VariableComputationNode(v1, [c1]) in nodes assert VariableComputationNode(v2, [c1]) in nodes assert VariableComputationNode(v3, [c1]) in nodes
def dcop_graphcoloring_3(): """ Build a simple 3-variable graph coloring problem. v1--v2--v3 Each variable has a cost function which makes it prefer one color: v1 prefers R v2 prefers G v3 prefers G Of course, the preferences of v2 and v3 conflict. The best affectation is v1 - R v2 - G v3 - R Returns ------- """ dcop = DCOP('graphcoloring_3') # Domain and variables d = Domain('color', '', ['R', 'G']) variables = create_variables('v', ['1', '2', '3'], d) # unary constraints for preferences dcop += 'cost_1', '-0.1 if v1 == "R" else 0.1 ', variables dcop += 'cost_2', '-0.1 if v2 == "G" else 0.1 ', variables dcop += 'cost_3', '-0.1 if v3 == "G" else 0.1 ', variables # coloring constraints : v1 != v2 != v3 dcop += 'c1', '1 if v1 == v2 else 0', variables dcop += 'c2', '1 if v3 == v2 else 0', variables # Note that we do not define the agents for this dcop here, # as the number of agents depends on the test case we will use the dcop for. return dcop
def generate_mixed_problem(args): logger.debug('generate_mixed_problem %s ', args) variable_count = args.variable_count constraint_count = args.constraint_count density = args.density real_density = density domain_range = args.range arity = args.arity auto_agents = args.agents is None capacity = args.capacity agents_count = variable_count if auto_agents else args.agents nb_max_edges = constraint_count * min(arity, variable_count) edges_count = int(nb_max_edges * density) hard_count = int(args.hard_constraint * edges_count) logger.info( 'Generating random DCOP graph with %s variables, whose domain ' 'are [0;%s], %s edges, %s agents, %s hard ' 'constraints and %s soft constraints', variable_count, domain_range - 1, edges_count, agents_count, hard_count, constraint_count - hard_count) if arity > variable_count: raise ValueError( "The arity of a constraint must be at most the " "number of variable. Arity: {}, Nb variables: {}".format( arity, variable_count)) if hard_count < 0: raise ValueError( "The argument '-h' (or '--hard_count') must be " "between 0 and 1. Currently set to: {}".format(hard_count)) # Create sets for the bipartite graph if constraint_count <= 0: raise ValueError( "The argument '-c' (or '--constraint_count') must be " "strictly positive. Currently set to: {}".format(constraint_count)) if variable_count < 0: raise ValueError( "The argument '-v' (or '--variable_count') must be " "at least 1. Currently set to: {}".format(variable_count)) if arity <= 0: raise ValueError("The argument '-a' (or '--arity') must be " "at least 1. Currently set to: {}".format(arity)) d = VariableDomain('levels', 'level', range(domain_range)) variables = {} agents = {} constraints = {} if arity == 1: if constraint_count != variable_count: raise ValueError("For max arity 1 you need the same number of " "variables, constraints and edges. You asked " "for {} variables and {} constraints.".format( variable_count, constraint_count)) nodes = [i + 1 for i in range(variable_count)] constraints_list = [("c{}".format(i + 1), 'hard') if i < hard_count else ("c{}".format(i + 1), 'soft') for i in range(constraint_count)] variables = {} constraints = {} while len(nodes) != 0: n = nodes.pop() c = constraints_list.pop( random.randint(0, len(constraints_list) - 1)) w = choose_weight() hard = c[1] == 'hard' objective = find_objective([w], domain_range - 1, hard) if hard: expression = "float('inf') if " + str(w) + "*v" + str(n) +\ " != " + str(objective) + " else 0" else: expression = str(w) + "*v" + str(n) + " - " + str(objective) v = Variable("v" + str(n), d) variables["v" + str(n)] = v constraints[c[0]] = relation_from_str(c[0], expression, [v]) if auto_agents: a_name = 'a' + str(n) agents[a_name] = AgentDef(a_name, capacity) if not auto_agents: for i in range(agents_count): a_name = 'a' + str(i) agents[a_name] = AgentDef(a_name, capacity) elif arity == 2: edges_count = int(variable_count * (variable_count - 1) * density / 2) if constraint_count != edges_count: logger.warning("edges count is different of constraint count ({} " "!= {}) but for arity 2, constraints are the deges" "of the graph. We use the density ({}) to determine" " the number of edges".format( edges_count, constraint_count, density)) is_connected = False while not is_connected: graph = nx.gnp_random_graph(variable_count, density) is_connected = nx.is_connected(graph) # Compute nb of hard constraints regarding the true density real_density = nx.density(graph) hard_count = args.hard_constraint * real_density * args.variable_count\ * (args.variable_count + 1) / 2 for i, node in enumerate(graph.nodes_iter()): logger.debug('node %s - %s', node, i) name = 'v' + str(i) variables[name] = Variable(name, d) if auto_agents: a_name = 'a' + str(i) agents[a_name] = AgentDef(a_name, capacity) if not auto_agents: for i in range(agents_count): a_name = 'a' + str(i) agents[a_name] = AgentDef(a_name, capacity) constraints = {} for i, edge in enumerate(graph.edges_iter()): logger.debug('edge %s - %s', edge, i) name = 'c' + str(i) u, v = edge weights = [round(choose_weight(), 2), round(choose_weight(), 2)] # Create hard_constraints if i < hard_count: objective = round(find_objective(weights, domain_range, True), 2) expression = "0 if v{} != v{} else float(" \ "'inf')".format(u, v) else: max_val = (weights[0] + weights[1]) * domain_range expression = 'abs(v{} + v{} - {})'\ .format(u, v, round(random.uniform(0, max_val), 2)) constraints[name] = relation_from_str(name, expression, variables.values()) logger.debug(repr(constraints[name])) else: if edges_count < constraint_count and arity != 1: raise ValueError( "The number of edges must be greater or equal to the " "number of constraints. Otherwise you have unused " "constraints. Edges: {}, Constraints: {}".format( edges_count, constraint_count)) nodes = [i for i in list(range(variable_count))] constraints = [("c{}".format(i), "hard") if i < hard_count else ("c{}".format(i), "soft") for i in list(range(constraint_count))] # Randomly add edges edges = defaultdict(lambda: []) # final set of edges # Available edges at a given run available_edges = {n: constraints.copy() for n in nodes} # First, make sure each variable has one constraint for n in nodes: if constraints: node = n c = constraints.pop(random.randint(0, len(constraints) - 1)) else: node, c = choose_in_available_edges(available_edges, n) add_edge(node, c, available_edges, edges, arity) logger.debug('Add edge (%s, %s)', n, c) edges_count -= variable_count # Second, make sure each constraint is used for c in constraints: n = random.choice(nodes) add_edge(n, c, available_edges, edges, arity) edges_count -= 1 logger.debug('Add edge (%s, %s)', n, c) # Third, randomly add remaining constraints while edges_count != 0: n, c = choose_in_available_edges(available_edges) if (n, c) == (None, None): # If more edges than possible are asked, returns just the maximum # edges (regarding nodes number and constraints arity) logger.warning( '%s edges were not added because you asked for too' ' many edges regarding the number of constraints (' '%s) and their maximum arity (%s)', edges_count - len(edges), constraint_count, args.arity) break else: add_edge(n, c, available_edges, edges, arity) edges_count -= 1 # Now create a DCOP from the graph for i in nodes: name = 'v' + str(i) variables[name] = Variable(name, d) if auto_agents: a_name = 'a' + str(i) agents[a_name] = AgentDef(a_name, capacity) if not auto_agents: for i in range(agents_count): a_name = 'a' + str(i) agents[a_name] = AgentDef(a_name, capacity) constraints = {} for c, neighbors in edges.items(): logger.debug('Constraint %s, variables: %s', c, neighbors) name, is_hard = c[0], c[1] == 'hard' c_variables = [variables["v" + str(name)] for name in neighbors] addition_string = "" first = True weights = [] max_val = 0 for i in neighbors: # Add random weights in constraints m = round(choose_weight(), 2) weights.append(m) max_val += m * (domain_range - 1) if not first: addition_string += ' + ' else: first = False if m != 1: addition_string += str(m) + '*' addition_string += 'v' + str(i) + ' ' # To ensure that our hard constraints are achievable, we use # the value obtained for a set of random values (in the domain) # as the objective. objective = round(find_objective(weights, domain_range, is_hard), 2) if is_hard: expression = "0 if " + addition_string + " == " + \ str(objective) + " else float('inf')" else: const_function = "abs(" + addition_string if objective: expression = const_function + " - " + str(objective) + ")" else: expression = addition_string constraints[name] = relation_from_str(name, expression, c_variables) logger.debug(repr(constraints[name])) dcop = DCOP('mixed constraints problem', 'min', domains={'levels': d}, variables=variables, constraints=constraints, agents=agents) if args.output is not None: outputfile = args.output[0] if args.correct_density: outputfile = correct_density(outputfile, real_density) write_in_file(outputfile, dcop_yaml(dcop)) else: print(dcop_yaml(dcop))
def generate_graph_coloring(args): logger.debug('generate_graph_coloring %s ', args) node_count = args.node_count density = args.density color_count = args.color_count auto_agents = args.agents is None agents_count = node_count if auto_agents else args.agents capacity = args.capacity logger.info( 'Generating random graph coloring with %s variables, ' '%s colors, target density %s and %s agents', node_count, color_count, args.density, agents_count) # First a random graph is_connected = False if not args.allow_subgraph: while not is_connected: graph = nx.gnp_random_graph(args.node_count, density) is_connected = nx.is_connected(graph) else: graph = nx.gnp_random_graph(args.node_count, density) is_connected = nx.is_connected(graph) real_density = nx.density(graph) logger.info(nx.info(graph)) logger.info('Connected : %s', nx.is_connected(graph)) logger.info('Density %s', nx.density(graph)) # Now create a DCOP from the graph d = VariableDomain('colors', 'color', range(color_count)) variables = {} agents = {} for i, node in enumerate(graph.nodes_iter()): logger.debug('node %s - %s', node, i) name = 'v' + str(i) variables[name] = Variable(name, d) if auto_agents: a_name = 'a' + str(i) agents[a_name] = AgentDef(a_name, capacity) if not auto_agents: for i in range(agents_count): a_name = 'a' + str(i) agents[a_name] = AgentDef(a_name, capacity) constraints = {} for i, edge in enumerate(graph.edges_iter()): logger.debug('edge %s - %s', edge, i) name = 'c' + str(i) u, v = edge expression = '1000 if v{} == v{} else 0'.format(u, v) constraints[name] = relation_from_str(name, expression, variables.values()) logger.debug(repr(constraints[name])) dcop = DCOP('graph coloring', 'min', domains={'colors': d}, variables=variables, agents=agents, constraints=constraints) if args.output: outputfile = args.output[0] if args.correct_density: outputfile = correct_density(outputfile, real_density) write_in_file(outputfile, dcop_yaml(dcop)) else: print(dcop_yaml(dcop))
def generate_iot(args): print("generate iot ", args.output) # Constraints and variables with a power-law constraint graph: variables, constraints, domain = generate_powerlaw_var_constraints( args.num, args.domain, args.range ) # Build a dcop and computation graph with no agents, just to be able to # compute the footprint of computations: dcop = DCOP( "graph coloring", "min", domains={"d": domain}, variables=variables, agents={}, constraints=constraints, ) graph_module = import_module("pydcop.computations_graph.factor_graph") cg = graph_module.build_computation_graph(dcop) algo_module = load_algorithm_module("maxsum") footprints = {c.name: algo_module.computation_memory(c) for c in cg.nodes} # Generate an agent for each variable computation and assign the # computation to that agent. agents = {} # type: Dict[str, AgentDef] mapping = defaultdict(lambda: []) # type: Dict[str, List[str]] for comp in cg.nodes: if isinstance(comp, VariableComputationNode): a_name = agt_name(comp.name) agt = AgentDef( a_name, capacity=footprints[comp.name] * 100, default_hosting_cost=10, hosting_costs=agt_hosting_costs(comp, cg), default_route=1, routes=agt_route_costs(comp, cg), ) logger.debug( "Create agent %s for computation %s with capacity %s", agt.name, comp.name, agt.capacity, ) agents[agt.name] = agt mapping[agt.name].append(comp.name) # Now, we have created all the agents and distributed all the variables # let's distribute the factor computations. msg_load = msg_load_func(cg, algo_module.communication_load) factor_mapping = distribute_factors(agents, cg, footprints, mapping, msg_load) for a in mapping: mapping[a].extend(factor_mapping[a]) dcop = DCOP( "graph coloring", "min", domains={"d": domain}, variables=variables, agents=agents, constraints=constraints, ) distribution = Distribution(mapping) if args.output: outputfile = args.output write_in_file(outputfile, dcop_yaml(dcop)) dist = distribution.mapping() cost = ilp_compref.distribution_cost( distribution, cg, dcop.agents.values(), computation_memory=algo_module.computation_memory, communication_load=algo_module.communication_load, ) result = { "inputs": { "dist_algo": "io_problem", "dcop": args.output, "graph": "factor_graph", "algo": "maxsum", }, "distribution": dist, "cost": cost, } outputfile = "dist_" + args.output write_in_file(outputfile, yaml.dump(result)) else: print(dcop_yaml(dcop))
def generate(args): slots, events, resources = generate_problem_definition( args.slots_count, args.resources_count, args.max_resource_value, args.events_count, args.max_length_event, args.max_resources_event, ) penalty = args.max_resource_value * args.slots_count * args.resources_count variables, constraints, agents = peav_model(slots, events, resources, penalty) domains = { variable.domain.name: variable.domain for variable in variables.values() } variables = {variable.name: variable for variable in variables.values()} # agents_defs = {agent.name: agent for agent, _ in agents.values()} # Generate agents hosting and route costs agents_defs = {} if not args.no_agents: for agent, agt_variables in agents.items(): kw = {} kw["hosting_costs"] = {v.name: 0 for v in agt_variables} if args.hosting_default: kw["default_hosting_cost"] = args.hosting_default if args.capacity: kw["capacity"] = args.capacity if args.routes_default: kw["default_route"] = args.routes_default agents_defs[agent] = AgentDef(agent, **kw) dcop = DCOP( "MeetingSceduling", objective="max", domains=domains, variables=variables, constraints=constraints, agents=agents_defs, ) if not args.no_agents: distribution = Distribution({ agent.name: [v.name for v in agents[agent.name]] for agent in agents_defs.values() }) if args.output: output_file = args.output with open(output_file, encoding="utf-8", mode="w") as fo: fo.write(dcop_yaml(dcop)) if not args.no_agents: dist_result = { "inputs": { "dist_algo": "peav", "dcop": output_file, "graph": "constraints_graph", "algo": "NA", }, "distribution": distribution.mapping(), "cost": None, } path, ext = splitext(output_file) dist_output_file = f"{path}_dist{ext}" with open(dist_output_file, encoding="utf-8", mode="w") as fo: fo.write(yaml.dump(dist_result)) else: print(dcop_yaml(dcop)) if not args.no_agents: dist_result = { "inputs": { "dist_algo": "peav", "dcop": "NA", "graph": "constraints_graph", "algo": "NA", }, "distribution": distribution.mapping(), "cost": None, } # FIXME proper serialization of the distribution: print(yaml.dump(dist_result))
def generate_small_world(args): logger.debug("generate small world problem %s ", args) # Erdős-Rényi graph aka binomial graph. graph = nx.barabasi_albert_graph(args.num, 2) # import matplotlib.pyplot as plt # plt.subplot(121) # nx.draw(graph) # default spring_layout # plt.show() domain = Domain("d", "d", range(args.domain)) variables = {} agents = {} for n in graph.nodes: v = Variable(var_name(n), domain) variables[v.name] = v logger.debug("Create var for node %s : %s", n, v) constraints = {} for i, (n1, n2) in enumerate(graph.edges): v1 = variables[var_name(n1)] v2 = variables[var_name(n2)] values = random_assignment_matrix([v1, v2], range(args.range)) c = NAryMatrixRelation([v1, v2], values, name=c_name(n1, n2)) logger.debug("Create constraints for edge (%s, %s) : %s", v1, v2, c) constraints[c.name] = c dcop = DCOP( "graph coloring", "min", domains={"d": domain}, variables=variables, agents={}, constraints=constraints, ) graph_module = import_module("pydcop.computations_graph.factor_graph") cg = graph_module.build_computation_graph(dcop) algo_module = load_algorithm_module("maxsum") footprints = {n.name: algo_module.computation_memory(n) for n in cg.nodes} f_vals = footprints.values() logger.info( "%s computations, footprint: \n sum: %s, avg: %s max: %s, " "min: %s", len(footprints), sum(f_vals), sum(f_vals) / len(footprints), max(f_vals), min(f_vals), ) default_hosting_cost = 2000 small_agents = [agt_name(i) for i in range(75)] small_capa, avg_capa, big_capa = 40, 200, 1000 avg_agents = [agt_name(i) for i in range(75, 95)] big_agents = [agt_name(i) for i in range(95, 100)] hosting_factor = 10 for a in small_agents: # communication costs with all other agents comm_costs = {other: 6 for other in small_agents if other != a} comm_costs.update({other: 8 for other in avg_agents}) comm_costs.update({other: 10 for other in big_agents}) # hosting cost for all computations hosting_costs = {} for n in cg.nodes: # hosting_costs[n.name] = hosting_factor * \ # abs(small_capa -footprints[n.name]) hosting_costs[n.name] = footprints[n.name] / small_capa agt = AgentDef( a, default_hosting_cost=default_hosting_cost, hosting_costs=hosting_costs, default_route=10, routes=comm_costs, capacity=small_capa, ) agents[agt.name] = agt logger.debug("Create small agt : %s", agt) for a in avg_agents: # communication costs with all other agents comm_costs = {other: 8 for other in small_agents} comm_costs.update({other: 2 for other in avg_agents if other != a}) comm_costs.update({other: 4 for other in big_agents}) # hosting cost for all computations hosting_costs = {} for n in cg.nodes: # hosting_costs[n.name] = hosting_factor * \ # abs(avg_capa - footprints[n.name]) hosting_costs[n.name] = footprints[n.name] / avg_capa agt = AgentDef( a, default_hosting_cost=default_hosting_cost, hosting_costs=hosting_costs, default_route=10, routes=comm_costs, capacity=avg_capa, ) agents[agt.name] = agt logger.debug("Create avg agt : %s", agt) for a in big_agents: # communication costs with all other agents comm_costs = {other: 10 for other in small_agents} comm_costs.update({other: 4 for other in avg_agents}) comm_costs.update({other: 1 for other in big_agents if other != a}) # hosting cost for all computations hosting_costs = {} for n in cg.nodes: hosting_costs[n.name] = footprints[n.name] / big_capa agt = AgentDef( a, default_hosting_cost=default_hosting_cost, hosting_costs=hosting_costs, default_route=10, routes=comm_costs, capacity=big_capa, ) agents[agt.name] = agt logger.debug("Create big agt : %s", agt) dcop = DCOP( "graph coloring", "min", domains={"d": domain}, variables=variables, agents=agents, constraints=constraints, ) if args.output: outputfile = args.output[0] write_in_file(outputfile, dcop_yaml(dcop)) else: print(dcop_yaml(dcop))