Ejemplo n.º 1
0
def test_gurobi_with_insufficient_node_resources_invalid_substrate_node(
        substrate, triangle_request):
    # triangle_request_copy will be embeddable, while triangle_request will have no valid mapping for node i
    triangle_request_copy = copy.deepcopy(triangle_request)
    triangle_request_copy.name = "test_req_copy"
    requests = [triangle_request, triangle_request_copy]
    for req in requests:
        req.profit = 1.0

    triangle_request.node[i]["demand"] = 1.0
    triangle_request_copy.node[i]["allowed_nodes"] = {"v"}
    substrate.node[u]["capacity"]["t1"] = 0.5

    scenario = datamodel.Scenario("test",
                                  substrate,
                                  requests,
                                  objective=datamodel.Objective.MAX_PROFIT)
    mc = commutativity_model.CommutativityModelCreator(
        scenario,
        gurobi_settings=modelcreator.GurobiSettings(threads=2, timelimit=60))
    mc.init_model_creator()
    solution = mc.compute_fractional_solution()

    assert solution is not None
    assert triangle_request not in solution.request_mapping
    assert len(solution.request_mapping[triangle_request_copy]) > 0
def test_create_constraints_track_node_loads(monkeypatch, substrate,
                                             triangle_request,
                                             import_gurobi_mock):
    MockConstr = import_gurobi_mock.MockConstr
    MockLinExpr = import_gurobi_mock.MockLinExpr
    MockModel = import_gurobi_mock.MockModel

    # add a request node with new type
    l = "l"
    t1, t2 = "t1", "t2"
    triangle_request.add_node(l, 0.75, t2, [v])
    triangle_request.add_edge(l, i, 2.0, None)

    substrate.node[v]["supported_types"].append(t2)
    substrate.node[v]["capacity"][t2] = 100.0
    substrate.node[v]["cost"][t2] = 0.25
    substrate.types.add(t2)

    scenario = datamodel.Scenario("test", substrate, [triangle_request])
    mc = commutativity_model.CommutativityModelCreator(scenario)
    mc.model = MockModel("mock_model")
    mc.preprocess_input()
    mc.create_variables_request_load()
    mc._create_node_mapping_variables()
    mc._create_constraints_track_node_loads()

    ku_index = frozenset([("k", "u")])
    kv_index = frozenset([("k", "v")])

    assert set(mc.model.constrs) == {
        MockConstr(MockLinExpr([
            (-1.0, mc.var_request_load[triangle_request][t2, v]),
            (0.75, mc.var_aggregated_node_mapping[triangle_request][l][v])
        ]),
                   GRB.EQUAL,
                   0.0,
                   name="track_node_load_req[test_req]_type[t2]_snode[v]"),
        MockConstr(MockLinExpr([
            (-1.0, mc.var_request_load[triangle_request][t1, v]),
            (1.0, mc.var_aggregated_node_mapping[triangle_request][j][v]),
            (1.0, mc.var_aggregated_node_mapping[triangle_request][k][v]),
        ]),
                   GRB.EQUAL,
                   0.0,
                   name="track_node_load_req[test_req]_type[t1]_snode[v]"),
        MockConstr(MockLinExpr([
            (-1.0, mc.var_request_load[triangle_request][t1, u]),
            (1.0, mc.var_aggregated_node_mapping[triangle_request][i][u]),
            (1.0, mc.var_aggregated_node_mapping[triangle_request][k][u]),
        ]),
                   GRB.EQUAL,
                   0.0,
                   name="track_node_load_req[test_req]_type[t1]_snode[u]"),
        MockConstr(MockLinExpr([
            (-1.0, mc.var_request_load[triangle_request][t1, w]),
        ]),
                   GRB.EQUAL,
                   0.0,
                   name="track_node_load_req[test_req]_type[t1]_snode[w]"),
    }
Ejemplo n.º 3
0
def test_gurobi_with_insufficient_node_resources_cannot_embed_all(
        substrate, triangle_request):
    triangle_request_copy = copy.deepcopy(triangle_request)
    triangle_request_copy.name = "test_req_copy"
    requests = [triangle_request, triangle_request_copy]
    for req in requests:
        req.profit = 1.0

    triangle_request.node[i]["demand"] = 1.0
    triangle_request_copy.node[i]["demand"] = 1.0
    triangle_request.node[k]["allowed_nodes"] = {"w"}
    triangle_request_copy.node[k]["allowed_nodes"] = {"w"}
    substrate.node[u]["capacity"]["t1"] = 1.5

    scenario = datamodel.Scenario("test",
                                  substrate,
                                  requests,
                                  objective=datamodel.Objective.MAX_PROFIT)
    mc = commutativity_model.CommutativityModelCreator(
        scenario,
        gurobi_settings=modelcreator.GurobiSettings(threads=2, timelimit=60))
    mc.init_model_creator()
    solution = mc.compute_fractional_solution()

    assert solution is not None
    assert len(solution.request_mapping[triangle_request]) > 0
    assert len(solution.request_mapping[triangle_request_copy]) > 0

    flow_sum = sum(solution.mapping_flows[m.name] for req in requests
                   for m in solution.request_mapping[req])
    assert flow_sum == 1.5
def test_extract_edge_mapping_reversed_edge(substrate, triangle_request):
    triangle_request.graph["root"] = j

    scenario = datamodel.Scenario("test", substrate, [triangle_request])

    mc = commutativity_model.CommutativityModelCreator(scenario)
    mc.model = MockModel("mockmodel")
    mc.preprocess_input()
    mc._create_sub_lp_variables()

    ku_index = frozenset([(k, u)])
    kv_index = frozenset([(k, v)])

    ji_sub_lp = list(mc.edge_sub_lp[triangle_request][("j", "i")].values())[0]
    ji_sub_lp.var_node_flow_source[v].x = 0.5
    ji_sub_lp.var_edge_flow[wu].x = 0.5
    ji_sub_lp.var_edge_flow[vw].x = 0.5
    ji_sub_lp.var_node_flow_sink[u].x = 0.5

    partial_mapping = solutions.Mapping("test_mapping", triangle_request,
                                        substrate, True)
    partial_mapping.map_node(j, v)

    assert ji_sub_lp.extract_edge_mapping(partial_mapping) == ([uw,
                                                                wv], u, 0.5)
Ejemplo n.º 5
0
def test_extract_edge_mapping_only_use_exit_with_remaining_node_sink_flow(substrate, triangle_request):
    triangle_request.node[j]["allowed_nodes"] = [v, w]
    scenario = datamodel.Scenario("test", substrate, [triangle_request])

    mc = commutativity_model.CommutativityModelCreator(scenario)
    mc.model = MockModel("mockmodel")
    mc.preprocess_input()
    mc._create_sub_lp_variables()

    ku_index = frozenset([(k, u)])
    ij_sub_lp = mc.edge_sub_lp[triangle_request][ij][ku_index]
    ij_sub_lp.var_node_flow_source[u].x = 1.0

    # This contains 3 mappings with values 0.5, 0.25 and 0.25
    ij_sub_lp.var_edge_flow[uw].x = 0.5
    ij_sub_lp.var_edge_flow[uv].x = 0.5
    ij_sub_lp.var_edge_flow[wv].x = 0.25

    ij_sub_lp.var_node_flow_sink[w].x = 0.25
    ij_sub_lp.var_node_flow_sink[v].x = 0.75

    partial_mapping = solutions.Mapping("test_mapping", triangle_request, substrate, True)
    partial_mapping.map_node(i, u)

    ij_sub_lp._used_flow_source[u] += 0.5
    ij_sub_lp._used_flow[uv] += 0.5
    ij_sub_lp._used_flow_sink[v] += 0.5
    assert ij_sub_lp.extract_edge_mapping(partial_mapping) == ([uw], w, 0.25)

    ij_sub_lp._used_flow_source[u] += 0.25
    ij_sub_lp._used_flow[uw] += 0.25
    ij_sub_lp._used_flow_sink[w] += 0.25
    assert ij_sub_lp.extract_edge_mapping(partial_mapping) == ([uw, wv], v, 0.25)
