コード例 #1
0
def test_small_nice_decomposition(req_id):
    req = create_test_request(req_id)
    td_comp = treewidth_model.TreeDecompositionComputation(req)
    tree_decomp = td_comp.compute_tree_decomposition()
    assert tree_decomp.is_tree_decomposition(req)
    sntd = treewidth_model.SmallSemiNiceTDArb(tree_decomp, req)
    assert sntd.is_tree_decomposition(req)
コード例 #2
0
def test_dyn_vmp(request_id):
    req = create_test_request(request_id)
    sub = get_test_substrate()
    alg = treewidth_model.DynVMPAlgorithm(req, sub)

    alg.preprocess_input()
    m = alg.compute_valid_mapping()
    assert set(m.mapping_nodes.keys()) == set(req.nodes)
    assert set(m.mapping_edges.keys()) == set(req.edges)
コード例 #3
0
def test_tw_formulation_precomputed_scenario(request_id):
    # build test scenario
    req = create_test_request(request_id)
    sub = create_test_substrate()
    scenario = datamodel.Scenario(name="test_scen",
                                  substrate=sub,
                                  requests=[req])

    tw_mc = treewidth_model._TreewidthModelCreator(scenario)
    tw_mc.init_model_creator()
コード例 #4
0
def test_shortest_valid_paths_computer(request_id):
    req = create_test_request(request_id, set_allowed_nodes=False)
    sub = create_test_substrate_large()
    # print(req)
    # print(sub)
    vmrc = treewidth_model.ValidMappingRestrictionComputer(sub, req)
    vmrc.compute()

    # uniform edge costs

    edge_costs = {sedge: 1.0 for sedge in sub.edges}

    svpc = treewidth_model.ShortestValidPathsComputer(sub, req, vmrc, edge_costs)

    svpc.compute()

    for reqedge in req.edges:
        for snode_source in sub.nodes:
            for snode_target in sub.nodes:
                if snode_source == snode_target:
                    assert svpc.valid_sedge_costs[reqedge][(snode_source, snode_target)] == 0
                else:
                    assert svpc.valid_sedge_costs[reqedge][(snode_source, snode_target)] >= 1

    # random edge costs

    edge_costs = {sedge: max(1, 1000.0 * random.random()) for sedge in sub.edges}
    for sedge in sub.edges:
        sub.edge[sedge]['cost'] = edge_costs[sedge]

    bellman_ford_time = time.time()
    sub.initialize_shortest_paths_costs()
    bellman_ford_time = time.time() - bellman_ford_time

    svpc = treewidth_model.ShortestValidPathsComputer(sub, req, vmrc, edge_costs)
    dijkstra_time = time.time()
    svpc.compute()
    dijkstra_time = time.time() - dijkstra_time

    for reqedge in req.edges:
        for snode_source in sub.nodes:
            for snode_target in sub.nodes:
                # print svpc.valid_sedge_costs[reqedge][(snode_source, snode_target)]
                # print sub.get_shortest_paths_cost(snode_source, snode_target)
                assert svpc.valid_sedge_costs[reqedge][(snode_source, snode_target)] == pytest.approx(
                    sub.get_shortest_paths_cost(snode_source, snode_target))

    print(
        "\nComputation times were:\n\tBellman-Ford: {}\n\tDijkstra:     {}\n\n\tSpeedup by using Dijkstra: {:2.2f} (<1 is bad)".format(
            bellman_ford_time, dijkstra_time, (bellman_ford_time / dijkstra_time)))
コード例 #5
0
def test_mapping_space_works():
    sub = create_test_substrate()
    req = create_test_request("simple path")
    req.node["i1"]["allowed_nodes"] = ["u", "v"]
    req.node["i2"]["allowed_nodes"] = ["w"]
    req.node["i3"]["allowed_nodes"] = None

    assert set(treewidth_model.mapping_space(req, sub,
                                             ["i1", "i2", "i3"])) == {
                                                 ("u", "w", "u"),
                                                 ("u", "w", "v"),
                                                 ("u", "w", "w"),
                                                 ("v", "w", "u"),
                                                 ("v", "w", "v"),
                                                 ("v", "w", "w"),
                                             }
コード例 #6
0
def test_dyn_vmp_with_allowed_nodes_restrictions(request_id):
    req = create_test_request(request_id)

    sub = get_test_substrate()

    # add some restrictions
    for i in req.nodes:
        num_allowed = random.randint(1, 2)
        req.node[i]["allowed_nodes"] = random.sample(list(sub.nodes),
                                                     num_allowed)

    alg = treewidth_model.DynVMPAlgorithm(req, sub)

    alg.preprocess_input()
    m = alg.compute_valid_mapping()
    assert set(m.mapping_nodes.keys()) == set(req.nodes)
    assert set(m.mapping_edges.keys()) == set(req.edges)
