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 recover_fractional_solution_from_variables(self): solution_name = modelcreator.construct_name( "solution_", req_name="", sub_name=self.substrate.name) self.solution = solutions.FractionalScenarioSolution( solution_name, self.scenario) for req in self.requests: # mapping_name = modelcreator.construct_name("fractual_mapping_", req_name=req.name, # sub_name=self.substrate.name) is_embedded = self.var_embedding_decision[req].x > 0.5 # mapping = mp_pkg.Mapping(mapping_name, req, self.substrate, is_embedded=is_embedded) if is_embedded: maps = self.obtain_fractional_mappings_of_request(req) if not maps: mapping_name = modelcreator.construct_name( "empty_mapping_", req_name=req.name, sub_name=self.substrate.name) self.solution.add_mapping( req, solutions.Mapping(mapping_name, req, self.substrate, False), {}, {}) for m, flow, load in maps: self.solution.add_mapping(req, m, flow, load) # TODO: even if the request is not embedded, a mapping object should be created, indicating that the request was not embedded return self.solution
def recover_integral_solution_from_variables(self): solution_name = modelcreator.construct_name( "solution_", req_name="", sub_name=self.substrate.name) self.solution = solutions.IntegralScenarioSolution( solution_name, self.scenario) for req in self.requests: # create mapping for specific req and substrate mapping_name = modelcreator.construct_name( "mapping_", req_name=req.name, sub_name=self.substrate.name) is_embedded = self.var_embedding_decision[req].x > 0.5 mapping = solutions.Mapping(mapping_name, req, self.substrate, is_embedded=is_embedded) if is_embedded: self.obtain_integral_mapping_of_request(req, mapping) self.solution.add_mapping(req, mapping) return self.solution
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_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_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 construct_results_object(self, result, feasible): """ Constructs :param result: :param feasible: :return: """ total_cost = 0.0 if feasible: node_mapping, link_mapping = result total_cost = self.calculate_solution_cost(node_mapping, link_mapping) solution_alib = solutions.IntegralScenarioSolution( name="GBA-solution", scenario=self.scenario) runtime = time.time() - self.start_time result_alib = GreedyBorderAllocationResult(self.scenario, feasible, runtime, total_cost) for req in self.scenario.requests: mapping_alib = solutions.Mapping("GBA-mapping-{}".format(req.name), req, self.scenario.substrate, is_embedded=feasible) # TODO: properly fill Mapping object solution_alib.add_mapping(req, mapping_alib) result_alib.solutions[result_alib.alg_key].append(solution_alib) return result_alib
def setup(self): self.substrate = datamodel.Substrate("sub1") self.request = datamodel.Request("req1") self.scenario = datamodel.Scenario("Sen1", self.substrate, [self.request]) self.mapping = solutions.Mapping("map1", self.request, self.substrate, True) self.scenariosolution = solutions.IntegralScenarioSolution( "Solution1", self.scenario)
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_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 _get_empty_mapping_of_correct_type(self): if self.edge_embedding_model == ViNEEdgeEmbeddingModel.UNSPLITTABLE: name = mc.construct_name( "shortest_path_mapping_", req_name=self._current_request.name, sub_name=self.original_substrate.name ) return solutions.Mapping( name, self._current_request, self.original_substrate, is_embedded=True, ) elif self.edge_embedding_model == ViNEEdgeEmbeddingModel.SPLITTABLE: name = mc.construct_name( "splittable_mapping_", req_name=self._current_request.name, sub_name=self.original_substrate.name ) return SplittableMapping( name, self._current_request, self.original_substrate, is_embedded=True, ) else: raise ValueError("Invalid edge mapping method: {}".format(self.edge_embedding_model))
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 _get_fractional_mapping_and_load_from_path(self, req, mapping_name, ext_graph, eedge_path): last_used_edge = 0 previous_vnode = None is_embedded = self.var_embedding_decision[req].x > 0.5 mapping = solutions.Mapping(mapping_name, req, self.substrate, is_embedded=is_embedded) load = {x: 0.0 for x in self.substrate.substrate_resources} for index, eedge in enumerate(eedge_path): if index == 0: # map first node of service chain according to first edge ntype, snode, vnode = ext_graph.edge[eedge]["node_origin"] mapping.map_node(vnode, snode) load[(ntype, snode)] += req.get_node_demand(vnode) last_used_edge = 0 previous_vnode = vnode else: if "node_origin" in ext_graph.edge[eedge]: # this edge represents a node mapping ntype, snode, vnode = ext_graph.edge[eedge]["node_origin"] mapping.map_node(vnode, snode) load[(ntype, snode)] += req.get_node_demand(vnode) # map path between previous_vnode and vnode eedge_path_connecting_previous_vnode_and_vnode = eedge_path[ last_used_edge + 1:index] se_path = [ ext_graph.edge[eedge]["edge_origin"][0] for eedge in eedge_path_connecting_previous_vnode_and_vnode ] new_edge = (previous_vnode, vnode) mapping.map_edge(new_edge, se_path) for u, v in se_path: load[(u, v)] += req.get_edge_demand(new_edge) last_used_edge = index previous_vnode = vnode return mapping, load
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_model_fixing_simple_scenario(self): sub = datamodel.Substrate("fixing_sub") sub.add_node("u", {"t1"}, {"t1": 10}, {"t1": 100}) sub.add_node("v", {"t1"}, {"t1": 10}, {"t1": 100}) sub.add_node("w", {"t1"}, {"t1": 10}, {"t1": 100}) sub.add_node("x", {"t1"}, {"t1": 10}, {"t1": 100}) sub.add_edge("u", "v") sub.add_edge("v", "w") sub.add_edge("w", "x") sub.add_edge("x", "u") req = datamodel.Request("fixing_req") req.profit = 1000 req.add_node("i", 5, "t1", {"u", "v", "w", "x"}) req.add_node("j", 5, "t1", {"u", "v", "w", "x"}) req.add_edge("i", "j", 0.5) mapping = solutions.Mapping("fixing_mapping", req, sub, True) mapping.map_node("i", "u") mapping.map_node("j", "x") mapping.map_edge(("i", "j"), [("u", "v"), ("v", "w"), ("w", "x")]) scenario = datamodel.Scenario("fixing_scen", sub, [req], datamodel.Objective.MAX_PROFIT) sol = solutions.IntegralScenarioSolution("fixing_sol", scenario) sol.add_mapping(req, mapping) mc_ecg = modelcreator_ecg_decomposition.ModelCreatorCactusDecomposition( scenario) mc_ecg.init_model_creator() mc_ecg.fix_mapping_variables_according_to_integral_solution(sol) ecg_sol = mc_ecg.compute_integral_solution() new_mapping = ecg_sol.solution.request_mapping[req] assert new_mapping.mapping_nodes == mapping.mapping_nodes assert new_mapping.mapping_edges == mapping.mapping_edges
def extract_request_mapping(self, req, labels, mapping_count): """ Extract a request mapping. This is called by :meth:`recover_fractional_solution_from_variables` as long as there is flow remaining. If there is remaining flow, this function should find a mapping. :param datamodel.Request req: the request :param CommutativityLabels labels: the labels of the request :param int mapping_count: the mapping count used for the mapping name :return: a mapping of the request and the corresponding flow :rtype: (solutions.Mapping, float) """ mapping = solutions.Mapping( "mapping_{}_{}".format(req.name, mapping_count), req, self.substrate, True) # TODO: Ask Matthias about is_embedded root = req.graph["root"] queue = deque([root]) added_to_queue = {root} min_flow_for_mapping = self.var_embedding_decision[ req].x - self._used_flow_embedding_decision[req] u_root_candidates = self.var_node_mapping[req][root].keys() for u in u_root_candidates: for comm_index, var in self.var_node_mapping[req][root][ u].iteritems(): if var.x - self._used_flow_node_mapping[req][root][u][ comm_index] > self.decomposition_epsilon: mapping.map_node(root, u) break if root in mapping.mapping_nodes: break while queue: i = queue.popleft() u = mapping.mapping_nodes[i] for comm_index, var in self.var_node_mapping[req][i][u].iteritems( ): i_mapping_remaining_flow = var.x - self._used_flow_node_mapping[ req][i][u][comm_index] if i_mapping_remaining_flow <= self.decomposition_epsilon: continue bag_key = {k for k, v in comm_index} mapped_nodes_index = self.get_commutativity_index_from_mapping( bag_key, mapping) if not (mapped_nodes_index <= comm_index): # index is incompatible with current mapping continue # comm_index is a valid choice, extend mapping by it for k, w_k in comm_index: if k not in mapping.mapping_nodes: mapping.map_node(k, w_k) min_flow_for_mapping = min(min_flow_for_mapping, i_mapping_remaining_flow) for j in self.dag_requests[req].get_out_neighbors(i): # handle edge ij # pick a comm index consistent with mapping ij = i, j ij_labels = labels.get_edge_labels(ij) # labels of ij are already fixed because labels of i are fixed comm_index = self.get_commutativity_index_from_mapping( ij_labels, mapping) ij_sub_lp = self.edge_sub_lp[req][ij][comm_index] uv_list, v_j, flow = ij_sub_lp.extract_edge_mapping(mapping) min_flow_for_mapping = min(min_flow_for_mapping, flow) if ij_sub_lp.is_reversed_edge: ij_original_orientation = j, i else: ij_original_orientation = ij if j not in mapping.mapping_nodes: mapping.map_node(j, v_j) mapping.map_edge(ij_original_orientation, uv_list) if j not in added_to_queue: queue.append(j) added_to_queue.add(j) return mapping, min_flow_for_mapping