def test_force_embedding_constraint_multiple_root_mappings(
        tiny_substrate, triangle_request, monkeypatch, import_gurobi_mock):
    MockModel = import_gurobi_mock.MockModel
    MockConstr = import_gurobi_mock.MockConstr
    MockLinExpr = import_gurobi_mock.MockLinExpr

    # Extend the root node's allowed nodes
    triangle_request.node[i]["allowed_nodes"] = set("uv")
    scenario = datamodel.Scenario("test", tiny_substrate, [triangle_request])
    mc = commutativity_model.CommutativityModelCreator(scenario)
    mc.model = MockModel("mock_model")

    mc.preprocess_input()
    mc.create_variables_embedding_decision()
    mc._create_node_mapping_variables()
    mc._create_force_embedding_constraint()

    assert set(mc.model.constrs) == {
        MockConstr(
            MockLinExpr([
                (-1.0, mc.var_embedding_decision[triangle_request]),
                (1.0, mc.var_aggregated_node_mapping[triangle_request][i][u]),
                (1.0, mc.var_aggregated_node_mapping[triangle_request][i][v]),
            ]), gurobipy.GRB.EQUAL, 0.0,
            "force_node_mapping_for_embedded_request_req[test_req]"),
    }
Ejemplo n.º 7
0
def test_extract_edge_mapping_multiple_start_nodes(substrate, triangle_request):
    triangle_request.node[i]["allowed_nodes"] = [u, v]
    scenario = datamodel.Scenario("test", substrate, [triangle_request])

    mc = commutativity_model.CommutativityModelCreator(scenario)
    mc.model = MockModel("mockmodel")
    mc.preprocess_input()
    mc._create_sub_lp_variables()

    ku_index = frozenset([(k, u)])
    ij_sub_lp = mc.edge_sub_lp[triangle_request][ij][ku_index]
    ij_sub_lp.var_node_flow_source[u].x = 0.3
    ij_sub_lp.var_node_flow_source[v].x = 0.7

    ij_sub_lp.var_edge_flow[uv].x = 0.3

    ij_sub_lp.var_node_flow_sink[v].x = 1.0

    partial_mapping = solutions.Mapping("test_mapping", triangle_request, substrate, True)
    partial_mapping.map_node(i, u)

    assert ij_sub_lp.extract_edge_mapping(partial_mapping) == ([uv], v, 0.3)

    partial_mapping = solutions.Mapping("test_mapping", triangle_request, substrate, True)
    partial_mapping.map_node(i, v)

    assert ij_sub_lp.extract_edge_mapping(partial_mapping) == ([], v, 0.7)
def test_reduce_flow_in_modelcreator(substrate, triangle_request, import_gurobi_mock):
    MockModel = import_gurobi_mock.MockModel
    scenario = datamodel.Scenario("test", substrate, [triangle_request])
    mc = commutativity_model.CommutativityModelCreator(scenario)
    mc.model = MockModel("mock_model")
    mc.preprocess_input()
    mc.create_variables_embedding_decision()
    mc._create_node_mapping_variables()
    mc._create_sub_lp_variables()

    ku_index = frozenset([(k, u)])

    mapping = solutions.Mapping("foo", triangle_request, substrate, True)
    mapping.mapping_nodes = {i: u, j: v, k: u}
    mapping.mapping_edges = {ij: [uv], jk: [vw, wu], ik: []}

    mc.reduce_flow(mapping, 0.25)
    assert mc._used_flow_embedding_decision[triangle_request] == 0.25

    assert mc._used_flow_node_mapping[triangle_request][i][u][ku_index] == 0.25
    assert mc._used_flow_node_mapping[triangle_request][j][v][ku_index] == 0.25
    assert mc._used_flow_node_mapping[triangle_request][k][u][frozenset()] == 0.25
    for ij_, uv_list in list(mapping.mapping_edges.items()):
        i_, j_ = ij_
        sub_lp = mc.edge_sub_lp[triangle_request][ij_][ku_index]
        assert sub_lp._used_flow_source[mapping.mapping_nodes[i_]] == 0.25
        assert sub_lp._used_flow_sink[mapping.mapping_nodes[j_]] == 0.25
        for uv_ in uv_list:
            u_, v_ = uv_
            assert sub_lp._used_flow[uv_] == 0.25
def test_create_node_mapping_variables(tiny_substrate, triangle_request,
                                       import_gurobi_mock):
    MockModel = import_gurobi_mock.MockModel
    scenario = datamodel.Scenario("test", tiny_substrate, [triangle_request])
    mc = commutativity_model.CommutativityModelCreator(scenario)
    mc.model = MockModel("mock_model")

    mc.preprocess_input()
    mc._create_node_mapping_variables()

    ku_index = frozenset([(k, u)])
    kv_index = frozenset([(k, v)])

    assert extract_var_names(mc.var_node_mapping[triangle_request][i][u]) == {
        ku_index:
        "node_mapping_req[test_req]_vnode[i]_snode[u]_comm_index[k_u]",
        kv_index:
        "node_mapping_req[test_req]_vnode[i]_snode[u]_comm_index[k_v]",
    }
    assert extract_var_names(mc.var_node_mapping[triangle_request][j][v]) == {
        ku_index:
        "node_mapping_req[test_req]_vnode[j]_snode[v]_comm_index[k_u]",
        kv_index:
        "node_mapping_req[test_req]_vnode[j]_snode[v]_comm_index[k_v]",
    }
    assert extract_var_names(mc.var_node_mapping[triangle_request][k][u]) == {
        frozenset():
        "node_mapping_req[test_req]_vnode[k]_snode[u]_comm_index[]",
    }
    assert extract_var_names(mc.var_node_mapping[triangle_request][k][v]) == {
        frozenset():
        "node_mapping_req[test_req]_vnode[k]_snode[v]_comm_index[]",
    }
Ejemplo n.º 10
0
def test_commutativity_with_gurobi(triangle_request, substrate):
    triangle_request.profit = 10000
    triangle_request.add_node("l", 0.75, "t1", [v])
    triangle_request.add_edge("l", i, 0.5, None)

    scenario = datamodel.Scenario("test",
                                  substrate, [triangle_request],
                                  objective=datamodel.Objective.MAX_PROFIT)
    mc = commutativity_model.CommutativityModelCreator(scenario)
    mc.init_model_creator()
    solution = mc.compute_fractional_solution()
    assert solution is not None
