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)
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
Exemple #3
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_topology_zoo(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))))
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)
Exemple #5
0
def test_opt_dynvmp(request_id):
    req = create_test_request(request_id, set_allowed_nodes=False)
    sub = create_test_substrate_topology_zoo()
    # 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 list(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 list(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()

    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 list(snode_costs.keys()):
        snode_costs[snode] *= 2
    for sedge in list(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))