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 reset(self): self.time_step = 0 self.episode_reward = 0.0 self.revenue = 0.0 self.acceptance_ratio = 0.0 self.rc_ratio = 0.0 self.link_embedding_fails_against_total_fails_ratio = 0.0 self.num_reset += 1 # if self.num_reset % 1 == 0: # self.substrate = copy.deepcopy(self.copied_substrate) self.substrate = Substrate() self.vnr_idx = 0 self.vnrs = [] for idx in range(config.NUM_VNR_FOR_TRAIN): self.vnrs.append( VNR( id=idx, vnr_duration_mean_rate=config.VNR_DURATION_MEAN_RATE, delay=config.VNR_DELAY, time_step_arrival=0 ) ) # self.vnrs = sorted( # self.vnrs, key=lambda vnr: vnr.revenue, reverse=True # ) self.vnr = self.vnrs[self.vnr_idx] self.v_node_embedding_success = [] self.vnr_embedding_success_count = [] self.already_embedded_v_nodes = [] self.embedding_s_nodes = {} self.num_processed_v_nodes = 0 self.previous_step_revenue = 0.0 self.previous_step_cost = 0.0 self.egb_trace = [1] * len(self.substrate.net.nodes) self.current_embedding = [0] * len(self.substrate.net.nodes) self.sorted_v_nodes = utils.get_sorted_v_nodes_with_node_ranking( vnr=self.vnr, type_of_node_ranking=config.TYPE_OF_VIRTUAL_NODE_RANKING.TYPE_2 ) self.current_v_node, current_v_node_data, _ = self.sorted_v_nodes[self.num_processed_v_nodes] self.current_v_cpu_demand = current_v_node_data['CPU'] substrate_features, substrate_edge_index, vnr_features = self.get_state_information( self.current_v_node, self.current_v_cpu_demand ) initial_state = A3C_GCN_State(substrate_features, substrate_edge_index, self.current_v_node, vnr_features) return initial_state
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): ''' 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 step(self, action: A3C_GCN_Action): self.time_step += 1 self.vnr = self.vnrs[self.vnr_idx] embedding_success = True v_cpu_demand = None node_embedding_fail_conditions = [ self.substrate.net.nodes[action.s_node]['CPU'] < self.vnr.net.nodes[action.v_node]['CPU'], self.current_embedding[action.s_node] == 1 ] sum_v_bandwidth_demand = 0.0 # for r_c calculation sum_s_bandwidth_embedded = 0.0 # for r_c calculation if any(node_embedding_fail_conditions): embedding_success = False else: # Success for node embedding v_cpu_demand = self.vnr.net.nodes[action.v_node]['CPU'] self.embedding_s_nodes[action.v_node] = action.s_node # Start to try link embedding for already_embedded_v_node in self.already_embedded_v_nodes: if self.vnr.net.has_edge(action.v_node, already_embedded_v_node): v_bandwidth_demand = self.vnr.net[action.v_node][already_embedded_v_node]['bandwidth'] sum_v_bandwidth_demand += v_bandwidth_demand subnet = nx.subgraph_view( self.substrate.net, filter_edge=lambda node_1_id, node_2_id: \ True if self.substrate.net.edges[(node_1_id, node_2_id)]['bandwidth'] >= v_bandwidth_demand else False ) src_s_node = self.embedding_s_nodes[already_embedded_v_node] dst_s_node = self.embedding_s_nodes[action.v_node] if len(subnet.edges) == 0 or not nx.has_path(subnet, source=src_s_node, target=dst_s_node): embedding_success = False del self.embedding_s_nodes[action.v_node] break else: MAX_K = 10 shortest_s_path = utils.k_shortest_paths(subnet, source=src_s_node, target=dst_s_node, k=MAX_K)[0] if len(shortest_s_path) > config.MAX_EMBEDDING_PATH_LENGTH: embedding_success = False break else: # SUCCESS --> EMBED VIRTUAL LINK! 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 self.substrate.net.edges[s_link]['bandwidth'] >= v_bandwidth_demand self.substrate.net.edges[s_link]['bandwidth'] -= v_bandwidth_demand sum_s_bandwidth_embedded += v_bandwidth_demand # calculate r_s if embedding_success: r_s = self.substrate.net.nodes[action.s_node]['CPU'] / self.substrate.initial_s_cpu_capacity[ action.s_node] else: r_s = 1.0 if embedding_success: # ALL SUCCESS --> EMBED VIRTUAL NODE! assert self.substrate.net.nodes[action.s_node]['CPU'] >= v_cpu_demand self.substrate.net.nodes[action.s_node]['CPU'] -= v_cpu_demand self.current_embedding[action.s_node] = 1 self.already_embedded_v_nodes.append(action.v_node) self.v_node_embedding_success.append(embedding_success) else: self.v_node_embedding_success.append(embedding_success) if action.v_node in self.embedding_s_nodes: del self.embedding_s_nodes[action.v_node] # 이 지점에서 self.num_processed_v_nodes += 1 매우 중요: 이후 next_state 및 reward 계산에 영향을 줌 self.num_processed_v_nodes += 1 reward = self.get_reward( embedding_success, v_cpu_demand, sum_v_bandwidth_demand, sum_s_bandwidth_embedded, action, r_s ) done = False # if not embedding_success or self.num_processed_v_nodes == len(self.vnr.net.nodes): if self.num_processed_v_nodes == len(self.vnr.net.nodes): if sum(self.v_node_embedding_success) == len(self.vnr.net.nodes): self.vnr_embedding_success_count.append(1) else: self.vnr_embedding_success_count.append(0) if self.vnr_idx == len(self.vnrs) - 1 or sum(self.vnr_embedding_success_count[-3:]) == 0: # if self.vnr_idx == len(self.vnrs) - 1: # print(self.vnr_embedding_success_count) print("The number of embedded success vnr: ", sum(self.vnr_embedding_success_count)) done = True next_state = A3C_GCN_State(None, None, None, None) else: self.vnr_idx += 1 self.vnr = self.vnrs[self.vnr_idx] self.sorted_v_nodes = utils.get_sorted_v_nodes_with_node_ranking( vnr=self.vnr, type_of_node_ranking=config.TYPE_OF_VIRTUAL_NODE_RANKING.TYPE_2 ) self.num_processed_v_nodes = 0 self.current_v_node, current_v_node_data, _ = self.sorted_v_nodes[self.num_processed_v_nodes] self.current_v_cpu_demand = current_v_node_data['CPU'] substrate_features, substrate_edge_index, vnr_features = self.get_state_information( self.current_v_node, self.current_v_cpu_demand ) next_state = A3C_GCN_State(substrate_features, substrate_edge_index, self.current_v_node, vnr_features) self.already_embedded_v_nodes = [] self.current_embedding = [0] * len(self.substrate.net.nodes) self.v_node_embedding_success = [] else: self.current_v_node, current_v_node_data, _ = self.sorted_v_nodes[self.num_processed_v_nodes] self.current_v_cpu_demand = current_v_node_data['CPU'] substrate_features, substrate_edge_index, vnr_features = self.get_state_information( self.current_v_node, self.current_v_cpu_demand ) next_state = A3C_GCN_State(substrate_features, substrate_edge_index, self.current_v_node, vnr_features) info = {} return next_state, reward, done, info
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