Ejemplo n.º 11
0
def test_solve_single_request_scenarios_with_gurobi(request_id, substrate):
    request = create_request(request_id)
    request.profit = 1.0

    scenario = datamodel.Scenario("test",
                                  substrate, [request],
                                  objective=datamodel.Objective.MAX_PROFIT)
    mc = commutativity_model.CommutativityModelCreator(scenario)
    mc.init_model_creator()
    solution = mc.compute_fractional_solution()

    assert solution is not None
    assert len(solution.request_mapping[request]) > 0
def test_create_node_mapping_constraints(request_id, substrate,
                                         import_gurobi_mock):
    MockModel = import_gurobi_mock.MockModel
    MockConstr = import_gurobi_mock.MockConstr
    MockLinExpr = import_gurobi_mock.MockLinExpr

    req = create_request(request_id)
    req.graph["root"] = example_requests[request_id]["assumed_root"]
    scenario = datamodel.Scenario("test", substrate, [req])

    mc = commutativity_model.CommutativityModelCreator(scenario)
    mc.model = MockModel("mock_model")

    if example_requests[request_id].get("ignore_bfs", False):
        mc.dag_requests[req] = req

    mc.preprocess_input()
    mc._create_sub_lp_variables()
    mc._create_node_mapping_variables()
    mc._create_node_mapping_constraints()

    def node_agg_var(i, u):
        return mc.var_aggregated_node_mapping[req][i][u]

    def node_mapping_var(i, index, u):
        return mc.var_node_mapping[req][i][u][index]

    def source_var(ij, index, u):
        return mc.edge_sub_lp[req][ij][index].var_node_flow_source[u]

    def sink_var(ij, index, v):
        return mc.edge_sub_lp[req][ij][index].var_node_flow_sink[v]

    var_type_lookup = dict(node_agg_var=node_agg_var,
                           node_mapping_var=node_mapping_var,
                           source_var=source_var,
                           sink_var=sink_var)

    expected = set()
    for constraint_data in example_requests[request_id]["constraints"][
            "node_mapping"]:
        name, expr_data = constraint_data
        name = name.format(req_name=req.name)
        expr = []
        for coeff, var_type, var_keys in expr_data:
            expr.append((coeff, var_type_lookup[var_type](*var_keys)))
        expected.add(
            MockConstr(MockLinExpr(expr), gurobipy.GRB.EQUAL, 0.0, name))

    assert set(mc.model.constrs) == expected
Ejemplo n.º 13
0
def test_fractional_solution_random_request_with_gurobi(seed, substrate):
    random.seed(seed)
    req = generate_random_request_graph(10, 0.25)
    requests = [req]
    req.profit = 1.0

    scenario = datamodel.Scenario("test",
                                  substrate,
                                  requests,
                                  objective=datamodel.Objective.MAX_PROFIT)
    mc = commutativity_model.CommutativityModelCreator(scenario)
    mc.init_model_creator()
    solution = mc.compute_fractional_solution()

    assert solution is not None
    assert len(solution.request_mapping[req]) > 0
def test_reduce_flow_in_modelcreator_with_reversed_edges(
        substrate, triangle_request, import_gurobi_mock):
    MockModel = import_gurobi_mock.MockModel
    triangle_request.graph["root"] = j
    scenario = datamodel.Scenario("test", substrate, [triangle_request])
    mc = commutativity_model.CommutativityModelCreator(scenario)
    mc.model = MockModel("mock_model")
    mc.preprocess_input()
    mc.create_variables_embedding_decision()
    mc._create_node_mapping_variables()
    mc._create_sub_lp_variables()

    mapping = solutions.Mapping("foo", triangle_request, substrate, True)
    mapping.mapping_nodes = {i: u, j: v, k: u}
    mapping.mapping_edges = {ij: [uv], jk: [vw, wu], ik: []}

    mc.reduce_flow(mapping, 0.25)
    assert mc._used_flow_embedding_decision[triangle_request] == 0.25

    dag_request = mc.dag_requests[triangle_request]
    cycle_end = [
        i_ for i_ in triangle_request.nodes
        if len(dag_request.get_in_neighbors(i_)) == 2
    ][0]
    comm_index = frozenset([(cycle_end, mapping.mapping_nodes[cycle_end])])

    for i_, u_ in mapping.mapping_nodes.items():
        if i_ == cycle_end:
            assert mc._used_flow_node_mapping[triangle_request][i_][u_][
                frozenset()] == 0.25
        else:
            assert mc._used_flow_node_mapping[triangle_request][i_][u_][
                comm_index] == 0.25
    for ij_, uv_list in mapping.mapping_edges.items():
        # We only need ij_ in the orientation of the BFS request
        if ij_ not in dag_request.edges:
            ij_ = ij_[1], ij_[0]
        i_, j_ = ij_
        sub_lp = mc.edge_sub_lp[triangle_request][ij_][comm_index]
        assert sub_lp._used_flow_source[mapping.mapping_nodes[i_]] == 0.25
        assert sub_lp._used_flow_sink[mapping.mapping_nodes[j_]] == 0.25
        for uv_ in uv_list:
            u_, v_ = uv_
            if sub_lp.is_reversed_edge:
                uv_ = v_, u_
            assert sub_lp._used_flow[uv_] == 0.25
Ejemplo n.º 15
0
def test_extract_edge_mapping_colocated_nodes(substrate, triangle_request):
    scenario = datamodel.Scenario("test", substrate, [triangle_request])

    mc = commutativity_model.CommutativityModelCreator(scenario)
    mc.model = MockModel("mockmodel")
    mc.preprocess_input()
    mc._create_sub_lp_variables()

    ku_index = frozenset([(k, u)])
    ik_sub_lp = mc.edge_sub_lp[triangle_request][ik][ku_index]
    ik_sub_lp.var_node_flow_source[u].x = 0.5
    ik_sub_lp.var_node_flow_sink[u].x = 0.5

    partial_mapping = solutions.Mapping("test_mapping", triangle_request, substrate, True)
    partial_mapping.map_node(i, u)

    assert ik_sub_lp.extract_edge_mapping(partial_mapping) == ([], u, 0.5)
def test_extract_request_mapping(substrate, triangle_request,
                                 import_gurobi_mock):
    MockModel = import_gurobi_mock.MockModel
    scenario = datamodel.Scenario("test", substrate, [triangle_request])

    mc = commutativity_model.CommutativityModelCreator(scenario)
    mc.model = MockModel("mock_model")
    mc.preprocess_input()
    mc.create_variables_embedding_decision()
    mc._create_node_mapping_variables()
    mc._create_sub_lp_variables()

    ku_index = frozenset([(k, u)])

    mc.var_embedding_decision[triangle_request].x = 0.25

    mc.var_node_mapping[triangle_request][i][u][ku_index].x = 0.25
    mc.var_node_mapping[triangle_request][j][v][ku_index].x = 0.25
    mc.var_node_mapping[triangle_request][k][u][frozenset()].x = 0.25

    ij_sub_lp = mc.edge_sub_lp[triangle_request][ij][ku_index]
    ij_sub_lp.var_node_flow_source[u].x = 0.25
    ij_sub_lp.var_edge_flow[uv].x = 0.25
    ij_sub_lp.var_node_flow_sink[v].x = 0.25

    jk_sub_lp = mc.edge_sub_lp[triangle_request][jk][ku_index]
    jk_sub_lp.var_node_flow_source[v].x = 0.25
    jk_sub_lp.var_edge_flow[vw].x = 0.25
    jk_sub_lp.var_edge_flow[wu].x = 0.25
    jk_sub_lp.var_node_flow_sink[u].x = 0.25

    ik_sub_lp = mc.edge_sub_lp[triangle_request][ik][ku_index]
    ik_sub_lp.var_node_flow_source[u].x = 0.25
    ik_sub_lp.var_node_flow_sink[u].x = 0.25

    mapping, flow = mc.extract_request_mapping(
        triangle_request, mc.request_labels[triangle_request], 1)

    assert flow == 0.25
    assert mapping.mapping_nodes == {i: u, j: v, k: u}
    assert mapping.mapping_edges == {
        ij: [uv],
        jk: [vw, wu],
        ik: [],
    }
