def act(self, observation): # get current network net = observation.net # generate current request src, dst, bandwidth, duration = observation.request # get pre-calculated k-sp path sd_tuple = (src, dst) paths = self.path_table[sort_tuple(sd_tuple)] # Search KSP-FF candidates = [] for i, path in enumerate(paths): path_len = net.distance(path) # physical length of the path n_req_slot = cal_slot(bandwidth, path_len) # calc entropy ent = edge_based_entropy(net, path, n_req_slot) min_ent = np.min(ent) slot_index = np.argmin(ent) # candidate (k-path, slot-idx, n_req_slot, entropy) candidates.append((i, int(slot_index), n_req_slot, min_ent)) # search the minimum entropy among k-sp i_th, start_idx, n_req_slot, _ = min(candidates, key=lambda item: item[3]) path = paths[i_th] act = Action(path, start_idx, n_req_slot, duration) return act
def min_cut_candidates(self, obs) -> list: net = obs.net # generate current request src, dst, bandwidth, duration = obs.request # get pre-calculated k-sp path paths = self.path_table[sort_tuple((src, dst))] candidates = [] min_n_cut = np.inf for path in paths: # calculate candidates of spectrum assignment path_slot = net.path_slot(path) path_len = net.distance(path) # physical length of the path n_req_slot = cal_slot(bandwidth, path_len) num, start_indices, _ = k_consecutive_available_slot( path_slot, n_req_slot) if num > 0: # explore all candidates for start_idx in start_indices: n_cut = count_cut(net, path, start_idx, n_req_slot) if n_cut < min_n_cut: min_n_cut = n_cut # empty candidates = [] # append cand = Action(path, start_idx, n_req_slot, duration) candidates.append(cand) elif n_cut == min_n_cut: # append cand = Action(path, start_idx, n_req_slot, duration) candidates.append(cand) return candidates
def distance(self, path: list) -> int: """Calculate distance of the path. Args: path (list): List of node-ids. Returns: int: distance of the target path. """ edges = path_to_edges(path) weight_dict = nx.get_edge_attributes(self.G, name='weight') distance = sum([weight_dict[sort_tuple(e)] for e in edges]) return distance
def preprocess(self, obs): """ """ net = obs.net src, dst, bandwidth, duration = obs.request # get k-sp sd_tuple = sort_tuple((src, dst)) paths = self.path_table[sd_tuple] fvec = [] # Feature 1: onehot of source-destination nodes node_onehot = onehot_list(net.n_nodes) fvec += node_onehot[src] fvec += node_onehot[dst] # path information if there is no available path # all_zeros = [0 for _ in range(3 + 2)] all_nega_ones = [-1 for _ in range(3 + 2)] # Feature 2: Path information for path in paths: # spectrum utilization on the whole path path_slot = net.path_slot(path) # calc path-length and the required number of slots path_len = net.distance(path) req_n_slot = cal_slot(bandwidth, path_len) # wavelength assignment isFound, slot_start_indices, slot_continuous = k_consecutive_available_slot( path_slot, req_n_slot) if isFound: # normalized slot num is added # (required number of FS: 2 <= req_n_slot <= 9) fvec.append((req_n_slot - 5.5) / 3.5) # slot start idx fvec.append(2 * (slot_start_indices[0] - 0.5 * net.n_slot) / net.n_slot) # slot continue fvec.append((slot_continuous[0] - 8) / 8) # total available FS's fvec.append(2 * (sum(slot_continuous) - 0.5 * net.n_slot) / net.n_slot) # mean size of FS-blocks fvec.append((np.mean(slot_continuous) - 4) / 4) else: fvec += all_nega_ones fvec = np.array(fvec, dtype=np.float32) return fvec
def sp_ff(self, obs): """Shortest path and first fit """ net = obs.net src, dst, bandwidth, duration = obs.request # select shortest path path = self.path_table[sort_tuple((src, dst))][0] path_len = net.distance(path) n_req_slot = cal_slot(bandwidth, path_len) # target path slot path_slot = net.path_slot(path) # first fit start_idx = SpectrumAssignment.first_fit(path_slot, n_req_slot) if start_idx is None: return None else: return Action(path, start_idx, n_req_slot, duration)
def map_drlout_to_action(self, obs, out): """Mapping RL outputs to KSP """ net = obs.net s, d, bandwidth, duration = obs.request paths = self.path_table[sort_tuple((s, d))] # map path = paths[out] #required slots path_len = net.distance(path) n_req_slot = cal_slot(bandwidth, path_len) # FF path_slot = net.path_slot(path) slot_index = SpectrumAssignment.first_fit(path_slot, n_req_slot) if slot_index is None: return None else: return Action(path, slot_index, n_req_slot, duration)
def adj_path_slot(self, path:list): """Get slot of adjacent edges on the path. Args: path (list): List of node-ids. Returns: adj_path_slot_list: list of adjacent path slot by bitarray """ adj_path_slot_list = [] edges = path_to_edges(path) for base_node in path: # search neighbors for node_id, attr in self.G[base_node].items(): e = (node_id, base_node) if sort_tuple(e) in edges: continue adj_path_slot_list.append(bitarray(attr["slot"])) return adj_path_slot_list
def act(self, observation): # get current network net = observation.net # generate current request src, dst, bandwidth, duration = observation.request sd_tuple = (src, dst) paths = self.path_table[sort_tuple(sd_tuple)] # Search assignable path & slot for path in paths: # physical length of the path path_len = net.distance(path) # number of requred slots n_req_slot = cal_slot(bandwidth, path_len) # spectrum assignment slot_idx = self.assign_spectrum(net, path, n_req_slot) if slot_idx is not None: return Action(path, slot_idx, n_req_slot, duration) return None