コード例 #7
0
def test_hardcoded_decompositions_are_valid(request_id):
    req = create_test_request(request_id=request_id)
    tree_decomp = create_test_tree_decomposition(
        VALID_TREE_DECOMPOSITIONS[request_id])
    assert tree_decomp.is_tree_decomposition(req)
コード例 #8
0
def test_trivial_decomposition_is_always_valid(request_id):
    req = create_test_request(request_id)
    tree_decomp = treewidth_model.TreeDecomposition("test")
    tree_decomp.add_node("bag_1", frozenset(req.nodes))
    assert tree_decomp.is_tree_decomposition(req)
コード例 #9
0
def test_opt_dynvmp_and_classic_mcf_agree_for_unambiguous_scenario(
        request_id, random_seed, allowed_nodes_ratio, allowed_edges_ratio
):
    random.seed(random_seed)
    print "allowed nodes: {} %, allowed edges: {} %".format(100 * allowed_nodes_ratio, 100 * allowed_edges_ratio)
    req = create_test_request(request_id, set_allowed_nodes=False)
    node_type = "test_type"
    sub = create_test_substrate_large(node_types=[node_type])
    assert set(sub.get_types()) == {node_type}

    num_allowed_nodes = int(allowed_nodes_ratio * len(sub.nodes))
    for i in req.nodes:
        assert req.get_type(i) == node_type
        req.node[i]["allowed_nodes"] = random.sample(list(sub.nodes), num_allowed_nodes)

    num_allowed_edges = int(allowed_edges_ratio * len(sub.edges))
    for ij in req.edges:
        req.edge[ij]["allowed_edges"] = random.sample(list(sub.edges), num_allowed_edges)

    snode_costs = {}
    sedge_costs = {}

    def randomize_substrate_costs():
        # randomize all costs to force unambiguous cost-optimal embedding
        for u in sub.nodes:
            for t in sub.get_supported_node_types(u):
                sub.node[u]["cost"][t] = random.random()
                snode_costs[u] = sub.node[u]["cost"][t]
        for uv in sub.edges:
            sub.edge[uv]["cost"] = random.random()
            sedge_costs[uv] = sub.edge[uv]["cost"]

    randomize_substrate_costs()

    td_comp = treewidth_model.TreeDecompositionComputation(req)
    tree_decomp = td_comp.compute_tree_decomposition()
    sntd = treewidth_model.SmallSemiNiceTDArb(tree_decomp, req)
    opt_dynvmp = treewidth_model.OptimizedDynVMP(sub, req, sntd, snode_costs, sedge_costs)
    times_dynvmp = []
    start_time = time.time()
    opt_dynvmp.initialize_data_structures()
    opt_dynvmp.compute_solution()
    root_cost, mapping = opt_dynvmp.recover_mapping()
    times_dynvmp.append(time.time() - start_time)

    number_of_tests = 10

    times_gurobi = []

    for x in range(number_of_tests):
        def compare_solutions():
            if root_cost is not None:  # solution exists
                assert gurobi_solution is not None
                gurobi_obj = gurobi_solution.status.objValue
                assert abs(root_cost - gurobi_obj) <= 0.0001
                assert mapping.mapping_nodes == gurobi_solution.solution.request_mapping[req].mapping_nodes
                assert mapping.mapping_edges == gurobi_solution.solution.request_mapping[req].mapping_edges
            else:
                assert gurobi_solution is None

        start_time = time.time()
        gurobi = mip.ClassicMCFModel(dm.Scenario("test", sub, [req], objective=dm.Objective.MIN_COST))
        gurobi.init_model_creator()
        gurobi_solution = gurobi.compute_integral_solution()
        times_gurobi.append(time.time()-start_time)

        compare_solutions()

        randomize_substrate_costs()

        start_time = time.time()
        opt_dynvmp.reinitialize(snode_costs, sedge_costs)
        opt_dynvmp.compute_solution()
        root_cost, mapping = opt_dynvmp.recover_mapping()
        times_dynvmp.append(time.time() - start_time)

    gurobi = mip.ClassicMCFModel(dm.Scenario("test", sub, [req], objective=dm.Objective.MIN_COST))
    gurobi.init_model_creator()
    gurobi_solution = gurobi.compute_integral_solution()

    compare_solutions()

    initial_computation_time = times_dynvmp[0]
    other_computation_times = times_dynvmp[1:]
    average_of_others = sum(other_computation_times) / float(len(other_computation_times))
    print("        Request graph size (|V|,|E|):  ({},{})\n"
          "             Width of the request is:  {}\n"
          "      Runtime of initial computation:  {:02.4f} s\n"
          "Runtime of later computations (avg.):  {:02.4f} s\n"
          "               This is a speed-up of:  {:02.2f} times\n"
          "               Total time in Dyn-VMP:  {:02.4f} s\n"
          "                Total time in Gurobi:  {:02.4f} s\n"
          "         Speedup Dyn-VMP over Gurobi:  {:02.2f} times (>1 is good)\n".format(len(req.nodes),
                                                                           len(req.edges),
                                                                           sntd.width,
                                                                           initial_computation_time,
                                                                           average_of_others,
                                                                           initial_computation_time / average_of_others,
                                                                           sum(times_dynvmp),
                                                                           sum(times_gurobi),
                                                                           sum(times_gurobi)/sum(times_dynvmp)))