Ejemplo n.º 17
0
def test_sublp_inconsistency_causes_exception(substrate, triangle_request):
    scenario = datamodel.Scenario("test", substrate, [triangle_request])

    mc = commutativity_model.CommutativityModelCreator(scenario)
    mc.model = MockModel("mockmodel")
    mc.preprocess_input()
    mc._create_sub_lp_variables()

    ku_index = frozenset([(k, u)])

    ij_sub_lp = mc.edge_sub_lp[triangle_request][ij][ku_index]

    ij_sub_lp.var_node_flow_source[u].x = 1.0
    partial_mapping = solutions.Mapping("", triangle_request, substrate, True)
    partial_mapping.mapping_nodes[i] = "u"
    with pytest.raises(ValueError) as e:
        ij_sub_lp.extract_edge_mapping(partial_mapping)
    assert str(e.value) == "Did not find valid edge mapping for ('i', 'j')"
Ejemplo n.º 18
0
def test_solve_all_request_scenarios_with_gurobi(substrate):
    requests = [
        create_request(request_id) for request_id in filter_requests_by_tags()
    ]
    for req in requests:
        req.profit = 1.0

    scenario = datamodel.Scenario("test",
                                  substrate,
                                  requests,
                                  objective=datamodel.Objective.MAX_PROFIT)
    mc = commutativity_model.CommutativityModelCreator(scenario)
    mc.init_model_creator()
    solution = mc.compute_fractional_solution()

    assert solution is not None
    for req in requests:
        assert len(solution.request_mapping[req]) > 0
Ejemplo n.º 19
0
def test_sublp_reduce_flow(substrate, triangle_request):
    scenario = datamodel.Scenario("test", substrate, [triangle_request])

    mc = commutativity_model.CommutativityModelCreator(scenario)
    mc.model = MockModel("mockmodel")
    mc.preprocess_input()
    mc._create_sub_lp_variables()

    ku_index = frozenset([(k, u)])

    ij_sub_lp = mc.edge_sub_lp[triangle_request][ij][ku_index]

    partial_mapping = solutions.Mapping("test_mapping", triangle_request, substrate, True)
    partial_mapping.map_node(i, u)
    partial_mapping.map_node(j, v)
    partial_mapping.map_edge(ij, [uw, wv])

    ij_sub_lp.reduce_flow(partial_mapping, 0.75)

    assert ij_sub_lp._used_flow[uw] == 0.75
    assert ij_sub_lp._used_flow[wv] == 0.75
    assert ij_sub_lp._used_flow_source[u] == 0.75
    assert ij_sub_lp._used_flow_sink[v] == 0.75
Ejemplo n.º 20
0
def test_fractional_solution_multiple_random_requests_with_gurobi(
        seed, substrate):
    random.seed(seed)
    requests = [
        generate_random_request_graph(7, 0.25, "test_req_{}".format(i))
        for i in range(1, 11)
    ]
    for req in requests:
        req.profit = 1.0

    scenario = datamodel.Scenario("test",
                                  substrate,
                                  requests,
                                  objective=datamodel.Objective.MAX_PROFIT)
    mc = commutativity_model.CommutativityModelCreator(
        scenario,
        gurobi_settings=modelcreator.GurobiSettings(threads=2, timelimit=60))
    mc.init_model_creator()
    solution = mc.compute_fractional_solution()

    assert solution is not None
    for req in requests:
        assert len(solution.request_mapping[req]) > 0
Ejemplo n.º 21
0
def test_decomposition_full_request(request_id, substrate):
    req = create_request(request_id)
    req.graph["root"] = example_requests[request_id]["assumed_root"]
    scenario = datamodel.Scenario("test", substrate, [req])

    mc = commutativity_model.CommutativityModelCreator(scenario)
    mc.model = MockModel("mockmodel")

    if example_requests[request_id].get("ignore_bfs", False):
        mc.dag_requests[req] = req

    mc.preprocess_input()
    mc.create_variables()

    def node_mapping_var(i, index, u):
        return mc.var_node_mapping[req][i][u][index]

    def source_var(ij, index, u):
        return mc.edge_sub_lp[req][ij][index].var_node_flow_source[u]

    def sink_var(ij, index, v):
        return mc.edge_sub_lp[req][ij][index].var_node_flow_sink[v]

    def edge_var(ij, index, uv):
        return mc.edge_sub_lp[req][ij][index].var_edge_flow[uv]

    var_type_lookup = dict(node_mapping_var=node_mapping_var,
                           source_var=source_var,
                           sink_var=sink_var,
                           edge_var=edge_var)

    expected_mappings = set()
    expected_embedding_flow = 0.0
    for test_mapping in example_requests[request_id]["mappings"]:
        flow = test_mapping["flow"]
        expected_embedding_flow += flow
        vars = test_mapping["variables"]
        expected_mappings.add(
            (flow,
             frozenset(test_mapping["expected"]["nodes"].items()),
             frozenset((k, tuple(v)) for (k, v) in test_mapping["expected"]["edges"].items()))
        )
        for var_type, req_key, comm_index, substrate_key in vars:
            var = var_type_lookup[var_type](req_key, comm_index, substrate_key)
            var.x += flow
        mc.var_embedding_decision[req].x += flow

    frac_sol = mc.recover_fractional_solution_from_variables()

    obtained_mappings = set()
    for mapping_list in frac_sol.request_mapping.values():
        for mapping in mapping_list:
            obtained_mappings.add((
                frac_sol.mapping_flows[mapping.name],
                frozenset(mapping.mapping_nodes.items()),
                frozenset((k, tuple(v)) for (k, v) in mapping.mapping_edges.items())
            ))

    assert obtained_mappings == expected_mappings
    assert mc._used_flow_embedding_decision[req] == expected_embedding_flow

    expected_used_node_flow = {req: {}}
    for i, u_comm_index_dict in mc.var_node_mapping[req].items():
        expected_used_node_flow[req][i] = {}
        for u, comm_index_dict in u_comm_index_dict.items():
            expected_used_node_flow[req][i][u] = {}
            for comm_index, var in comm_index_dict.items():
                expected_used_node_flow[req][i][u][comm_index] = var.x
    assert mc._used_flow_node_mapping == expected_used_node_flow

    for ij in mc.dag_requests[req].edges:
        for comm_index, sub_lp in mc.edge_sub_lp[req][ij].iteritems():
            expected_used_source_flow = {
                u: var.x for u, var in sub_lp.var_node_flow_source.iteritems()
            }
            assert sub_lp._used_flow_source == expected_used_source_flow
            expected_used_sink_flow = {
                u: var.x for u, var in sub_lp.var_node_flow_sink.iteritems()
            }
            assert sub_lp._used_flow_sink == expected_used_sink_flow
            expected_used_edge_flow = {
                uv: var.x for uv, var in sub_lp.var_edge_flow.iteritems()
            }
            assert sub_lp._used_flow == expected_used_edge_flow
