Beispiel #1
0
    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
Beispiel #2
0
    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
Beispiel #3
0
    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
Beispiel #4
0
    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
Beispiel #5
0
    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
Beispiel #6
0
    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