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 test_construct_name(): assert construct_name("foo") == "foo" assert construct_name( name="node_mapping", req_name="req1", snode="u", vnode="i", ) == "node_mapping_req[req1]_vnode[i]_snode[u]" assert construct_name( "compute_edge_load", req_name="req1", sedge=("u", "v"), ) == "compute_edge_load_req[req1]_sedge[('u','v')]" assert construct_name( name="1", req_name=2, type=3, vnode=4, snode=5, vedge=6, sedge=7, other=8, sub_name=9, sol_name=10, ) == "1_req[2]_type[3]_vnode[4]_snode[5]_vedge[6]_sedge[7]_other[8]_substrate[9]_solution[10]"
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 _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 _flow_induction_constraints(self): for req in self.requests: ext_graph = self.extended_graph[req] ssource = ext_graph.super_source expr = LinExpr([(-1.0, self.var_embedding_decision[req])] + [(1.0, self.var_flow[req][sedge_ext]) for sedge_ext in ext_graph.out_edges[ssource]]) constr_name = modelcreator.construct_name("flow_induction", req_name=req.name) self.model.addConstr(expr, GRB.EQUAL, 0.0, name=constr_name)
def _load_computation_nodes_constraints(self): for req in self.requests: for (ntype, snode) in self.substrate.substrate_node_resources: expr = LinExpr( [(req.get_node_demand(i), self.var_flow[req][sedge_ext]) for (sedge_ext, i) in self.ext_graph_edges_node[req][ (ntype, snode)]] + [(-1.0, self.var_request_load[req][(ntype, snode)])]) constr_name = modelcreator.construct_name("compute_node_load", req_name=req.name, snode=snode, type=ntype) self.model.addConstr(expr, GRB.EQUAL, 0.0, name=constr_name)
def create_variables_other_than_embedding_decision_and_request_load(self): # flow variables for req in self.requests: self.var_flow[req] = {} for sedge_ext in self.extended_graph[req].edges: variable_id = modelcreator.construct_name("flow", req_name=req.name, other=sedge_ext) self.var_flow[req][sedge_ext] = self.model.addVar( lb=0.0, ub=1.0, obj=0.0, vtype=GRB.BINARY, name=variable_id)
def obtain_fractional_mappings_of_request(self, req, eps=0.00001): maps = [] total_flow = self.var_flow[req] ext_graph = self.extended_graph[req] # dictionary: edge(from extended graph) -> remaining flow remaining_flow_dict = { eedge: total_flow[eedge].X for eedge in ext_graph.edges } sum_outgoing_flow_super_source = self.var_embedding_decision[req].x number_maps = 0 while sum_outgoing_flow_super_source > eps: predecessor_dict = ModelCreatorDecomp._search_path_through_extended_graph( ext_graph, remaining_flow_dict) # reconstruct path eedge_path = [] current_enode = ext_graph.super_sink min_flow_on_path = 1.0 while current_enode is not ext_graph.super_source: previous_hop = predecessor_dict[current_enode] eedge = (previous_hop, current_enode) min_flow_on_path = min(min_flow_on_path, remaining_flow_dict[eedge]) eedge_path.append((previous_hop, current_enode)) current_enode = previous_hop # reverse edges such that path leads from super source to super sink eedge_path.reverse() for eedge in eedge_path: remaining_flow_dict[eedge] -= min_flow_on_path sum_outgoing_flow_super_source -= min_flow_on_path # lookup minimal used_flow on any of the edges TODO mapping_name = modelcreator.construct_name( "mapping_" + str(number_maps), req_name=req.name, sub_name=self.substrate.name) number_maps += 1 mapping, load = self._get_fractional_mapping_and_load_from_path( req, mapping_name, ext_graph, eedge_path) # RECONSTRUCT MAPPING FROM PATH maps.append((mapping, min_flow_on_path, load)) return maps
def _flow_preservation_constraints(self): for req in self.requests: ext_graph = self.extended_graph[req] for ext_node in ext_graph.nodes: if ext_node == ext_graph.super_source or ext_node == ext_graph.super_sink: continue expr = LinExpr( [(+1.0, self.var_flow[req][sedge_ext]) for sedge_ext in ext_graph.out_edges[ext_node]] + [(-1.0, self.var_flow[req][sedge_ext]) for sedge_ext in ext_graph.in_edges[ext_node]]) constr_name = modelcreator.construct_name("flow_preservation", req_name=req.name, other=ext_node) self.model.addConstr(expr, GRB.EQUAL, 0.0, name=constr_name)
def compute_integral_solution(self): vine_instance = ViNESingleScenario( substrate=self.scenario.substrate, vine_settings=self.vine_settings, gurobi_settings=self.gurobi_settings, optimization_callback=self.optimization_callback, lp_output_file=self.lp_output_file, potential_iis_filename=self.potential_iis_filename, logger=self.logger ) solution_name = mc.construct_name("solution_", sub_name=self.scenario.name) solution = solutions.IntegralScenarioSolution(solution_name, self.scenario) overall_runtime_start = time.time() runtime_per_request = {} mapping_status_per_request = {} for req in sorted(self.scenario.requests, key=lambda r: r.profit, reverse=True): t_start = time.time() mapping, status = vine_instance.vine_procedure_single_request(req) runtime_per_request[req] = time.time() - t_start mapping_status_per_request[req] = status solution.add_mapping(req, mapping) # assert solution.validate_solution() test is limited but worked, no need to keep it in the evaluation # assert solution.validate_solution_fulfills_capacity() test is limited but worked, no need to keep it in the evaluation overall_runtime = time.time() - overall_runtime_start result = OfflineViNEResult( solution=solution, vine_settings=self.vine_settings, runtime=overall_runtime, runtime_per_request=runtime_per_request, mapping_status_per_request=mapping_status_per_request, ) return result