def test_create_sub_lp_variables(tiny_substrate, triangle_request,
                                 import_gurobi_mock):
    MockModel = import_gurobi_mock.MockModel
    scenario = datamodel.Scenario("test", tiny_substrate, [triangle_request])
    mc = commutativity_model.CommutativityModelCreator(scenario)
    mc.model = MockModel("mock_model")

    mc.preprocess_input()
    mc._create_sub_lp_variables()

    ku_index = frozenset([(k, u)])
    kv_index = frozenset([(k, v)])

    assert extract_var_names(
        mc.edge_sub_lp[triangle_request][ij][ku_index].var_edge_flow
    ) == {
        uv:
        "edge_flow_req[test_req]_vedge[('i','j')]_sedge[('u','v')]_comm_index[k_u]",
        vu:
        "edge_flow_req[test_req]_vedge[('i','j')]_sedge[('v','u')]_comm_index[k_u]",
    }
    assert extract_var_names(
        mc.edge_sub_lp[triangle_request][ij][kv_index].var_edge_flow
    ) == {
        uv:
        "edge_flow_req[test_req]_vedge[('i','j')]_sedge[('u','v')]_comm_index[k_v]",
        vu:
        "edge_flow_req[test_req]_vedge[('i','j')]_sedge[('v','u')]_comm_index[k_v]",
    }
    assert extract_var_names(
        mc.edge_sub_lp[triangle_request][jk][ku_index].var_edge_flow
    ) == {
        uv:
        "edge_flow_req[test_req]_vedge[('j','k')]_sedge[('u','v')]_comm_index[k_u]",
        vu:
        "edge_flow_req[test_req]_vedge[('j','k')]_sedge[('v','u')]_comm_index[k_u]",
    }
    assert extract_var_names(
        mc.edge_sub_lp[triangle_request][jk][kv_index].var_edge_flow
    ) == {
        uv:
        "edge_flow_req[test_req]_vedge[('j','k')]_sedge[('u','v')]_comm_index[k_v]",
        vu:
        "edge_flow_req[test_req]_vedge[('j','k')]_sedge[('v','u')]_comm_index[k_v]",
    }
    assert extract_var_names(
        mc.edge_sub_lp[triangle_request][ik][ku_index].var_edge_flow
    ) == {
        uv:
        "edge_flow_req[test_req]_vedge[('i','k')]_sedge[('u','v')]_comm_index[k_u]",
        vu:
        "edge_flow_req[test_req]_vedge[('i','k')]_sedge[('v','u')]_comm_index[k_u]",
    }
    assert extract_var_names(
        mc.edge_sub_lp[triangle_request][ik][kv_index].var_edge_flow
    ) == {
        uv:
        "edge_flow_req[test_req]_vedge[('i','k')]_sedge[('u','v')]_comm_index[k_v]",
        vu:
        "edge_flow_req[test_req]_vedge[('i','k')]_sedge[('v','u')]_comm_index[k_v]",
    }

    assert extract_var_names(
        mc.edge_sub_lp[triangle_request][ij][ku_index].var_node_flow_source
    ) == {
        u:
        "node_flow_source_req[test_req]_snode[u]_vedge[('i','j')]_comm_index[k_u]",
    }
    assert extract_var_names(
        mc.edge_sub_lp[triangle_request][ij][kv_index].var_node_flow_source
    ) == {
        u:
        "node_flow_source_req[test_req]_snode[u]_vedge[('i','j')]_comm_index[k_v]",
    }
    assert extract_var_names(
        mc.edge_sub_lp[triangle_request][jk][ku_index].var_node_flow_source
    ) == {
        v:
        "node_flow_source_req[test_req]_snode[v]_vedge[('j','k')]_comm_index[k_u]",
    }
    assert extract_var_names(
        mc.edge_sub_lp[triangle_request][jk][kv_index].var_node_flow_source
    ) == {
        v:
        "node_flow_source_req[test_req]_snode[v]_vedge[('j','k')]_comm_index[k_v]",
    }
    assert extract_var_names(
        mc.edge_sub_lp[triangle_request][ik][ku_index].var_node_flow_source
    ) == {
        u:
        "node_flow_source_req[test_req]_snode[u]_vedge[('i','k')]_comm_index[k_u]",
    }
    assert extract_var_names(
        mc.edge_sub_lp[triangle_request][ik][kv_index].var_node_flow_source
    ) == {
        u:
        "node_flow_source_req[test_req]_snode[u]_vedge[('i','k')]_comm_index[k_v]",
    }

    assert extract_var_names(
        mc.edge_sub_lp[triangle_request][ij][ku_index].var_node_flow_sink
    ) == {
        v:
        "node_flow_sink_req[test_req]_snode[v]_vedge[('i','j')]_comm_index[k_u]",
    }
    assert extract_var_names(
        mc.edge_sub_lp[triangle_request][ij][kv_index].var_node_flow_sink
    ) == {
        v:
        "node_flow_sink_req[test_req]_snode[v]_vedge[('i','j')]_comm_index[k_v]",
    }
    assert extract_var_names(
        mc.edge_sub_lp[triangle_request][jk][ku_index].var_node_flow_sink
    ) == {
        u:
        "node_flow_sink_req[test_req]_snode[u]_vedge[('j','k')]_comm_index[k_u]",
    }
    assert extract_var_names(
        mc.edge_sub_lp[triangle_request][jk][kv_index].var_node_flow_sink
    ) == {
        v:
        "node_flow_sink_req[test_req]_snode[v]_vedge[('j','k')]_comm_index[k_v]",
    }
    assert extract_var_names(
        mc.edge_sub_lp[triangle_request][ik][ku_index].var_node_flow_sink
    ) == {
        u:
        "node_flow_sink_req[test_req]_snode[u]_vedge[('i','k')]_comm_index[k_u]",
    }
    assert extract_var_names(
        mc.edge_sub_lp[triangle_request][ik][kv_index].var_node_flow_sink
    ) == {
        v:
        "node_flow_sink_req[test_req]_snode[v]_vedge[('i','k')]_comm_index[k_v]",
    }