コード例 #10
0
def test_valid_mapping_restriction_computer(request_id):
    req = create_test_request(request_id, set_allowed_nodes=False)
    sub = create_test_substrate_large()
    # print(req)
    # print(sub)
    vmrc = treewidth_model.ValidMappingRestrictionComputer(sub, req)
    vmrc.compute()

    # assert that all nodes and all edges may be mapped anywhere...
    substrate_node_set = set(sub.nodes)
    substrate_edge_set = set(sub.edges)

    for reqnode in req.nodes:
        allowed_nodes = vmrc.get_allowed_snode_list(reqnode)
        assert set(allowed_nodes) == substrate_node_set

    for reqedge in req.edges:
        allowed_edges = vmrc.get_allowed_sedge_set(reqedge)
        assert allowed_edges == substrate_edge_set

    # set substrate node and edge capacities randomly
    for snode in sub.nodes:
        sub.node[snode]['capacity'] = 2.0 * random.random()

    for sedge in sub.edges:
        sub.edge[sedge]['capacity'] = 2.0 * random.random()

    vmrc = treewidth_model.ValidMappingRestrictionComputer(sub, req)
    vmrc.compute()

    for reqnode in req.nodes:
        allowed_nodes = vmrc.get_allowed_snode_list(reqnode)
        snodes_with_not_enough_capacity = set([snode for snode in sub.nodes
                                               if sub.get_node_capacity(snode) < req.get_node_demand(reqnode)])
        assert snodes_with_not_enough_capacity.union(set(allowed_nodes)) == substrate_node_set

    for reqedge in req.edges:
        allowed_edges = vmrc.get_allowed_sedge_set(reqedge)
        sedges_with_not_enough_capacity = set([sedge for sedge in sub.edges
                                               if sub.get_edge_capacity(sedge) < req.get_edge_demand(reqedge)])
        assert sedges_with_not_enough_capacity.union(set(allowed_edges)) == substrate_edge_set

    snode_list = list(sub.nodes)
    sedge_list = list(sub.edges)

    # now additionally also introduce some mapping restrictions
    for reqnode in req.nodes:
        random.shuffle(snode_list)
        req.set_allowed_nodes(reqnode, snode_list[0:random.randint(1, len(snode_list))])
    for reqedge in req.edges:
        random.shuffle(sedge_list)
        req.set_allowed_edges(reqedge, sedge_list[0:random.randint(1, len(sedge_list))])

    vmrc = treewidth_model.ValidMappingRestrictionComputer(sub, req)
    vmrc.compute()

    for reqnode in req.nodes:
        allowed_nodes = vmrc.get_allowed_snode_list(reqnode)
        snodes_with_not_enough_capacity = set([snode for snode in sub.nodes
                                               if sub.get_node_capacity(snode) < req.get_node_demand(reqnode)])
        forbidden_snodes = set([snode for snode in sub.nodes if snode not in allowed_nodes])
        assert snodes_with_not_enough_capacity.union(forbidden_snodes).union(set(allowed_nodes)) == substrate_node_set

    for reqedge in req.edges:
        allowed_edges = vmrc.get_allowed_sedge_set(reqedge)
        sedges_with_not_enough_capacity = set([sedge for sedge in sub.edges
                                               if sub.get_edge_capacity(sedge) < req.get_edge_demand(reqedge)])
        forbidden_sedges = set([sedge for sedge in sub.edges if sedge not in allowed_edges])
        assert sedges_with_not_enough_capacity.union(forbidden_sedges).union(set(allowed_edges)) == substrate_edge_set
