def embedding(self, VNRs_COLLECTED, COPIED_SUBSTRATE, action): sorted_vnrs = sorted(VNRs_COLLECTED.values(), key=lambda vnr: vnr.revenue, reverse=True) for vnr in sorted_vnrs: original_copied_substrate = copy.deepcopy(COPIED_SUBSTRATE) s_nodes_combinations = self.find_substrate_nodes_combinations( vnr, COPIED_SUBSTRATE) assert original_copied_substrate == COPIED_SUBSTRATE if s_nodes_combinations is None: action.vnrs_postponement[vnr.id] = vnr continue early_stopping = GAEarlyStopping( patience=config.STOP_PATIENCE_COUNT, verbose=True, delta=0.0001, copied_substrate=COPIED_SUBSTRATE) multi_ga_operator = MultiGAOperator(vnr, s_nodes_combinations, COPIED_SUBSTRATE) ### INITIALIZE ### is_ok = multi_ga_operator.initialize() if not is_ok: self.num_link_embedding_fails += 1 msg = "VNR {0} REJECTED ({1}): 'no suitable LINK for bandwidth demand: {2}}".format( vnr.id, self.num_link_embedding_fails, vnr) self.logger.info("{0} {1}".format( utils.step_prefix(self.time_step), msg)) action.vnrs_postponement[vnr.id] = vnr continue multi_ga_operator.process() expected_generation = 1 while True: if multi_ga_operator.is_all_one_generation_finished( expected_generation=expected_generation): multi_ga_operator.evaluate_all_results_from_workers() solved, _ = early_stopping.evaluate( elite=multi_ga_operator.elite, evaluation_value=multi_ga_operator.elite.fitness) if solved: break multi_ga_operator.go_next_generation() expected_generation += 1 time.sleep(0.1) assert original_copied_substrate == COPIED_SUBSTRATE
def complete_vnrs_serving(self): ''' processing of serving_completed :return: vnrs_serving_completed ''' vnrs_serving_completed = [] for vnr, embedding_s_nodes, embedding_s_paths in self.VNRs_SERVING.values( ): if vnr.time_step_serving_completed and vnr.time_step_serving_completed <= self.time_step: vnrs_serving_completed.append(vnr) for s_node_id, v_cpu_demand in embedding_s_nodes.values(): self.SUBSTRATE.net.nodes[s_node_id]['CPU'] += v_cpu_demand for s_links_in_path, v_bandwidth_demand in embedding_s_paths.values( ): for s_link in s_links_in_path: self.SUBSTRATE.net.edges[s_link][ 'bandwidth'] += v_bandwidth_demand for vnr in vnrs_serving_completed: assert vnr.id in self.VNRs_SERVING del self.VNRs_SERVING[vnr.id] if self.logger: self.logger.info("{0} VNR SERVING COMPLETED {1}".format( utils.step_prefix(self.time_step), vnr)) return vnrs_serving_completed
def collect_vnrs_new_arrival(self): for vnr in self.VNRs_INFO.values(): if vnr.time_step_arrival == self.time_step: self.VNRs_COLLECTED[vnr.id] = vnr self.total_arrival_vnrs += 1 if self.logger: self.logger.info("{0} NEW VNR ARRIVED {1}".format( utils.step_prefix(self.time_step), vnr))
def find_substrate_path(self, copied_substrate, vnr, embedding_s_nodes): embedding_s_paths = {} directed_copied_substrate = copied_substrate.net.to_directed() # mapping the virtual nodes and substrate_net nodes for src_v_node, dst_v_node, edge_data in vnr.net.edges(data=True): v_link = (src_v_node, dst_v_node) src_s_node = embedding_s_nodes[src_v_node][0] dst_s_node = embedding_s_nodes[dst_v_node][0] v_bandwidth_demand = edge_data['bandwidth'] if src_s_node == dst_s_node: s_links_in_path = [] embedding_s_paths[v_link] = (s_links_in_path, v_bandwidth_demand) else: subnet = nx.subgraph_view( copied_substrate.net, filter_edge=lambda node_1_id, node_2_id: \ True if copied_substrate.net.edges[(node_1_id, node_2_id)][ 'bandwidth'] >= v_bandwidth_demand else False ) # Just for assertion # for u, v, a in subnet.edges(data=True): # assert a["bandwidth"] >= v_bandwidth_demand if len(subnet.edges) == 0 or not nx.has_path(subnet, source=src_s_node, target=dst_s_node): self.num_link_embedding_fails += 1 msg = "VNR {0} REJECTED ({1}): 'no suitable LINK for bandwidth demand: {2} {3}".format( vnr.id, self.num_link_embedding_fails, v_bandwidth_demand, vnr ) self.logger.info("{0} {1}".format(utils.step_prefix(self.time_step), msg)) return None MAX_K = 1 # shortest_s_path = utils.k_shortest_paths(subnet, source=src_s_node, target=dst_s_node, k=MAX_K)[0] # https://networkx.org/documentation/stable//reference/algorithms/generated/networkx.algorithms.flow.shortest_augmenting_path.html residual_network = shortest_augmenting_path(directed_copied_substrate, src_s_node, dst_s_node, capacity='bandwidth', cutoff=v_bandwidth_demand) s_links_in_path = [] path = [] for src_r_node, dst_r_node, r_edge_data in residual_network.edges(data=True): if r_edge_data['flow'] > 0: s_links_in_path.append((src_r_node, dst_r_node)) # s_links_in_path = [] # for node_idx in range(len(shortest_s_path) - 1): # s_links_in_path.append((shortest_s_path[node_idx], shortest_s_path[node_idx + 1])) for s_link in s_links_in_path: # assert copied_substrate.net.edges[s_link]['bandwidth'] >= v_bandwidth_demand copied_substrate.net.edges[s_link]['bandwidth'] -= v_bandwidth_demand embedding_s_paths[v_link] = (s_links_in_path, v_bandwidth_demand) return embedding_s_paths
def find_substrate_nodes(self, copied_substrate, vnr): subset_S_per_v_node = {} embedding_s_nodes = {} already_embedding_s_nodes = [] current_embedding_s_nodes = [0] * len(copied_substrate.net.nodes) # self.config.TYPE_OF_VIRTUAL_NODE_RANKING.TYPE_2 sorted_v_nodes_with_node_ranking = utils.get_sorted_v_nodes_with_node_ranking( vnr=vnr, type_of_node_ranking=self.type_of_virtual_node_ranking) num_remain_v_node = 1 for v_node_id, v_node_data, _ in sorted_v_nodes_with_node_ranking: v_cpu_demand = v_node_data['CPU'] v_node_location = v_node_data['LOCATION'] v_pending = len( sorted_v_nodes_with_node_ranking) - num_remain_v_node # Find the subset S of substrate nodes that satisfy restrictions and # available CPU capacity (larger than that specified by the request.) subset_S_per_v_node[ v_node_id] = utils.find_subset_S_for_virtual_node( copied_substrate, v_cpu_demand, v_node_location, already_embedding_s_nodes) # Generate the state substrate_features, edge_index, vnr_features = self.get_state_information( copied_substrate, vnr, current_embedding_s_nodes, v_node_id, v_cpu_demand, v_pending) # select the node selected_s_node_id = self.a3c_gcn_agent.select_node( substrate_features, edge_index, vnr_features) if copied_substrate.net.nodes[selected_s_node_id]['CPU'] <= v_cpu_demand or \ selected_s_node_id in already_embedding_s_nodes: self.num_node_embedding_fails += 1 msg = "VNR {0} REJECTED ({1}): 'no suitable SUBSTRATE NODE for nodal constraints: {2}' {3}".format( vnr.id, self.num_node_embedding_fails, v_cpu_demand, vnr) self.logger.info("{0} {1}".format( utils.step_prefix(self.time_step), msg)) return None assert selected_s_node_id != -1 embedding_s_nodes[v_node_id] = (selected_s_node_id, v_cpu_demand) if not self.allow_embedding_to_same_substrate_node: already_embedding_s_nodes.append(selected_s_node_id) assert copied_substrate.net.nodes[selected_s_node_id][ 'CPU'] >= v_cpu_demand copied_substrate.net.nodes[selected_s_node_id][ 'CPU'] -= v_cpu_demand current_embedding_s_nodes[selected_s_node_id] = 1 num_remain_v_node += 1 return embedding_s_nodes
def release_vnrs_expired_from_collected(self, vnrs_embedding): ''' processing of leave_from_queue :return: vnrs_left_from_queue ''' vnrs_left_from_queue = [] for vnr in self.VNRs_COLLECTED.values(): if vnr.time_step_leave_from_queue <= self.time_step and vnr.id not in vnrs_embedding: vnrs_left_from_queue.append(vnr) for vnr in vnrs_left_from_queue: del self.VNRs_COLLECTED[vnr.id] if self.logger: self.logger.info("{0} VNR LEFT OUT {1}".format( utils.step_prefix(self.time_step), vnr)) return vnrs_left_from_queue
def find_substrate_nodes_combinations(self, vnr, COPIED_SUBSTRATE): sorted_v_nodes_with_node_ranking = utils.get_sorted_v_nodes_with_node_ranking( vnr=vnr, type_of_node_ranking=config.TYPE_OF_VIRTUAL_NODE_RANKING.TYPE_2) #print(sorted_v_nodes_with_node_ranking, "!!!!!") all_combinations = [] self.make_top_n_combinations( sorted_v_nodes_with_node_ranking=sorted_v_nodes_with_node_ranking, idx=0, combination=[], all_combinations=all_combinations, copied_substrate=COPIED_SUBSTRATE, already_embedding_s_nodes=[]) print("TOTAL {0} combinations".format(len(all_combinations))) # for idx, combination in enumerate(all_combinations): # print(idx, combination) s_nodes_combinations = [] for combination_idx, combination in enumerate(all_combinations): if len(combination) != len(sorted_v_nodes_with_node_ranking): self.num_node_embedding_fails += 1 msg = "VNR {0} REJECTED ({1}): 'no suitable SUBSTRATE NODE for nodal constraints' {2}".format( vnr.id, self.num_node_embedding_fails, vnr) self.logger.info("{0} {1}".format( utils.step_prefix(self.time_step), msg)) return None #print(vnr.id, combination_idx, combination) embedding_s_nodes = {} for idx, selected_s_node_id in enumerate(combination): v_node_id = sorted_v_nodes_with_node_ranking[idx][0] v_cpu_demand = sorted_v_nodes_with_node_ranking[idx][1]['CPU'] embedding_s_nodes[v_node_id] = (selected_s_node_id, v_cpu_demand) s_nodes_combinations.append(embedding_s_nodes) return s_nodes_combinations
def find_substrate_nodes(self, copied_substrate, vnr): subset_S_per_v_node = {} embedding_s_nodes = {} already_embedding_s_nodes = [] for v_node_id, v_node_data in vnr.net.nodes(data=True): v_cpu_demand = v_node_data['CPU'] v_node_location = v_node_data['LOCATION'] # Find the subset S of substrate nodes that satisfy restrictions and # available CPU capacity (larger than that specified by the request.) subset_S_per_v_node[ v_node_id] = utils.find_subset_S_for_virtual_node( copied_substrate, v_cpu_demand, v_node_location, already_embedding_s_nodes) selected_s_node_id = max(subset_S_per_v_node[v_node_id], key=lambda s_node_id: copied_substrate.net .nodes[s_node_id]['CPU'] - v_cpu_demand, default=None) if selected_s_node_id is None: self.num_node_embedding_fails += 1 msg = "VNR {0} REJECTED ({1}): 'no suitable SUBSTRATE NODE for nodal constraints: {2}' {3}".format( vnr.id, self.num_node_embedding_fails, v_cpu_demand, vnr) self.logger.info("{0} {1}".format( utils.step_prefix(self.time_step), msg)) return None assert selected_s_node_id != -1 embedding_s_nodes[v_node_id] = (selected_s_node_id, v_cpu_demand) if not config.ALLOW_EMBEDDING_TO_SAME_SUBSTRATE_NODE: already_embedding_s_nodes.append(selected_s_node_id) assert copied_substrate.net.nodes[selected_s_node_id][ 'CPU'] >= v_cpu_demand copied_substrate.net.nodes[selected_s_node_id][ 'CPU'] -= v_cpu_demand return embedding_s_nodes
def starting_serving_for_a_vnr(self, vnr, embedding_s_nodes, embedding_s_paths): for s_node_id, v_cpu_demand in embedding_s_nodes.values(): self.SUBSTRATE.net.nodes[s_node_id]['CPU'] -= v_cpu_demand for s_links_in_path, v_bandwidth_demand in embedding_s_paths.values(): for s_link in s_links_in_path: self.SUBSTRATE.net.edges[s_link][ 'bandwidth'] -= v_bandwidth_demand vnr.time_step_serving_started = self.time_step vnr.time_step_serving_completed = self.time_step + vnr.duration vnr.cost = utils.get_cost_VNR(vnr, embedding_s_paths) self.VNRs_SERVING[vnr.id] = (vnr, embedding_s_nodes, embedding_s_paths) if self.logger: self.logger.info("{0} VNR SERVING STARTED {1}".format( utils.step_prefix(self.time_step), vnr)) self.total_embedded_vnrs += 1 del self.VNRs_COLLECTED[vnr.id]
def find_substrate_nodes(self, copied_substrate, vnr): ''' Execute Step 1 :param copied_substrate: copied substrate network :param vnr: virtual network request :return: embedded substrate nodesƒ ''' subset_S_per_v_node = {} embedding_s_nodes = {} already_embedding_s_nodes = [] # config.TYPE_OF_VIRTUAL_NODE_RANKING.TYPE_2 sorted_v_nodes_with_node_ranking = utils.get_sorted_v_nodes_with_node_ranking( vnr=vnr, type_of_node_ranking=self.type_of_virtual_node_ranking) for v_node_id, v_node_data, _ in sorted_v_nodes_with_node_ranking: v_cpu_demand = v_node_data['CPU'] v_node_location = v_node_data['LOCATION'] # Find the subset S of substrate nodes that satisfy restrictions and # available CPU capacity (larger than that specified by the request.) subset_S_per_v_node[ v_node_id] = utils.find_subset_S_for_virtual_node( copied_substrate, v_cpu_demand, v_node_location, already_embedding_s_nodes) # if len(subset_S_per_v_node[v_node_id]) == 0: # self.num_node_embedding_fails += 1 # msg = "VNR {0} REJECTED ({1}): 'no subset S' - {2}".format(vnr.id, self.num_node_embedding_fails, vnr) # self.logger.info("{0} {1}".format(utils.step_prefix(self.time_step), msg)) # return None # max_node_ranking = -1.0 * 1e10 # selected_s_node_id = -1 selected_s_node_id = max( subset_S_per_v_node[v_node_id], key=lambda s_node_id: self.calculate_node_ranking( copied_substrate.net.nodes[s_node_id]['CPU'], copied_substrate.net[s_node_id]), default=None) if selected_s_node_id is None: self.num_node_embedding_fails += 1 msg = "VNR {0} REJECTED ({1}): 'no suitable SUBSTRATE NODE for nodal constraints: {2}' {3}".format( vnr.id, self.num_node_embedding_fails, v_cpu_demand, vnr) self.logger.info("{0} {1}".format( utils.step_prefix(self.time_step), msg)) return None # for s_node_id in subset_S_per_v_node[v_node_id]: # node_ranking = self.calculate_node_ranking( # copied_substrate.net.nodes[s_node_id]['CPU'], # copied_substrate.net[s_node_id] # ) # # if node_ranking > max_node_ranking: # max_node_ranking = node_ranking # selected_s_node_id = s_node_id assert selected_s_node_id != -1 embedding_s_nodes[v_node_id] = (selected_s_node_id, v_cpu_demand) if not self.allow_embedding_to_same_substrate_node: already_embedding_s_nodes.append(selected_s_node_id) assert copied_substrate.net.nodes[selected_s_node_id][ 'CPU'] >= v_cpu_demand copied_substrate.net.nodes[selected_s_node_id][ 'CPU'] -= v_cpu_demand return embedding_s_nodes
def find_substrate_nodes(self, copied_substrate, vnr): ''' Execute Step 1 :param copied_substrate: copied substrate network :param vnr: virtual network request :return: embedded substrate nodes ''' subset_S_per_v_node = {} embedding_s_nodes = {} already_embedding_s_nodes = [] # Generate the augmented substrate network with location info. self.change_to_augmented_substrate(copied_substrate, vnr, self.substrate_nodes) opt_lp_f_vars, opt_lp_x_vars = self.calculate_LP_variables( copied_substrate, vnr) for v_node_id, v_node_data in vnr.net.nodes(data=True): v_cpu_demand = v_node_data['CPU'] v_node_location = v_node_data['LOCATION'] # Find the subset S of substrate nodes that satisfy restrictions and # available CPU capacity (larger than that specified by the request.) subset_S_per_v_node[ v_node_id] = utils.find_subset_S_for_virtual_node( copied_substrate, v_cpu_demand, v_node_location, already_embedding_s_nodes) selected_s_node_p_value = [] candidate_s_node_id = [] selected_s_node_id = max( subset_S_per_v_node[v_node_id], key=lambda s_node_id: sum(opt_lp_f_vars[ (opt_lp_f_vars['u'] == s_node_id) & (opt_lp_f_vars['v'] == v_node_id + self.substrate_nodes) ]['solution_value'].values + opt_lp_f_vars[ (opt_lp_f_vars['u'] == v_node_id + self.substrate_nodes) & (opt_lp_f_vars['v'] == s_node_id)][ 'solution_value'].values) * opt_lp_x_vars[ (opt_lp_x_vars['u'] == s_node_id) & (opt_lp_x_vars['v'] == v_node_id + self. substrate_nodes)]['solution_value'].values, default=None) # for calculating p_value # selected_s_node_p_value = [] # candidate_s_node_id = [] # for s_node_id in subset_S_per_v_node[v_node_id]: # candidate_s_node_id.append(s_node_id) # selected_s_node_p_value.append( # sum(opt_lp_f_vars[ # (opt_lp_f_vars['u'] == s_node_id) & # (opt_lp_f_vars['v'] == v_node_id + self.substrate_nodes)]['solution_value'].values + # opt_lp_f_vars[ # (opt_lp_f_vars['u'] == v_node_id + self.substrate_nodes) & # (opt_lp_f_vars['v'] == s_node_id)]['solution_value'].values)) # Calculate the probability # scipy softmax 추가하여 이용하기 # https://docs.scipy.org/doc/scipy/reference/generated/scipy.special.softmax.html total_p_value = sum(selected_s_node_p_value) if total_p_value == 0: self.num_node_embedding_fails += 1 msg = "VNR {0} REJECTED ({1}): 'no suitable SUBSTRATE NODE for nodal constraints: {2}' {3}".format( vnr.id, self.num_node_embedding_fails, v_cpu_demand, vnr) self.logger.info("{0} {1}".format( utils.step_prefix(self.time_step), msg)) self.revoke_from_augmented_substrate(copied_substrate, vnr, self.substrate_nodes) return None else: probability = softmax(selected_s_node_p_value) selected_s_node_id = np.random.choice(candidate_s_node_id, p=probability) if selected_s_node_id is None: self.num_node_embedding_fails += 1 msg = "VNR {0} REJECTED ({1}): 'no suitable SUBSTRATE NODE for nodal constraints: {2}' {3}".format( vnr.id, self.num_node_embedding_fails, v_cpu_demand, vnr) self.logger.info("{0} {1}".format( utils.step_prefix(self.time_step), msg)) self.revoke_from_augmented_substrate(copied_substrate, vnr, self.substrate_nodes) return None assert selected_s_node_id != -1 embedding_s_nodes[v_node_id] = (selected_s_node_id, v_cpu_demand) if not self.allow_embedding_to_same_substrate_node: already_embedding_s_nodes.append(selected_s_node_id) assert copied_substrate.net.nodes[selected_s_node_id][ 'CPU'] >= v_cpu_demand copied_substrate.net.nodes[selected_s_node_id][ 'CPU'] -= v_cpu_demand self.revoke_from_augmented_substrate(copied_substrate, vnr, self.substrate_nodes) return embedding_s_nodes
def find_substrate_nodes(self, copied_substrate, vnr): ''' Execute Step 1 :param copied_substrate: copied substrate network :param vnr: virtual network request :return: embedded substrate nodes ''' subset_S_per_v_node = {} embedding_s_nodes = {} already_embedding_s_nodes = [] # Generate the augmented substrate network with location info. self.change_to_augmented_substrate(copied_substrate, vnr, self.substrate_nodes) opt_lp_f_vars, opt_lp_x_vars = self.calculate_LP_variables(copied_substrate, vnr) for v_node_id, v_node_data in vnr.net.nodes(data=True): v_cpu_demand = v_node_data['CPU'] v_node_location = v_node_data['LOCATION'] # Find the subset S of substrate nodes that satisfy restrictions and # available CPU capacity (larger than that specified by the request.) subset_S_per_v_node[v_node_id] = utils.find_subset_S_for_virtual_node( copied_substrate, v_cpu_demand, v_node_location, already_embedding_s_nodes ) # selected_s_node_id = max( # subset_S_per_v_node[v_node_id], # key=lambda s_node_id: # sum(opt_lp_f_vars[(opt_lp_f_vars['u'] == s_node_id) & # (opt_lp_f_vars['v'] == v_node_id + self.substrate_nodes)]['solution_value'].values + # opt_lp_f_vars[(opt_lp_f_vars['u'] == v_node_id + self.substrate_nodes) & # (opt_lp_f_vars['v'] == s_node_id)]['solution_value'].values # ) * # opt_lp_x_vars[(opt_lp_x_vars['u'] == s_node_id) & # (opt_lp_x_vars['v'] == v_node_id + self.substrate_nodes)]['solution_value'].values, # default=None # ) selected_s_node_id = max( subset_S_per_v_node[v_node_id], key=lambda s_node_id: sum(opt_lp_f_vars[(opt_lp_f_vars['u'] == s_node_id) & (opt_lp_f_vars['v'] == v_node_id + self.substrate_nodes)]['solution_value'].values + opt_lp_f_vars[(opt_lp_f_vars['u'] == v_node_id + self.substrate_nodes) & (opt_lp_f_vars['v'] == s_node_id)]['solution_value'].values) * opt_lp_x_vars[(opt_lp_x_vars['u'] == s_node_id) & (opt_lp_x_vars['v'] == v_node_id + self.substrate_nodes)]['solution_value'].values[0], default=None ) if selected_s_node_id is None: self.num_node_embedding_fails += 1 msg = "VNR {0} REJECTED ({1}): 'no suitable SUBSTRATE NODE for nodal constraints: {2}' {3}".format( vnr.id, self.num_node_embedding_fails, v_cpu_demand, vnr ) self.logger.info("{0} {1}".format(utils.step_prefix(self.time_step), msg)) self.revoke_from_augmented_substrate(copied_substrate, vnr, self.substrate_nodes) return None assert selected_s_node_id != -1 embedding_s_nodes[v_node_id] = (selected_s_node_id, v_cpu_demand) if not self.allow_embedding_to_same_substrate_node: already_embedding_s_nodes.append(selected_s_node_id) assert copied_substrate.net.nodes[selected_s_node_id]['CPU'] >= v_cpu_demand copied_substrate.net.nodes[selected_s_node_id]['CPU'] -= v_cpu_demand self.revoke_from_augmented_substrate(copied_substrate, vnr, self.substrate_nodes) return embedding_s_nodes
def find_substrate_nodes(self, copied_substrate, vnr): ''' Execute Step 1 :param copied_substrate: copied substrate network :param vnr: virtual network request :return: embedded substrate nodes ''' subset_S_per_v_node = {} embedding_s_nodes = {} already_embedding_s_nodes = [] # self.config.TYPE_OF_VIRTUAL_NODE_RANKING.TYPE_1 sorted_v_nodes_with_node_ranking = utils.get_sorted_v_nodes_with_node_ranking( vnr=vnr, type_of_node_ranking=self.type_of_virtual_node_ranking, beta=self.beta) vnr_num_node = 0 for v_node_id, v_node_data, _ in sorted_v_nodes_with_node_ranking: v_cpu_demand = v_node_data['CPU'] v_node_location = v_node_data['LOCATION'] if vnr_num_node == 0: # Find the subset S of substrate nodes that satisfy restrictions and # available CPU capacity (larger than that specified by the request.) subset_S_per_v_node[ v_node_id] = utils.find_subset_S_for_virtual_node( copied_substrate, v_cpu_demand, v_node_location, already_embedding_s_nodes) selected_s_node_id = max( subset_S_per_v_node[v_node_id], key=lambda s_node_id: self.calculate_node_ranking( copied_substrate.net.nodes[s_node_id]['CPU'], copied_substrate.net[s_node_id]), default=None) elif vnr_num_node != 0 and selected_s_node_id is not None: radius = 1 sub_ego_graph_length = 0 while sub_ego_graph_length != len(copied_substrate.net.nodes): # make the previous selected node's ego graph sub_ego_graph = nx.ego_graph(copied_substrate.net, selected_s_node_id, radius=radius) sub_ego_graph_length = len(sub_ego_graph.nodes) subset_S_per_v_node[ v_node_id] = utils.find_subset_S_for_virtual_node( sub_ego_graph, v_cpu_demand, v_node_location, already_embedding_s_nodes) if len(subset_S_per_v_node[v_node_id]) == 0: if sub_ego_graph_length == len( copied_substrate.net.nodes): selected_s_node_id = None break else: radius += 1 continue else: selected_s_node_id = max( subset_S_per_v_node[v_node_id], key=lambda s_node_id: self.calculate_node_ranking( copied_substrate.net.nodes[s_node_id]['CPU'], copied_substrate.net[s_node_id]), default=None) if selected_s_node_id is not None: break radius += 1 vnr_num_node += 1 if selected_s_node_id is None: self.num_node_embedding_fails += 1 msg = "VNR {0} REJECTED ({1}): 'no suitable SUBSTRATE NODE for nodal constraints: {2}' {3}".format( vnr.id, self.num_node_embedding_fails, v_cpu_demand, vnr) self.logger.info("{0} {1}".format( utils.step_prefix(self.time_step), msg)) return None assert selected_s_node_id != -1 embedding_s_nodes[v_node_id] = (selected_s_node_id, v_cpu_demand) if not self.allow_embedding_to_same_substrate_node: already_embedding_s_nodes.append(selected_s_node_id) assert copied_substrate.net.nodes[selected_s_node_id][ 'CPU'] >= v_cpu_demand copied_substrate.net.nodes[selected_s_node_id][ 'CPU'] -= v_cpu_demand return embedding_s_nodes
def find_substrate_path(self, copied_substrate, vnr, embedding_s_nodes): embedding_s_paths = {} # mapping the virtual nodes and substrate_net nodes for src_v_node, dst_v_node, edge_data in vnr.net.edges(data=True): v_link = (src_v_node, dst_v_node) src_s_node = embedding_s_nodes[src_v_node][0] dst_s_node = embedding_s_nodes[dst_v_node][0] v_bandwidth_demand = edge_data['bandwidth'] if src_s_node == dst_s_node: embedding_s_paths[v_link] = ([], v_bandwidth_demand) else: subnet = nx.subgraph_view( copied_substrate.net, filter_edge=lambda node_1_id, node_2_id: \ True if copied_substrate.net.edges[(node_1_id, node_2_id)]['bandwidth'] >= v_bandwidth_demand else False ) # Just for assertion # for u, v, a in subnet.edges(data=True): # assert a["bandwidth"] >= v_bandwidth_demand if len(subnet.edges) == 0 or not nx.has_path( subnet, source=src_s_node, target=dst_s_node): self.num_link_embedding_fails += 1 msg = "VNR {0} REJECTED ({1}): 'no suitable LINK for bandwidth demand: {2} {3}".format( vnr.id, self.num_link_embedding_fails, v_bandwidth_demand, vnr) self.logger.info("{0} {1}".format( utils.step_prefix(self.time_step), msg)) return None MAX_K = 1 shortest_s_path = utils.k_shortest_paths(subnet, source=src_s_node, target=dst_s_node, k=MAX_K)[0] # Check the path length if len(shortest_s_path) > self.max_embedding_path_length: self.num_link_embedding_fails += 1 msg = "VNR {0} REJECTED ({1}): 'no suitable LINK for bandwidth demand: {2} {3}".format( vnr.id, self.num_link_embedding_fails, v_bandwidth_demand, vnr) self.logger.info("{0} {1}".format( utils.step_prefix(self.time_step), msg)) return None # if hasattr(config, "MAX_EMBEDDING_PATH_LENGTH") and len(shortest_s_path) - 1 > config.MAX_EMBEDDING_PATH_LENGTH: # self.num_link_embedding_fails += 1 # msg = "VNR {0} REJECTED ({1}): 'Suitable LINK for bandwidth demand, however the path length {2} is higher than {3}".format( # vnr.id, self.num_link_embedding_fails, len(shortest_s_path) - 1, config.MAX_EMBEDDING_PATH_LENGTH # ) # self.logger.info("{0} {1}".format(utils.step_prefix(self.time_step), msg)) # return None s_links_in_path = [] for node_idx in range(len(shortest_s_path) - 1): s_links_in_path.append((shortest_s_path[node_idx], shortest_s_path[node_idx + 1])) for s_link in s_links_in_path: assert copied_substrate.net.edges[s_link][ 'bandwidth'] >= v_bandwidth_demand copied_substrate.net.edges[s_link][ 'bandwidth'] -= v_bandwidth_demand embedding_s_paths[v_link] = (s_links_in_path, v_bandwidth_demand) return embedding_s_paths
def find_substrate_path(self, copied_substrate, vnr, embedding_s_nodes): is_ok, results = utils.find_all_s_paths_2(copied_substrate, embedding_s_nodes, vnr) if is_ok: all_s_paths = results else: (v_link, v_bandwidth_demand) = results self.num_link_embedding_fails += 1 if v_bandwidth_demand: msg = "VNR {0} REJECTED ({1}): 'no suitable LINK for bandwidth demand: {2} {3}".format( vnr.id, self.num_link_embedding_fails, v_bandwidth_demand, vnr) else: msg = "VNR {0} REJECTED ({1}): 'not found for any substrate path for v_link: {2} {3}".format( vnr.id, self.num_link_embedding_fails, v_link, vnr) self.logger.info("{0} {1}".format( utils.step_prefix(self.time_step), msg)) return None # GENETIC ALGORITHM START: mapping the virtual nodes and substrate_net nodes print("[[VNR {0}] GA Started for {1} Virtual Links]".format( vnr.id, len(vnr.net.edges(data=True)))) # LINK EMBEDDING VIA GENETIC ALGORITHM original_copied_substrate = copy.deepcopy(copied_substrate) early_stopping = GAEarlyStopping(patience=config.STOP_PATIENCE_COUNT, verbose=True, delta=0.0001, copied_substrate=copied_substrate) ga_operator = GAOperator(vnr, all_s_paths, copied_substrate, config.POPULATION_SIZE) ga_operator.initialize() generation_idx = 0 while True: generation_idx += 1 ga_operator.selection() ga_operator.crossover() ga_operator.mutation() ga_operator.sort_population_and_set_elite() solved, best_elite = early_stopping.evaluate( elite=ga_operator.elite, evaluation_value=ga_operator.elite.fitness) if solved: break assert original_copied_substrate == copied_substrate # s_path is selected from elite chromosome # early_stopping.print_best_elite() for v_link, ( s_links_in_path, v_bandwidth_demand) in best_elite.embedding_s_paths.items(): for s_link in s_links_in_path: if copied_substrate.net.edges[s_link][ 'bandwidth'] < v_bandwidth_demand: self.num_link_embedding_fails += 1 msg = "VNR {0} REJECTED ({1}): 'After GA (fitness: {2:.6f}) " \ "-> no suitable LINK for bandwidth demand: {3} {4}".format( vnr.id, self.num_link_embedding_fails, best_elite.fitness, v_bandwidth_demand, vnr ) self.logger.info("{0} {1}".format( utils.step_prefix(self.time_step), msg)) return None copied_substrate.net.edges[s_link][ 'bandwidth'] -= v_bandwidth_demand return best_elite.embedding_s_paths