def test_modelcreator_create_constraints_track_edge_loads(substrate, triangle_request, import_gurobi_mock):
    MockConstr = import_gurobi_mock.MockConstr
    MockLinExpr = import_gurobi_mock.MockLinExpr
    MockModel = import_gurobi_mock.MockModel

    # add a single edge to the request that will be reversed
    l = "l"
    li = l, i
    il = i, l
    triangle_request.add_node(l, 1.0, "t1", [v])
    triangle_request.add_edge(l, i, 2.0, None)

    # set some different demands on different edges
    triangle_request.edge[ij]["demand"] = 0.5
    triangle_request.edge[ik]["demand"] = 1.5

    scenario = datamodel.Scenario("test", substrate, [triangle_request])
    mc = commutativity_model.CommutativityModelCreator(scenario)
    mc.model = MockModel("mock_model")
    mc.preprocess_input()
    mc.create_variables_request_load()
    mc._create_sub_lp_variables()
    mc._create_constraints_track_edge_loads()

    ku_index = frozenset([("k", "u")])
    kv_index = frozenset([("k", "v")])
    sub_lp_li = mc.edge_sub_lp[triangle_request][il][frozenset()]
    sub_lp_ij_ku = mc.edge_sub_lp[triangle_request][ij][ku_index]
    sub_lp_ij_kv = mc.edge_sub_lp[triangle_request][ij][kv_index]
    sub_lp_jk_ku = mc.edge_sub_lp[triangle_request][jk][ku_index]
    sub_lp_jk_kv = mc.edge_sub_lp[triangle_request][jk][kv_index]
    sub_lp_ik_ku = mc.edge_sub_lp[triangle_request][ik][ku_index]
    sub_lp_ik_kv = mc.edge_sub_lp[triangle_request][ik][kv_index]

    assert set(mc.model.constrs) == {
        MockConstr(
            MockLinExpr(
                [(-1.0, mc.var_request_load[triangle_request][uv]),
                 (2.0, sub_lp_li.var_edge_flow[vu]),  # substrate will be reversed in decomp. => sub_lp uses vu as dict key for var_edge_flow
                 (0.5, sub_lp_ij_ku.var_edge_flow[uv]),
                 (0.5, sub_lp_ij_kv.var_edge_flow[uv]),
                 (1.0, sub_lp_jk_ku.var_edge_flow[uv]),
                 (1.0, sub_lp_jk_kv.var_edge_flow[uv]),
                 (1.5, sub_lp_ik_ku.var_edge_flow[uv]),
                 (1.5, sub_lp_ik_kv.var_edge_flow[uv])]
            ),
            GRB.EQUAL, 0.0, name="track_edge_load_req[test_req]_sedge[('u','v')]"
        ),
        MockConstr(
            MockLinExpr(
                [(-1.0, mc.var_request_load[triangle_request][vu]),
                 (2.0, sub_lp_li.var_edge_flow[uv]),  # substrate will be reversed in decomp. => sub_lp uses vu as dict key for var_edge_flow
                 (0.5, sub_lp_ij_ku.var_edge_flow[vu]),
                 (0.5, sub_lp_ij_kv.var_edge_flow[vu]),
                 (1.0, sub_lp_jk_ku.var_edge_flow[vu]),
                 (1.0, sub_lp_jk_kv.var_edge_flow[vu]),
                 (1.5, sub_lp_ik_ku.var_edge_flow[vu]),
                 (1.5, sub_lp_ik_kv.var_edge_flow[vu])]
            ),
            GRB.EQUAL, 0.0, name="track_edge_load_req[test_req]_sedge[('v','u')]"
        ),
        MockConstr(
            MockLinExpr(
                [(-1.0, mc.var_request_load[triangle_request][vw]),
                 (2.0, sub_lp_li.var_edge_flow[wv]),  # substrate will be reversed in decomp. => sub_lp uses vu as dict key for var_edge_flow
                 (0.5, sub_lp_ij_ku.var_edge_flow[vw]),
                 (0.5, sub_lp_ij_kv.var_edge_flow[vw]),
                 (1.0, sub_lp_jk_ku.var_edge_flow[vw]),
                 (1.0, sub_lp_jk_kv.var_edge_flow[vw]),
                 (1.5, sub_lp_ik_ku.var_edge_flow[vw]),
                 (1.5, sub_lp_ik_kv.var_edge_flow[vw])]
            ),
            GRB.EQUAL, 0.0, name="track_edge_load_req[test_req]_sedge[('v','w')]"
        ),
        MockConstr(
            MockLinExpr(
                [(-1.0, mc.var_request_load[triangle_request][wv]),
                 (2.0, sub_lp_li.var_edge_flow[vw]),  # substrate will be reversed in decomp. => sub_lp uses vu as dict key for var_edge_flow
                 (0.5, sub_lp_ij_ku.var_edge_flow[wv]),
                 (0.5, sub_lp_ij_kv.var_edge_flow[wv]),
                 (1.0, sub_lp_jk_ku.var_edge_flow[wv]),
                 (1.0, sub_lp_jk_kv.var_edge_flow[wv]),
                 (1.5, sub_lp_ik_ku.var_edge_flow[wv]),
                 (1.5, sub_lp_ik_kv.var_edge_flow[wv])]
            ),
            GRB.EQUAL, 0.0, name="track_edge_load_req[test_req]_sedge[('w','v')]"
        ),
        MockConstr(
            MockLinExpr(
                [(-1.0, mc.var_request_load[triangle_request][uw]),
                 (2.0, sub_lp_li.var_edge_flow[wu]),  # substrate will be reversed in decomp. => sub_lp uses vu as dict key for var_edge_flow
                 (0.5, sub_lp_ij_ku.var_edge_flow[uw]),
                 (0.5, sub_lp_ij_kv.var_edge_flow[uw]),
                 (1.0, sub_lp_jk_ku.var_edge_flow[uw]),
                 (1.0, sub_lp_jk_kv.var_edge_flow[uw]),
                 (1.5, sub_lp_ik_ku.var_edge_flow[uw]),
                 (1.5, sub_lp_ik_kv.var_edge_flow[uw])]
            ),
            GRB.EQUAL, 0.0, name="track_edge_load_req[test_req]_sedge[('u','w')]"
        ),
        MockConstr(
            MockLinExpr(
                [(-1.0, mc.var_request_load[triangle_request][wu]),
                 (2.0, sub_lp_li.var_edge_flow[uw]),  # substrate will be reversed in decomp. => sub_lp uses vu as dict key for var_edge_flow
                 (0.5, sub_lp_ij_ku.var_edge_flow[wu]),
                 (0.5, sub_lp_ij_kv.var_edge_flow[wu]),
                 (1.0, sub_lp_jk_ku.var_edge_flow[wu]),
                 (1.0, sub_lp_jk_kv.var_edge_flow[wu]),
                 (1.5, sub_lp_ik_ku.var_edge_flow[wu]),
                 (1.5, sub_lp_ik_kv.var_edge_flow[wu])]
            ),
            GRB.EQUAL, 0.0, name="track_edge_load_req[test_req]_sedge[('w','u')]"
        ),
    }
