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]"), }
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)
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]"), }
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[]", }
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
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
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
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: [], }
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')"
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
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
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
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