コード例 #11
0
def test_opt_dynvmp(request_id):
    req = create_test_request(request_id, set_allowed_nodes=False)
    sub = create_test_substrate_large()

    print sub.node

    # assert that all nodes and all edges may be mapped anywhere...
    substrate_node_set = set(sub.nodes)
    substrate_edge_set = set(sub.edges)

    # set substrate node and edge capacities high
    for snode in sub.nodes:
        for type in sub.node[snode]['capacity'].keys():
            sub.node[snode]['capacity'][type] = 100

    for sedge in sub.edges:
        sub.edge[sedge]['capacity'] = 100

    snode_list = list(sub.nodes)
    sedge_list = list(sub.edges)
    valid_reqnode_list = [snode for snode in sub.nodes if sub.get_node_capacity(snode) > 1.01]

    # # now additionally also introduce some mapping restrictions
    for reqnode in req.nodes:
        random.shuffle(valid_reqnode_list)

        selected_nodes = []
        while len(selected_nodes) == 0:
            print "selected nodes are {}".format(selected_nodes)
            selected_nodes = valid_reqnode_list[0:random.randint(10, len(valid_reqnode_list))]
        req.set_allowed_nodes(reqnode, selected_nodes)
        print "Allowd nodes for {} are {}.".format(reqnode, req.get_allowed_nodes(reqnode))
    for reqedge in req.edges:
        random.shuffle(sedge_list)
        req.set_allowed_edges(reqedge, sedge_list[0:random.randint(20, len(sedge_list))])
        print "Allowd edges for {} are {}.".format(reqedge, req.get_allowed_edges(reqedge))

    # random edge costs
    edge_costs = {sedge: max(1, 1000.0 * random.random()) for sedge in sub.edges}
    for sedge in sub.edges:
        sub.edge[sedge]['cost'] = 1  # edge_costs[sedge]
    for snode in sub.nodes:
        for type in sub.node[snode]['cost'].keys():
            sub.node[snode]['cost'][type] = 1

    scenario = dm.Scenario("test", sub, [req])
    gurobi = mip.ClassicMCFModel(scenario)
    gurobi.init_model_creator()
    gurobi.model.setParam("LogToConsole", 1)
    gurobi.compute_integral_solution()
    gurobi.model.write("foo.lp")

    td_comp = treewidth_model.TreeDecompositionComputation(req)
    tree_decomp = td_comp.compute_tree_decomposition()
    assert tree_decomp.is_tree_decomposition(req)
    sntd = treewidth_model.SmallSemiNiceTDArb(tree_decomp, req)
    assert sntd.is_tree_decomposition(req)

    opt_dynvmp = treewidth_model.OptimizedDynVMP(sub,
                                                 req,
                                                 sntd)
    opt_dynvmp.initialize_data_structures()
    opt_dynvmp.compute_solution()

    obj = opt_dynvmp.get_optimal_solution_cost()
    if obj is not None:
        costs, mapping_indices = opt_dynvmp.get_ordered_root_solution_costs_and_mapping_indices(maximum_number_of_solutions_to_return=100)
        for index, cost in np.ndenumerate(costs):
            if index == 0:
                assert cost == obj
            print "{}-th best cost is: {} and index is {}".format(index, cost, mapping_indices[index])
        corresponding_mappings = opt_dynvmp.recover_list_of_mappings(mapping_indices)
        print "Number of obtained mappings: {}, mappings: {}".format(len(corresponding_mappings), corresponding_mappings)

    result_mapping = opt_dynvmp.recover_mapping()
    print "Returned mapping! Namely, the following: {}".format(result_mapping)

    # change costs
    snode_costs = opt_dynvmp.snode_costs
    sedge_costs = opt_dynvmp.sedge_costs
    for snode in snode_costs.keys():
        snode_costs[snode] *= 2
    for sedge in sedge_costs.keys():
        sedge_costs[sedge] *= 2

    opt_dynvmp.reinitialize(snode_costs, sedge_costs)
    opt_dynvmp.compute_solution()
    result_mapping = opt_dynvmp.recover_mapping()
    print "Returned mapping! Namely, the following: {}".format(result_mapping)
コード例 #12
0
def test_conversion_to_PACE_format_works(test_data):
    req_id, expected = test_data
    req = create_test_request(req_id)
    td_comp = treewidth_model.TreeDecompositionComputation(req)
    assert td_comp._convert_graph_to_td_input_format() == expected
コード例 #13
0
def test_tree_decomposition_computation_returns_valid_tree_decompositions(
        req_id):
    req = create_test_request(req_id)
    td_comp = treewidth_model.TreeDecompositionComputation(req)
    tree_decomp = td_comp.compute_tree_decomposition()
    assert tree_decomp.is_tree_decomposition(req)