def test_sublp_extend_edge_load_constraints(substrate, triangle_request, import_gurobi_mock):
    MockModel = import_gurobi_mock.MockModel
    # add a single edge to the request that will be reversed
    l = "l"
    li = l, i
    triangle_request.add_node(l, 1.0, "t1", [v])
    triangle_request.add_edge(l, i, 2.0, None)

    # set some different demands on different edges
    triangle_request.edge[ij]["demand"] = 0.5
    triangle_request.edge[ik]["demand"] = 1.5

    scenario = datamodel.Scenario("test", substrate, [triangle_request])
    mc = commutativity_model.CommutativityModelCreator(scenario)
    mc.model = MockModel("mock_model")
    mc.preprocess_input()
    mc.create_variables_request_load()
    mc._create_sub_lp_variables()

    ku_index = frozenset([("k", "u")])
    kv_index = frozenset([("k", "u")])
    sub_lp_li = mc.edge_sub_lp[triangle_request][(i, l)][frozenset()]
    sub_lp_ij_ku = mc.edge_sub_lp[triangle_request][ij][ku_index]
    sub_lp_ij_kv = mc.edge_sub_lp[triangle_request][ij][kv_index]
    sub_lp_jk_ku = mc.edge_sub_lp[triangle_request][jk][ku_index]
    sub_lp_jk_kv = mc.edge_sub_lp[triangle_request][jk][kv_index]
    sub_lp_ik_ku = mc.edge_sub_lp[triangle_request][ik][ku_index]
    sub_lp_ik_kv = mc.edge_sub_lp[triangle_request][ik][kv_index]

    request_load_var_dict = mc.var_request_load[triangle_request]

    edge_load_constraint_dict = {
        sub_edge: [(-1.0, mc.var_request_load[triangle_request][sub_edge])]
        for sub_edge in substrate.edges
    }
    sub_lp_li.extend_edge_load_constraints(edge_load_constraint_dict)
    sub_lp_ij_ku.extend_edge_load_constraints(edge_load_constraint_dict)
    sub_lp_ij_kv.extend_edge_load_constraints(edge_load_constraint_dict)
    sub_lp_jk_ku.extend_edge_load_constraints(edge_load_constraint_dict)
    sub_lp_jk_kv.extend_edge_load_constraints(edge_load_constraint_dict)
    sub_lp_ik_ku.extend_edge_load_constraints(edge_load_constraint_dict)
    sub_lp_ik_kv.extend_edge_load_constraints(edge_load_constraint_dict)

    assert edge_load_constraint_dict == {
        uv: [(-1.0, request_load_var_dict[uv]),
             (2.0, sub_lp_li.var_edge_flow[vu]),  # substrate will be reversed in decomp. => sub_lp uses vu as dict key for var_edge_flow
             (0.5, sub_lp_ij_ku.var_edge_flow[uv]),
             (0.5, sub_lp_ij_kv.var_edge_flow[uv]),
             (1.0, sub_lp_jk_ku.var_edge_flow[uv]),
             (1.0, sub_lp_jk_kv.var_edge_flow[uv]),
             (1.5, sub_lp_ik_ku.var_edge_flow[uv]),
             (1.5, sub_lp_ik_kv.var_edge_flow[uv])],
        vu: [(-1.0, request_load_var_dict[vu]),
             (2.0, sub_lp_li.var_edge_flow[uv]),  # substrate will be reversed in decomp. => sub_lp uses vu as dict key for var_edge_flow
             (0.5, sub_lp_ij_ku.var_edge_flow[vu]),
             (0.5, sub_lp_ij_kv.var_edge_flow[vu]),
             (1.0, sub_lp_jk_ku.var_edge_flow[vu]),
             (1.0, sub_lp_jk_kv.var_edge_flow[vu]),
             (1.5, sub_lp_ik_ku.var_edge_flow[vu]),
             (1.5, sub_lp_ik_kv.var_edge_flow[vu])],
        vw: [(-1.0, request_load_var_dict[vw]),
             (2.0, sub_lp_li.var_edge_flow[wv]),  # substrate copy will be reversed in decomp. => sub_lp uses wv as dict key for var_edge_flow
             (0.5, sub_lp_ij_ku.var_edge_flow[vw]),
             (0.5, sub_lp_ij_kv.var_edge_flow[vw]),
             (1.0, sub_lp_jk_ku.var_edge_flow[vw]),
             (1.0, sub_lp_jk_kv.var_edge_flow[vw]),
             (1.5, sub_lp_ik_ku.var_edge_flow[vw]),
             (1.5, sub_lp_ik_kv.var_edge_flow[vw])],
        wv: [(-1.0, request_load_var_dict[wv]),
             (2.0, sub_lp_li.var_edge_flow[vw]),  # substrate copy will be reversed in decomp. => sub_lp uses wv as dict key for var_edge_flow
             (0.5, sub_lp_ij_ku.var_edge_flow[wv]),
             (0.5, sub_lp_ij_kv.var_edge_flow[wv]),
             (1.0, sub_lp_jk_ku.var_edge_flow[wv]),
             (1.0, sub_lp_jk_kv.var_edge_flow[wv]),
             (1.5, sub_lp_ik_ku.var_edge_flow[wv]),
             (1.5, sub_lp_ik_kv.var_edge_flow[wv])],
        uw: [(-1.0, request_load_var_dict[uw]),
             (2.0, sub_lp_li.var_edge_flow[wu]),  # substrate copy will be reversed in decomp. => sub_lp uses wv as dict key for var_edge_flow
             (0.5, sub_lp_ij_ku.var_edge_flow[uw]),
             (0.5, sub_lp_ij_kv.var_edge_flow[uw]),
             (1.0, sub_lp_jk_ku.var_edge_flow[uw]),
             (1.0, sub_lp_jk_kv.var_edge_flow[uw]),
             (1.5, sub_lp_ik_ku.var_edge_flow[uw]),
             (1.5, sub_lp_ik_kv.var_edge_flow[uw])],
        wu: [(-1.0, request_load_var_dict[wu]),
             (2.0, sub_lp_li.var_edge_flow[uw]),  # substrate copy will be reversed in decomp. => sub_lp uses wv as dict key for var_edge_flow
             (0.5, sub_lp_ij_ku.var_edge_flow[wu]),
             (0.5, sub_lp_ij_kv.var_edge_flow[wu]),
             (1.0, sub_lp_jk_ku.var_edge_flow[wu]),
             (1.0, sub_lp_jk_kv.var_edge_flow[wu]),
             (1.5, sub_lp_ik_ku.var_edge_flow[wu]),
             (1.5, sub_lp_ik_kv.var_edge_flow[wu])]
    }
