コード例 #1
0
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'
コード例 #2
0
ファイル: generate.py プロジェクト: PierreRust/pyDcop
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))
コード例 #3
0
    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)
コード例 #4
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)
コード例 #5
0
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}
コード例 #6
0
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
コード例 #7
0
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}
コード例 #8
0
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
コード例 #9
0
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"}
コード例 #10
0
    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)
コード例 #11
0
ファイル: ising.py プロジェクト: sankarshandamle/pyDcop
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)
コード例 #12
0
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"}
コード例 #13
0
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
コード例 #14
0
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
コード例 #15
0
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
コード例 #16
0
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}
コード例 #17
0
    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)
コード例 #18
0
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'
コード例 #19
0
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
コード例 #20
0
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
コード例 #21
0
ファイル: secp.py プロジェクト: sankarshandamle/pyDcop
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))
コード例 #22
0
ファイル: yamldcop.py プロジェクト: qslim/pyDcop
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
コード例 #23
0
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
コード例 #24
0
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
コード例 #25
0
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
コード例 #26
0
ファイル: generate.py プロジェクト: PierreRust/pyDcop
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))
コード例 #27
0
ファイル: generate.py プロジェクト: PierreRust/pyDcop
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))
コード例 #28
0
ファイル: iot.py プロジェクト: sankarshandamle/pyDcop
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))
コード例 #29
0
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))
コード例 #30
0
ファイル: smallworld.py プロジェクト: sankarshandamle/pyDcop
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))