def test_recover_fractional_solution_from_variables(substrate, triangle_request, import_gurobi_mock):
    MockModel = import_gurobi_mock.MockModel
    l = "l"
    li = l, i
    t1 = "t1"
    triangle_request.add_node(l, 0.75, t1, [w])
    triangle_request.add_edge(l, i, 2.0, None)

    scenario = datamodel.Scenario("test", substrate, [triangle_request])

    mc = commutativity_model.CommutativityModelCreator(scenario)
    mc.model = MockModel("mock_model")
    mc.preprocess_input()
    mc.create_variables_embedding_decision()
    mc._create_node_mapping_variables()
    mc._create_sub_lp_variables()

    load_base = {uv_: 0.0 for uv_ in substrate.edges}
    load_base.update({(t1, u_): 0.0 for u_ in substrate.nodes})

    ku_index = frozenset([(k, u)])
    kv_index = frozenset([(k, v)])

    li_sub_lp = mc.edge_sub_lp[triangle_request][(i, l)][frozenset()]

    ij_sub_lp_ku = mc.edge_sub_lp[triangle_request][ij][ku_index]
    jk_sub_lp_ku = mc.edge_sub_lp[triangle_request][jk][ku_index]
    ik_sub_lp_ku = mc.edge_sub_lp[triangle_request][ik][ku_index]

    ij_sub_lp_kv = mc.edge_sub_lp[triangle_request][ij][kv_index]
    jk_sub_lp_kv = mc.edge_sub_lp[triangle_request][jk][kv_index]
    ik_sub_lp_kv = mc.edge_sub_lp[triangle_request][ik][kv_index]

    # Mapping 1
    flow_1 = 0.25
    mc.var_embedding_decision[triangle_request].x += flow_1

    mc.var_node_mapping[triangle_request][l][w][frozenset()].x += flow_1
    mc.var_node_mapping[triangle_request][i][u][ku_index].x += flow_1
    mc.var_node_mapping[triangle_request][j][v][ku_index].x += flow_1
    mc.var_node_mapping[triangle_request][k][u][frozenset()].x += flow_1

    li_sub_lp.var_node_flow_source[u].x += flow_1
    li_sub_lp.var_edge_flow[uw].x += flow_1
    li_sub_lp.var_node_flow_sink[w].x += flow_1

    ij_sub_lp_ku.var_node_flow_source[u].x += flow_1
    ij_sub_lp_ku.var_edge_flow[uv].x += flow_1
    ij_sub_lp_ku.var_node_flow_sink[v].x += flow_1

    jk_sub_lp_ku.var_node_flow_source[v].x += flow_1
    jk_sub_lp_ku.var_edge_flow[vw].x += flow_1
    jk_sub_lp_ku.var_edge_flow[wu].x += flow_1
    jk_sub_lp_ku.var_node_flow_sink[u].x += flow_1

    ik_sub_lp_ku.var_node_flow_source[u].x += flow_1
    ik_sub_lp_ku.var_node_flow_sink[u].x += flow_1

    load_1 = load_base.copy()
    load_1.update({
        (t1, u): 1.0 + 1.0,  # i, k
        (t1, v): 1.0,  # j
        (t1, w): 0.75,  # l
        uv: 1.0,  # ij
        wu: 2.0 + 1.0,  # li (reversed), jk
        vw: 1.0,  # jk
    })

    # Mapping 2
    flow_2 = 0.125
    mc.var_embedding_decision[triangle_request].x += flow_2

    mc.var_node_mapping[triangle_request][l][w][frozenset()].x += flow_2
    mc.var_node_mapping[triangle_request][i][u][ku_index].x += flow_2
    mc.var_node_mapping[triangle_request][j][v][ku_index].x += flow_2
    mc.var_node_mapping[triangle_request][k][u][frozenset()].x += flow_2

    li_sub_lp.var_node_flow_source[u].x += flow_2
    li_sub_lp.var_edge_flow[uw].x += flow_2
    li_sub_lp.var_node_flow_sink[w].x += flow_2

    ij_sub_lp_ku.var_node_flow_source[u].x += flow_2
    ij_sub_lp_ku.var_edge_flow[uw].x += flow_2
    ij_sub_lp_ku.var_edge_flow[wv].x += flow_2
    ij_sub_lp_ku.var_node_flow_sink[v].x += flow_2

    jk_sub_lp_ku.var_node_flow_source[v].x += flow_2
    jk_sub_lp_ku.var_edge_flow[vw].x += flow_2
    jk_sub_lp_ku.var_edge_flow[wu].x += flow_2
    jk_sub_lp_ku.var_node_flow_sink[u].x += flow_2

    ik_sub_lp_ku.var_node_flow_source[u].x += flow_2
    ik_sub_lp_ku.var_node_flow_sink[u].x += flow_2

    load_2 = load_base.copy()
    load_2.update({
        (t1, u): 1.0 + 1.0,  # i, k
        (t1, v): 1.0,  # j
        (t1, w): 0.75,  # l
        uw: 1.0,  # ij
        wv: 1.0,  # ij
        wu: 2.0 + 1.0,  # li (reversed), jk
        vw: 1.0,  # jk
    })

    # Mapping 3
    flow_3 = 0.25 + 0.0625
    mc.var_embedding_decision[triangle_request].x += flow_3

    mc.var_node_mapping[triangle_request][l][w][frozenset()].x += flow_3
    mc.var_node_mapping[triangle_request][i][u][kv_index].x += flow_3
    mc.var_node_mapping[triangle_request][j][v][kv_index].x += flow_3
    mc.var_node_mapping[triangle_request][k][v][frozenset()].x += flow_3

    li_sub_lp.var_node_flow_source[u].x += flow_3
    li_sub_lp.var_edge_flow[uw].x += flow_3
    li_sub_lp.var_node_flow_sink[w].x += flow_3

    ij_sub_lp_kv.var_node_flow_source[u].x += flow_3
    ij_sub_lp_kv.var_edge_flow[uw].x += flow_3
    ij_sub_lp_kv.var_edge_flow[wv].x += flow_3
    ij_sub_lp_kv.var_node_flow_sink[v].x += flow_3

    jk_sub_lp_kv.var_node_flow_source[v].x += flow_3
    jk_sub_lp_kv.var_node_flow_sink[v].x += flow_3

    ik_sub_lp_kv.var_node_flow_source[u].x += flow_3
    ik_sub_lp_kv.var_edge_flow[uv].x += flow_3
    ik_sub_lp_kv.var_node_flow_sink[v].x += flow_3

    load_3 = load_base.copy()
    load_3.update({
        (t1, u): 1.0,  # i
        (t1, v): 1.0 + 1.0,  # j, k
        (t1, w): 0.75,  # l
        uw: 1.0,  # ij
        wu: 2.0,  # li  (reversed)
        wv: 1.0,  # ij
        uv: 1.0,  # ik
    })

    mapping_nt = namedtuple("MappingNT", "flow nodes edges load")
    edge_mapping_nt = namedtuple("EdgeMappingNT", "ij uv_list")

    expected_mappings_as_tuples = {
        mapping_nt(
            flow_1,
            frozenset(list({i: u, l: w, j: v, k: u}.items())),
            frozenset([
                edge_mapping_nt(li, (wu,)),
                edge_mapping_nt(ij, (uv,)),
                edge_mapping_nt(jk, (vw, wu)),
                edge_mapping_nt(ik, ())
            ]),
            frozenset(list(load_1.items()))
        ),
        mapping_nt(
            flow_2,
            frozenset(list({i: u, l: w, j: v, k: u}.items())),
            frozenset([
                edge_mapping_nt(li, (wu,)),
                edge_mapping_nt(ij, (uw, wv)),
                edge_mapping_nt(jk, (vw, wu)),
                edge_mapping_nt(ik, ())
            ]),
            frozenset(list(load_2.items()))
        ),
        mapping_nt(
            flow_3,
            frozenset(list({i: u, l: w, j: v, k: v}.items())),
            frozenset([
                edge_mapping_nt(li, (wu,)),
                edge_mapping_nt(ij, (uw, wv)),
                edge_mapping_nt(jk, ()),
                edge_mapping_nt(ik, (uv,))
            ]),
            frozenset(list(load_3.items()))
        )
    }

    obtained_solution = mc.recover_fractional_solution_from_variables()
    obtained_mappings_as_tuples = {
        mapping_nt(
            obtained_solution.mapping_flows[m.name],
            frozenset(list(m.mapping_nodes.items())),
            frozenset(edge_mapping_nt(k_, tuple(v_))
                      for (k_, v_) in list(m.mapping_edges.items())),
            frozenset(list(obtained_solution.mapping_loads[m.name].items())),
        )
        for m in obtained_solution.request_mapping[triangle_request]
    }

    assert obtained_mappings_as_tuples == expected_mappings_as_tuples