├── PrioritizedReplayDDQN ├── DeepQNetwork.py └── config.py ├── README.md ├── code ├── ActiveSearch.py ├── DSDP.py ├── DTDP.py ├── DeepQNetwork.py ├── Embedding_and_Release.py ├── HetNet_data │ └── memory_data │ │ └── memory ├── PerformanceEvaluation.py ├── PtrNet.py ├── Read_helpers.py ├── Test.py ├── __pycache__ │ ├── DeepQNetwork.cpython-38.pyc │ ├── config.cpython-38.pyc │ ├── network.cpython-38.pyc │ ├── replay_memory.cpython-38.pyc │ └── utils.cpython-38.pyc ├── config.py ├── natureDQN.py ├── network.py ├── ran.py ├── replay_memory.py ├── static.py └── utils.py ├── data └── data_500 │ ├── maprecord.txt │ └── virtualnetworkTP2.txt └── users_plus ├── DDQN_30.py ├── DDQN_40.py ├── DDQN_50.py ├── DeepQNetwork.py ├── DeepQNetwork_40.py ├── DeepQNetwork_50.py ├── HetNet_data ├── checkpoints │ └── 新建文本文档.txt ├── image │ └── 新建文本文档.txt ├── memory_data │ └── 新建文本文档.txt ├── processed_data │ └── 新建文本文档.txt ├── summary │ └── 新建文本文档.txt ├── test_data │ └── 新建文本文档.txt └── train_data │ └── 新建文本文档.txt ├── __pycache__ ├── DeepQNetwork.cpython-38.pyc ├── config.cpython-38.pyc ├── network.cpython-38.pyc ├── replay_memory.cpython-38.pyc └── utils.cpython-38.pyc ├── config.py ├── config_40.py ├── config_50.py ├── network2.py ├── network_40.py ├── network_50.py ├── replay_memory.py └── utils.py /PrioritizedReplayDDQN/DeepQNetwork.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn as nn 3 | import torch.nn.functional as F 4 | import torch.optim as optim 5 | 6 | 7 | class Net(nn.Module): 8 | def __init__(self): 9 | super(Net, self).__init__() 10 | self.fc1 = nn.Linear(20, 60) 11 | self.fc1_p = nn.Linear(60, 20) 12 | self.fc1_c = nn.Linear(60, 20) 13 | self.fc2_p = nn.Linear(60, 20) 14 | self.fc2_c = nn.Linear(60, 20) 15 | self.fc3_p = nn.Linear(60, 20) 16 | self.fc3_c = nn.Linear(60, 20) 17 | self.fc4_p = nn.Linear(60, 20) 18 | self.fc4_c = nn.Linear(60, 20) 19 | self.fc5_p = nn.Linear(60, 20) 20 | self.fc5_c = nn.Linear(60, 20) 21 | self.fc6_p = nn.Linear(60, 20) 22 | self.fc6_c = nn.Linear(60, 20) 23 | self.fc7_p = nn.Linear(60, 20) 24 | self.fc7_c = nn.Linear(60, 20) 25 | self.fc8_p = nn.Linear(60, 20) 26 | self.fc8_c = nn.Linear(60, 20) 27 | self.fc9_p = nn.Linear(60, 20) 28 | self.fc9_c = nn.Linear(60, 20) 29 | self.fc10_p = nn.Linear(60, 20) 30 | self.fc10_c = nn.Linear(60, 20) 31 | self.fc11_p = nn.Linear(60, 20) 32 | self.fc11_c = nn.Linear(60, 20) 33 | self.fc12_p = nn.Linear(60, 20) 34 | self.fc12_c = nn.Linear(60, 20) 35 | self.fc13_p = nn.Linear(60, 20) 36 | self.fc13_c = nn.Linear(60, 20) 37 | self.fc14_p = nn.Linear(60, 20) 38 | self.fc14_c = nn.Linear(60, 20) 39 | self.fc15_p = nn.Linear(60, 20) 40 | self.fc15_c = nn.Linear(60, 20) 41 | self.fc16_p = nn.Linear(60, 20) 42 | self.fc16_c = nn.Linear(60, 20) 43 | self.fc17_p = nn.Linear(60, 20) 44 | self.fc17_c = nn.Linear(60, 20) 45 | self.fc18_p = nn.Linear(60, 20) 46 | self.fc18_c = nn.Linear(60, 20) 47 | self.fc19_p = nn.Linear(60, 20) 48 | self.fc19_c = nn.Linear(60, 20) 49 | self.fc20_p = nn.Linear(60, 20) 50 | self.fc20_c = nn.Linear(60, 20) 51 | self.dropout = nn.Dropout(p=0.5) 52 | 53 | def forward(self, x): 54 | x = x.view(-1, 1, 20) # 1*1*3 55 | x = F.relu(self.fc1(x)) # 1*1*180 56 | 57 | x1_p = self.dropout(F.relu(self.fc1_p(x))).view(-1,1,20) # 20 58 | x1_c = self.dropout(F.relu(self.fc1_c(x))).view(-1,1,20) # 6 59 | x2_p = self.dropout(F.relu(self.fc2_p(x))).view(-1,1,20) # 20 60 | x2_c = self.dropout(F.relu(self.fc2_c(x))).view(-1,1,20) # 6 61 | x3_p = self.dropout(F.relu(self.fc3_p(x))).view(-1,1,20) # 20 62 | x3_c = self.dropout(F.relu(self.fc3_c(x))).view(-1,1,20) # 6 63 | x4_p = self.dropout(F.relu(self.fc4_p(x))).view(-1,1,20) # 20 64 | x4_c = self.dropout(F.relu(self.fc4_c(x))).view(-1,1,20) # 6 65 | x5_p = self.dropout(F.relu(self.fc5_p(x))).view(-1,1,20) # 20 66 | x5_c = self.dropout(F.relu(self.fc5_c(x))).view(-1,1,20) # 6 67 | x6_p = self.dropout(F.relu(self.fc6_p(x))).view(-1,1,20) # 20 68 | x6_c = self.dropout(F.relu(self.fc6_c(x))).view(-1,1,20) # 6 69 | x7_p = self.dropout(F.relu(self.fc7_p(x))).view(-1,1,20) # 20 70 | x7_c = self.dropout(F.relu(self.fc7_c(x))).view(-1,1,20) # 6 71 | x8_p = self.dropout(F.relu(self.fc8_p(x))).view(-1,1,20) # 20 72 | x8_c = self.dropout(F.relu(self.fc8_c(x))).view(-1,1,20) # 6 73 | x9_p = self.dropout(F.relu(self.fc9_p(x))).view(-1,1,20) # 20 74 | x9_c = self.dropout(F.relu(self.fc9_c(x))).view(-1,1,20) # 6 75 | x10_p = self.dropout(F.relu(self.fc10_p(x))).view(-1,1,20) # 20 76 | x10_c = self.dropout(F.relu(self.fc10_c(x))).view(-1,1,20) # 6 77 | x11_p = self.dropout(F.relu(self.fc11_p(x))).view(-1,1,20) # 20 78 | x11_c = self.dropout(F.relu(self.fc11_c(x))).view(-1,1,20) # 6 79 | x12_p = self.dropout(F.relu(self.fc12_p(x))).view(-1,1,20) # 20 80 | x12_c = self.dropout(F.relu(self.fc12_c(x))).view(-1,1,20) # 6 81 | x13_p = self.dropout(F.relu(self.fc13_p(x))).view(-1,1,20) # 20 82 | x13_c = self.dropout(F.relu(self.fc13_c(x))).view(-1,1,20) # 6 83 | x14_p = self.dropout(F.relu(self.fc14_p(x))).view(-1,1,20) # 20 84 | x14_c = self.dropout(F.relu(self.fc14_c(x))).view(-1,1,20) # 6 85 | x15_p = self.dropout(F.relu(self.fc15_p(x))).view(-1,1,20) # 20 86 | x15_c = self.dropout(F.relu(self.fc15_c(x))).view(-1,1,20) # 6 87 | x16_p = self.dropout(F.relu(self.fc16_p(x))).view(-1,1,20) # 20 88 | x16_c = self.dropout(F.relu(self.fc16_c(x))).view(-1,1,20) # 6 89 | x17_p = self.dropout(F.relu(self.fc17_p(x))).view(-1,1,20) # 20 90 | x17_c = self.dropout(F.relu(self.fc17_c(x))).view(-1,1,20) # 6 91 | x18_p = self.dropout(F.relu(self.fc18_p(x))).view(-1,1,20) # 20 92 | x18_c = self.dropout(F.relu(self.fc18_c(x))).view(-1,1,20) # 6 93 | x19_p = self.dropout(F.relu(self.fc19_p(x))).view(-1,1,20) # 20 94 | x19_c = self.dropout(F.relu(self.fc19_c(x))).view(-1,1,20) # 6 95 | x20_p = self.dropout(F.relu(self.fc20_p(x))).view(-1,1,20) # 20 96 | x20_c = self.dropout(F.relu(self.fc20_c(x))).view(-1,1,20) # 6 97 | 98 | return x1_p,x1_c,x2_p,x2_c,x3_p,x3_c,x4_p,x4_c,x5_p,x5_c,x6_p,x6_c,x7_p,x7_c,x8_p,x8_c,x9_p,x9_c,x10_p,x10_c,\ 99 | x11_p,x11_c,x12_p,x12_c,x13_p,x13_c,x14_p,x14_c,x15_p,x15_c,x16_p,x16_c,x17_p,x17_c,x18_p,x18_c,x19_p,x19_c,x20_p,x20_c 100 | # x_c:u_c 用户信道分配 101 | # x_p:u_p 用户功率分配 102 | 103 | 104 | 105 | -------------------------------------------------------------------------------- /PrioritizedReplayDDQN/config.py: -------------------------------------------------------------------------------- 1 | # capacity = 8000 2 | # learning_rate = 1e-3 3 | # memory_count = 0 4 | # batch_size = 256 5 | # gamma = 0.995 6 | # update_count = 0 7 | # coding=utf-8 8 | import numpy as np 9 | 10 | #replay_memory所需的相关参数 11 | class AgentConfig(object): 12 | kesi = 0.1 # kesi是随机选动作 13 | heigth = 1 14 | length = 1 15 | width = 20 16 | # fc_out_dims = 1000 17 | 18 | # learning_rate = 0.0025 19 | # learning_rate = 3e-4 20 | LEARNING_RATE = 1e-3 21 | learning_rate_policy = 5e-3 22 | learning_rate_value = 1e-3 23 | learning_rate_q = 1e-3 24 | # learning_rate_minimum = 0.0025 25 | # learning_rate_decay = 0.96 26 | # learning_rate_decay_step = 5000 27 | # discount = 0.9 28 | max_step = 30000 # 训练次数 29 | learn_start = 1000 # 1000次之后网络开始更新 30 | train_frequency = 4 # 1000次之后每4个动作更新一下训练网络 31 | # train_step = 2000 32 | train_step = 2000 # 暂时每100次print一次 33 | test_step = 2000 # 2000次判断一下是否保存模型,然后对数据进行summary 34 | target_q_update_step = 1000 # 1000次之后,每1000次更新一下目标网络 35 | play_step = 500 # 每3000次看下模型调节能力 36 | play_times = 30 37 | 38 | batch_size = 32 39 | 40 | memory_size = 2000 41 | test_play = 500 42 | # test_produce = 43 | 44 | action_rows = 20 #20个次用户 45 | action_cols = 20 #20个信道 46 | # action_size = 44 47 | reward_size = 1 48 | 49 | 50 | 51 | 52 | #神经网络所需参数 53 | class NetworkConfig(object): 54 | mbs_number = 1 # macro基站数量:1 55 | sbs_number = 1 # small基站数量:1 56 | u_number = 20 # 用户数量:20 57 | c_num = 20 # 信道数量 58 | BW_sc = 18e4 # 每个信道的带宽 59 | sp_max = 1 # 基站发射功率最大值 60 | N0 = 5e-22 # AWGN噪声 61 | net_size = (100, 100) # 网络尺寸 62 | #E2E delay limit 63 | latency_limit = 10 64 | latency_limit2 = 240 65 | rate_limit = 2e5 66 | reward_alpha = 0 -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Latency-Equalization-E2E-NS-RL 2 | 3 | [ Latency Equalization Policy of End-to-End Network Slicing Based on Reinforcement Learning | IEEE Journals & Magazine | IEEE Xplore](https://ieeexplore.ieee.org/document/9903906) 4 | 5 | This repository contains Python scripts implementing the slicing resource allocation algorithms (RAN and CN) and latency equalization policies proposed in the paper "Latency Equalization Policy of End-to-End Network Slicing Based on Reinforcement Learning". 6 | 7 | Run "DSDP.py"/"DTDP.py"/"static.py" to excute the latency equalization policies to generate the results. 8 | 9 | The slicing algorithms in RAN and CN have been abstracted into functions (rlRAN, test) in "ran.py" and "Test.py". 10 | 11 | "config.py" contains some parameter information for the wireless network. 12 | 13 | The "user_plus" folder contains the updated rlRAN() , which only adjust the number of users. 14 | 15 | The "data" folder contains "virtualnetworkTP.txt", which records the information of the SFCs. You can add new SFCs by following the same format. 16 | 17 | 18 | -------------------------------------------------------------------------------- /code/ActiveSearch.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import torch 3 | 4 | from Embedding_and_Release import get_hops_and_link_consumptions 5 | 6 | Max_Jump = 6 7 | Min_Jump = 2 8 | INF = 9999999999 9 | seed = 100 10 | 11 | torch.manual_seed(seed) 12 | 13 | def active_search(hlp, ptr_net, s_nodes, s_links, v_nodes, v_links, 14 | iter_time=300, batch_size=10, 15 | lr_p=0.01, beta1=0.9, alpha=0.01, alpha_decay=0.9, current_node_utilization=0, 16 | use_node_utilization=False, device='cpu'): 17 | ''' 18 | searching for shortest node_mapping for a particular s_node_resource distribution 19 | s_nodes:(s_nodes_num),list 20 | v_nodes:(v_nodes_num),list 21 | s_links:(s_links_num),list,(node,node,bandwith) 22 | v_links:(v_links_num),list,(node,node,bandwith) 23 | 24 | return : result,0个或1个成功的映射方案(包括节点映射和链路映射) 25 | ''' 26 | 27 | ptr_op = torch.optim.Adam(ptr_net.parameters(), lr=lr_p, betas=(beta1, 0.999)) 28 | s_input = get_input(nodes=s_nodes, links=s_links) 29 | v_input = get_input(nodes=v_nodes, links=v_links) 30 | 31 | best_mapping_solution = { 32 | 'embedding_success': False, 33 | 'node_mapping_solution': [], 34 | 'link_mapping_solution': dict(), 35 | 'link_consumption': INF 36 | } 37 | baseline = -1 38 | 39 | # 搜索 40 | for i in range(iter_time): 41 | # shuffle input 42 | s_node_indexes, s_inputs = get_shuffled_indexes_and_inputs(input=s_input, batch_size=batch_size) 43 | 44 | # 使用ptrnet,对给定的输入,输出node mapping solutions 45 | node_mapping_solutions, shuffled_node_mapping_solutions, output_weights = ptr_net.get_node_mapping( 46 | s_node_indexes=s_node_indexes.to(device=device), 47 | s_inputs=s_inputs.to(device=device), 48 | v_input=v_input.to(device=device), 49 | ) 50 | 51 | # 检测node mapping solutions是否符合,若符合则进行链路映射 52 | embedding_successes, link_mapping_solutions, link_consumptions, hops = get_hops_and_link_consumptions( 53 | s_nodes=s_nodes, 54 | s_links=s_links, 55 | v_nodes=v_nodes, 56 | v_links=v_links, 57 | node_mapping=node_mapping_solutions 58 | ) 59 | 60 | # 记录下最优 61 | j = torch.argmin(link_consumptions) 62 | if link_consumptions[j] < best_mapping_solution['link_consumption']: 63 | best_mapping_solution['node_mapping_solution'] = node_mapping_solutions[j] 64 | best_mapping_solution['link_mapping_solution'] = link_mapping_solutions[j] 65 | best_mapping_solution['link_consumption'] = link_consumptions[j] 66 | best_mapping_solution['embedding_success'] = embedding_successes[j] 67 | 68 | if baseline == -1: 69 | baseline = link_consumptions.mean() #按列取平均值 70 | 71 | # 加入sla---->hlp,更改linkloss 72 | for i in range(node_mapping_solutions.shape[0]): 73 | if link_consumptions[i]/2500 > hlp and link_consumptions[i] < 1e7: 74 | link_consumptions[i] += 1e8 75 | 76 | # 计算loss 77 | adv = (baseline - link_consumptions).squeeze().to(device=device) 78 | cross_entropy_loss = ptr_net.get_CrossEntropyLoss(output_weights, shuffled_node_mapping_solutions) 79 | ptr_loss = torch.dot(cross_entropy_loss, adv) 80 | 81 | # ptr_loss = ptr_loss * (1.0 - current_node_utilization) 82 | # print('iter_time = ', i, '针对此虚拟网络请求,当前模型参数下预测的节点映射对应的baseline = ', baseline) 83 | 84 | # Adam优化参数 85 | ptr_net.zero_grad() 86 | ptr_loss.backward() 87 | ptr_op.step() 88 | 89 | # 更新滑动平均baseline 90 | baseline = baseline * alpha_decay + (1 - alpha_decay) * link_consumptions.mean() 91 | 92 | return { 93 | 'ptr_net': ptr_net, 94 | 'best_mapping_solution': best_mapping_solution 95 | } 96 | 97 | 98 | # 给定nodes和links,生成网络的输入数据input si =(s1,s2,s3,...) 99 | def get_input(nodes, links): 100 | node_num = len(nodes) 101 | node_resource = torch.Tensor(nodes).view(size=(node_num,)) 102 | node_neighbour_link_resource_sum = torch.zeros(size=(node_num,)) 103 | # node_neighbour_link_resource_min = torch.zeros(size=(node_num,)) 104 | node_neighbour_link_resource_max = torch.ones(size=(node_num,)) * INF 105 | for link in links: 106 | u_node = link[0] 107 | v_node = link[1] 108 | bandwidth = link[2] 109 | node_neighbour_link_resource_sum[u_node] += bandwidth 110 | node_neighbour_link_resource_sum[v_node] += bandwidth 111 | # node_neighbour_link_resource_min[u_node] = min(node_neighbour_link_resource_min[u_node], bandwidth) 112 | # node_neighbour_link_resource_min[v_node] = min(node_neighbour_link_resource_min[v_node], bandwidth) 113 | node_neighbour_link_resource_max[u_node] = max(node_neighbour_link_resource_max[u_node], bandwidth) 114 | node_neighbour_link_resource_max[v_node] = max(node_neighbour_link_resource_max[v_node], bandwidth) 115 | 116 | input = torch.stack( 117 | [ 118 | node_resource, 119 | node_neighbour_link_resource_sum, 120 | # node_neighbour_link_resource_min, 121 | node_neighbour_link_resource_max 122 | ], 123 | dim=1 124 | ) 125 | 126 | return input 127 | 128 | 129 | # 给定一个网络输入数据input,输出多个乱序的inputs 130 | def get_shuffled_indexes_and_inputs(input, batch_size=10): 131 | node_num = input.size()[0] 132 | node_indexes = [] 133 | 134 | for i in range(batch_size): 135 | shuffled_index = torch.randperm(node_num) #返回一行 从1到node_num的随机排列 136 | node_indexes.append(shuffled_index) 137 | 138 | node_indexes = torch.stack(node_indexes, dim=0).long() 139 | inputs = input[node_indexes] 140 | node_indexes = node_indexes.unsqueeze(dim=2) 141 | 142 | return node_indexes, inputs 143 | -------------------------------------------------------------------------------- /code/DSDP.py: -------------------------------------------------------------------------------- 1 | from ran import * 2 | #from users_plus.DDQN_50 import rlRan 3 | #from users_plus.DeepQNetwork_50 import * 4 | from Test import test 5 | import copy 6 | import os 7 | import numpy as np 8 | np.random.seed(0) 9 | 10 | from Plot import plot 11 | lowerbound = 0.1 12 | upperbound = 0.9 13 | 14 | cs1 = 200 #eMBB latency limit 15 | cs2 = 10 #URLLC l.. l.. 16 | num = 50 # total users 17 | sep = 25 # embb users' number 18 | alpha = 0 19 | rate_limit = 3e5 20 | train = 200 21 | 22 | if __name__ == '__main__': 23 | #各切片E2E时延约束集合 24 | t = [cs1]*sep + [cs2]*(num-sep) 25 | t = np.array(t) 26 | 27 | #随机或者固定比例 初始化. sla代表端到端时延约束分配给ran的比例 28 | #sla = [0.6]*10 + [0.4]*10 29 | # sla = [0.75]*sep + [0.25]*(20-sep) 30 | sla = [0.8]*sep + [0.2]*(num-sep) 31 | 32 | sla = np.array(sla) 33 | #sla = np.random.rand(20) 34 | #sla = np.random.randint(1,10,20)/10 35 | old = copy.deepcopy(sla) 36 | SLA = [] 37 | SLA.append(copy.deepcopy(sla)) 38 | print('***********第1次**********************第1次**********************第1次***********') 39 | target_net, act_net = Net(), Net() 40 | # act_net.load_state_dict(torch.load('../models/act')) 41 | # target_net.load_state_dict(torch.load('../models/target')) 42 | l1, r, ssl =rlRan(sla, target_net, act_net, train) #0.001的学习率,300个episode得到一个接近最终的结果 43 | #np.savetxt('r.csv', r, fmt="%.6f", delimiter=',') 44 | 45 | e_ran, e_cn = 0, 0 # embb ran/cn accessed 46 | u_ran, u_cn = 0, 0 # urllc ran/cn accessed 47 | 48 | sla2 = 1 - sla #端到端时延约束分配给cn的比例 49 | s_h = 2 50 | hlp = s_h * np.multiply(t, sla2) #时延转换成跳数 51 | sfc_hop = np.array(test(hlp)) # 52 | l2 = sfc_hop/ s_h 53 | l2[0:sep] += 20 #前sep个是embb用户,额外的时延 54 | 55 | d1 = np.multiply(t, sla) - l1 # RAN时延余量 56 | d2 = np.multiply(t, sla2) - l2 # cn时延余量 57 | credit = d1 + d2 #credit 若大于某值,表示部分切片存在时延余量,存在优化资源分配的空间 58 | 59 | xi = 50 #迭代划分比例的终止条件 试探得出 60 | xii = 5 61 | qoe = 0 62 | QoE = [] 63 | Reward =[] 64 | iter = 0 65 | #每个切片SLA划分不同 66 | # while any(credit > xi): 67 | #thresh = min(sep * 40, 1200) 68 | thresh = 900 69 | while sum(credit) > thresh: 70 | qoe = 0 71 | e_ran, e_cn = 0, 0 # embb ran/cn accessed 72 | u_ran, u_cn = 0, 0 # urllc ran/cn accessed 73 | reward = 0 74 | # 计算成功连接的人数 函数的输出可以选择吗? 75 | for i in range(num): 76 | if d1[i] > 0 and d2[i] > 0: 77 | qoe += 1 78 | if i < sep: 79 | if d1[i] > 0: 80 | e_ran += 1 81 | if d2[i] > 0: 82 | e_cn += 1 83 | else: 84 | if d1[i] > 0: 85 | u_ran += 1 86 | if d2[i] > 0: 87 | u_cn += 1 88 | QoE.append(copy.deepcopy(qoe)) 89 | reward = alpha * ssl + (1 - alpha) * qoe 90 | Reward.append(copy.deepcopy(reward)) 91 | print('第', (iter + 1), '次迭代,E2E接入人数为:', qoe, 'SSL:', ssl, 'reward=', reward, 92 | 'eMBB切片:RAN接入', e_ran, 'CN接入', e_cn, 'URLLC切片:RAN接入', u_ran, 'CN接入', u_cn) 93 | # np.savetxt('qoe__.csv', QoE, fmt="%.6f", delimiter=',') # 保存为2位小数的浮点数,用逗号分隔 94 | for i in range(num): 95 | if i < sep: 96 | if credit[i] > xi: #不满足约束的切片 进行片内均衡 97 | if d1[i] > 0 and d2[i] < 0: 98 | sla[i] = max(sla[i] - 0.1, lowerbound) 99 | elif d2[i] > 0 and d1[i] < 0: 100 | sla[i] = min(sla[i] + 0.1, upperbound) 101 | elif d1[i] > d2[i]: #满足约束的切片 进行片间均衡 102 | sla[i] = max(sla[i] - 0.05, lowerbound) 103 | elif d2[i] > d1[i]: 104 | sla[i] = min(sla[i] + 0.05, upperbound) 105 | elif credit[i] > xii: 106 | if d1[i] > 0 and d2[i] < 0: 107 | sla[i] = max(sla[i] - 0.1, lowerbound) 108 | elif d2[i] > 0 and d1[i] < 0: 109 | sla[i] = min(sla[i] + 0.1, upperbound) 110 | elif d1[i] > d2[i]: # 满足约束的切片 进行片间均衡 111 | sla[i] = max(sla[i] - 0.05, lowerbound) 112 | elif d2[i] > d1[i]: 113 | sla[i] = min(sla[i] + 0.05, upperbound) 114 | 115 | iter += 1 116 | if qoe == num or iter == 35 or (old == sla).all(): 117 | break 118 | # if (old == sla).all(): 119 | # break 120 | old = copy.deepcopy(sla) 121 | SLA.append(copy.deepcopy(sla)) 122 | print('***********第',(iter+1),'次***********','***********第',(iter+1),'次***********','***********第',(iter+1),'次***********') 123 | l1, r, ssl = rlRan(sla, target_net, act_net, train) 124 | np.savetxt('r.csv', r, fmt="%.6f", delimiter=',') 125 | 126 | sla2 = 1 - sla 127 | sfc_hop = np.array(test(hlp)) 128 | l2 = sfc_hop / s_h 129 | l2[0:sep] += 20 130 | d1 = np.multiply(t, sla) - l1 # RAN时延余量 131 | d2 = np.multiply(t, sla2) - l2 # cn时延余量 132 | credit = d1 + d2# 也= t - l1 -l2 133 | # np.savetxt('d1.csv', d1, fmt="%.6f", delimiter=',') # 保存为整数 134 | # np.savetxt('credit.csv', credit, fmt="%.6f", delimiter=',') # 保存为整数 135 | # np.savetxt('sla.csv', SLA, fmt="%.6f", delimiter=',') # 保存为整数 136 | 137 | SLA.append(copy.deepcopy(sla)) 138 | qoe = 0 139 | # for i in range(20): 140 | # if i < 10: 141 | # if r[0][i] >= rate_limit: # rate limit 142 | # qoe += 1 143 | # elif d1[i] > 0 and d2[i] > 0: 144 | # qoe += 1 145 | #统一成时延约束后 146 | for i in range(num): 147 | if d1[i] > 0 and d2[i] > 0: 148 | qoe += 1 149 | if i < sep: 150 | if d1[i] > 0: 151 | e_ran += 1 152 | if d2[i] > 0: 153 | e_cn += 1 154 | else: 155 | if d1[i] > 0: 156 | u_ran += 1 157 | if d2[i] > 0: 158 | u_cn += 1 159 | QoE.append(copy.deepcopy(qoe)) 160 | reward = alpha * ssl + (1 - alpha) * qoe 161 | Reward.append(copy.deepcopy(reward)) 162 | 163 | plot(QoE, len(QoE), 'One slice one sla QoE changes during equalization', 0, len(QoE)) 164 | 165 | #np.savetxt('ITERATIONS.csv', iter, fmt="%.6f", delimiter=',') # 保存为整数 166 | # np.savetxt('d1.csv', d1, fmt="%.6f", delimiter=',') # 保存为整数 167 | # np.savetxt('credit.csv', credit, fmt="%.6f", delimiter=',') # 保存为整数 168 | # np.savetxt('sla.csv', SLA, fmt="%.6f", delimiter=',') # 保存为整数 169 | # np.savetxt('qoe.csv', QoE, fmt="%.6f", delimiter=',') # 保存为2位小数的浮点数,用逗号分隔 170 | # print('max E2E QoE=', max(QoE), "\nbest sla:", SLA[np.argmax(QoE)],'iteration:', (np.argmax(QoE)+1)) 171 | print('max E2E QoE=', max(QoE), "\nbest sla:", SLA[np.argmax(QoE)], 'iteration:', (np.argmax(QoE) + 1), 'reward =', 172 | Reward[np.argmax(QoE)]) 173 | print('max E2E Reward=', max(Reward), "\nbest sla:", SLA[np.argmax(Reward)], 'iteration:', (np.argmax(Reward) + 1), 174 | 'QoE = ', QoE[np.argmax(Reward)]) 175 | -------------------------------------------------------------------------------- /code/DTDP.py: -------------------------------------------------------------------------------- 1 | from ran import * 2 | from DeepQNetwork import * 3 | #from users_plus.DDQN_50 import rlRan 4 | #from users_plus.DeepQNetwork_50 import * 5 | from Test import test 6 | import copy 7 | import os 8 | import numpy as np 9 | np.random.seed(0) 10 | #from Test import test 11 | from Plot import plot 12 | lowerbound = 0.1 13 | upperbound = 0.9 14 | 15 | cs1 = 200 #eMBB latency limit 16 | cs2 = 10 #URLLC l.. l.. 17 | num = 50 # total users 18 | sep = 25 # embb users' number 19 | alpha = 0 20 | rate_limit = 3e5 21 | train = 200 22 | 23 | if __name__ == '__main__': 24 | #各切片E2E时延约束集合 25 | t = [cs1]*sep + [cs2]*(num-sep) 26 | t = np.array(t) 27 | ratio1 = 0.5 28 | ratio2 = 0.5 29 | 30 | #随机或者固定比例 初始化. sla代表端到端时延约束分配给ran的比例 31 | sla = [ratio1]*sep + [ratio2]*(num-sep) 32 | sla = np.array(sla) 33 | #sla = np.random.rand(20) 34 | #sla = np.random.randint(1,10,20)/10 35 | old = copy.deepcopy(sla) 36 | SLA = [] 37 | SLA.append(copy.deepcopy(sla)) 38 | print('***********第1次**********************第1次**********************第1次***********') 39 | target_net, act_net = Net(), Net() 40 | # act_net.load_state_dict(torch.load('../models/act')) 41 | # target_net.load_state_dict(torch.load('../models/target')) 42 | l1, r,ssl =rlRan(sla, target_net, act_net, train) #0.001的学习率,300个episode得到一个接近最终的结果 43 | #np.savetxt('r__.csv', r, fmt="%.6f", delimiter=',') 44 | 45 | 46 | e_ran,e_cn = 0,0 #embb ran/cn accessed 47 | u_ran,u_cn = 0,0 #urllc ran/cn accessed 48 | 49 | 50 | sla2 = 1 - sla #端到端时延约束分配给cn的比例 51 | s_h = 2 52 | hlp = s_h * np.multiply(t, sla2) #时延转换成跳数 53 | sfc_hop = np.array(test(hlp)) # 54 | l2 = sfc_hop/ s_h 55 | l2[0:sep] += 20 56 | 57 | d1 = np.multiply(t, sla) - l1 # RAN时延余量 58 | d2 = np.multiply(t, sla2) - l2 # cn时延余量 59 | credit = d1 + d2 #credit 若大于某值,表示部分切片存在时延余量,存在优化资源分配的空间 60 | 61 | xi = 60 #迭代划分比例的终止条件 试探得出 62 | qoe = 0 63 | reward = 0 64 | QoE = [] 65 | Reward = [] 66 | iter = 0 67 | #两类不同的sla 68 | 69 | # while any(credit > xi): 70 | thresh = min(sep * 30, 600) 71 | while sum(credit) > thresh: 72 | qoe = 0 73 | e_ran, e_cn = 0, 0 # embb ran/cn accessed 74 | u_ran, u_cn = 0, 0 # urllc ran/cn accessed 75 | reward = 0 76 | # 计算成功连接的人数 函数的输出可以选择吗? 77 | for i in range(num): 78 | if d1[i] > 0 and d2[i] > 0: 79 | qoe += 1 80 | if i < sep: 81 | if d1[i]>0: 82 | e_ran += 1 83 | if d2[i]>0: 84 | e_cn += 1 85 | else: 86 | if d1[i]>0: 87 | u_ran += 1 88 | if d2[i]>0: 89 | u_cn += 1 90 | QoE.append(copy.deepcopy(qoe)) 91 | reward = alpha * ssl + (1 - alpha) * qoe 92 | Reward.append(copy.deepcopy(reward)) 93 | print('第', (iter + 1), '次迭代,E2E接入人数为:', qoe,'SSL:',ssl,'reward=',reward, 94 | 'eMBB切片:RAN接入',e_ran,'CN接入',e_cn,'URLLC切片:RAN接入',u_ran,'CN接入',u_cn) 95 | #np.savetxt('qoe__.csv', QoE, fmt="%.6f", delimiter=',') # 保存为2位小数的浮点数,用逗号分隔 96 | 97 | credit1 = credit[0:sep] 98 | credit2 = credit[sep:] 99 | if sum(credit1)/cs1 > sum(credit2)/cs2: 100 | ratio1 = max(ratio1 - 0.05, lowerbound) 101 | ratio2 = min(ratio2 + 0.05, upperbound) 102 | else: 103 | ratio1 = min(ratio1 + 0.05, upperbound) 104 | ratio2 = max(ratio2 - 0.05, lowerbound) 105 | iter += 1 106 | sla = [ratio1]*sep + [ratio2]*(num-sep) 107 | sla = np.array(sla) 108 | 109 | if qoe == num or iter == 35 or (old == sla).all(): 110 | break 111 | old = copy.deepcopy(sla) 112 | SLA.append(copy.deepcopy(sla)) 113 | # print('***********第', (iter + 1), '次***********') 114 | print('***********第', (iter + 1), '次***********', '***********第', (iter + 1), '次***********', '***********第', 115 | (iter + 1), '次***********') 116 | l1, r, ssl = rlRan(sla, target_net, act_net, train) 117 | #np.savetxt('r___.csv', r, fmt="%.6f", delimiter=',') 118 | 119 | sla2 = 1 - sla 120 | sfc_hop = np.array(test(hlp)) 121 | l2 = sfc_hop / s_h 122 | l2[0:sep] += 20 123 | d1 = np.multiply(t, sla) - l1 # RAN时延余量 124 | d2 = np.multiply(t, sla2) - l2 # cn时延余量 125 | credit = d1 + d2# 也= t - l1 -l2 126 | # np.savetxt('d1___.csv', d1, fmt="%.6f", delimiter=',') # 保存为整数 127 | # np.savetxt('credit__.csv', credit, fmt="%.6f", delimiter=',') # 保存为整数 128 | # np.savetxt('sla__.csv', SLA, fmt="%.6f", delimiter=',') # 保存为整数 129 | 130 | SLA.append(copy.deepcopy(sla)) 131 | qoe = 0 132 | # for i in range(20): 133 | # if i < 10: 134 | # if r[0][i] >= rate_limit: # rate limit 135 | # qoe += 1 136 | # elif d1[i] > 0 and d2[i] > 0: 137 | # qoe += 1 138 | #统一成时延约束后 139 | for i in range(num): 140 | if d1[i] > 0 and d2[i] > 0: 141 | qoe += 1 142 | if i < sep: 143 | if d1[i] > 0: 144 | e_ran += 1 145 | if d2[i] > 0: 146 | e_cn += 1 147 | else: 148 | if d1[i] > 0: 149 | u_ran += 1 150 | if d2[i] > 0: 151 | u_cn += 1 152 | QoE.append(copy.deepcopy(qoe)) 153 | reward = alpha * ssl + (1 - alpha) * qoe 154 | Reward.append(copy.deepcopy(reward)) 155 | #plot(QoE, len(QoE), 'QoE changes during equalization', 0, len(QoE)) 156 | 157 | #np.savetxt('ITERATIONS.csv', iter, fmt="%.6f", delimiter=',') # 保存为整数 158 | # np.savetxt('d1__.csv', d1, fmt="%.6f", delimiter=',') # 保存为整数 159 | # np.savetxt('credit__.csv', credit, fmt="%.6f", delimiter=',') # 保存为整数 160 | # np.savetxt('sla__.csv', SLA, fmt="%.6f", delimiter=',') # 保存为整数 161 | # np.savetxt('qoe__.csv', QoE, fmt="%.6f", delimiter=',') # 保存为2位小数的浮点数,用逗号分隔 162 | #print('max E2E QoE=', max(QoE), "\nbest sla:", SLA[np.argmax(QoE)]) 163 | print('max E2E QoE=', max(QoE), "\nbest sla:", SLA[np.argmax(QoE)], 'iteration:', (np.argmax(QoE) + 1), 'reward =', 164 | Reward[np.argmax(QoE)]) 165 | print('max E2E Reward=', max(Reward), "\nbest sla:", SLA[np.argmax(Reward)], 'iteration:', (np.argmax(Reward) + 1), 166 | 'QoE = ', QoE[np.argmax(Reward)]) 167 | -------------------------------------------------------------------------------- /code/DeepQNetwork.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn as nn 3 | import torch.nn.functional as F 4 | import torch.optim as optim 5 | 6 | 7 | class Net(nn.Module): 8 | def __init__(self): 9 | super(Net, self).__init__() 10 | self.fc1 = nn.Linear(20, 60) 11 | self.fc1_p = nn.Linear(60, 20) 12 | self.fc1_c = nn.Linear(60, 20) 13 | self.fc2_p = nn.Linear(60, 20) 14 | self.fc2_c = nn.Linear(60, 20) 15 | self.fc3_p = nn.Linear(60, 20) 16 | self.fc3_c = nn.Linear(60, 20) 17 | self.fc4_p = nn.Linear(60, 20) 18 | self.fc4_c = nn.Linear(60, 20) 19 | self.fc5_p = nn.Linear(60, 20) 20 | self.fc5_c = nn.Linear(60, 20) 21 | self.fc6_p = nn.Linear(60, 20) 22 | self.fc6_c = nn.Linear(60, 20) 23 | self.fc7_p = nn.Linear(60, 20) 24 | self.fc7_c = nn.Linear(60, 20) 25 | self.fc8_p = nn.Linear(60, 20) 26 | self.fc8_c = nn.Linear(60, 20) 27 | self.fc9_p = nn.Linear(60, 20) 28 | self.fc9_c = nn.Linear(60, 20) 29 | self.fc10_p = nn.Linear(60, 20) 30 | self.fc10_c = nn.Linear(60, 20) 31 | self.fc11_p = nn.Linear(60, 20) 32 | self.fc11_c = nn.Linear(60, 20) 33 | self.fc12_p = nn.Linear(60, 20) 34 | self.fc12_c = nn.Linear(60, 20) 35 | self.fc13_p = nn.Linear(60, 20) 36 | self.fc13_c = nn.Linear(60, 20) 37 | self.fc14_p = nn.Linear(60, 20) 38 | self.fc14_c = nn.Linear(60, 20) 39 | self.fc15_p = nn.Linear(60, 20) 40 | self.fc15_c = nn.Linear(60, 20) 41 | self.fc16_p = nn.Linear(60, 20) 42 | self.fc16_c = nn.Linear(60, 20) 43 | self.fc17_p = nn.Linear(60, 20) 44 | self.fc17_c = nn.Linear(60, 20) 45 | self.fc18_p = nn.Linear(60, 20) 46 | self.fc18_c = nn.Linear(60, 20) 47 | self.fc19_p = nn.Linear(60, 20) 48 | self.fc19_c = nn.Linear(60, 20) 49 | self.fc20_p = nn.Linear(60, 20) 50 | self.fc20_c = nn.Linear(60, 20) 51 | self.dropout = nn.Dropout(p=0.5) 52 | 53 | def forward(self, x): 54 | x = x.view(-1, 1, 20) # 1*1*3 55 | x = F.relu(self.fc1(x)) # 1*1*180 56 | 57 | x1_p = self.dropout(F.relu(self.fc1_p(x))).view(-1,1,20) # 20 58 | x1_c = self.dropout(F.relu(self.fc1_c(x))).view(-1,1,20) # 6 59 | x2_p = self.dropout(F.relu(self.fc2_p(x))).view(-1,1,20) # 20 60 | x2_c = self.dropout(F.relu(self.fc2_c(x))).view(-1,1,20) # 6 61 | x3_p = self.dropout(F.relu(self.fc3_p(x))).view(-1,1,20) # 20 62 | x3_c = self.dropout(F.relu(self.fc3_c(x))).view(-1,1,20) # 6 63 | x4_p = self.dropout(F.relu(self.fc4_p(x))).view(-1,1,20) # 20 64 | x4_c = self.dropout(F.relu(self.fc4_c(x))).view(-1,1,20) # 6 65 | x5_p = self.dropout(F.relu(self.fc5_p(x))).view(-1,1,20) # 20 66 | x5_c = self.dropout(F.relu(self.fc5_c(x))).view(-1,1,20) # 6 67 | x6_p = self.dropout(F.relu(self.fc6_p(x))).view(-1,1,20) # 20 68 | x6_c = self.dropout(F.relu(self.fc6_c(x))).view(-1,1,20) # 6 69 | x7_p = self.dropout(F.relu(self.fc7_p(x))).view(-1,1,20) # 20 70 | x7_c = self.dropout(F.relu(self.fc7_c(x))).view(-1,1,20) # 6 71 | x8_p = self.dropout(F.relu(self.fc8_p(x))).view(-1,1,20) # 20 72 | x8_c = self.dropout(F.relu(self.fc8_c(x))).view(-1,1,20) # 6 73 | x9_p = self.dropout(F.relu(self.fc9_p(x))).view(-1,1,20) # 20 74 | x9_c = self.dropout(F.relu(self.fc9_c(x))).view(-1,1,20) # 6 75 | x10_p = self.dropout(F.relu(self.fc10_p(x))).view(-1,1,20) # 20 76 | x10_c = self.dropout(F.relu(self.fc10_c(x))).view(-1,1,20) # 6 77 | x11_p = self.dropout(F.relu(self.fc11_p(x))).view(-1,1,20) # 20 78 | x11_c = self.dropout(F.relu(self.fc11_c(x))).view(-1,1,20) # 6 79 | x12_p = self.dropout(F.relu(self.fc12_p(x))).view(-1,1,20) # 20 80 | x12_c = self.dropout(F.relu(self.fc12_c(x))).view(-1,1,20) # 6 81 | x13_p = self.dropout(F.relu(self.fc13_p(x))).view(-1,1,20) # 20 82 | x13_c = self.dropout(F.relu(self.fc13_c(x))).view(-1,1,20) # 6 83 | x14_p = self.dropout(F.relu(self.fc14_p(x))).view(-1,1,20) # 20 84 | x14_c = self.dropout(F.relu(self.fc14_c(x))).view(-1,1,20) # 6 85 | x15_p = self.dropout(F.relu(self.fc15_p(x))).view(-1,1,20) # 20 86 | x15_c = self.dropout(F.relu(self.fc15_c(x))).view(-1,1,20) # 6 87 | x16_p = self.dropout(F.relu(self.fc16_p(x))).view(-1,1,20) # 20 88 | x16_c = self.dropout(F.relu(self.fc16_c(x))).view(-1,1,20) # 6 89 | x17_p = self.dropout(F.relu(self.fc17_p(x))).view(-1,1,20) # 20 90 | x17_c = self.dropout(F.relu(self.fc17_c(x))).view(-1,1,20) # 6 91 | x18_p = self.dropout(F.relu(self.fc18_p(x))).view(-1,1,20) # 20 92 | x18_c = self.dropout(F.relu(self.fc18_c(x))).view(-1,1,20) # 6 93 | x19_p = self.dropout(F.relu(self.fc19_p(x))).view(-1,1,20) # 20 94 | x19_c = self.dropout(F.relu(self.fc19_c(x))).view(-1,1,20) # 6 95 | x20_p = self.dropout(F.relu(self.fc20_p(x))).view(-1,1,20) # 20 96 | x20_c = self.dropout(F.relu(self.fc20_c(x))).view(-1,1,20) # 6 97 | 98 | return x1_p,x1_c,x2_p,x2_c,x3_p,x3_c,x4_p,x4_c,x5_p,x5_c,x6_p,x6_c,x7_p,x7_c,x8_p,x8_c,x9_p,x9_c,x10_p,x10_c,\ 99 | x11_p,x11_c,x12_p,x12_c,x13_p,x13_c,x14_p,x14_c,x15_p,x15_c,x16_p,x16_c,x17_p,x17_c,x18_p,x18_c,x19_p,x19_c,x20_p,x20_c 100 | # x_c:u_c 用户信道分配 101 | # x_p:u_p 用户功率分配 102 | 103 | 104 | 105 | -------------------------------------------------------------------------------- /code/Embedding_and_Release.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import torch 3 | seed = 100 4 | np.random.seed(seed) 5 | torch.manual_seed(seed) 6 | #用到了节点数量 7 | def short_path(slinks, start, end, v_bandwidth): # 最短路径 8 | node_num = 148 9 | inf = 1000 10 | node_map = np.zeros(shape=(node_num, node_num), dtype=float) 11 | for link in slinks: 12 | node_map[link[0]][link[1]] = node_map[link[1]][link[0]] = link[2] 13 | 14 | hop = [inf for i in range(node_num)] 15 | visited = [False for i in range(node_num)] 16 | pre = [-1 for i in range(node_num)] 17 | hop[start] = 0 18 | 19 | 20 | for i in range(node_num): 21 | u = -1 22 | for j in range(node_num): 23 | if not visited[j]: 24 | if u == -1 or hop[j] < hop[u]: 25 | u = j 26 | visited[u] = True 27 | if u == end: 28 | break 29 | 30 | for j in range(node_num): 31 | if hop[j] > hop[u] + 1 and node_map[u][j] >= v_bandwidth: 32 | hop[j] = hop[u] + 1 33 | pre[j] = u 34 | 35 | path = [] 36 | if pre[end] !=-1: 37 | v = end 38 | while v!=-1: 39 | path.append(v) 40 | v = pre[v] 41 | path.reverse() 42 | 43 | return path 44 | 45 | def link_embedding(s_links, slink_path, v_bandwidth): 46 | for i in range(1, len(slink_path)): 47 | u = slink_path[i - 1] 48 | v = slink_path[i] 49 | for j in range(len(s_links)): 50 | u2 = s_links[j][0] 51 | v2 = s_links[j][1] 52 | if (u == u2 and v == v2) or (u == v2 and v == u2): 53 | s_links[j][2] -= v_bandwidth 54 | 55 | 56 | def link_release(s_links, slink_path, v_bandwidth): 57 | for i in range(1, len(slink_path)): 58 | u = slink_path[i - 1] 59 | v = slink_path[i] 60 | for j in range(len(s_links)): 61 | u2 = s_links[j][0] 62 | v2 = s_links[j][1] 63 | if (u == u2 and v == v2) or (u == v2 and v == u2): 64 | s_links[j][2] += v_bandwidth 65 | 66 | 67 | def get_hops_and_link_consumptions(s_nodes, s_links, v_nodes, v_links, node_mapping): 68 | ''' 69 | :param s_nodes: 物理节点资源 list (s_node_num,) 70 | :param s_links: 物理链路资源 list (s_link_num,), struct s_link = (u, v, bandwidth) 71 | :param v_nodes: 虚拟节点资源 list (v_node_num,) 72 | :param v_links: 虚拟链路资源 list (v_link_num,), struct v_link = (u, v, bandwidth) 73 | :param node_mapping: 节点映射方案 74 | :return: embedding success 是否映射成功; link_mapping_solutions 链路映射方案, link_consumptions 链路映射消耗, hops 链路映射消耗跳数 75 | ''' 76 | 77 | batch_size = node_mapping.shape[0] 78 | v_node_num = node_mapping.shape[1] 79 | hops = torch.zeros(size=(batch_size, 1)) 80 | link_consumptions = torch.zeros(size=(batch_size, 1)) 81 | link_mapping_solutions = [dict() for i in range(batch_size)] 82 | embedding_success = [False for i in range(batch_size)] 83 | 84 | for i in range(batch_size): 85 | node_mapping_success = True 86 | link_mapping_success = True 87 | 88 | for j in range(v_node_num): 89 | if s_nodes[node_mapping[i][j]] < v_nodes[j]: 90 | node_mapping_success = False 91 | link_mapping_success = False 92 | # print('节点映射失败') 93 | break 94 | 95 | v_link_consumption_sum = 0 96 | for v_link in v_links: 97 | v_link_consumption_sum += v_link[2] 98 | 99 | if node_mapping_success: 100 | embedded_paths = [] 101 | for v_link in v_links: 102 | v_from_node = v_link[0] 103 | v_to_node = v_link[1] 104 | v_bandwidth = v_link[2] 105 | 106 | s_from_node = node_mapping[i][v_from_node] 107 | s_to_node = node_mapping[i][v_to_node] 108 | 109 | s_path = short_path(s_links, s_from_node, s_to_node, v_bandwidth) 110 | 111 | if s_path == []: 112 | link_mapping_success = False 113 | # print('链路映射失败') 114 | break 115 | else: 116 | link_embedding(s_links, s_path, v_bandwidth) 117 | embedded_paths.append([s_path, v_bandwidth]) 118 | hops[i][0] += len(s_path) - 1 119 | #一条虚拟链路映射带来的带宽支出 120 | link_consumptions[i][0] += (len(s_path) - 1) * v_bandwidth 121 | link_mapping_solutions[i].update({v_link: s_path}) 122 | 123 | for path, v_bandwidth in embedded_paths: 124 | link_release(s_links, path, v_bandwidth) 125 | 126 | if not link_mapping_success: 127 | hops[i] = 7 * len(v_links) 128 | link_consumptions[i] = v_link_consumption_sum * 7 * 2 129 | link_mapping_solutions[i] = dict() 130 | else: 131 | hops[i] = 7 * len(v_links) 132 | link_consumptions[i] = v_link_consumption_sum * 7 * 2 133 | link_mapping_solutions[i] = dict() 134 | 135 | if node_mapping_success and link_mapping_success: 136 | embedding_success[i] = True 137 | 138 | return embedding_success, link_mapping_solutions, link_consumptions, hops 139 | 140 | 141 | # 给定一个映射方案mapping solution(包括节点映射方案node mapping solution和链路映射方案link mapping solution), 142 | # 更新当前的物理网络资源s_nodes和s_links 143 | def update_SN(s_nodes, s_links, snode_update_matrix, slink_update_matrix): # 更新物理链路节点和带宽资源 144 | ''' 145 | s_nodes : 当前物理网络节点资源 146 | s_links : 当前物理网络链路资源 147 | snode_update_matrix: 物理节点资源更新矩阵,映射网络时是负的节点资源cost矩阵,释放网络时是正的节点资源cost矩阵 148 | slink_update_matrix: 物理链路资源更新矩阵,映射网络时是负的链路资源cost矩阵,释放网络时是正的链路资源cost矩阵 149 | return: s_nodes,更新后的s_nodes; s_links,更新后的s_links 150 | ''' 151 | for i in range(len(s_nodes)): 152 | s_nodes[i] += snode_update_matrix[i][0] 153 | 154 | for i in range(len(s_links)): 155 | u = s_links[i][0] 156 | v = s_links[i][1] 157 | s_links[i][2] += slink_update_matrix[u][v] 158 | 159 | return s_nodes, s_links 160 | 161 | 162 | # 给定一个映射方案mapping solution(包括节点映射方案node mapping solution和链路映射方案link mapping solution), 163 | # 计算他总共的消耗,存在一个cost矩阵中,包括节点资源的cost矩阵,链路资源的cost矩阵。这是一个n×n的邻接矩阵,这样映射这个网络的时候, 164 | # 就减去cost矩阵,释放一个网络的时候就加上他的cost矩阵。 165 | def get_cost_matrix(snode_num, v_nodes, mapping_solution): 166 | cost_matrix = { 167 | 'snode_cost_matrix': np.zeros(shape=(snode_num, 1), dtype=float), 168 | 'slink_cost_matrix': np.zeros(shape=(snode_num, snode_num), dtype=float) 169 | } 170 | 171 | node_mapping_solution = mapping_solution['node_mapping_solution'] 172 | link_mapping_solution = mapping_solution['link_mapping_solution'] 173 | 174 | # get snode_cost_matrix 175 | for i in range(len(node_mapping_solution)): 176 | cost_matrix['snode_cost_matrix'][node_mapping_solution[i]][0] += v_nodes[i] 177 | 178 | # get slink_cost_matrix 179 | for v_link, s_path in link_mapping_solution.items(): 180 | vlink_bandwidth = v_link[2] 181 | for i in range(1, len(s_path)): 182 | u = s_path[i - 1] 183 | v = s_path[i] 184 | cost_matrix['slink_cost_matrix'][u][v] += vlink_bandwidth 185 | cost_matrix['slink_cost_matrix'][v][u] += vlink_bandwidth 186 | 187 | return cost_matrix 188 | 189 | 190 | # 给定一个虚拟网络的映射方案(包括节点映射和链路映射方案),以比较美观的方式输出这个方案。这是一个输出函数而已 191 | def print_mapping_solution(mapping_solution): 192 | node_mapping_solution = mapping_solution['node_mapping_solution'] 193 | link_mapping_solution = mapping_solution['link_mapping_solution'] 194 | 195 | print('\t\t节点映射方案为') 196 | print('\t\t {}'.format(node_mapping_solution)) 197 | 198 | print('\t\t链路映射方案为') 199 | if link_mapping_solution == dict(): 200 | print('\t\t []') 201 | else: 202 | for v_link, s_path in link_mapping_solution.items(): 203 | embedded_s_links = [] 204 | for i in range(1, len(s_path)): 205 | embedded_s_links.append((s_path[i - 1], s_path[i])) 206 | print('\t\t {} -> {}'.format(v_link, embedded_s_links)) 207 | -------------------------------------------------------------------------------- /code/HetNet_data/memory_data/memory: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moooontoo/Latency-Equalization-E2E-NS-RL/2ec08851631b8a9da8d662ca7c8df9844b6bbeb7/code/HetNet_data/memory_data/memory -------------------------------------------------------------------------------- /code/PerformanceEvaluation.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 4 | def get_total_link_resources(links): 5 | link_resources = 0 6 | for link in links: 7 | link_resources += link[2] 8 | 9 | return link_resources 10 | 11 | 12 | def get_total_node_resources(nodes): 13 | node_resources = 0 14 | for node in nodes: 15 | node_resources += node 16 | 17 | return node_resources 18 | 19 | 20 | def get_total_resources(nodes, links): 21 | node_resources = get_total_node_resources(nodes) 22 | link_resources = get_total_link_resources(links) 23 | resources = node_resources + link_resources 24 | 25 | return resources 26 | 27 | 28 | def get_node_utilization(current_s_nodes, original_s_nodes): 29 | current_node_resources = get_total_node_resources(current_s_nodes) 30 | total_node_resources = get_total_node_resources(original_s_nodes) 31 | used_node_resources = total_node_resources - current_node_resources 32 | 33 | node_utilization = 0 34 | try: 35 | node_utilization = used_node_resources / total_node_resources 36 | except ZeroDivisionError: 37 | print('除0错误') 38 | 39 | return node_utilization 40 | 41 | 42 | def get_link_utilization(current_s_links, original_s_links): 43 | current_link_resources = get_total_link_resources(current_s_links) 44 | total_link_resources = get_total_link_resources(original_s_links) 45 | used_link_resources = total_link_resources - current_link_resources 46 | 47 | link_utilization = 0 48 | try: 49 | link_utilization = used_link_resources / total_link_resources 50 | except ZeroDivisionError: 51 | print('除0错误') 52 | 53 | return link_utilization 54 | 55 | 56 | def get_utilization(current_s_nodes, original_s_nodes, current_s_links, original_s_links): 57 | current_resources = get_total_resources(current_s_nodes, current_s_links) 58 | total_resources = get_total_resources(original_s_nodes, original_s_links) 59 | used_resources = total_resources - current_resources 60 | 61 | utilization = 0 62 | try: 63 | utilization = used_resources / total_resources 64 | except ZeroDivisionError: 65 | print('除0错误') 66 | 67 | return utilization 68 | 69 | 70 | def get_revenue_cost_ratio(revenue, cost): 71 | try: 72 | revenue_cost_ratio = revenue / cost 73 | except ZeroDivisionError: 74 | revenue_cost_ratio = 0 75 | return revenue_cost_ratio 76 | -------------------------------------------------------------------------------- /code/PtrNet.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import numpy as np 3 | import torch 4 | import torch.nn as nn 5 | 6 | seed = 100 7 | np.random.seed(seed) 8 | torch.manual_seed(seed) 9 | 10 | class Ptr_Net(nn.Module): 11 | def __init__(self, hidden_size=128, embedding_size=128, num_directions=2, 12 | input_size=1, batch_size=128, initialization_stddev=0.1, 13 | dropout_p=0, penalty=1e6, s_input_information = {}, use_neighbour_link_penalty =False,device='cpu'): 14 | super(Ptr_Net, self).__init__() 15 | if s_input_information['snode resource'] or s_input_information['snode index']: 16 | input_size = 1 17 | else: 18 | input_size = 3 19 | self.use_neighbour_link_penalty = use_neighbour_link_penalty 20 | # Define Embedded 21 | self.Embed = torch.nn.Linear(input_size, embedding_size, bias=False) #对输入的每个物理节点进行线性变换,并将其嵌入信息传递给encoder 22 | # Define Encoder 23 | self.Encoder = torch.nn.LSTM(input_size=embedding_size, hidden_size=hidden_size, batch_first=True, 24 | bidirectional=True) 25 | # Define Attention 26 | self.W_ref = torch.nn.Linear(num_directions * hidden_size, num_directions * hidden_size, bias=False) 27 | self.W_q = torch.nn.Linear(num_directions * hidden_size, num_directions * hidden_size, bias=False) 28 | self.v = torch.nn.Linear(num_directions * hidden_size, 1, bias=False) 29 | # Define Decoder 30 | self.Decoder = torch.nn.LSTM(input_size=embedding_size * 2, hidden_size=hidden_size, batch_first=True, 31 | bidirectional=True) 32 | self.DropOut1 = nn.Dropout(p=dropout_p) 33 | self.DropOut2 = nn.Dropout(p=dropout_p) 34 | self.W_ref2 = torch.nn.Linear(num_directions * hidden_size, num_directions * hidden_size, bias=False) 35 | self.W_q2 = torch.nn.Linear(num_directions * hidden_size, num_directions * hidden_size, bias=False) 36 | self.v2 = torch.nn.Linear(num_directions * hidden_size, 1, bias=False) 37 | self.Softmax_Cross_Entrophy = torch.nn.CrossEntropyLoss(reduction='none') #reduction:用来指定损失结果返回的是mean、sum还是none 38 | self.penalty = penalty 39 | self.s_input_information = s_input_information 40 | self.device = device 41 | 42 | def get_CrossEntropyLoss(self, output_weights, test_node_mappings): 43 | test_node_mappings = test_node_mappings.astype(float) # numpy强制类型转换,04182150 44 | test_node_mappings = torch.LongTensor(test_node_mappings).to(self.device) #torch.Tensor默认是torch.FloatTensor是32位浮点类型数据,torch.LongTensor是64位整型 45 | v_node_num = test_node_mappings.size()[1] 46 | path_loss = 0 47 | for i in range(v_node_num): 48 | path_loss += self.Softmax_Cross_Entrophy( 49 | output_weights[i], 50 | test_node_mappings[:, i].T.squeeze() 51 | ) 52 | return path_loss 53 | 54 | def get_node_mapping(self, s_node_indexes, s_inputs, v_input): 55 | batch_size = s_node_indexes.size()[0] 56 | s_node_num = s_node_indexes.size()[1] 57 | v_node_num = v_input.size()[0] # v_node_num 58 | cannot_penalty = self.penalty 59 | 60 | # Embedding 61 | # s_node_indexes:(batch,s_node_num,1) 62 | if self.s_input_information['snode resource']: # 输入信息仅为s_node_resource 63 | S_node_Embedding = self.Embed(s_inputs[:, :, 0].unsqueeze(dim=2)) 64 | 65 | if self.s_input_information['snode index']: # 输入信息仅为s_node_index 66 | S_node_Embedding = self.Embed(s_node_indexes.float()) 67 | 68 | # 输入信息为s_node_resource和s_node_neighbour_link_resource 69 | if self.s_input_information['snode resource and neighbour link resource']: 70 | S_node_Embedding = self.Embed(s_inputs) 71 | 72 | ''' 73 | Encoder 74 | S_node_Embedding:(batch,s_node_num,embedding=128) 75 | ''' 76 | Enc, (hn, cn) = self.Encoder(S_node_Embedding, None) 77 | 78 | ''' 79 | Attention and Decoder 80 | Enc:(batch, s_node_num, num_directions * hidden_size) 81 | hn: (batch,num_layers * num_directions, hidden_size) 82 | cn: (batch,num_layers * num_directions, hidden_size) 83 | ''' 84 | decoder_input = torch.zeros(Enc.size()[0], 1, Enc.size()[2]).to(self.device) 85 | decoder_state = (hn, cn) 86 | already_played_actions = torch.zeros(Enc.size()[0], s_node_num).to(self.device) 87 | decoder_outputs = [] 88 | output_weights = [] 89 | 90 | for i in range(v_node_num): 91 | 92 | # Decoder是一个lstm单元, 输入是encoder的输出e0 93 | decoder_output, decoder_state = self.Decoder(decoder_input, decoder_state) 94 | decoder_output = self.DropOut2(decoder_output) 95 | 96 | Enc = self.DropOut1(Enc) 97 | 98 | # 判断结点是否满足,对s_node进行变形,对应s_inputs排序,然后再torch.lt 99 | nodes_without_enough_cpu = torch.lt(s_inputs[:, :, 0], v_input[i][0]) # < 100 | cannot_satisfy_nodes = nodes_without_enough_cpu 101 | if self.use_neighbour_link_penalty: 102 | nodes_without_enough_bandwidth = torch.lt(s_inputs[:, :, 1], v_input[i][1]) #1 放的是临边的和 103 | nodes_without_enough_bandwidth += torch.lt(s_inputs[:, :, 2], v_input[i][2]) #2 放的是最大的 104 | cannot_satisfy_nodes += nodes_without_enough_bandwidth 105 | 106 | cannot_node = cannot_satisfy_nodes + already_played_actions 107 | 108 | 109 | # 输入 e0 和 decoder的输出 110 | # output_weight 是decoder的输出,即一个虚拟节点对应的物理节点选择概率向量 111 | output_weight = torch.squeeze( 112 | self.v(torch.tanh( 113 | self.W_ref(Enc) + self.W_q(decoder_output.repeat(1, s_node_num, 1)) 114 | )) 115 | ) - cannot_penalty * cannot_node 116 | output_weights.append(output_weight) 117 | 118 | # 输入 dropout后的e0 和 decoder的输入, 计算出attetion权重,并输出权重 119 | attention_weight = torch.nn.functional.softmax( 120 | torch.squeeze( 121 | self.v2(torch.tanh( 122 | self.W_ref2(Enc) + self.W_q2(decoder_input) 123 | )) 124 | ), dim=1 #去掉1维的张量 125 | ) 126 | 127 | # 将计算出的attetion权重矩阵 应用于e0, 得到新的e, 新的e作为下一个decoder的输入 128 | decoder_input = torch.unsqueeze(torch.einsum('ij,ijk->ik', attention_weight, Enc), dim=1) #batch矩阵相乘 129 | 130 | decoder_outputs.append(torch.argmax(output_weight, dim=1)) #按照行取最大值索引返回 131 | selected_actions = torch.zeros(Enc.size()[0], s_node_num).to(self.device) 132 | selected_actions = selected_actions.scatter_(1, torch.unsqueeze(decoder_outputs[-1], dim=1), 1) #在指定位置写上1 133 | already_played_actions += selected_actions 134 | 135 | shuffled_node_mapping = np.array([list(item.cpu()) for item in decoder_outputs]).T 136 | 137 | original_node_mapping = np.zeros(shape=(batch_size, v_node_num), dtype=int) 138 | for i in range(batch_size): 139 | for j in range(v_node_num): 140 | original_node_mapping[i][j] = s_node_indexes[i][shuffled_node_mapping[i][j]] 141 | 142 | return original_node_mapping, shuffled_node_mapping, output_weights # 返回值都是numpy array ##signal 143 | 144 | def weights_init(m): 145 | if isinstance(m, torch.nn.LSTM): #判断m 是不是 torch.nn.LSTM类型 146 | torch.nn.init.uniform_(m.weight_ih_l0.data, a=-0.08, b=0.08) #torch.nn.init.uniform(tensor, a=0, b=1) 从均匀分布U(a, b)中生成值,填充输入的张量或变量 147 | torch.nn.init.uniform_(m.weight_hh_l0.data, a=-0.08, b=0.08) 148 | torch.nn.init.uniform_(m.bias_ih_l0.data, a=-0.08, b=0.08) 149 | torch.nn.init.uniform_(m.bias_hh_l0.data, a=-0.08, b=0.08) 150 | torch.nn.init.uniform_(m.weight_ih_l0_reverse.data, a=-0.08, b=0.08) 151 | torch.nn.init.uniform_(m.weight_hh_l0_reverse.data, a=-0.08, b=0.08) 152 | torch.nn.init.uniform_(m.bias_ih_l0_reverse.data, a=-0.08, b=0.08) 153 | torch.nn.init.uniform_(m.bias_hh_l0_reverse.data, a=-0.08, b=0.08) 154 | else: 155 | try: 156 | torch.nn.init.uniform_(m.weight.data, a=-0.08, b=0.08) 157 | torch.nn.init.uniform_(m.bias.data, a=-0.08, b=0.08) 158 | except Exception: 159 | 1 + 1 160 | -------------------------------------------------------------------------------- /code/Read_helpers.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import numpy as np 4 | import re 5 | seed = 100 6 | np.random.seed(seed) 7 | 8 | def get_SN_Node(file): #从文件中读取物理网络的结点,返回以时序为key,以矩阵为value的字典 9 | SN_dict={} 10 | fo=open(file,"r") 11 | pattern=re.compile(r'This is PS network for virtual network----') 12 | line=fo.readline() 13 | while line: 14 | if re.match(pattern,line):#匹配pattern语句 15 | #line=fo.readline() #读取下一行 16 | num=[int(r) for r in re.findall(r"\d+\.?\d*",line)] #提取数字存为list pattern后面的序号 17 | key=num[0] 18 | value=np.zeros([148,148]) #定义一个空矩阵 19 | for i in range(148): #读取结点存入矩阵 148个点的节点资源 20 | line=fo.readline() 21 | num=[int(r) for r in re.findall(r"\d+\.?\d*",line)] 22 | value[num[0]][num[0]]=num[1] #对角矩阵 23 | SN_dict.update({key:value})#存入字典 key 是pttern后面的序号 24 | line=fo.readline() 25 | fo.close() 26 | return SN_dict 27 | 28 | def get_VN_Node(file):#从文件中读取虚拟网络的结点,返回以时序为key,以矩阵为value的字典 29 | VN_dict={} 30 | vector=[] 31 | value=[] 32 | fo=open(file,"r") 33 | pattern=re.compile(r'This is virtual network')#pattern=re.compile(r'This is virtual network----')#开始标志 34 | end_pattern=re.compile(r'node-link-information:')#结束标志 35 | line=fo.readline() 36 | while line: 37 | if re.match(pattern,line):#匹配pattern语句 38 | num=[int(r) for r in re.findall(r"\d+\.?\d*",line)] #提取数字存为list 39 | key=num[0] 40 | vector=[] 41 | value=[] 42 | # value=np.zeros([10,10]) #定义一个空矩阵 43 | line=fo.readline() 44 | while not re.match(end_pattern,line) and line.strip()!='': #读取结点存入矩阵 line.strip() 去除line中头尾包含的空格或换行符 45 | num=[int(r) for r in re.findall(r"\d+\.?\d*",line)] 46 | vector.append(num[0]) #虚拟节点编号 47 | value.append(num[1]) #虚拟节点所需资源数 48 | # value[num[0]%10][num[0]%10]=num[1] #虚拟网络最大节点数为10 49 | line=fo.readline() 50 | size=len(vector) #VN的虚拟节点数 51 | values=np.zeros([size,size]) 52 | min_v=min(vector) 53 | for i in range(len(vector)): #把虚拟节点所需资源 排布成一个对角阵 54 | vector[i]=vector[i]-min_v 55 | values[vector[i]][vector[i]]=value[i] 56 | VN_dict.update({key:values}) 57 | line=fo.readline() 58 | fo.close() 59 | return VN_dict 60 | 61 | def get_SN_Link(file,SN_dict):#读取物理网络的边 62 | fo=open(file,"r") 63 | SN_key_pattern=re.compile(r'This is PS network for virtual network----')#判断key 64 | link_pattern=re.compile(r'node-link-information:')#判断link information 65 | SN_end_pattern=re.compile(r'This is virtual network')#判断结束 结尾处要么是空行 要么是vn 66 | line=fo.readline() 67 | while line: 68 | if re.match(SN_key_pattern,line):#找到SN 69 | #line=fo.readline() #读取下一行 70 | num=[int(r) for r in re.findall(r"\d+\.?\d*",line)] #将一行数字处理成list 71 | key=num[0] #SN的序号 72 | value=SN_dict.get(key) 73 | line=fo.readline() #读取下一行 74 | while not re.match(link_pattern,line): 75 | line=fo.readline() 76 | line=fo.readline() #读取下一行 77 | while (not re.match(SN_end_pattern,line)) and line.strip()!='': 78 | num=[float(r) for r in re.findall(r"\d+\.?\d*",line)] 79 | value[int(num[0])][int(num[1])]=num[2] 80 | value[int(num[1])][int(num[0])]=num[2] 81 | line=fo.readline() #读取下一行 82 | SN_dict.update({key:value}) 83 | line=fo.readline() 84 | fo.close() 85 | return SN_dict 86 | 87 | def get_VN_Link(file,VN_dict):#读取虚拟网路的边 88 | fo=open(file,"r") 89 | VN_key_pattern=re.compile(r'This is virtual network')#判断key 90 | link_pattern=re.compile(r'node-link-information:')#判断link information 91 | VN_end_pattern=re.compile(r'The life time is:')#判断结束 92 | line=fo.readline() 93 | while line: 94 | if re.match(VN_key_pattern,line):#找到VN 95 | num=[int(r) for r in re.findall(r"\d+\.?\d*",line)] #将一行数字处理成list 96 | key=num[0] #VN的序号 97 | vector1=[] 98 | vector2=[] 99 | value=[] 100 | 101 | values=VN_dict.get(key) 102 | line=fo.readline() #读取下一行 103 | while not re.match(link_pattern,line): 104 | line=fo.readline() 105 | line=fo.readline() #读取下一行 106 | while not re.match(VN_end_pattern,line) and line.strip()!='': 107 | #print(line) 108 | num=[float(r) for r in re.findall(r"\d+\.?\d*",line)] 109 | vector1.append(num[0]) 110 | vector2.append(num[1]) 111 | value.append(num[2]) 112 | line=fo.readline() #读取下一行 113 | if len(vector1)>0: 114 | min_v1=min(vector1) 115 | min_v2=min(vector2) 116 | min_v=min(min_v1,min_v2) 117 | for i in range(len(vector1)): 118 | vector1[i]=int(vector1[i]-min_v) 119 | vector2[i]=int(vector2[i]-min_v) 120 | values[vector1[i]][vector2[i]]=value[i] 121 | values[vector2[i]][vector1[i]]=value[i] 122 | 123 | VN_dict.update({key:values}) 124 | line=fo.readline() 125 | fo.close() 126 | return VN_dict 127 | 128 | def get_SN_Path(file):#读取物理网络的边,按三元组方式存 129 | SN_path={} 130 | fo=open(file,"r") 131 | SN_key_pattern=re.compile(r'This is PS network for virtual network----')#判断时序 132 | link_pattern=re.compile(r'node-link-information:')#判断link information 133 | SN_end_pattern=re.compile(r'This is virtual network')#判断结束 结尾处要么是空行 要么是vn 134 | line=fo.readline() 135 | while line: 136 | if re.match(SN_key_pattern,line):#找到SN 137 | #line=fo.readline() #读取下一行 138 | num=[int(r) for r in re.findall(r"\d+\.?\d*",line)] #将一行数字处理成list 139 | key=num[0] #SN的序号 140 | value=[] 141 | line=fo.readline() #读取下一行 142 | while not re.match(link_pattern,line): 143 | line=fo.readline() 144 | line=fo.readline() #读取下一行 145 | while (not re.match(SN_end_pattern,line)) and (line!='\n'): 146 | num=[float(r) for r in re.findall(r"\d+\.?\d*",line)] #读取 两个节点的序号 两节点之间带宽 147 | node_list=[int(num[0]),int(num[1]),num[2]] 148 | value.append(node_list) 149 | line=fo.readline() #读取下一行 150 | SN_path.update({key:value}) 151 | line=fo.readline() 152 | fo.close() 153 | return SN_path 154 | 155 | def get_VN_Path(file):#读取虚拟网络的边,按三元组方式存 156 | VN_path={} 157 | fo=open(file,"r") 158 | VN_key_pattern=re.compile(r'This is virtual network')#判断时序 159 | link_pattern=re.compile(r'node-link-information:')#判断link information 160 | VN_end_pattern=re.compile(r'The life time is:')#判断结束 161 | line=fo.readline() 162 | while line: 163 | if re.match(VN_key_pattern,line):#找到VN 164 | #line=fo.readline() #读取下一行 165 | num=[int(r) for r in re.findall(r"\d+\.?\d*",line)] #将一行数字处理成list 166 | key=num[0] #VN的序号 167 | vector1=[] 168 | vector2=[] 169 | value=[] 170 | values=[] 171 | 172 | line=fo.readline() #读取下一行 173 | while not re.match(link_pattern,line): 174 | line=fo.readline() 175 | line=fo.readline() #读取下一行 176 | while (not re.match(VN_end_pattern,line)) and (line!='\n'): 177 | num=[float(r) for r in re.findall(r"\d+\.?\d*",line)] 178 | vector1.append(num[0]) #相连的两节点中1个 179 | vector2.append(num[1]) #相连的两节点中1个 180 | value.append(num[2]) #两节点 虚拟带宽 181 | 182 | # node_list=(int(num[0]%6),int(num[1]%6),num[2]) #固定6个节点 183 | # values.append(node_list) 184 | line=fo.readline() #读取下一行 185 | if len(vector1)>0: #存在虚拟链路 186 | min_v1=min(vector1) 187 | min_v2=min(vector2) 188 | min_v=min(min_v1,min_v2) 189 | for i in range(len(vector1)): 190 | vector1[i]=int(vector1[i]-min_v) #和VN节点的编号对应起来 191 | vector2[i]=int(vector2[i]-min_v) 192 | node_list=(vector1[i],vector2[i],value[i]) 193 | values.append(node_list) 194 | VN_path.update({key:values}) 195 | line=fo.readline() 196 | fo.close() 197 | return VN_path 198 | 199 | def get_Solution(file):#从 maprecord 文件中读取的映射结果 节点映射结果 200 | MP_dict={} 201 | fo=open(file,"r") 202 | pattern=re.compile(r'This is MP Solution for virtual network')#开始标志 203 | #bad_pattern=re.compile(r'.*\[.*\].*')#不读入的行 204 | end_pattern=re.compile(r'link MP Solution:')#结束标志 205 | line=fo.readline() 206 | while line: 207 | if re.match(pattern,line): 208 | num=[int(r) for r in re.findall(r"\d+\.?\d*",line)] #将一行数字处理成list 209 | key=num[0] #MP的序号 210 | value=np.zeros([148,10]) #VN 的虚拟节点都在10个以内 节点映射结果 211 | line=fo.readline() #读取下一行 212 | while not re.match(end_pattern,line) :#and not re.match(bad_pattern,line): 213 | num=[int(r) for r in re.findall(r"\d+\.?\d*",line)] #将一行数字处理成list 214 | value[num[1]][num[0]%10]=1 215 | line=fo.readline() #读取下一行 216 | MP_dict.update({key:value}) 217 | line=fo.readline() #读取下一行 218 | fo.close() 219 | return MP_dict 220 | 221 | def get_period(file):#从文件中读取虚拟网络的生命周期,返回VN_period={时序key:[[序号num,生命周期period,结束时间end_time],]} 222 | VN_path={} 223 | fo=open(file,"r") 224 | VN_key_pattern=re.compile(r'This is virtual network')#判断序号 225 | time_pattern=re.compile(r'The life time is:')#判断life time 226 | line=fo.readline() 227 | value=[] 228 | while line: 229 | if re.match(VN_key_pattern,line):#找到VN 230 | #line=fo.readline() #读取下一行 231 | num=[int(r) for r in re.findall(r"\d+\.?\d*",line)] #将一行数字处理成list 232 | key=num[0] #VN的序号 233 | while not re.match(time_pattern,line): 234 | line=fo.readline() 235 | life_time=[int(r) for r in re.findall(r"\d+\.?\d*",line)] 236 | item=[key,life_time[0],0,0] 237 | value.append(item) 238 | line=fo.readline() #读取下一行 239 | VN_period={0:value} 240 | fo.close() 241 | return (VN_period) 242 | 243 | 244 | 245 | def read_SN_VN(file1,file2): 246 | solution=get_Solution(file1) 247 | sn_link=get_SN_Link(file1,get_SN_Node(file1)) 248 | vn_link=get_VN_Link(file2,get_VN_Node(file2)) 249 | sn_path=get_SN_Path(file1) 250 | 251 | SN_Link=sn_path[0] 252 | VN_Link=get_VN_Path(file2) 253 | VN_Life=get_period(file2) 254 | SN_Node=[] 255 | for i in range(len(sn_link[0])): 256 | SN_Node.append(sn_link[0][i][i]) 257 | VN_Node={} 258 | for i in range(len(vn_link)): 259 | v_node=[] 260 | for j in range(len(vn_link[i])): 261 | v_node.append(vn_link[i][j][j]) 262 | VN_Node.update({i:v_node}) 263 | return (solution,SN_Link,SN_Node,VN_Link,VN_Node,VN_Life) 264 | 265 | import re 266 | def get_CostRatio_UtilizationRate(file):#从文件中读取资源利用率和成本比,返回CostRatio和UtilizationRate两个字典 267 | fo=open(file,"r",encoding="gbk") 268 | line=fo.readline() 269 | #print(type(line)) 270 | pattern1=re.compile(r'.*当前接受的虚拟网络数为.*')#匹配有用行 271 | pattern2=re.compile(r'(?<=-)\d+(?=\.\d-当前接受的虚拟网络数为)')#匹配第一个数字(时序) 272 | #pattern5=re.compile(r'(?#-\d+\.\d)(?<=-当前接受的虚拟网络数为-)\d+(?=-)')#匹配网络的序号 273 | pattern3=re.compile(r'(?#-\d+\.\d-当前接受的虚拟网络数为-\d+-total fitness is:-\d+\.\d+-total cost is-\d+\.\d+-benifit-)(?<=cost ratio is:-)\d+\.\d+(?=-)')#匹配cost_ratio 274 | pattern4=re.compile(r'(?#-\d+\.\d-当前接受的虚拟网络数为-\d+-total fitness is:-\d+\.\d+-total cost is-\d+\.\d+-benifit-cost ratio is:-\d+\.\d+)(?<=-Utilization rate is:-)\d+\.\d+(?=-)')#匹配utilization_rate 275 | CostRatio={} 276 | UtilizationRate={} 277 | while line: 278 | #print(line) 279 | if re.match(pattern1,line): 280 | #print("ok") 281 | key=int(re.findall(pattern2,line)[0])#读取时序作为键值 282 | print(key) 283 | if key not in CostRatio: 284 | Cvalue=[] 285 | CostRatio.update({key:Cvalue}) 286 | if key not in UtilizationRate: 287 | Uvalue=[] 288 | UtilizationRate.update({key:Uvalue}) 289 | #num=int(re.findall(pattern4,line)[0])#序号 290 | cost_ratio=float(re.findall(pattern3,line)[0]) 291 | utilization_rate=float(re.findall(pattern4,line)[0]) 292 | #Cvalue_item=[num,cost_ratio] 293 | #Uvalue_item=[num,utilization_rate] 294 | #CostRatio[key].append(Cvalue_item) 295 | #UtilizationRate[key].append(Uvalue_item) 296 | CostRatio[key].append(cost_ratio) 297 | UtilizationRate[key].append(utilization_rate) 298 | line=fo.readline() 299 | fo.close() 300 | return CostRatio, UtilizationRate 301 | -------------------------------------------------------------------------------- /code/__pycache__/DeepQNetwork.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moooontoo/Latency-Equalization-E2E-NS-RL/2ec08851631b8a9da8d662ca7c8df9844b6bbeb7/code/__pycache__/DeepQNetwork.cpython-38.pyc -------------------------------------------------------------------------------- /code/__pycache__/config.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moooontoo/Latency-Equalization-E2E-NS-RL/2ec08851631b8a9da8d662ca7c8df9844b6bbeb7/code/__pycache__/config.cpython-38.pyc -------------------------------------------------------------------------------- /code/__pycache__/network.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moooontoo/Latency-Equalization-E2E-NS-RL/2ec08851631b8a9da8d662ca7c8df9844b6bbeb7/code/__pycache__/network.cpython-38.pyc -------------------------------------------------------------------------------- /code/__pycache__/replay_memory.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moooontoo/Latency-Equalization-E2E-NS-RL/2ec08851631b8a9da8d662ca7c8df9844b6bbeb7/code/__pycache__/replay_memory.cpython-38.pyc -------------------------------------------------------------------------------- /code/__pycache__/utils.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moooontoo/Latency-Equalization-E2E-NS-RL/2ec08851631b8a9da8d662ca7c8df9844b6bbeb7/code/__pycache__/utils.cpython-38.pyc -------------------------------------------------------------------------------- /code/config.py: -------------------------------------------------------------------------------- 1 | # capacity = 8000 2 | # learning_rate = 1e-3 3 | # memory_count = 0 4 | # batch_size = 256 5 | # gamma = 0.995 6 | # update_count = 0 7 | # coding=utf-8 8 | import numpy as np 9 | 10 | #replay_memory所需的相关参数 11 | class AgentConfig(object): 12 | kesi = 0.1 # kesi是随机选动作 13 | heigth = 1 14 | length = 1 15 | width = 20 16 | # fc_out_dims = 1000 17 | 18 | # learning_rate = 0.0025 19 | # learning_rate = 3e-4 20 | LEARNING_RATE = 1e-3 21 | learning_rate_policy = 5e-3 22 | learning_rate_value = 1e-3 23 | learning_rate_q = 1e-3 24 | # learning_rate_minimum = 0.0025 25 | # learning_rate_decay = 0.96 26 | # learning_rate_decay_step = 5000 27 | # discount = 0.9 28 | max_step = 30000 # 训练次数 29 | learn_start = 1000 # 1000次之后网络开始更新 30 | train_frequency = 4 # 1000次之后每4个动作更新一下训练网络 31 | # train_step = 2000 32 | train_step = 2000 # 暂时每100次print一次 33 | test_step = 2000 # 2000次判断一下是否保存模型,然后对数据进行summary 34 | target_q_update_step = 1000 # 1000次之后,每1000次更新一下目标网络 35 | play_step = 500 # 每3000次看下模型调节能力 36 | play_times = 30 37 | 38 | batch_size = 32 39 | 40 | memory_size = 2000 41 | test_play = 500 42 | # test_produce = 43 | 44 | action_rows = 20 #20个次用户 45 | action_cols = 20 #20个信道 46 | # action_size = 44 47 | reward_size = 1 48 | 49 | 50 | 51 | 52 | #神经网络所需参数 53 | class NetworkConfig(object): 54 | mbs_number = 1 # macro基站数量:1 55 | sbs_number = 1 # small基站数量:1 56 | u_number = 20 # 用户数量:20 57 | c_num = 20 # 信道数量 58 | 59 | BW_sc = 18e4 # 每个信道的带宽 60 | sp_max = 1 # 基站发射功率最大值 61 | N0 = 5e-22 # AWGN噪声 62 | net_size = (100, 100) # 网络尺寸 63 | reward_alpha = 1 64 | #E2E delay limit 65 | 66 | latency_limit = 10 67 | latency_limit2 = 200 68 | #rate_limit = 2e5 69 | rate_limit = 3e5 70 | 71 | sep = 5 # embb用户数量 72 | loss_fac = 1 -------------------------------------------------------------------------------- /code/natureDQN.py: -------------------------------------------------------------------------------- 1 | '''将RAN资源分配强化学习作为函数,供外部调用''' 2 | import time 3 | import numpy as np 4 | 5 | import torch 6 | import torch.nn as nn 7 | import torch.nn.functional as F 8 | import torch.optim as optim 9 | 10 | from network import Network 11 | from DeepQNetwork import * 12 | from config import * 13 | from replay_memory import ReplayMemory 14 | from utils import * 15 | from numpy import random 16 | 17 | import os 18 | os.environ["PYTHONIOENCODING"] = "utf-8" 19 | os.environ["CUDA_VISIBLE_DEVICES"] = '1' 20 | 21 | 22 | #随机选信道、信道上功率 23 | def random_select_action(): 24 | #np.random.ranint(a,b)-->[a,b) 25 | #生成[0,20)上取值为随机整数,1x20的向量 26 | x_c = np.random.randint(0, 20, size=20) 27 | x_p = np.random.randint(0, 20, size=20) 28 | action_c = np.zeros((20, 20)) 29 | action_pc = np.zeros((20, 20)) 30 | 31 | for i in range(20): 32 | action_c[i][x_c[i]] = 1 33 | action_pc[i][x_c[i]] = x_p[i] * 2 34 | #每个等级2W 35 | return action_pc, action_c 36 | 37 | 38 | #act_net()用于生成动作 39 | def select_action(state,act_net): 40 | # 参数 state:1*3 41 | state = torch.from_numpy(state).float() 42 | x1_p, x1_c, x2_p, x2_c, x3_p, x3_c, x4_p, x4_c, x5_p, x5_c, x6_p, x6_c, x7_p, x7_c, x8_p, x8_c, x9_p, x9_c, x10_p, x10_c,\ 43 | x11_p, x11_c, x12_p, x12_c, x13_p, x13_c, x14_p, x14_c, x15_p, x15_c, x16_p, x16_c, x17_p, x17_c, x18_p, x18_c, x19_p, x19_c,\ 44 | x20_p, x20_c = act_net(state) 45 | # 功率选择为20个功率等级 46 | x1_p = np.argmax(x1_p.view(20).cpu().detach().numpy()) 47 | x2_p = np.argmax(x2_p.view(20).cpu().detach().numpy()) 48 | x3_p = np.argmax(x3_p.view(20).cpu().detach().numpy()) 49 | x4_p = np.argmax(x4_p.view(20).cpu().detach().numpy()) 50 | x5_p = np.argmax(x5_p.view(20).cpu().detach().numpy()) 51 | x6_p = np.argmax(x6_p.view(20).cpu().detach().numpy()) 52 | x7_p = np.argmax(x7_p.view(20).cpu().detach().numpy()) 53 | x8_p = np.argmax(x8_p.view(20).cpu().detach().numpy()) 54 | x9_p = np.argmax(x9_p.view(20).cpu().detach().numpy()) 55 | x10_p = np.argmax(x10_p.view(20).cpu().detach().numpy()) 56 | x11_p = np.argmax(x11_p.view(20).cpu().detach().numpy()) 57 | x12_p = np.argmax(x12_p.view(20).cpu().detach().numpy()) 58 | x13_p = np.argmax(x13_p.view(20).cpu().detach().numpy()) 59 | x14_p = np.argmax(x14_p.view(20).cpu().detach().numpy()) 60 | x15_p = np.argmax(x15_p.view(20).cpu().detach().numpy()) 61 | x16_p = np.argmax(x16_p.view(20).cpu().detach().numpy()) 62 | x17_p = np.argmax(x17_p.view(20).cpu().detach().numpy()) 63 | x18_p = np.argmax(x18_p.view(20).cpu().detach().numpy()) 64 | x19_p = np.argmax(x19_p.view(20).cpu().detach().numpy()) 65 | x20_p = np.argmax(x20_p.view(20).cpu().detach().numpy()) 66 | x_p = np.array( 67 | [x1_p, x2_p, x3_p, x4_p, x5_p, x6_p, x7_p, x8_p, x9_p, x10_p, x11_p, x12_p, x13_p, x14_p, x15_p, x16_p, x17_p, 68 | x18_p, x19_p, x20_p]) 69 | # 信道选择为6个可选信道 70 | x1_c = np.argmax(x1_c.view(20).cpu().detach().numpy()) 71 | x2_c = np.argmax(x2_c.view(20).cpu().detach().numpy()) 72 | x3_c = np.argmax(x3_c.view(20).cpu().detach().numpy()) 73 | x4_c = np.argmax(x4_c.view(20).cpu().detach().numpy()) 74 | x5_c = np.argmax(x5_c.view(20).cpu().detach().numpy()) 75 | x6_c = np.argmax(x6_c.view(20).cpu().detach().numpy()) 76 | x7_c = np.argmax(x7_c.view(20).cpu().detach().numpy()) 77 | x8_c = np.argmax(x8_c.view(20).cpu().detach().numpy()) 78 | x9_c = np.argmax(x9_c.view(20).cpu().detach().numpy()) 79 | x10_c = np.argmax(x10_c.view(20).cpu().detach().numpy()) 80 | x11_c = np.argmax(x11_c.view(20).cpu().detach().numpy()) 81 | x12_c = np.argmax(x12_c.view(20).cpu().detach().numpy()) 82 | x13_c = np.argmax(x13_c.view(20).cpu().detach().numpy()) 83 | x14_c = np.argmax(x14_c.view(20).cpu().detach().numpy()) 84 | x15_c = np.argmax(x15_c.view(20).cpu().detach().numpy()) 85 | x16_c = np.argmax(x16_c.view(20).cpu().detach().numpy()) 86 | x17_c = np.argmax(x17_c.view(20).cpu().detach().numpy()) 87 | x18_c = np.argmax(x18_c.view(20).cpu().detach().numpy()) 88 | x19_c = np.argmax(x19_c.view(20).cpu().detach().numpy()) 89 | x20_c = np.argmax(x20_c.view(20).cpu().detach().numpy()) 90 | 91 | x_c = np.array( 92 | [x1_c, x2_c, x3_c, x4_c, x5_c, x6_c, x7_c, x8_c, x9_c, x10_c, x11_c, x12_c, x13_c, x14_c, x15_c, x16_c, x17_c, 93 | x18_c, x19_c, x20_c]) 94 | 95 | action_c = np.zeros((20, 20)) 96 | action_pc = np.zeros((20, 20)) 97 | 98 | for i in range(20): 99 | action_c[i][x_c[i]] = 1 100 | action_pc[i][x_c[i]] = x_p[i] * 2 #每个功率等级2W 101 | 102 | if np.random.rand(1) >= 0.9: # epslion greedy 103 | action_pc, action_c = random_select_action() # epslion greedy 104 | 105 | return action_pc, action_c # 返回用户信道 功率分配情况 106 | 107 | '''输入 sla列表,两个神经网络,最大episode值''' 108 | def rlRan(sla,target_net,act_net,max_episodes = 5000): 109 | # Transition = namedtuple('Transition', ['state', 'action', 'reward', 'next_state']) 110 | episodes = max_episodes 111 | learning_rate = 0.001 112 | gamma = 0.995 113 | 114 | #device = 'cuda' if torch.cuda.is_available() else 'cpu' 115 | device = 'cpu' 116 | 117 | optimizer = optim.Adam(act_net.parameters(), learning_rate) 118 | 119 | cong = NetworkConfig 120 | # 物理网络所需的若干功能,比如计算信道增益、速率等等 121 | net = Network(cong) 122 | 123 | memory = ReplayMemory(AgentConfig) 124 | # max_avg_ep_reward = 0. 125 | ep_rewards = [] 126 | ep_se = [] 127 | ep_qoe = [] 128 | ep_latency = [] 129 | 130 | s = net.state_first() # 先代入初始状态 之后进行更新 131 | s = np.array(s).reshape(1, 20) 132 | 133 | se = 0. 134 | qoe = 0. 135 | for i_episode in range(episodes): 136 | # choose action 137 | a_p, a_c = select_action(s,act_net) # 动作:20个次用户的信道分配以及功率分配 138 | 139 | ##将20个用户的数据率作为状态 140 | s_ = net.u_rate(a_p, a_c) 141 | s_ = np.array(s_).reshape(1, 20) 142 | 143 | # compute reward 144 | r, se, qoe, ep_latency = net.compute_reward(a_p, a_c, sla) 145 | ep_rewards.append(np.sum(r)) 146 | ep_se.append(np.sum(se)) 147 | ep_qoe.append(np.sum(qoe)) 148 | memory.add(s, r, a_p) 149 | s = s_ # 状态转移 150 | 151 | # 前200个回合 进行试探 152 | if (i_episode + 1) <= 200 and (i_episode + 1) % 100 == 0: 153 | avg_ep_reward = np.mean(ep_rewards) 154 | print('step:', (i_episode + 1), 'avg_ep_reward:', avg_ep_reward) 155 | ep_rewards = [] 156 | se = [] 157 | qoe = [] 158 | # kkw 159 | # end 存储 160 | 161 | if (i_episode + 1) > 200: # 原2000,原200,还是200比较合适 162 | # kkw 163 | bn_s, bn_a, bn_r, bn_s_ = memory.sample() # 先放一放这个 164 | bn_s = torch.tensor(bn_s).float().to(device) # [batch_size, 1, 50, 1] 165 | bn_a = torch.tensor(bn_a).float().to(device) # [batch_size, 10, 10] 166 | bn_r = torch.tensor(bn_r).float().to(device) # [batch_size, 1] 167 | bn_s_ = torch.tensor(bn_s_).float().to(device) # [batch_size, 1, 50, 1] 168 | 169 | # reward = (bn_r - bn_r.mean()) / (reward.std() + 1e-7) 170 | 171 | x1_p, x1_c, x2_p, x2_c, x3_p, x3_c, x4_p, x4_c, x5_p, x5_c, x6_p, x6_c, x7_p, x7_c, x8_p, x8_c, x9_p, x9_c, x10_p, x10_c, x11_p, x11_c, x12_p, \ 172 | x12_c, x13_p, x13_c, x14_p, x14_c, x15_p, x15_c, x16_p, x16_c, x17_p, x17_c, x18_p, \ 173 | x18_c, x19_p, x19_c, x20_p, x20_c = act_net(bn_s) 174 | x1_p_t, x1_c_t, x2_p_t, x2_c_t, x3_p_t, x3_c_t, x4_p_t, x4_c_t, x5_p_t, x5_c_t, x6_p_t, x6_c_t, x7_p_t, x7_c_t, x8_p_t, x8_c_t, x9_p_t, x9_c_t, x10_p_t, x10_c_t, \ 175 | x11_p_t, x11_c_t, x12_p_t, x12_c_t, x13_p_t, x13_c_t, x14_p_t, x14_c_t, x15_p_t, x15_c_t, x16_p_t, x16_c_t, x17_p_t, x17_c_t, x18_p_t, x18_c_t, \ 176 | x19_p_t, x19_c_t, x20_p_t, x20_c_t = target_net(bn_s_) 177 | 178 | x = torch.zeros(32, 1, 40) 179 | x_t = torch.zeros(32, 1, 40) 180 | 181 | for i in range(32): 182 | x[i][0][0] = torch.max(x1_c[i][0]) 183 | x[i][0][1] = torch.max(x1_p[i][0]) 184 | 185 | 186 | x[i][0][2] = torch.max(x2_c[i][0]) 187 | x[i][0][3] = torch.max(x2_p[i][0]) 188 | 189 | 190 | x[i][0][4] = torch.max(x3_c[i][0]) 191 | x[i][0][5] = torch.max(x3_p[i][0]) 192 | 193 | 194 | x[i][0][6] = torch.max(x4_c[i][0]) 195 | x[i][0][7] = torch.max(x4_p[i][0]) 196 | 197 | 198 | x[i][0][8] = torch.max(x5_c[i][0]) 199 | x[i][0][9] = torch.max(x5_p[i][0]) 200 | 201 | 202 | x[i][0][10] = torch.max(x6_c[i][0]) 203 | x[i][0][11] = torch.max(x6_p[i][0]) 204 | 205 | 206 | x[i][0][12] = torch.max(x7_c[i][0]) 207 | x[i][0][13] = torch.max(x7_p[i][0]) 208 | 209 | 210 | x[i][0][14] = torch.max(x8_c[i][0]) 211 | x[i][0][15] = torch.max(x8_p[i][0]) 212 | 213 | 214 | x[i][0][16] = torch.max(x9_c[i][0]) 215 | x[i][0][17] = torch.max(x9_p[i][0]) 216 | 217 | 218 | x[i][0][18] = torch.max(x10_c[i][0]) 219 | x[i][0][19] = torch.max(x10_p[i][0]) 220 | 221 | 222 | x[i][0][20] = torch.max(x11_c[i][0]) 223 | x[i][0][21] = torch.max(x11_p[i][0]) 224 | 225 | 226 | x[i][0][22] = torch.max(x12_c[i][0]) 227 | x[i][0][23] = torch.max(x12_p[i][0]) 228 | 229 | 230 | x[i][0][24] = torch.max(x13_c[i][0]) 231 | x[i][0][25] = torch.max(x13_p[i][0]) 232 | 233 | 234 | x[i][0][26] = torch.max(x14_c[i][0]) 235 | x[i][0][27] = torch.max(x14_p[i][0]) 236 | 237 | 238 | x[i][0][28] = torch.max(x15_c[i][0]) 239 | x[i][0][29] = torch.max(x15_p[i][0]) 240 | 241 | 242 | x[i][0][30] = torch.max(x16_c[i][0]) 243 | x[i][0][31] = torch.max(x16_p[i][0]) 244 | 245 | 246 | x[i][0][32] = torch.max(x17_c[i][0]) 247 | x[i][0][33] = torch.max(x17_p[i][0]) 248 | 249 | 250 | x[i][0][34] = torch.max(x18_c[i][0]) 251 | x[i][0][35] = torch.max(x18_p[i][0]) 252 | 253 | 254 | x[i][0][36] = torch.max(x19_c[i][0]) 255 | x[i][0][37] = torch.max(x19_p[i][0]) 256 | 257 | 258 | x[i][0][38] = torch.max(x20_c[i][0]) 259 | x[i][0][39] = torch.max(x20_p[i][0]) 260 | 261 | x_t[i][0][0] = x1_c_t[i][0].max() 262 | x_t[i][0][1] = x1_p_t[i][0].max() 263 | x_t[i][0][2] = x2_c_t[i][0].max() 264 | x_t[i][0][3] = x2_p_t[i][0].max() 265 | x_t[i][0][4] = x3_c_t[i][0].max() 266 | x_t[i][0][5] = x3_p_t[i][0].max() 267 | x_t[i][0][6] = x4_c_t[i][0].max() 268 | x_t[i][0][7] = x4_p_t[i][0].max() 269 | x_t[i][0][8] = x5_c_t[i][0].max() 270 | x_t[i][0][9] = x5_p_t[i][0].max() 271 | x_t[i][0][10] = x6_c_t[i][0].max() 272 | x_t[i][0][11] = x6_p_t[i][0].max() 273 | x_t[i][0][12] = x7_c_t[i][0].max() 274 | x_t[i][0][13] = x7_p_t[i][0].max() 275 | x_t[i][0][14] = x8_c_t[i][0].max() 276 | x_t[i][0][15] = x8_p_t[i][0].max() 277 | x_t[i][0][16] = x9_c_t[i][0].max() 278 | x_t[i][0][17] = x9_p_t[i][0].max() 279 | x_t[i][0][18] = x10_c_t[i][0].max() 280 | x_t[i][0][19] = x10_p_t[i][0].max() 281 | x_t[i][0][20] = x11_c_t[i][0].max() 282 | x_t[i][0][21] = x11_p_t[i][0].max() 283 | x_t[i][0][22] = x12_c_t[i][0].max() 284 | x_t[i][0][23] = x12_p_t[i][0].max() 285 | x_t[i][0][24] = x13_c_t[i][0].max() 286 | x_t[i][0][25] = x13_p_t[i][0].max() 287 | x_t[i][0][26] = x14_c_t[i][0].max() 288 | x_t[i][0][27] = x14_p_t[i][0].max() 289 | x_t[i][0][28] = x15_c_t[i][0].max() 290 | x_t[i][0][29] = x15_p_t[i][0].max() 291 | x_t[i][0][30] = x16_c_t[i][0].max() 292 | x_t[i][0][31] = x16_p_t[i][0].max() 293 | x_t[i][0][32] = x17_c_t[i][0].max() 294 | x_t[i][0][33] = x17_p_t[i][0].max() 295 | x_t[i][0][34] = x18_c_t[i][0].max() 296 | x_t[i][0][35] = x18_p_t[i][0].max() 297 | x_t[i][0][36] = x19_c_t[i][0].max() 298 | x_t[i][0][37] = x19_p_t[i][0].max() 299 | x_t[i][0][38] = x20_c_t[i][0].max() 300 | x_t[i][0][39] = x20_p_t[i][0].max() 301 | 302 | bn_r = bn_r.view(-1, 1, 1) 303 | # reward normalization 304 | # reward = (bn_r - bn_r.mean()) / (bn_r.std() + 1e-7) #这个e-7是防止溢出 305 | # kkw 306 | # reward = (bn_r - bn_r.mean()) / (bn_r.std()) 307 | # no normalization 308 | # reward = bn_r 309 | with torch.no_grad(): 310 | # target_v = reward + gamma * x_t #v_ x_ 311 | target_v = bn_r + gamma * x_t 312 | # print(target_v, v) 313 | # kww 314 | optimizer.zero_grad() 315 | loss = nn.MSELoss()(target_v, x) # v x1 316 | loss.backward() 317 | optimizer.step() 318 | if (i_episode + 1) % 100 == 0: # 原来是2000 319 | if (i_episode + 1) % 2000 == 0: # 原来是2000,1000的结果和2000一样,不能是4000 320 | target_net.load_state_dict(act_net.state_dict()) 321 | avg_ep_reward = np.mean(ep_rewards) 322 | avg_ep_se = np.mean(ep_se) 323 | avg_ep_qoe = np.mean(ep_qoe) 324 | # print('step:', i_episode, 'reward:', avg_ep_reward, 'loss:', loss.detach().numpy()) 325 | print('step:', (i_episode + 1), 'avg_ep_reward:', avg_ep_reward) 326 | # with open('ep_rewards.csv', 'ab') as f: 327 | # np.savetxt(f, np.array([(i_episode + 1), avg_ep_reward]), delimiter=',', fmt='%.4f') 328 | 329 | # if max_avg_ep_reward * 0.9 <= avg_ep_reward: # 如果目前reward大于之前reward的百分之90 330 | # # # self.step_assign_op.eval({self.step_input: self.step + 1}) #m,感觉像是记录一共多少次记录 331 | # # save() 332 | # # self.memory.save() 333 | # max_avg_ep_reward = np.max([max_avg_ep_reward, avg_ep_reward]) 334 | # save() 335 | ep_rewards = [] 336 | se = [] 337 | qoe = [] 338 | 339 | torch.save(act_net.state_dict(), '../models/actNature') 340 | torch.save(target_net.state_dict(), '../models/targetNature') 341 | return ep_latency, s 342 | if __name__ == '__main__': 343 | sla = [0.8]*20 344 | target_net, act_net = Net(), Net() 345 | l, s = rlRan(sla, target_net, act_net, 5000) 346 | 347 | print(l, s) 348 | -------------------------------------------------------------------------------- /code/network.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | import numpy as np 3 | from scipy.spatial.distance import pdist, squareform 4 | import math 5 | from config import * 6 | from utils import * 7 | import random 8 | 9 | import matplotlib.pyplot as plt 10 | import torch 11 | 12 | 13 | class Network: 14 | 15 | def __init__(self, config, show_config=True): # 尽量搞懂这些是啥意思 16 | self.config = config 17 | try: 18 | self._attrs = config.__dict__['__flags'] 19 | except: 20 | self._attrs = class_vars(config) # 把NetworkConfig里面的变量和值 当成字典输出 21 | 22 | if show_config: 23 | print('Network configs...') 24 | pp(self._attrs) 25 | 26 | for attr in self._attrs: 27 | name = attr if not attr.startswith('_') else attr[1:] 28 | setattr(self, name, getattr(self.config, attr)) 29 | 30 | self.start() 31 | 32 | def start(self): 33 | # 用户基站距离 34 | self.mbs_u_distance = [] 35 | self.sbs_u_distance = [] 36 | 37 | # 用户基站位置 38 | self.mbs_location = [45, 55] 39 | self.sbs_location = [55, 45] 40 | self.u_location = [[10., 55.], [25., 35.], [35., 70.], [60., 25.], [75., 45.], [80., 60.], [6., 23.], 41 | [46., 21.], [12., 76.], [53., 50.], [75., 57.], [93., 65.], [10., 78.], [91., 51.], 42 | [67., 91.], [15., 90.], [23., 34.], [49., 79.], [75., 14.], [12., 69.]] 43 | 44 | self.create_topology() 45 | 46 | # 得到用户和基站的信道增益gain 47 | def create_topology(self): 48 | all_location = np.vstack((self.mbs_location, self.sbs_location, self.u_location)) 49 | all_distance = pdist(all_location, 'euclidean') 50 | 51 | self.mbs_u_distance = all_distance[1:1 + self.u_number] 52 | self.sbs_u_distance = all_distance[1 + self.u_number:1 + 2 * self.u_number] 53 | 54 | self.gain_sbs_u = self._channel_gain(self.sbs_u_distance, shape=20) # 6 55 | self.gain_mbs_u = self._channel_gain(self.mbs_u_distance, shape=20) # 6 56 | #print(self.gain_mbs_u) 57 | 58 | # 计算信道增益 59 | def _channel_gain(self, distance, shape): 60 | path_loss_bs_user = 37 + 30 * np.log2(distance) 61 | path_loss_bs_user = path_loss_bs_user + self.generate_shadow_fading(0, 8, shape, 1) 62 | gain = np.power(10, -path_loss_bs_user / 10) 63 | return gain 64 | 65 | def generate_shadow_fading(self, mean, sigma, num_user, num_bs): 66 | ''' 67 | 本函数生成对数正态分布的阴影衰落 68 | :param mean: 均值dB 69 | :param sigma: 标准差 dB 70 | :param num_bs: 71 | :param num_user: 72 | :return: 73 | ''' 74 | sigma = np.power(10, sigma / 10) 75 | mean = np.power(10, mean / 10) 76 | m = np.log(mean ** 2 / np.sqrt(sigma ** 2 + mean ** 2)) 77 | sigma = np.sqrt(np.log(sigma ** 2 / mean ** 2 + 1)) 78 | lognormal_fade = np.exp(np.random.randn(num_user, num_bs) * sigma + m) 79 | return lognormal_fade.reshape(num_user) 80 | 81 | def draw_net(self): 82 | '''画出PU SU分布图保存为model.jpg''' 83 | # # plt.subplot(111) 84 | # pt_location = self.pt_location 85 | # pr_location = self.pr_location 86 | # st_location = self.st_location 87 | # sr_location = self.sr_location 88 | 89 | # plt.rcParams['font.sans-serif'] = ['Arial'] # 如果要显示中文字体,则在此处设为:SimHei 90 | # plt.rcParams['axes.unicode_minus'] = False # 显示负号 91 | # plt.plot(pt_location[:, 0], pt_location[:, 1], '+', color='red', ms=15, label='PT') 92 | # plt.plot(pr_location[:, 0], pr_location[:, 1], '.r', ms=15, label='PR') 93 | # plt.plot(st_location[:, 0], st_location[:, 1], 's', color='blue', ms=10, label='ST') 94 | # plt.plot(sr_location[:, 0], sr_location[:, 1], '^b', ms=8, label='SR') 95 | # # plt.plot(su_location[:, 0], su_location[:, 1], '^b', ms=8, label='SU') 96 | # # plt.plot(30, 70, '+', color='red', ms=15, label='PBS') 97 | # # plt.plot(70, 30, 's', color='blue', ms=10, label='CBS') 98 | # plt.xlim(0, 100) 99 | # plt.ylim(0, 100) 100 | # plt.legend() 101 | # plt.savefig('model.jpg') 102 | # plt.show() 103 | 104 | '''def pu_snr(self, su_p, su_c): 105 | p_num = self.config.pu_number 106 | s_num = self.config.su_number 107 | pu_p = self.pu_p 108 | pu_c = self.pu_c 109 | pus_snr = [] 110 | pus_rate = [] 111 | for i in range(p_num): 112 | pu_signal = 0. 113 | su_signal = 0. 114 | for j in range(self.config.c_num): 115 | if pu_c[i][j] == 1: 116 | pu_signal += pu_p[i][j] * self.gain_pbs_pu[i] 117 | for k in range(s_num): 118 | su_signal += su_p[k][j] * su_c[k][j] * self.gain_mbs_u[k] 119 | interference = su_signal + self.config.N0 120 | pu_snr = pu_signal / interference 121 | pu_rate = self.BW_sc*math.log2(1 + pu_snr) #假设带宽为1 122 | pus_snr.append(pu_snr) 123 | pus_rate.append(pu_rate) 124 | return pus_snr, pus_rate 125 | ''' 126 | 127 | def u_rate(self, u_p, u_c): 128 | u_num = self.config.u_number 129 | us_rate = [] 130 | for i in range(u_num): 131 | u_rate = 0. 132 | u_interference = 0. 133 | for j in range(self.config.c_num): 134 | if u_c[i][j] == 1.: 135 | u_signal = u_p[i][j] * self.gain_mbs_u[i] 136 | for i_ in range(u_num): 137 | if (u_c[i_][j] == 1.) and (i != i_): 138 | u_interference += u_p[i_][j] * self.gain_mbs_u[i_] 139 | # 同道干扰 140 | 141 | interference = self.loss_fac*u_interference + self.config.N0 142 | # interference = self.config.N0 143 | u_snr = u_signal / interference 144 | #print(u_snr) 145 | u_rate = self.BW_sc * math.log2(1 + u_snr) 146 | 147 | us_rate.append(u_rate) 148 | return us_rate 149 | 150 | ''' 151 | def compute_reward(self, u_p, u_c): 152 | # 网络频谱效率计算 153 | sus_rate = self.u_rate(u_p, u_c) 154 | sus_rate_sum = np.sum(sus_rate) 155 | #频谱效率 156 | n_se = sus_rate_sum/(self.c_num*self.BW_sc) 157 | # 感知用户QoE计算 158 | latency = np.zeros(20) 159 | latency_limit = 10000 160 | rate_limit = 0.5e3 161 | Qoe_counter = 0 162 | arrive_package_rate = np.random.poisson(lam=1,size=10) 163 | #对两类用户,判断满足QoE的用户数量 164 | for i in range(self.u_number): 165 | if i < 10: 166 | # Qoe_counter+=1 167 | if sus_rate[i] >= rate_limit: 168 | Qoe_counter+=1 169 | else: 170 | latency[i] = 1./(sus_rate[i] - arrive_package_rate[i-10]+1e-7) 171 | if latency[i] <= latency_limit: 172 | Qoe_counter+=1 173 | 174 | QoE = Qoe_counter/self.u_number 175 | # SE与QoE线性组合 176 | reward_alpha = 0 177 | reward = reward_alpha*n_se + (1-reward_alpha)*QoE 178 | reward_c = reward 179 | 180 | return reward_c,n_se,QoE 181 | ''' 182 | 183 | # 提供初始状态 184 | def state_first(self): 185 | u_c = [[1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.], 186 | [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 187 | [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 188 | [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 189 | [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 190 | [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 191 | [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 192 | [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 193 | [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 194 | [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 195 | [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 196 | [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 197 | [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 198 | [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 199 | [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 200 | [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 201 | [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 202 | [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 203 | [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 204 | [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]] 205 | u_c = np.array(u_c) 206 | u_p = [[1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 207 | [0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 208 | [0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 209 | [0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 210 | [0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 211 | [0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 212 | [0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 213 | [0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 214 | [0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 215 | [0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 216 | [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 217 | [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0.], 218 | [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0.], 219 | [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0.], 220 | [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0.], 221 | [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0.], 222 | [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0.], 223 | [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0.], 224 | [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0.], 225 | [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1.]] 226 | u_p = np.array(u_p) 227 | # pus_snr, _ = self.pu_snr(su_p, su_c) # 获得主用户SINR 228 | 229 | # 各用户的数据率 230 | us_rate = self.u_rate(u_c, u_p) 231 | 232 | return us_rate 233 | 234 | 235 | '''用于计算每个用户空口时延 0704''' 236 | def u_latency(self, u_p, u_c, sla): 237 | # 用户空口时延计算 238 | latency = np.zeros(20) 239 | #arrive_package_rate = np.random.poisson(lam=100, size=20) 240 | #对比 241 | arrive_package_rate = np.random.poisson(lam=1, size=20) 242 | sus_rate = self.u_rate(u_p, u_c) 243 | for i in range(self.u_number): 244 | if i < self.sep: 245 | #latency[i] = 4e7 / (sus_rate[i] - 2e5 + 1e-7) 246 | latency[i] = 50 + 5.7e7 / (sus_rate[i] + 1e-7) #0812 247 | #latency[i] = 50 + 3.01e7 / (sus_rate[i] + 1e-7) #0824 248 | #latency[i] = 50 + 3.6e7 / (sus_rate[i] + 1e-7) #0814 249 | #latency[i] = 20 + (sus_rate[i] + 1e-7)/self.rate_limit * 10 250 | if sus_rate[i] < self.rate_limit or latency[i] > self.latency_limit2: 251 | latency[i] = self.latency_limit2 252 | else: 253 | #latency[i] = 10. / (sus_rate[i] - arrive_package_rate[i] + 1e-7) 254 | #对比算法 255 | latency[i] = 1. / (sus_rate[i] - arrive_package_rate[i] + 1e-7) 256 | if latency[i] < 0 or latency[i] > self.latency_limit: 257 | latency[i] = self.latency_limit 258 | return latency 259 | 260 | 261 | '''单纯根据不同切片空口时延比例的计算QoE 作为reward,没加入频谱效率的权重 0705''' 262 | def compute_reward(self, u_p, u_c, sla): 263 | # 网络频谱效率计算 264 | sus_rate = self.u_rate(u_p, u_c) 265 | sus_rate_sum = np.sum(sus_rate) 266 | latency = self.u_latency(u_p, u_c, sla) 267 | # 频谱效率 268 | n_se = sus_rate_sum / (self.c_num * self.BW_sc) 269 | # 用户QoE计算 270 | Qoe_counter = 0 271 | #embb用户满意度 272 | # ssl_1, ssl_2 = np.zeros(self.sep), np.zeros(self.sep) 273 | ssl_1 = sus_rate[0: self.sep] 274 | ssl_1 = np.array(ssl_1)/self.rate_limit + 0.1 275 | # ssl_2 = np.log2(ssl_1) 276 | # ssl_2 = np.log(ssl_1) 277 | ssl_2 = np.log10(ssl_1) 278 | ssl = np.sum(ssl_2) 279 | # for i in range(self.sep): 280 | # ssl = ssl * ssl_2[i] 281 | 282 | # 对两类用户,判断满足QoE的用户数量 283 | # for i in range(self.u_number): 284 | # if i < 10: 285 | # # Qoe_counter+=1 286 | # if sus_rate[i] >= self.rate_limit: 287 | # Qoe_counter += 1 288 | # elif latency[i] <= self.latency_limit * sla[i]: 289 | # Qoe_counter += 1 290 | 291 | 292 | #都转换成时延的约束 293 | for i in range(self.u_number): 294 | if i < self.sep: 295 | if latency[i] < self.latency_limit2 * sla[i]: 296 | Qoe_counter += 1 297 | elif i == self.sep: 298 | es = Qoe_counter 299 | if latency[i] < self.latency_limit * sla[i]: 300 | Qoe_counter += 1 301 | elif latency[i] < self.latency_limit * sla[i]: 302 | Qoe_counter += 1 303 | 304 | us = Qoe_counter - es 305 | QoE = Qoe_counter / self.u_number 306 | # SE与QoE线性组合 307 | reward_alpha = self.reward_alpha 308 | #reward = reward_alpha * n_se + (1 - reward_alpha) * QoE 309 | reward = reward_alpha * ssl + (1 - reward_alpha) * QoE 310 | return reward, n_se, QoE, latency, ssl, es, us 311 | 312 | if __name__ == '__main__': 313 | cong = NetworkConfig 314 | net = Network(cong) 315 | # s = net.state_first() -------------------------------------------------------------------------------- /code/replay_memory.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | import shelve 3 | from utils import * 4 | import numpy as np 5 | import os 6 | import time as t 7 | 8 | from config import * 9 | 10 | class ReplayMemory: 11 | def __init__(self, config): 12 | self.memory_size = config.memory_size 13 | self.width = config.width 14 | self.heigth = config.heigth 15 | self.length = config.length 16 | self.batch_size = config.batch_size # 32 17 | # lin1307 18 | # 这是一个有限度的存储 19 | if not (self.is_empty()): # is_empty()是空的,返回true 20 | self.actions, self.screens, self.rewards, self.count, self.current = self.load() 21 | else: 22 | self.actions = np.empty((self.memory_size, config.action_rows, config.action_cols), 23 | dtype=np.float32) # .shape[8000, 3, 4] 24 | self.rewards = np.empty((self.memory_size, config.reward_size), 25 | dtype=np.float32) # .shape[8000, 1] 26 | self.screens = np.empty((self.memory_size, self.heigth, self.width), 27 | dtype=np.float32) # [8000, 1, 4] 28 | # print(self.screens.shape) 29 | # screens.shape = (8000, 1, 50, 1) 30 | # kkw 31 | self.count = 0 # 这个count用来跟current比较,判断是否存储器存储满了 32 | self.current = 0 # 在存储器中的顺序,有点像指针,只能是1—8000 33 | 34 | self.current_states = np.empty((self.batch_size, self.heigth, self.width), 35 | dtype=np.float64) # (32,1,4) 36 | self.next_states = np.empty((self.batch_size, self.heigth, self.width), 37 | dtype=np.float64) # (32,1,4) 38 | 39 | def add(self, screen, reward, action): # self.memory.add(s_t, reward, power) 40 | self.actions[self.current, ...] = action 41 | # print(action) 42 | # kkw 43 | self.screens[self.current, ...] = screen # s_t 44 | self.rewards[self.current, ...] = reward 45 | self.count = max(self.count, self.current + 1) 46 | # print(self.count) 47 | self.current = (self.current + 1) % self.memory_size 48 | # 保存的都是actions,screens,rewards 49 | 50 | def sample(self): # 从存储器里随机抽取 self.current_states, actions, reward, self.next_states 51 | indexes = [] 52 | # print(len(indexes)) 53 | # jjlin 54 | while len(indexes) < self.batch_size: 55 | # print(self.count) 56 | # jjlin 57 | if self.count > self.current + 1: # 说明memory_size已经满了,current重新计数了 58 | index = np.random.randint(1, self.memory_size) # 在整个满的memory_size随机抽取 59 | else: 60 | index = np.random.randint(1, self.current) # 在已存储的记忆里(记忆没满)随机抽取 61 | 62 | self.current_states[len(indexes), ...] = self.screens[index - 1, ...] 63 | self.next_states[len(indexes), ...] = self.screens[index, ...] 64 | indexes.append(index) 65 | # 以上的意思是随机抽取batch_size个记忆,并赋给current_states和next_states 66 | 67 | actions = self.actions[indexes, :] 68 | reward = self.rewards[indexes] 69 | return self.current_states, actions, reward, self.next_states 70 | 71 | # 将数据保存到硬盘 72 | def save(self): 73 | print('\n [*]Data saving...') 74 | tim = str(int(t.time())) 75 | # kkw 76 | filenames = os.listdir(Tools.memory_data) 77 | if len(filenames) != 0: 78 | for data in filenames: 79 | os.remove(Tools.memory_data + '/' + data) 80 | try: 81 | datas = shelve.open(Tools.memory_data + '/' + tim + '_.db', writeback=True, flag='c') 82 | # kkw 83 | datas['actions'] = self.actions 84 | datas['screens'] = self.screens 85 | datas['rewards'] = self.rewards 86 | datas['count'] = self.count 87 | datas['current'] = self.current 88 | print('[>^<]Data save SUCCESS') 89 | except KeyError: 90 | print('[!]Data save FAILED!!!') 91 | finally: 92 | datas.close() 93 | # kkw 94 | 95 | def is_empty(self): 96 | # jjlin 97 | filenames1 = os.listdir(Tools.memory_data) # Tools.memory_data为地址 98 | # kkw 99 | # jjlin 100 | # print(len(filenames1)) 101 | # print(filenames1) 102 | # kkw 103 | if len(filenames1) == 0: 104 | print('\n[!]There no data!!!') 105 | # kkw 106 | return True 107 | # kkw 108 | print('\n[>^<]There have data') 109 | return False 110 | 111 | def load(self): # 从已存储的数据中恢复出来 112 | try: 113 | datas = os.listdir(Tools.memory_data) # 返回指定文件列表 114 | tim = [] 115 | 116 | for i in range(len(datas)): # i代表文件的个数 117 | tim.append(int(datas[i].split('_')[0])) 118 | '''加载最新的数据''' 119 | datas = shelve.open(Tools.memory_data + '/' + str(np.max(tim)) + '_.db', writeback=True, 120 | flag='c') # writeback=true可以随时修改存储 121 | actions = datas['actions'] 122 | screens = datas['screens'] 123 | rewards = datas['rewards'] 124 | count = datas['count'] 125 | current = datas['current'] 126 | print('\n[>^<]Data load success') 127 | return actions, screens, rewards, count, current 128 | except KeyError: 129 | print('\n[!]Data load FAILED!!!') 130 | finally: 131 | datas.close() 132 | 133 | -------------------------------------------------------------------------------- /code/static.py: -------------------------------------------------------------------------------- 1 | from ran import * 2 | from DeepQNetwork import * 3 | from Test import test 4 | 5 | import copy 6 | import os 7 | import numpy as np 8 | np.random.seed(0) 9 | #from Test import test 10 | from Plot import plot 11 | lowerbound = 0.1 12 | upperbound = 0.9 13 | cs1 = 200 #eMBB latency limit 14 | cs2 = 10 #URLLC l.. l.. 15 | num = 50 # total users 16 | sep = 25 # embb users' number 17 | alpha = 0 18 | rate_limit = 3e5 19 | 20 | 21 | if __name__ == '__main__': 22 | #各切片E2E时延约束集合 23 | t = [cs1]*sep + [cs2]*(num-sep) 24 | t = np.array(t) 25 | ratio1 = 0.5 26 | ratio2 = 0.5 27 | 28 | #随机或者固定比例 初始化. sla代表端到端时延约束分配给ran的比例 29 | sla = [ratio1]*sep + [ratio2]*(num-sep) 30 | sla = np.array(sla) 31 | #sla = np.random.rand(20) 32 | #sla = np.random.randint(1,10,20)/10 33 | old = copy.deepcopy(sla) 34 | SLA = [] 35 | SLA.append(copy.deepcopy(sla)) 36 | print('***********第1次**********************第1次**********************第1次***********') 37 | target_net, act_net = Net(), Net() 38 | # act_net.load_state_dict(torch.load('../models/act')) 39 | # target_net.load_state_dict(torch.load('../models/target')) 40 | l1, r,ssl =rlRan(sla, target_net, act_net, 100) #0.001的学习率,300个episode得到一个接近最终的结果 41 | #np.savetxt('r__.csv', r, fmt="%.6f", delimiter=',') 42 | 43 | 44 | e_ran,e_cn = 0,0 #embb ran/cn accessed 45 | u_ran,u_cn = 0,0 #urllc ran/cn accessed 46 | 47 | 48 | sla2 = 1 - sla #端到端时延约束分配给cn的比例 49 | s_h = 2 50 | hlp = s_h * np.multiply(t, sla2) #时延转换成跳数 51 | sfc_hop = np.array(test(hlp)) # 52 | l2 = sfc_hop/ s_h 53 | l2[0:sep] += 20 54 | 55 | d1 = np.multiply(t, sla) - l1 # RAN时延余量 56 | d2 = np.multiply(t, sla2) - l2 # cn时延余量 57 | credit = d1 + d2 #credit 若大于某值,表示部分切片存在时延余量,存在优化资源分配的空间 58 | 59 | xi = 60 #迭代划分比例的终止条件 试探得出 60 | qoe = 0 61 | reward = 0 62 | QoE = [] 63 | Reward = [] 64 | iter = 0 65 | #两类不同的sla 66 | 67 | # while any(credit > xi): 68 | thresh = min(sep * 30, 600) 69 | #while sum(credit) > thresh: 70 | if iter == 0: 71 | qoe = 0 72 | e_ran, e_cn = 0, 0 # embb ran/cn accessed 73 | u_ran, u_cn = 0, 0 # urllc ran/cn accessed 74 | reward = 0 75 | # 计算成功连接的人数 函数的输出可以选择吗? 76 | for i in range(num): 77 | if d1[i] > 0 and d2[i] > 0: 78 | qoe += 1 79 | if i < sep: 80 | if d1[i]>0: 81 | e_ran += 1 82 | if d2[i]>0: 83 | e_cn += 1 84 | else: 85 | if d1[i]>0: 86 | u_ran += 1 87 | if d2[i]>0: 88 | u_cn += 1 89 | QoE.append(copy.deepcopy(qoe)) 90 | reward = alpha * ssl + (1 - alpha) * qoe 91 | Reward.append(copy.deepcopy(reward)) 92 | print('第', (iter + 1), '次迭代,E2E接入人数为:', qoe,'SSL:',ssl,'reward=',reward, 93 | 'eMBB切片:RAN接入',e_ran,'CN接入',e_cn,'URLLC切片:RAN接入',u_ran,'CN接入',u_cn) 94 | #np.savetxt('qoe__.csv', QoE, fmt="%.6f", delimiter=',') # 保存为2位小数的浮点数,用逗号分隔 95 | 96 | credit1 = credit[0:sep] 97 | credit2 = credit[sep:] 98 | if sum(credit1)/cs1 > sum(credit2)/cs2: 99 | ratio1 = max(ratio1 - 0.05, lowerbound) 100 | ratio2 = min(ratio2 + 0.05, upperbound) 101 | else: 102 | ratio1 = min(ratio1 + 0.05, upperbound) 103 | ratio2 = max(ratio2 - 0.05, lowerbound) 104 | iter += 1 105 | sla = [ratio1]*sep + [ratio2]*(20-sep) 106 | sla = np.array(sla) 107 | # if qoe == num or iter == 35 or (old == sla).all(): 108 | # break 109 | old = copy.deepcopy(sla) 110 | SLA.append(copy.deepcopy(sla)) 111 | # print('***********第', (iter + 1), '次***********') 112 | #print('***********第', (iter + 1), '次***********', '***********第', (iter + 1), '次***********', '***********第', 113 | # (iter + 1), '次***********') 114 | # l1, r, ssl = rlRan(sla, target_net, act_net, 200) 115 | # #np.savetxt('r___.csv', r, fmt="%.6f", delimiter=',') 116 | # 117 | # sla2 = 1 - sla 118 | # sfc_hop = np.array(test(hlp)) 119 | # l2 = sfc_hop / s_h 120 | # l2[0:sep] += 20 121 | # d1 = np.multiply(t, sla) - l1 # RAN时延余量 122 | # d2 = np.multiply(t, sla2) - l2 # cn时延余量 123 | # credit = d1 + d2# 也= t - l1 -l2 124 | # # np.savetxt('d1___.csv', d1, fmt="%.6f", delimiter=',') # 保存为整数 125 | # # np.savetxt('credit__.csv', credit, fmt="%.6f", delimiter=',') # 保存为整数 126 | # # np.savetxt('sla__.csv', SLA, fmt="%.6f", delimiter=',') # 保存为整数 127 | 128 | SLA.append(copy.deepcopy(sla)) 129 | qoe = 0 130 | # for i in range(20): 131 | # if i < 10: 132 | # if r[0][i] >= rate_limit: # rate limit 133 | # qoe += 1 134 | # elif d1[i] > 0 and d2[i] > 0: 135 | # qoe += 1 136 | #统一成时延约束后 137 | for i in range(num): 138 | if d1[i] > 0 and d2[i] > 0: 139 | qoe += 1 140 | if i < sep: 141 | if d1[i] > 0: 142 | e_ran += 1 143 | if d2[i] > 0: 144 | e_cn += 1 145 | else: 146 | if d1[i] > 0: 147 | u_ran += 1 148 | if d2[i] > 0: 149 | u_cn += 1 150 | QoE.append(copy.deepcopy(qoe)) 151 | reward = alpha * ssl + (1 - alpha) * qoe 152 | Reward.append(copy.deepcopy(reward)) 153 | #plot(QoE, len(QoE), 'QoE changes during equalization', 0, len(QoE)) 154 | 155 | #np.savetxt('ITERATIONS.csv', iter, fmt="%.6f", delimiter=',') # 保存为整数 156 | # np.savetxt('d1__.csv', d1, fmt="%.6f", delimiter=',') # 保存为整数 157 | # np.savetxt('credit__.csv', credit, fmt="%.6f", delimiter=',') # 保存为整数 158 | # np.savetxt('sla__.csv', SLA, fmt="%.6f", delimiter=',') # 保存为整数 159 | # np.savetxt('qoe__.csv', QoE, fmt="%.6f", delimiter=',') # 保存为2位小数的浮点数,用逗号分隔 160 | #print('max E2E QoE=', max(QoE), "\nbest sla:", SLA[np.argmax(QoE)]) 161 | print('max E2E QoE=', max(QoE), "\nbest sla:", SLA[np.argmax(QoE)], 'iteration:', (np.argmax(QoE) + 1), 'reward =', 162 | Reward[np.argmax(QoE)]) 163 | print('max E2E Reward=', max(Reward), "\nbest sla:", SLA[np.argmax(Reward)], 'iteration:', (np.argmax(Reward) + 1), 164 | 'QoE = ', QoE[np.argmax(Reward)]) 165 | -------------------------------------------------------------------------------- /code/utils.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | import os 3 | import numpy as np 4 | import tensorflow as tf 5 | # import matplotlib.pyplot as plt 6 | import inspect 7 | import pprint 8 | 9 | 10 | pp = pprint.PrettyPrinter().pprint 11 | 12 | 13 | class Tools: 14 | hetnet_data = 'HetNet_data' 15 | checkpoints = hetnet_data + '/checkpoints' 16 | summary = hetnet_data + '/summary' 17 | train_data = hetnet_data + '/train_data' 18 | image = hetnet_data + '/image' 19 | memory_data = hetnet_data + '/memory_data' 20 | processed_data = hetnet_data + '/processed_data' 21 | test_data = hetnet_data + '/test_data' 22 | 23 | @classmethod 24 | def create_dirs(cls): 25 | if not (os.path.exists(cls.hetnet_data)): 26 | os.mkdir(cls.hetnet_data) 27 | # jjlin 28 | if not (os.path.exists(cls.checkpoints)): 29 | os.mkdir(cls.checkpoints) 30 | if not (os.path.exists(cls.summary)): 31 | os.mkdir(cls.summary) 32 | if not (os.path.exists(cls.train_data)): 33 | os.mkdir(cls.train_data) 34 | if not (os.path.exists(cls.image)): 35 | os.mkdir(cls.image) 36 | if not (os.path.exists(cls.memory_data)): 37 | os.mkdir(cls.memory_data) 38 | if not (os.path.exists(cls.processed_data)): 39 | os.mkdir(cls.processed_data) 40 | if not (os.path.exists(cls.test_data)): 41 | os.mkdir(cls.test_data) 42 | 43 | def get_epoch_data(net): # network #epoch_data include gain and adjacent_matrix 44 | gain = net.gain #gain.shape=(400,9) 45 | gain = np.reshape(gain, [60, 60]) 46 | gain_mean = np.mean(gain) 47 | adjacent_matrix = net.adjacent_matrix 48 | adjacent_matrix = np.reshape(adjacent_matrix, [60, 60]) * gain_mean #adjacent不是0和1而是具体的数值 49 | epoch_data = np.zeros((1, 2, 60, 60)) 50 | epoch_data[0, 0] = gain 51 | epoch_data[0, 1] = adjacent_matrix 52 | epoch_data = np.transpose(epoch_data, (0, 2, 3, 1)) #(1,60,60,2)这是一个state的值 53 | return epoch_data 54 | 55 | 56 | def is_gpu_available(): 57 | is_gpu = tf.test.is_gpu_available(True) 58 | return is_gpu 59 | 60 | 61 | def get_available_gpus(): 62 | """ 63 | code from http://stackoverflow.com/questions/38559755/how-to-get-current-available-gpus-in-tensorflow 64 | """ 65 | from tensorflow.python.client import device_lib as _device_lib 66 | local_device_protos = _device_lib.list_local_devices() 67 | gpu_name = [x.name for x in local_device_protos if x.device_type == 'GPU'] 68 | return len(gpu_name) # 返回gpu的个数 69 | 70 | 71 | def set_gpu(): 72 | if is_gpu_available(): 73 | gpus = get_available_gpus() 74 | print('There are %d GPUS'%gpus) 75 | os.environ["CUDA_VISIBLE_DEVICES"] = ','.join(['{i}'.format(i=a) for a in range(gpus)]) # 对所有gpu可见 76 | config = tf.ConfigProto() 77 | config.gpu_options.per_process_gpu_memory_fraction = 0.6 # 设置GPU使用量,但是需求比较大时会自动多分配 78 | # config.gpu_options.allow_growth=True # 不全部占满显存,按需分配 79 | session = tf.InteractiveSession(config=config) 80 | return session 81 | else: 82 | print('There are no gpu! ') 83 | return tf.InteractiveSession() 84 | 85 | 86 | def class_vars(obj): #m,obj config 87 | return {k: v for k, v in inspect.getmembers(obj) #--return all the members in a list of object 88 | if not k.startswith('__') and not callable(k)} #String.StartsWith 用以检测字符串是否以指定的前缀开始 89 | 90 | 91 | def str_map_float(str_array): 92 | nums = [] 93 | for strs in str_array: 94 | nums.append(float(strs)) 95 | return nums 96 | 97 | 98 | def save_data(filepath, data): 99 | np.savetxt(filepath, data, delimiter=',') 100 | 101 | # def load_data(filepath): 102 | # np.loadtxt(filepath, delimiter=',') 103 | 104 | 105 | # def get_random_action(net): 106 | # number = [] 107 | # mbs_number = np.random.randint(20, 40, size=1) 108 | # pbs_number = np.random.randint(10, 20, size=4) 109 | # fbs_number = np.random.randint(5, 10, size=4) 110 | # number += (list(mbs_number)) 111 | # number += (list(pbs_number)) 112 | # number += (list(fbs_number)) 113 | # number = np.floor(number / np.sum(number) * net.UE_num) 114 | # if np.sum(number) == net.UE_num: 115 | # return number 116 | # number[0] += int(net.UE_num - np.sum(number)) 117 | # assert np.sum(number) == net.UE_num 118 | # number = [int(num) for num in number] 119 | # return np.array(number) 120 | 121 | 122 | # def number2adjacent(net, number): 123 | # if np.sum(number) != net.UE_num: 124 | # raise Exception('用户没有完全覆盖或者用户数目不对') 125 | # adjacent_matrix = np.zeros_like(net.BS_UE_distance) 126 | # index = np.argsort(net.BS_UE_distance, axis=0) # 考虑距离进行分配是否妥当? 127 | # '''先考虑FBS的选择,后考虑PBS,再考虑MBS, 后期可以考虑添加约束条件''' 128 | # bs_user = [] 129 | # for bs in range(net.expectBS-1, -1, -1): 130 | # num = 0 131 | # while np.sum(adjacent_matrix[:, bs]) < number[bs]: 132 | # bu_temp = index[:number[bs] + num, bs] 133 | # adjacent_matrix[list(set(bu_temp).difference(set(bs_user))), bs] = 1 134 | # num += 1 135 | # bs_user = np.concatenate((bs_user, bu_temp)) 136 | # return adjacent_matrix 137 | 138 | # Tools().create_dirs() -------------------------------------------------------------------------------- /data/data_500/virtualnetworkTP2.txt: -------------------------------------------------------------------------------- 1 | This is virtual network-----0 2 | 0 2250 3 | 1 1750 4 | 2 1750 5 | 3 2250 6 | 4 2000 7 | 5 750 8 | node-link-information: 9 | from: 1 to: 0 bw: 1500.0 10 | from: 2 to: 1 bw: 1500.0 11 | from: 3 to: 2 bw: 1500.0 12 | from: 4 to: 3 bw: 2500.0 13 | from: 5 to: 4 bw: 1500.0 14 | The life time is:--- 9999 15 | This is virtual network-----1 16 | 6 250 17 | 7 750 18 | 8 1250 19 | 9 2500 20 | 10 2250 21 | 11 2500 22 | node-link-information: 23 | from: 7 to: 6 bw: 1500.0 24 | from: 8 to: 7 bw: 1500.0 25 | from: 9 to: 8 bw: 1500.0 26 | from: 10 to: 9 bw: 2500.0 27 | from: 11 to: 10 bw: 1500.0 28 | The life time is:--- 9999 29 | -------------------------------------------------------------------------------- /users_plus/DeepQNetwork.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn as nn 3 | import torch.nn.functional as F 4 | import torch.optim as optim 5 | num = 30 6 | 7 | class Net(nn.Module): 8 | def __init__(self): 9 | super(Net, self).__init__() 10 | self.fc1 = nn.Linear(num, 60) 11 | self.fc1_p = nn.Linear(60, num) 12 | self.fc1_c = nn.Linear(60, num) 13 | self.fc2_p = nn.Linear(60, num) 14 | self.fc2_c = nn.Linear(60, num) 15 | self.fc3_p = nn.Linear(60, num) 16 | self.fc3_c = nn.Linear(60, num) 17 | self.fc4_p = nn.Linear(60, num) 18 | self.fc4_c = nn.Linear(60, num) 19 | self.fc5_p = nn.Linear(60, num) 20 | self.fc5_c = nn.Linear(60, num) 21 | self.fc6_p = nn.Linear(60, num) 22 | self.fc6_c = nn.Linear(60, num) 23 | self.fc7_p = nn.Linear(60, num) 24 | self.fc7_c = nn.Linear(60, num) 25 | self.fc8_p = nn.Linear(60, num) 26 | self.fc8_c = nn.Linear(60, num) 27 | self.fc9_p = nn.Linear(60, num) 28 | self.fc9_c = nn.Linear(60, num) 29 | self.fc10_p = nn.Linear(60, num) 30 | self.fc10_c = nn.Linear(60, num) 31 | self.fc11_p = nn.Linear(60, num) 32 | self.fc11_c = nn.Linear(60, num) 33 | self.fc12_p = nn.Linear(60, num) 34 | self.fc12_c = nn.Linear(60, num) 35 | self.fc13_p = nn.Linear(60, num) 36 | self.fc13_c = nn.Linear(60, num) 37 | self.fc14_p = nn.Linear(60, num) 38 | self.fc14_c = nn.Linear(60, num) 39 | self.fc15_p = nn.Linear(60, num) 40 | self.fc15_c = nn.Linear(60, num) 41 | self.fc16_p = nn.Linear(60, num) 42 | self.fc16_c = nn.Linear(60, num) 43 | self.fc17_p = nn.Linear(60, num) 44 | self.fc17_c = nn.Linear(60, num) 45 | self.fc18_p = nn.Linear(60, num) 46 | self.fc18_c = nn.Linear(60, num) 47 | self.fc19_p = nn.Linear(60, num) 48 | self.fc19_c = nn.Linear(60, num) 49 | self.fc20_p = nn.Linear(60, num) 50 | self.fc20_c = nn.Linear(60, num) 51 | self.fc21_p = nn.Linear(60, num) 52 | self.fc21_c = nn.Linear(60, num) 53 | self.fc22_p = nn.Linear(60, num) 54 | self.fc22_c = nn.Linear(60, num) 55 | self.fc23_p = nn.Linear(60, num) 56 | self.fc23_c = nn.Linear(60, num) 57 | self.fc24_p = nn.Linear(60, num) 58 | self.fc24_c = nn.Linear(60, num) 59 | self.fc25_p = nn.Linear(60, num) 60 | self.fc25_c = nn.Linear(60, num) 61 | self.fc26_p = nn.Linear(60, num) 62 | self.fc26_c = nn.Linear(60, num) 63 | self.fc27_p = nn.Linear(60, num) 64 | self.fc27_c = nn.Linear(60, num) 65 | self.fc28_p = nn.Linear(60, num) 66 | self.fc28_c = nn.Linear(60, num) 67 | self.fc29_p = nn.Linear(60, num) 68 | self.fc29_c = nn.Linear(60, num) 69 | self.fc30_p = nn.Linear(60, num) 70 | self.fc30_c = nn.Linear(60, num) 71 | self.dropout = nn.Dropout(p=0.5) 72 | 73 | def forward(self, x): 74 | x = x.view(-1, 1, num) # 1*1*3 75 | x = F.relu(self.fc1(x)) # 1*1*180 76 | 77 | x1_p = self.dropout(F.relu(self.fc1_p(x))).view(-1,1,num) # 20 78 | x1_c = self.dropout(F.relu(self.fc1_c(x))).view(-1,1,num) # 6 79 | x2_p = self.dropout(F.relu(self.fc2_p(x))).view(-1,1,num) # 20 80 | x2_c = self.dropout(F.relu(self.fc2_c(x))).view(-1,1,num) # 6 81 | x3_p = self.dropout(F.relu(self.fc3_p(x))).view(-1,1,num) # 20 82 | x3_c = self.dropout(F.relu(self.fc3_c(x))).view(-1,1,num) # 6 83 | x4_p = self.dropout(F.relu(self.fc4_p(x))).view(-1,1,num) # 20 84 | x4_c = self.dropout(F.relu(self.fc4_c(x))).view(-1,1,num) # 6 85 | x5_p = self.dropout(F.relu(self.fc5_p(x))).view(-1,1,num) # 20 86 | x5_c = self.dropout(F.relu(self.fc5_c(x))).view(-1,1,num) # 6 87 | x6_p = self.dropout(F.relu(self.fc6_p(x))).view(-1,1,num) # 20 88 | x6_c = self.dropout(F.relu(self.fc6_c(x))).view(-1,1,num) # 6 89 | x7_p = self.dropout(F.relu(self.fc7_p(x))).view(-1,1,num) # 20 90 | x7_c = self.dropout(F.relu(self.fc7_c(x))).view(-1,1,num) # 6 91 | x8_p = self.dropout(F.relu(self.fc8_p(x))).view(-1,1,num) # 20 92 | x8_c = self.dropout(F.relu(self.fc8_c(x))).view(-1,1,num) # 6 93 | x9_p = self.dropout(F.relu(self.fc9_p(x))).view(-1,1,num) # 20 94 | x9_c = self.dropout(F.relu(self.fc9_c(x))).view(-1,1,num) # 6 95 | x10_p = self.dropout(F.relu(self.fc10_p(x))).view(-1,1,num) # 20 96 | x10_c = self.dropout(F.relu(self.fc10_c(x))).view(-1,1,num) # 6 97 | x11_p = self.dropout(F.relu(self.fc11_p(x))).view(-1,1,num) # 20 98 | x11_c = self.dropout(F.relu(self.fc11_c(x))).view(-1,1,num) # 6 99 | x12_p = self.dropout(F.relu(self.fc12_p(x))).view(-1,1,num) # 20 100 | x12_c = self.dropout(F.relu(self.fc12_c(x))).view(-1,1,num) # 6 101 | x13_p = self.dropout(F.relu(self.fc13_p(x))).view(-1,1,num) # 20 102 | x13_c = self.dropout(F.relu(self.fc13_c(x))).view(-1,1,num) # 6 103 | x14_p = self.dropout(F.relu(self.fc14_p(x))).view(-1,1,num) # 20 104 | x14_c = self.dropout(F.relu(self.fc14_c(x))).view(-1,1,num) # 6 105 | x15_p = self.dropout(F.relu(self.fc15_p(x))).view(-1,1,num) # 20 106 | x15_c = self.dropout(F.relu(self.fc15_c(x))).view(-1,1,num) # 6 107 | x16_p = self.dropout(F.relu(self.fc16_p(x))).view(-1,1,num) # 20 108 | x16_c = self.dropout(F.relu(self.fc16_c(x))).view(-1,1,num) # 6 109 | x17_p = self.dropout(F.relu(self.fc17_p(x))).view(-1,1,num) # 20 110 | x17_c = self.dropout(F.relu(self.fc17_c(x))).view(-1,1,num) # 6 111 | x18_p = self.dropout(F.relu(self.fc18_p(x))).view(-1,1,num) # 20 112 | x18_c = self.dropout(F.relu(self.fc18_c(x))).view(-1,1,num) # 6 113 | x19_p = self.dropout(F.relu(self.fc19_p(x))).view(-1,1,num) # 20 114 | x19_c = self.dropout(F.relu(self.fc19_c(x))).view(-1,1,num) # 6 115 | x20_p = self.dropout(F.relu(self.fc20_p(x))).view(-1,1,num) # 20 116 | x20_c = self.dropout(F.relu(self.fc20_c(x))).view(-1,1,num) # 6 117 | x21_p = self.dropout(F.relu(self.fc21_p(x))).view(-1, 1, num) # 20 118 | x21_c = self.dropout(F.relu(self.fc21_c(x))).view(-1, 1, num) # 6 119 | x22_p = self.dropout(F.relu(self.fc22_p(x))).view(-1, 1, num) # 20 120 | x22_c = self.dropout(F.relu(self.fc22_c(x))).view(-1, 1, num) # 6 121 | x23_p = self.dropout(F.relu(self.fc23_p(x))).view(-1, 1, num) # 20 122 | x23_c = self.dropout(F.relu(self.fc23_c(x))).view(-1, 1, num) # 6 123 | x24_p = self.dropout(F.relu(self.fc24_p(x))).view(-1, 1, num) # 20 124 | x24_c = self.dropout(F.relu(self.fc24_c(x))).view(-1, 1, num) # 6 125 | x25_p = self.dropout(F.relu(self.fc25_p(x))).view(-1, 1, num) # 20 126 | x25_c = self.dropout(F.relu(self.fc25_c(x))).view(-1, 1, num) # 6 127 | x26_p = self.dropout(F.relu(self.fc26_p(x))).view(-1, 1, num) # 20 128 | x26_c = self.dropout(F.relu(self.fc26_c(x))).view(-1, 1, num) # 6 129 | x27_p = self.dropout(F.relu(self.fc27_p(x))).view(-1, 1, num) # 20 130 | x27_c = self.dropout(F.relu(self.fc27_c(x))).view(-1, 1, num) # 6 131 | x28_p = self.dropout(F.relu(self.fc28_p(x))).view(-1, 1, num) # 20 132 | x28_c = self.dropout(F.relu(self.fc28_c(x))).view(-1, 1, num) # 6 133 | x29_p = self.dropout(F.relu(self.fc29_p(x))).view(-1, 1, num) # 20 134 | x29_c = self.dropout(F.relu(self.fc29_c(x))).view(-1, 1, num) # 6 135 | x30_p = self.dropout(F.relu(self.fc30_p(x))).view(-1, 1, num) # 20 136 | x30_c = self.dropout(F.relu(self.fc30_c(x))).view(-1, 1, num) # 6 137 | 138 | return x1_p,x1_c,x2_p,x2_c,x3_p,x3_c,x4_p,x4_c,x5_p,x5_c,x6_p,x6_c,x7_p,x7_c,x8_p,x8_c,x9_p,x9_c,x10_p,x10_c,\ 139 | x11_p,x11_c,x12_p,x12_c,x13_p,x13_c,x14_p,x14_c,x15_p,x15_c,x16_p,x16_c,x17_p,x17_c,x18_p,x18_c,x19_p,x19_c,x20_p,x20_c,\ 140 | x21_p, x21_c, x22_p, x22_c, x23_p, x23_c, x24_p, x24_c, x25_p, x25_c, x26_p, x26_c, x27_p, x27_c, x28_p, x28_c, x29_p, x29_c,\ 141 | x30_p, x30_c 142 | # x_c:su_c 次用户信道分配 143 | # x_p:su_p 次用户功率分配 144 | 145 | 146 | 147 | -------------------------------------------------------------------------------- /users_plus/DeepQNetwork_40.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn as nn 3 | import torch.nn.functional as F 4 | import torch.optim as optim 5 | num = 40 6 | 7 | class Net(nn.Module): 8 | def __init__(self): 9 | super(Net, self).__init__() 10 | self.fc1 = nn.Linear(num, 60) 11 | self.fc1_p = nn.Linear(60, num) 12 | self.fc1_c = nn.Linear(60, num) 13 | self.fc2_p = nn.Linear(60, num) 14 | self.fc2_c = nn.Linear(60, num) 15 | self.fc3_p = nn.Linear(60, num) 16 | self.fc3_c = nn.Linear(60, num) 17 | self.fc4_p = nn.Linear(60, num) 18 | self.fc4_c = nn.Linear(60, num) 19 | self.fc5_p = nn.Linear(60, num) 20 | self.fc5_c = nn.Linear(60, num) 21 | self.fc6_p = nn.Linear(60, num) 22 | self.fc6_c = nn.Linear(60, num) 23 | self.fc7_p = nn.Linear(60, num) 24 | self.fc7_c = nn.Linear(60, num) 25 | self.fc8_p = nn.Linear(60, num) 26 | self.fc8_c = nn.Linear(60, num) 27 | self.fc9_p = nn.Linear(60, num) 28 | self.fc9_c = nn.Linear(60, num) 29 | self.fc10_p = nn.Linear(60, num) 30 | self.fc10_c = nn.Linear(60, num) 31 | self.fc11_p = nn.Linear(60, num) 32 | self.fc11_c = nn.Linear(60, num) 33 | self.fc12_p = nn.Linear(60, num) 34 | self.fc12_c = nn.Linear(60, num) 35 | self.fc13_p = nn.Linear(60, num) 36 | self.fc13_c = nn.Linear(60, num) 37 | self.fc14_p = nn.Linear(60, num) 38 | self.fc14_c = nn.Linear(60, num) 39 | self.fc15_p = nn.Linear(60, num) 40 | self.fc15_c = nn.Linear(60, num) 41 | self.fc16_p = nn.Linear(60, num) 42 | self.fc16_c = nn.Linear(60, num) 43 | self.fc17_p = nn.Linear(60, num) 44 | self.fc17_c = nn.Linear(60, num) 45 | self.fc18_p = nn.Linear(60, num) 46 | self.fc18_c = nn.Linear(60, num) 47 | self.fc19_p = nn.Linear(60, num) 48 | self.fc19_c = nn.Linear(60, num) 49 | self.fc20_p = nn.Linear(60, num) 50 | self.fc20_c = nn.Linear(60, num) 51 | self.fc21_p = nn.Linear(60, num) 52 | self.fc21_c = nn.Linear(60, num) 53 | self.fc22_p = nn.Linear(60, num) 54 | self.fc22_c = nn.Linear(60, num) 55 | self.fc23_p = nn.Linear(60, num) 56 | self.fc23_c = nn.Linear(60, num) 57 | self.fc24_p = nn.Linear(60, num) 58 | self.fc24_c = nn.Linear(60, num) 59 | self.fc25_p = nn.Linear(60, num) 60 | self.fc25_c = nn.Linear(60, num) 61 | self.fc26_p = nn.Linear(60, num) 62 | self.fc26_c = nn.Linear(60, num) 63 | self.fc27_p = nn.Linear(60, num) 64 | self.fc27_c = nn.Linear(60, num) 65 | self.fc28_p = nn.Linear(60, num) 66 | self.fc28_c = nn.Linear(60, num) 67 | self.fc29_p = nn.Linear(60, num) 68 | self.fc29_c = nn.Linear(60, num) 69 | self.fc30_p = nn.Linear(60, num) 70 | self.fc30_c = nn.Linear(60, num) 71 | self.fc31 = nn.Linear(num, 60) 72 | self.fc31_p = nn.Linear(60, num) 73 | self.fc31_c = nn.Linear(60, num) 74 | self.fc32_p = nn.Linear(60, num) 75 | self.fc32_c = nn.Linear(60, num) 76 | self.fc33_p = nn.Linear(60, num) 77 | self.fc33_c = nn.Linear(60, num) 78 | self.fc34_p = nn.Linear(60, num) 79 | self.fc34_c = nn.Linear(60, num) 80 | self.fc35_p = nn.Linear(60, num) 81 | self.fc35_c = nn.Linear(60, num) 82 | self.fc36_p = nn.Linear(60, num) 83 | self.fc36_c = nn.Linear(60, num) 84 | self.fc37_p = nn.Linear(60, num) 85 | self.fc37_c = nn.Linear(60, num) 86 | self.fc38_p = nn.Linear(60, num) 87 | self.fc38_c = nn.Linear(60, num) 88 | self.fc39_p = nn.Linear(60, num) 89 | self.fc39_c = nn.Linear(60, num) 90 | self.fc40_p = nn.Linear(60, num) 91 | self.fc40_c = nn.Linear(60, num) 92 | self.dropout = nn.Dropout(p=0.5) 93 | 94 | def forward(self, x): 95 | x = x.view(-1, 1, num) # 1*1*3 96 | x = F.relu(self.fc1(x)) # 1*1*180 97 | 98 | x1_p = self.dropout(F.relu(self.fc1_p(x))).view(-1,1,num) # 20 99 | x1_c = self.dropout(F.relu(self.fc1_c(x))).view(-1,1,num) # 6 100 | x2_p = self.dropout(F.relu(self.fc2_p(x))).view(-1,1,num) # 20 101 | x2_c = self.dropout(F.relu(self.fc2_c(x))).view(-1,1,num) # 6 102 | x3_p = self.dropout(F.relu(self.fc3_p(x))).view(-1,1,num) # 20 103 | x3_c = self.dropout(F.relu(self.fc3_c(x))).view(-1,1,num) # 6 104 | x4_p = self.dropout(F.relu(self.fc4_p(x))).view(-1,1,num) # 20 105 | x4_c = self.dropout(F.relu(self.fc4_c(x))).view(-1,1,num) # 6 106 | x5_p = self.dropout(F.relu(self.fc5_p(x))).view(-1,1,num) # 20 107 | x5_c = self.dropout(F.relu(self.fc5_c(x))).view(-1,1,num) # 6 108 | x6_p = self.dropout(F.relu(self.fc6_p(x))).view(-1,1,num) # 20 109 | x6_c = self.dropout(F.relu(self.fc6_c(x))).view(-1,1,num) # 6 110 | x7_p = self.dropout(F.relu(self.fc7_p(x))).view(-1,1,num) # 20 111 | x7_c = self.dropout(F.relu(self.fc7_c(x))).view(-1,1,num) # 6 112 | x8_p = self.dropout(F.relu(self.fc8_p(x))).view(-1,1,num) # 20 113 | x8_c = self.dropout(F.relu(self.fc8_c(x))).view(-1,1,num) # 6 114 | x9_p = self.dropout(F.relu(self.fc9_p(x))).view(-1,1,num) # 20 115 | x9_c = self.dropout(F.relu(self.fc9_c(x))).view(-1,1,num) # 6 116 | x10_p = self.dropout(F.relu(self.fc10_p(x))).view(-1,1,num) # 20 117 | x10_c = self.dropout(F.relu(self.fc10_c(x))).view(-1,1,num) # 6 118 | x11_p = self.dropout(F.relu(self.fc11_p(x))).view(-1,1,num) # 20 119 | x11_c = self.dropout(F.relu(self.fc11_c(x))).view(-1,1,num) # 6 120 | x12_p = self.dropout(F.relu(self.fc12_p(x))).view(-1,1,num) # 20 121 | x12_c = self.dropout(F.relu(self.fc12_c(x))).view(-1,1,num) # 6 122 | x13_p = self.dropout(F.relu(self.fc13_p(x))).view(-1,1,num) # 20 123 | x13_c = self.dropout(F.relu(self.fc13_c(x))).view(-1,1,num) # 6 124 | x14_p = self.dropout(F.relu(self.fc14_p(x))).view(-1,1,num) # 20 125 | x14_c = self.dropout(F.relu(self.fc14_c(x))).view(-1,1,num) # 6 126 | x15_p = self.dropout(F.relu(self.fc15_p(x))).view(-1,1,num) # 20 127 | x15_c = self.dropout(F.relu(self.fc15_c(x))).view(-1,1,num) # 6 128 | x16_p = self.dropout(F.relu(self.fc16_p(x))).view(-1,1,num) # 20 129 | x16_c = self.dropout(F.relu(self.fc16_c(x))).view(-1,1,num) # 6 130 | x17_p = self.dropout(F.relu(self.fc17_p(x))).view(-1,1,num) # 20 131 | x17_c = self.dropout(F.relu(self.fc17_c(x))).view(-1,1,num) # 6 132 | x18_p = self.dropout(F.relu(self.fc18_p(x))).view(-1,1,num) # 20 133 | x18_c = self.dropout(F.relu(self.fc18_c(x))).view(-1,1,num) # 6 134 | x19_p = self.dropout(F.relu(self.fc19_p(x))).view(-1,1,num) # 20 135 | x19_c = self.dropout(F.relu(self.fc19_c(x))).view(-1,1,num) # 6 136 | x20_p = self.dropout(F.relu(self.fc20_p(x))).view(-1,1,num) # 20 137 | x20_c = self.dropout(F.relu(self.fc20_c(x))).view(-1,1,num) # 6 138 | x21_p = self.dropout(F.relu(self.fc21_p(x))).view(-1, 1, num) # 20 139 | x21_c = self.dropout(F.relu(self.fc21_c(x))).view(-1, 1, num) # 6 140 | x22_p = self.dropout(F.relu(self.fc22_p(x))).view(-1, 1, num) # 20 141 | x22_c = self.dropout(F.relu(self.fc22_c(x))).view(-1, 1, num) # 6 142 | x23_p = self.dropout(F.relu(self.fc23_p(x))).view(-1, 1, num) # 20 143 | x23_c = self.dropout(F.relu(self.fc23_c(x))).view(-1, 1, num) # 6 144 | x24_p = self.dropout(F.relu(self.fc24_p(x))).view(-1, 1, num) # 20 145 | x24_c = self.dropout(F.relu(self.fc24_c(x))).view(-1, 1, num) # 6 146 | x25_p = self.dropout(F.relu(self.fc25_p(x))).view(-1, 1, num) # 20 147 | x25_c = self.dropout(F.relu(self.fc25_c(x))).view(-1, 1, num) # 6 148 | x26_p = self.dropout(F.relu(self.fc26_p(x))).view(-1, 1, num) # 20 149 | x26_c = self.dropout(F.relu(self.fc26_c(x))).view(-1, 1, num) # 6 150 | x27_p = self.dropout(F.relu(self.fc7_p(x))).view(-1, 1, num) # 20 151 | x27_c = self.dropout(F.relu(self.fc27_c(x))).view(-1, 1, num) # 6 152 | x28_p = self.dropout(F.relu(self.fc28_p(x))).view(-1, 1, num) # 20 153 | x28_c = self.dropout(F.relu(self.fc28_c(x))).view(-1, 1, num) # 6 154 | x29_p = self.dropout(F.relu(self.fc29_p(x))).view(-1, 1, num) # 20 155 | x29_c = self.dropout(F.relu(self.fc29_c(x))).view(-1, 1, num) # 6 156 | x30_p = self.dropout(F.relu(self.fc30_p(x))).view(-1, 1, num) # 20 157 | x30_c = self.dropout(F.relu(self.fc30_c(x))).view(-1, 1, num) # 6 158 | x31_p = self.dropout(F.relu(self.fc31_p(x))).view(-1, 1, num) # 20 159 | x31_c = self.dropout(F.relu(self.fc31_c(x))).view(-1, 1, num) # 6 160 | x32_p = self.dropout(F.relu(self.fc32_p(x))).view(-1, 1, num) # 20 161 | x32_c = self.dropout(F.relu(self.fc32_c(x))).view(-1, 1, num) # 6 162 | x33_p = self.dropout(F.relu(self.fc33_p(x))).view(-1, 1, num) # 20 163 | x33_c = self.dropout(F.relu(self.fc33_c(x))).view(-1, 1, num) # 6 164 | x34_p = self.dropout(F.relu(self.fc34_p(x))).view(-1, 1, num) # 20 165 | x34_c = self.dropout(F.relu(self.fc34_c(x))).view(-1, 1, num) # 6 166 | x35_p = self.dropout(F.relu(self.fc35_p(x))).view(-1, 1, num) # 20 167 | x35_c = self.dropout(F.relu(self.fc35_c(x))).view(-1, 1, num) # 6 168 | x36_p = self.dropout(F.relu(self.fc36_p(x))).view(-1, 1, num) # 20 169 | x36_c = self.dropout(F.relu(self.fc36_c(x))).view(-1, 1, num) # 6 170 | x37_p = self.dropout(F.relu(self.fc37_p(x))).view(-1, 1, num) # 20 171 | x37_c = self.dropout(F.relu(self.fc37_c(x))).view(-1, 1, num) # 6 172 | x38_p = self.dropout(F.relu(self.fc38_p(x))).view(-1, 1, num) # 20 173 | x38_c = self.dropout(F.relu(self.fc38_c(x))).view(-1, 1, num) # 6 174 | x39_p = self.dropout(F.relu(self.fc39_p(x))).view(-1, 1, num) # 20 175 | x39_c = self.dropout(F.relu(self.fc39_c(x))).view(-1, 1, num) # 6 176 | x40_p = self.dropout(F.relu(self.fc40_p(x))).view(-1, 1, num) # 20 177 | x40_c = self.dropout(F.relu(self.fc40_c(x))).view(-1, 1, num) # 6 178 | 179 | return x1_p,x1_c,x2_p,x2_c,x3_p,x3_c,x4_p,x4_c,x5_p,x5_c,x6_p,x6_c,x7_p,x7_c,x8_p,x8_c,x9_p,x9_c,x10_p,x10_c,\ 180 | x11_p,x11_c,x12_p,x12_c,x13_p,x13_c,x14_p,x14_c,x15_p,x15_c,x16_p,x16_c,x17_p,x17_c,x18_p,x18_c,x19_p,x19_c,x20_p,x20_c,\ 181 | x21_p, x21_c, x22_p, x22_c, x23_p, x23_c, x24_p, x24_c, x25_p, x25_c, x26_p, x26_c, x27_p, x27_c, x28_p, x28_c, x29_p, x29_c,\ 182 | x30_p, x30_c,x31_p,x31_c,x32_p,x32_c,x33_p,x33_c,x34_p,x34_c,x35_p,x35_c,x36_p,x36_c,x37_p,x37_c,x38_p,x38_c,x39_p,x39_c,x40_p,x40_c 183 | # x_c:su_c 次用户信道分配 184 | # x_p:su_p 次用户功率分配 185 | 186 | 187 | 188 | 189 | 190 | -------------------------------------------------------------------------------- /users_plus/DeepQNetwork_50.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn as nn 3 | import torch.nn.functional as F 4 | import torch.optim as optim 5 | num = 50 6 | 7 | class Net(nn.Module): 8 | def __init__(self): 9 | super(Net, self).__init__() 10 | self.fc1 = nn.Linear(num, 60) 11 | self.fc1_p = nn.Linear(60, num) 12 | self.fc1_c = nn.Linear(60, num) 13 | self.fc2_p = nn.Linear(60, num) 14 | self.fc2_c = nn.Linear(60, num) 15 | self.fc3_p = nn.Linear(60, num) 16 | self.fc3_c = nn.Linear(60, num) 17 | self.fc4_p = nn.Linear(60, num) 18 | self.fc4_c = nn.Linear(60, num) 19 | self.fc5_p = nn.Linear(60, num) 20 | self.fc5_c = nn.Linear(60, num) 21 | self.fc6_p = nn.Linear(60, num) 22 | self.fc6_c = nn.Linear(60, num) 23 | self.fc7_p = nn.Linear(60, num) 24 | self.fc7_c = nn.Linear(60, num) 25 | self.fc8_p = nn.Linear(60, num) 26 | self.fc8_c = nn.Linear(60, num) 27 | self.fc9_p = nn.Linear(60, num) 28 | self.fc9_c = nn.Linear(60, num) 29 | self.fc10_p = nn.Linear(60, num) 30 | self.fc10_c = nn.Linear(60, num) 31 | self.fc11_p = nn.Linear(60, num) 32 | self.fc11_c = nn.Linear(60, num) 33 | self.fc12_p = nn.Linear(60, num) 34 | self.fc12_c = nn.Linear(60, num) 35 | self.fc13_p = nn.Linear(60, num) 36 | self.fc13_c = nn.Linear(60, num) 37 | self.fc14_p = nn.Linear(60, num) 38 | self.fc14_c = nn.Linear(60, num) 39 | self.fc15_p = nn.Linear(60, num) 40 | self.fc15_c = nn.Linear(60, num) 41 | self.fc16_p = nn.Linear(60, num) 42 | self.fc16_c = nn.Linear(60, num) 43 | self.fc17_p = nn.Linear(60, num) 44 | self.fc17_c = nn.Linear(60, num) 45 | self.fc18_p = nn.Linear(60, num) 46 | self.fc18_c = nn.Linear(60, num) 47 | self.fc19_p = nn.Linear(60, num) 48 | self.fc19_c = nn.Linear(60, num) 49 | self.fc20_p = nn.Linear(60, num) 50 | self.fc20_c = nn.Linear(60, num) 51 | self.fc21_p = nn.Linear(60, num) 52 | self.fc21_c = nn.Linear(60, num) 53 | self.fc22_p = nn.Linear(60, num) 54 | self.fc22_c = nn.Linear(60, num) 55 | self.fc23_p = nn.Linear(60, num) 56 | self.fc23_c = nn.Linear(60, num) 57 | self.fc24_p = nn.Linear(60, num) 58 | self.fc24_c = nn.Linear(60, num) 59 | self.fc25_p = nn.Linear(60, num) 60 | self.fc25_c = nn.Linear(60, num) 61 | self.fc26_p = nn.Linear(60, num) 62 | self.fc26_c = nn.Linear(60, num) 63 | self.fc27_p = nn.Linear(60, num) 64 | self.fc27_c = nn.Linear(60, num) 65 | self.fc28_p = nn.Linear(60, num) 66 | self.fc28_c = nn.Linear(60, num) 67 | self.fc29_p = nn.Linear(60, num) 68 | self.fc29_c = nn.Linear(60, num) 69 | self.fc30_p = nn.Linear(60, num) 70 | self.fc30_c = nn.Linear(60, num) 71 | self.fc31 = nn.Linear(num, 60) 72 | self.fc31_p = nn.Linear(60, num) 73 | self.fc31_c = nn.Linear(60, num) 74 | self.fc32_p = nn.Linear(60, num) 75 | self.fc32_c = nn.Linear(60, num) 76 | self.fc33_p = nn.Linear(60, num) 77 | self.fc33_c = nn.Linear(60, num) 78 | self.fc34_p = nn.Linear(60, num) 79 | self.fc34_c = nn.Linear(60, num) 80 | self.fc35_p = nn.Linear(60, num) 81 | self.fc35_c = nn.Linear(60, num) 82 | self.fc36_p = nn.Linear(60, num) 83 | self.fc36_c = nn.Linear(60, num) 84 | self.fc37_p = nn.Linear(60, num) 85 | self.fc37_c = nn.Linear(60, num) 86 | self.fc38_p = nn.Linear(60, num) 87 | self.fc38_c = nn.Linear(60, num) 88 | self.fc39_p = nn.Linear(60, num) 89 | self.fc39_c = nn.Linear(60, num) 90 | self.fc40_p = nn.Linear(60, num) 91 | self.fc40_c = nn.Linear(60, num) 92 | self.fc41 = nn.Linear(num, 60) 93 | self.fc41_p = nn.Linear(60, num) 94 | self.fc41_c = nn.Linear(60, num) 95 | self.fc42_p = nn.Linear(60, num) 96 | self.fc42_c = nn.Linear(60, num) 97 | self.fc43_p = nn.Linear(60, num) 98 | self.fc43_c = nn.Linear(60, num) 99 | self.fc44_p = nn.Linear(60, num) 100 | self.fc44_c = nn.Linear(60, num) 101 | self.fc45_p = nn.Linear(60, num) 102 | self.fc45_c = nn.Linear(60, num) 103 | self.fc46_p = nn.Linear(60, num) 104 | self.fc46_c = nn.Linear(60, num) 105 | self.fc47_p = nn.Linear(60, num) 106 | self.fc47_c = nn.Linear(60, num) 107 | self.fc48_p = nn.Linear(60, num) 108 | self.fc48_c = nn.Linear(60, num) 109 | self.fc49_p = nn.Linear(60, num) 110 | self.fc49_c = nn.Linear(60, num) 111 | self.fc50_p = nn.Linear(60, num) 112 | self.fc50_c = nn.Linear(60, num) 113 | self.dropout = nn.Dropout(p=0.5) 114 | 115 | def forward(self, x): 116 | x = x.view(-1, 1, num) # 1*1*3 117 | x = F.relu(self.fc1(x)) # 1*1*180 118 | 119 | x1_p = self.dropout(F.relu(self.fc1_p(x))).view(-1,1,num) # 20 120 | x1_c = self.dropout(F.relu(self.fc1_c(x))).view(-1,1,num) # 6 121 | x2_p = self.dropout(F.relu(self.fc2_p(x))).view(-1,1,num) # 20 122 | x2_c = self.dropout(F.relu(self.fc2_c(x))).view(-1,1,num) # 6 123 | x3_p = self.dropout(F.relu(self.fc3_p(x))).view(-1,1,num) # 20 124 | x3_c = self.dropout(F.relu(self.fc3_c(x))).view(-1,1,num) # 6 125 | x4_p = self.dropout(F.relu(self.fc4_p(x))).view(-1,1,num) # 20 126 | x4_c = self.dropout(F.relu(self.fc4_c(x))).view(-1,1,num) # 6 127 | x5_p = self.dropout(F.relu(self.fc5_p(x))).view(-1,1,num) # 20 128 | x5_c = self.dropout(F.relu(self.fc5_c(x))).view(-1,1,num) # 6 129 | x6_p = self.dropout(F.relu(self.fc6_p(x))).view(-1,1,num) # 20 130 | x6_c = self.dropout(F.relu(self.fc6_c(x))).view(-1,1,num) # 6 131 | x7_p = self.dropout(F.relu(self.fc7_p(x))).view(-1,1,num) # 20 132 | x7_c = self.dropout(F.relu(self.fc7_c(x))).view(-1,1,num) # 6 133 | x8_p = self.dropout(F.relu(self.fc8_p(x))).view(-1,1,num) # 20 134 | x8_c = self.dropout(F.relu(self.fc8_c(x))).view(-1,1,num) # 6 135 | x9_p = self.dropout(F.relu(self.fc9_p(x))).view(-1,1,num) # 20 136 | x9_c = self.dropout(F.relu(self.fc9_c(x))).view(-1,1,num) # 6 137 | x10_p = self.dropout(F.relu(self.fc10_p(x))).view(-1,1,num) # 20 138 | x10_c = self.dropout(F.relu(self.fc10_c(x))).view(-1,1,num) # 6 139 | x11_p = self.dropout(F.relu(self.fc11_p(x))).view(-1,1,num) # 20 140 | x11_c = self.dropout(F.relu(self.fc11_c(x))).view(-1,1,num) # 6 141 | x12_p = self.dropout(F.relu(self.fc12_p(x))).view(-1,1,num) # 20 142 | x12_c = self.dropout(F.relu(self.fc12_c(x))).view(-1,1,num) # 6 143 | x13_p = self.dropout(F.relu(self.fc13_p(x))).view(-1,1,num) # 20 144 | x13_c = self.dropout(F.relu(self.fc13_c(x))).view(-1,1,num) # 6 145 | x14_p = self.dropout(F.relu(self.fc14_p(x))).view(-1,1,num) # 20 146 | x14_c = self.dropout(F.relu(self.fc14_c(x))).view(-1,1,num) # 6 147 | x15_p = self.dropout(F.relu(self.fc15_p(x))).view(-1,1,num) # 20 148 | x15_c = self.dropout(F.relu(self.fc15_c(x))).view(-1,1,num) # 6 149 | x16_p = self.dropout(F.relu(self.fc16_p(x))).view(-1,1,num) # 20 150 | x16_c = self.dropout(F.relu(self.fc16_c(x))).view(-1,1,num) # 6 151 | x17_p = self.dropout(F.relu(self.fc17_p(x))).view(-1,1,num) # 20 152 | x17_c = self.dropout(F.relu(self.fc17_c(x))).view(-1,1,num) # 6 153 | x18_p = self.dropout(F.relu(self.fc18_p(x))).view(-1,1,num) # 20 154 | x18_c = self.dropout(F.relu(self.fc18_c(x))).view(-1,1,num) # 6 155 | x19_p = self.dropout(F.relu(self.fc19_p(x))).view(-1,1,num) # 20 156 | x19_c = self.dropout(F.relu(self.fc19_c(x))).view(-1,1,num) # 6 157 | x20_p = self.dropout(F.relu(self.fc20_p(x))).view(-1,1,num) # 20 158 | x20_c = self.dropout(F.relu(self.fc20_c(x))).view(-1,1,num) # 6 159 | x21_p = self.dropout(F.relu(self.fc21_p(x))).view(-1, 1, num) # 20 160 | x21_c = self.dropout(F.relu(self.fc21_c(x))).view(-1, 1, num) # 6 161 | x22_p = self.dropout(F.relu(self.fc22_p(x))).view(-1, 1, num) # 20 162 | x22_c = self.dropout(F.relu(self.fc22_c(x))).view(-1, 1, num) # 6 163 | x23_p = self.dropout(F.relu(self.fc23_p(x))).view(-1, 1, num) # 20 164 | x23_c = self.dropout(F.relu(self.fc23_c(x))).view(-1, 1, num) # 6 165 | x24_p = self.dropout(F.relu(self.fc24_p(x))).view(-1, 1, num) # 20 166 | x24_c = self.dropout(F.relu(self.fc24_c(x))).view(-1, 1, num) # 6 167 | x25_p = self.dropout(F.relu(self.fc25_p(x))).view(-1, 1, num) # 20 168 | x25_c = self.dropout(F.relu(self.fc25_c(x))).view(-1, 1, num) # 6 169 | x26_p = self.dropout(F.relu(self.fc26_p(x))).view(-1, 1, num) # 20 170 | x26_c = self.dropout(F.relu(self.fc26_c(x))).view(-1, 1, num) # 6 171 | x27_p = self.dropout(F.relu(self.fc7_p(x))).view(-1, 1, num) # 20 172 | x27_c = self.dropout(F.relu(self.fc27_c(x))).view(-1, 1, num) # 6 173 | x28_p = self.dropout(F.relu(self.fc28_p(x))).view(-1, 1, num) # 20 174 | x28_c = self.dropout(F.relu(self.fc28_c(x))).view(-1, 1, num) # 6 175 | x29_p = self.dropout(F.relu(self.fc29_p(x))).view(-1, 1, num) # 20 176 | x29_c = self.dropout(F.relu(self.fc29_c(x))).view(-1, 1, num) # 6 177 | x30_p = self.dropout(F.relu(self.fc30_p(x))).view(-1, 1, num) # 20 178 | x30_c = self.dropout(F.relu(self.fc30_c(x))).view(-1, 1, num) # 6 179 | x31_p = self.dropout(F.relu(self.fc31_p(x))).view(-1, 1, num) # 20 180 | x31_c = self.dropout(F.relu(self.fc31_c(x))).view(-1, 1, num) # 6 181 | x32_p = self.dropout(F.relu(self.fc32_p(x))).view(-1, 1, num) # 20 182 | x32_c = self.dropout(F.relu(self.fc32_c(x))).view(-1, 1, num) # 6 183 | x33_p = self.dropout(F.relu(self.fc33_p(x))).view(-1, 1, num) # 20 184 | x33_c = self.dropout(F.relu(self.fc33_c(x))).view(-1, 1, num) # 6 185 | x34_p = self.dropout(F.relu(self.fc34_p(x))).view(-1, 1, num) # 20 186 | x34_c = self.dropout(F.relu(self.fc34_c(x))).view(-1, 1, num) # 6 187 | x35_p = self.dropout(F.relu(self.fc35_p(x))).view(-1, 1, num) # 20 188 | x35_c = self.dropout(F.relu(self.fc35_c(x))).view(-1, 1, num) # 6 189 | x36_p = self.dropout(F.relu(self.fc36_p(x))).view(-1, 1, num) # 20 190 | x36_c = self.dropout(F.relu(self.fc36_c(x))).view(-1, 1, num) # 6 191 | x37_p = self.dropout(F.relu(self.fc37_p(x))).view(-1, 1, num) # 20 192 | x37_c = self.dropout(F.relu(self.fc37_c(x))).view(-1, 1, num) # 6 193 | x38_p = self.dropout(F.relu(self.fc38_p(x))).view(-1, 1, num) # 20 194 | x38_c = self.dropout(F.relu(self.fc38_c(x))).view(-1, 1, num) # 6 195 | x39_p = self.dropout(F.relu(self.fc39_p(x))).view(-1, 1, num) # 20 196 | x39_c = self.dropout(F.relu(self.fc39_c(x))).view(-1, 1, num) # 6 197 | x40_p = self.dropout(F.relu(self.fc40_p(x))).view(-1, 1, num) # 20 198 | x40_c = self.dropout(F.relu(self.fc40_c(x))).view(-1, 1, num) # 6 199 | x41_p = self.dropout(F.relu(self.fc41_p(x))).view(-1, 1, num) # 20 200 | x41_c = self.dropout(F.relu(self.fc41_c(x))).view(-1, 1, num) # 6 201 | x42_p = self.dropout(F.relu(self.fc42_p(x))).view(-1, 1, num) # 20 202 | x42_c = self.dropout(F.relu(self.fc42_c(x))).view(-1, 1, num) # 6 203 | x43_p = self.dropout(F.relu(self.fc43_p(x))).view(-1, 1, num) # 20 204 | x43_c = self.dropout(F.relu(self.fc43_c(x))).view(-1, 1, num) # 6 205 | x44_p = self.dropout(F.relu(self.fc44_p(x))).view(-1, 1, num) # 20 206 | x44_c = self.dropout(F.relu(self.fc44_c(x))).view(-1, 1, num) # 6 207 | x45_p = self.dropout(F.relu(self.fc45_p(x))).view(-1, 1, num) # 20 208 | x45_c = self.dropout(F.relu(self.fc45_c(x))).view(-1, 1, num) # 6 209 | x46_p = self.dropout(F.relu(self.fc46_p(x))).view(-1, 1, num) # 20 210 | x46_c = self.dropout(F.relu(self.fc46_c(x))).view(-1, 1, num) # 6 211 | x47_p = self.dropout(F.relu(self.fc47_p(x))).view(-1, 1, num) # 20 212 | x47_c = self.dropout(F.relu(self.fc47_c(x))).view(-1, 1, num) # 6 213 | x48_p = self.dropout(F.relu(self.fc48_p(x))).view(-1, 1, num) # 20 214 | x48_c = self.dropout(F.relu(self.fc48_c(x))).view(-1, 1, num) # 6 215 | x49_p = self.dropout(F.relu(self.fc49_p(x))).view(-1, 1, num) # 20 216 | x49_c = self.dropout(F.relu(self.fc49_c(x))).view(-1, 1, num) # 6 217 | x50_p = self.dropout(F.relu(self.fc50_p(x))).view(-1, 1, num) # 20 218 | x50_c = self.dropout(F.relu(self.fc50_c(x))).view(-1, 1, num) # 6 219 | 220 | return x1_p,x1_c,x2_p,x2_c,x3_p,x3_c,x4_p,x4_c,x5_p,x5_c,x6_p,x6_c,x7_p,x7_c,x8_p,x8_c,x9_p,x9_c,x10_p,x10_c,\ 221 | x11_p,x11_c,x12_p,x12_c,x13_p,x13_c,x14_p,x14_c,x15_p,x15_c,x16_p,x16_c,x17_p,x17_c,x18_p,x18_c,x19_p,x19_c,x20_p,x20_c,\ 222 | x21_p, x21_c, x22_p, x22_c, x23_p, x23_c, x24_p, x24_c, x25_p, x25_c, x26_p, x26_c, x27_p, x27_c, x28_p, x28_c, x29_p, x29_c,\ 223 | x30_p, x30_c,x31_p,x31_c,x32_p,x32_c,x33_p,x33_c,x34_p,x34_c,x35_p,x35_c,x36_p,x36_c,x37_p,x37_c,x38_p,x38_c,x39_p,x39_c,x40_p,x40_c,x41_p, x41_c, x42_p, x42_c, x43_p, x43_c, x44_p, x44_c, x45_p, x45_c, x46_p, x46_c, x47_p, x47_c, x48_p, x48_c, x49_p, x49_c, x50_p, x50_c 224 | # x_c:su_c 次用户信道分配 225 | # x_p:su_p 次用户功率分配 226 | 227 | 228 | 229 | 230 | -------------------------------------------------------------------------------- /users_plus/HetNet_data/checkpoints/新建文本文档.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moooontoo/Latency-Equalization-E2E-NS-RL/2ec08851631b8a9da8d662ca7c8df9844b6bbeb7/users_plus/HetNet_data/checkpoints/新建文本文档.txt -------------------------------------------------------------------------------- /users_plus/HetNet_data/image/新建文本文档.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moooontoo/Latency-Equalization-E2E-NS-RL/2ec08851631b8a9da8d662ca7c8df9844b6bbeb7/users_plus/HetNet_data/image/新建文本文档.txt -------------------------------------------------------------------------------- /users_plus/HetNet_data/memory_data/新建文本文档.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moooontoo/Latency-Equalization-E2E-NS-RL/2ec08851631b8a9da8d662ca7c8df9844b6bbeb7/users_plus/HetNet_data/memory_data/新建文本文档.txt -------------------------------------------------------------------------------- /users_plus/HetNet_data/processed_data/新建文本文档.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moooontoo/Latency-Equalization-E2E-NS-RL/2ec08851631b8a9da8d662ca7c8df9844b6bbeb7/users_plus/HetNet_data/processed_data/新建文本文档.txt -------------------------------------------------------------------------------- /users_plus/HetNet_data/summary/新建文本文档.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moooontoo/Latency-Equalization-E2E-NS-RL/2ec08851631b8a9da8d662ca7c8df9844b6bbeb7/users_plus/HetNet_data/summary/新建文本文档.txt -------------------------------------------------------------------------------- /users_plus/HetNet_data/test_data/新建文本文档.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moooontoo/Latency-Equalization-E2E-NS-RL/2ec08851631b8a9da8d662ca7c8df9844b6bbeb7/users_plus/HetNet_data/test_data/新建文本文档.txt -------------------------------------------------------------------------------- /users_plus/HetNet_data/train_data/新建文本文档.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moooontoo/Latency-Equalization-E2E-NS-RL/2ec08851631b8a9da8d662ca7c8df9844b6bbeb7/users_plus/HetNet_data/train_data/新建文本文档.txt -------------------------------------------------------------------------------- /users_plus/__pycache__/DeepQNetwork.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moooontoo/Latency-Equalization-E2E-NS-RL/2ec08851631b8a9da8d662ca7c8df9844b6bbeb7/users_plus/__pycache__/DeepQNetwork.cpython-38.pyc -------------------------------------------------------------------------------- /users_plus/__pycache__/config.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moooontoo/Latency-Equalization-E2E-NS-RL/2ec08851631b8a9da8d662ca7c8df9844b6bbeb7/users_plus/__pycache__/config.cpython-38.pyc -------------------------------------------------------------------------------- /users_plus/__pycache__/network.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moooontoo/Latency-Equalization-E2E-NS-RL/2ec08851631b8a9da8d662ca7c8df9844b6bbeb7/users_plus/__pycache__/network.cpython-38.pyc -------------------------------------------------------------------------------- /users_plus/__pycache__/replay_memory.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moooontoo/Latency-Equalization-E2E-NS-RL/2ec08851631b8a9da8d662ca7c8df9844b6bbeb7/users_plus/__pycache__/replay_memory.cpython-38.pyc -------------------------------------------------------------------------------- /users_plus/__pycache__/utils.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moooontoo/Latency-Equalization-E2E-NS-RL/2ec08851631b8a9da8d662ca7c8df9844b6bbeb7/users_plus/__pycache__/utils.cpython-38.pyc -------------------------------------------------------------------------------- /users_plus/config.py: -------------------------------------------------------------------------------- 1 | # capacity = 8000 2 | # learning_rate = 1e-3 3 | # memory_count = 0 4 | # batch_size = 256 5 | # gamma = 0.995 6 | # update_count = 0 7 | # coding=utf-8 8 | import numpy as np 9 | num = 30 10 | #replay_memory所需的相关参数 11 | class AgentConfig(object): 12 | kesi = 0.1 # kesi是随机选动作 13 | heigth = 1 14 | length = 1 15 | #width = 20 16 | width = num #0822 17 | # fc_out_dims = 1000 18 | 19 | # learning_rate = 0.0025 20 | # learning_rate = 3e-4 21 | LEARNING_RATE = 1e-3 22 | learning_rate_policy = 5e-3 23 | learning_rate_value = 1e-3 24 | learning_rate_q = 1e-3 25 | # learning_rate_minimum = 0.0025 26 | # learning_rate_decay = 0.96 27 | # learning_rate_decay_step = 5000 28 | # discount = 0.9 29 | max_step = 30000 # 训练次数 30 | learn_start = 1000 # 1000次之后网络开始更新 31 | train_frequency = 4 # 1000次之后每4个动作更新一下训练网络 32 | # train_step = 2000 33 | train_step = 2000 # 暂时每100次print一次 34 | test_step = 2000 # 2000次判断一下是否保存模型,然后对数据进行summary 35 | target_q_update_step = 1000 # 1000次之后,每1000次更新一下目标网络 36 | play_step = 500 # 每3000次看下模型调节能力 37 | play_times = 30 38 | 39 | batch_size = 32 40 | 41 | memory_size = 2000 42 | test_play = 500 43 | # test_produce = 44 | 45 | 46 | # action_size = 44 47 | reward_size = 1 48 | 49 | action_rows = num # 20个次用户 50 | action_cols = num # 20个信道 51 | 52 | 53 | #神经网络所需参数 54 | class NetworkConfig(object): 55 | mbs_number = 1 # macro基站数量:1 56 | sbs_number = 1 # small基站数量:1 57 | # u_number = 20 # 用户数量:20 58 | # c_num = 20 # 信道数量 59 | u_number = num # 用户数量:30 0822 60 | c_num = num # 信道数量 0822 61 | 62 | BW_sc = 180000 # 每个信道的带宽 63 | sp_max = 1 # 感知基站发射功率最大值 64 | N0 = 1.1e-22 # AWGN噪声 65 | net_size = (100, 100) # 网络尺寸 66 | reward_alpha = 0 67 | 68 | latency_limit = 10 69 | latency_limit2 = 200#0822 70 | # rate_limit = 2e5 71 | rate_limit = 3e5 72 | sep = 15 -------------------------------------------------------------------------------- /users_plus/config_40.py: -------------------------------------------------------------------------------- 1 | # capacity = 8000 2 | # learning_rate = 1e-3 3 | # memory_count = 0 4 | # batch_size = 256 5 | # gamma = 0.995 6 | # update_count = 0 7 | # coding=utf-8 8 | import numpy as np 9 | num = 40 10 | #replay_memory所需的相关参数 11 | class AgentConfig(object): 12 | kesi = 0.1 # kesi是随机选动作 13 | heigth = 1 14 | length = 1 15 | #width = 20 16 | width = num #0822 17 | # fc_out_dims = 1000 18 | 19 | # learning_rate = 0.0025 20 | # learning_rate = 3e-4 21 | LEARNING_RATE = 1e-3 22 | learning_rate_policy = 5e-3 23 | learning_rate_value = 1e-3 24 | learning_rate_q = 1e-3 25 | # learning_rate_minimum = 0.0025 26 | # learning_rate_decay = 0.96 27 | # learning_rate_decay_step = 5000 28 | # discount = 0.9 29 | max_step = 30000 # 训练次数 30 | learn_start = 1000 # 1000次之后网络开始更新 31 | train_frequency = 4 # 1000次之后每4个动作更新一下训练网络 32 | # train_step = 2000 33 | train_step = 2000 # 暂时每100次print一次 34 | test_step = 2000 # 2000次判断一下是否保存模型,然后对数据进行summary 35 | target_q_update_step = 1000 # 1000次之后,每1000次更新一下目标网络 36 | play_step = 500 # 每3000次看下模型调节能力 37 | play_times = 30 38 | 39 | batch_size = 32 40 | 41 | memory_size = 2000 42 | test_play = 500 43 | # test_produce = 44 | 45 | 46 | # action_size = 44 47 | reward_size = 1 48 | 49 | action_rows = num # 20个次用户 50 | action_cols = num # 20个信道 51 | 52 | 53 | #神经网络所需参数 54 | class NetworkConfig(object): 55 | mbs_number = 1 # macro基站数量:1 56 | sbs_number = 1 # small基站数量:1 57 | # u_number = 20 # 用户数量:20 58 | # c_num = 20 # 信道数量 59 | u_number = num # 用户数量:30 0822 60 | c_num = num # 信道数量 0822 61 | 62 | BW_sc = 180000 # 每个信道的带宽 63 | sp_max = 1 # 感知基站发射功率最大值 64 | N0 = 1.1e-22 # AWGN噪声 65 | net_size = (100, 100) # 网络尺寸 66 | reward_alpha = 0 67 | 68 | latency_limit = 10 69 | latency_limit2 = 200#0822 70 | # rate_limit = 2e5 71 | rate_limit = 3e5 72 | sep = 20 -------------------------------------------------------------------------------- /users_plus/config_50.py: -------------------------------------------------------------------------------- 1 | # capacity = 8000 2 | # learning_rate = 1e-3 3 | # memory_count = 0 4 | # batch_size = 256 5 | # gamma = 0.995 6 | # update_count = 0 7 | # coding=utf-8 8 | import numpy as np 9 | num = 50 10 | #replay_memory所需的相关参数 11 | class AgentConfig(object): 12 | kesi = 0.1 # kesi是随机选动作 13 | heigth = 1 14 | length = 1 15 | #width = 20 16 | width = num #0822 17 | # fc_out_dims = 1000 18 | 19 | # learning_rate = 0.0025 20 | # learning_rate = 3e-4 21 | LEARNING_RATE = 1e-3 22 | learning_rate_policy = 5e-3 23 | learning_rate_value = 1e-3 24 | learning_rate_q = 1e-3 25 | # learning_rate_minimum = 0.0025 26 | # learning_rate_decay = 0.96 27 | # learning_rate_decay_step = 5000 28 | # discount = 0.9 29 | max_step = 30000 # 训练次数 30 | learn_start = 1000 # 1000次之后网络开始更新 31 | train_frequency = 4 # 1000次之后每4个动作更新一下训练网络 32 | # train_step = 2000 33 | train_step = 2000 # 暂时每100次print一次 34 | test_step = 2000 # 2000次判断一下是否保存模型,然后对数据进行summary 35 | target_q_update_step = 1000 # 1000次之后,每1000次更新一下目标网络 36 | play_step = 500 # 每3000次看下模型调节能力 37 | play_times = 30 38 | 39 | batch_size = 32 40 | 41 | memory_size = 2000 42 | test_play = 500 43 | # test_produce = 44 | 45 | 46 | # action_size = 44 47 | reward_size = 1 48 | 49 | action_rows = num # 20个次用户 50 | action_cols = num # 20个信道 51 | 52 | 53 | #神经网络所需参数 54 | class NetworkConfig(object): 55 | mbs_number = 1 # macro基站数量:1 56 | sbs_number = 1 # small基站数量:1 57 | # u_number = 20 # 用户数量:20 58 | # c_num = 20 # 信道数量 59 | u_number = num # 用户数量:30 0822 60 | c_num = num # 信道数量 0822 61 | 62 | BW_sc = 180000 # 每个信道的带宽 63 | sp_max = 1 # 感知基站发射功率最大值 64 | N0 = 1.1e-22 # AWGN噪声 65 | net_size = (100, 100) # 网络尺寸 66 | reward_alpha = 0 67 | 68 | latency_limit = 10 69 | latency_limit2 = 200#0822 70 | # rate_limit = 2e5 71 | rate_limit = 3e5 72 | sep = 25 -------------------------------------------------------------------------------- /users_plus/network2.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | import numpy as np 3 | from scipy.spatial.distance import pdist, squareform 4 | import math 5 | from config import * 6 | from utils import * 7 | import random 8 | 9 | import matplotlib.pyplot as plt 10 | import torch 11 | 12 | 13 | class Network: 14 | 15 | def __init__(self, config, show_config=True): # 尽量搞懂这些是啥意思 16 | self.config = config 17 | try: 18 | self._attrs = config.__dict__['__flags'] 19 | except: 20 | self._attrs = class_vars(config) # 把NetworkConfig里面的变量和值 当成字典输出 21 | 22 | if show_config: 23 | print('Network configs...') 24 | pp(self._attrs) 25 | 26 | for attr in self._attrs: 27 | name = attr if not attr.startswith('_') else attr[1:] 28 | setattr(self, name, getattr(self.config, attr)) 29 | 30 | self.start() 31 | 32 | def start(self): 33 | # 用户基站距离 34 | self.mbs_u_distance = [] 35 | self.sbs_u_distance = [] 36 | 37 | # 用户基站位置 38 | self.mbs_location = [45, 55] 39 | self.sbs_location = [55, 45] 40 | # self.u_location = [[10., 55.], [25., 35.], [35., 70.], [60., 25.], [75., 45.], [80., 60.], [6., 23.], 41 | # [46., 21.], [12., 76.], [53., 50.], [75., 57.], [93., 65.], [10., 78.], [91., 51.], 42 | # [67., 91.], [15., 90.], [23., 34.], [49., 79.], [75., 14.], [12., 69.]] 43 | self.u_location = [[10., 55.], [25., 35.], [35., 70.], [60., 25.], [75., 45.], [80., 60.], [6., 23.], 44 | [46., 21.], [12., 76.], [53., 50.], [75., 57.], [93., 65.], [10., 78.], [91., 51.], 45 | [67., 91.], [15., 90.], [23., 34.], [49., 79.], [75., 14.], [12., 69.], 46 | [55,10],[35,25],[70,35],[25,60],[45,75],[60,80],[23,6],[21,46],[76,12],[50,53]] 47 | 48 | self.create_topology() 49 | 50 | # 得到用户和基站的信道增益gain 51 | def create_topology(self): 52 | all_location = np.vstack((self.mbs_location, self.sbs_location, self.u_location)) 53 | all_distance = pdist(all_location, 'euclidean') 54 | 55 | self.mbs_u_distance = all_distance[1:1 + self.u_number] 56 | self.sbs_u_distance = all_distance[1 + self.u_number:1 + 2 * self.u_number] 57 | 58 | self.gain_sbs_u = self._channel_gain(self.sbs_u_distance, shape=self.u_number) # 6 59 | self.gain_mbs_u = self._channel_gain(self.mbs_u_distance, shape=self.u_number) # 6 60 | 61 | # 计算信道增益 62 | def _channel_gain(self, distance, shape): 63 | path_loss_bs_user = 37 + 30 * np.log2(distance) 64 | path_loss_bs_user = path_loss_bs_user + self.generate_shadow_fading(0, 8, shape, 1) 65 | gain = np.power(10, -path_loss_bs_user / 10) 66 | return gain 67 | 68 | def generate_shadow_fading(self, mean, sigma, num_user, num_bs): 69 | ''' 70 | 本函数生成对数正态分布的阴影衰落 71 | :param mean: 均值dB 72 | :param sigma: 标准差 dB 73 | :param num_bs: 74 | :param num_user: 75 | :return: 76 | ''' 77 | sigma = np.power(10, sigma / 10) 78 | mean = np.power(10, mean / 10) 79 | m = np.log(mean ** 2 / np.sqrt(sigma ** 2 + mean ** 2)) 80 | sigma = np.sqrt(np.log(sigma ** 2 / mean ** 2 + 1)) 81 | lognormal_fade = np.exp(np.random.randn(num_user, num_bs) * sigma + m) 82 | return lognormal_fade.reshape(num_user) 83 | 84 | def draw_net(self): 85 | '''画出PU SU分布图保存为model.jpg''' 86 | # # plt.subplot(111) 87 | # pt_location = self.pt_location 88 | # pr_location = self.pr_location 89 | # st_location = self.st_location 90 | # sr_location = self.sr_location 91 | 92 | # plt.rcParams['font.sans-serif'] = ['Arial'] # 如果要显示中文字体,则在此处设为:SimHei 93 | # plt.rcParams['axes.unicode_minus'] = False # 显示负号 94 | # plt.plot(pt_location[:, 0], pt_location[:, 1], '+', color='red', ms=15, label='PT') 95 | # plt.plot(pr_location[:, 0], pr_location[:, 1], '.r', ms=15, label='PR') 96 | # plt.plot(st_location[:, 0], st_location[:, 1], 's', color='blue', ms=10, label='ST') 97 | # plt.plot(sr_location[:, 0], sr_location[:, 1], '^b', ms=8, label='SR') 98 | # # plt.plot(su_location[:, 0], su_location[:, 1], '^b', ms=8, label='SU') 99 | # # plt.plot(30, 70, '+', color='red', ms=15, label='PBS') 100 | # # plt.plot(70, 30, 's', color='blue', ms=10, label='CBS') 101 | # plt.xlim(0, 100) 102 | # plt.ylim(0, 100) 103 | # plt.legend() 104 | # plt.savefig('model.jpg') 105 | # plt.show() 106 | 107 | '''def pu_snr(self, su_p, su_c): 108 | p_num = self.config.pu_number 109 | s_num = self.config.su_number 110 | pu_p = self.pu_p 111 | pu_c = self.pu_c 112 | pus_snr = [] 113 | pus_rate = [] 114 | for i in range(p_num): 115 | pu_signal = 0. 116 | su_signal = 0. 117 | for j in range(self.config.c_num): 118 | if pu_c[i][j] == 1: 119 | pu_signal += pu_p[i][j] * self.gain_pbs_pu[i] 120 | for k in range(s_num): 121 | su_signal += su_p[k][j] * su_c[k][j] * self.gain_mbs_u[k] 122 | interference = su_signal + self.config.N0 123 | pu_snr = pu_signal / interference 124 | pu_rate = self.BW_sc*math.log2(1 + pu_snr) #假设带宽为1 125 | pus_snr.append(pu_snr) 126 | pus_rate.append(pu_rate) 127 | return pus_snr, pus_rate 128 | ''' 129 | 130 | def u_rate(self, u_p, u_c): 131 | u_num = self.config.u_number 132 | us_rate = [] 133 | for i in range(u_num): 134 | u_rate = 0. 135 | u_interference = 0. 136 | for j in range(self.config.c_num): 137 | if u_c[i][j] == 1.: 138 | u_signal = u_p[i][j] * self.gain_mbs_u[i] 139 | for i_ in range(u_num): 140 | if (u_c[i_][j] == 1.) and (i != i_): 141 | u_interference += u_p[i_][j] * self.gain_mbs_u[i_] 142 | # 同道干扰 143 | interference = u_interference + self.config.N0 144 | # interference = self.config.N0 145 | u_snr = u_signal / interference 146 | u_rate = self.BW_sc * math.log2(1 + u_snr) 147 | us_rate.append(u_rate) 148 | return us_rate 149 | 150 | ''' 151 | def compute_reward(self, u_p, u_c): 152 | # 网络频谱效率计算 153 | sus_rate = self.u_rate(u_p, u_c) 154 | sus_rate_sum = np.sum(sus_rate) 155 | #频谱效率 156 | n_se = sus_rate_sum/(self.c_num*self.BW_sc) 157 | # 感知用户QoE计算 158 | latency = np.zeros(20) 159 | latency_limit = 10000 160 | rate_limit = 0.5e3 161 | Qoe_counter = 0 162 | arrive_package_rate = np.random.poisson(lam=1,size=10) 163 | #对两类用户,判断满足QoE的用户数量 164 | for i in range(self.u_number): 165 | if i < 10: 166 | # Qoe_counter+=1 167 | if sus_rate[i] >= rate_limit: 168 | Qoe_counter+=1 169 | else: 170 | latency[i] = 1./(sus_rate[i] - arrive_package_rate[i-10]+1e-7) 171 | if latency[i] <= latency_limit: 172 | Qoe_counter+=1 173 | 174 | QoE = Qoe_counter/self.u_number 175 | # SE与QoE线性组合 176 | reward_alpha = 0 177 | reward = reward_alpha*n_se + (1-reward_alpha)*QoE 178 | reward_c = reward 179 | 180 | return reward_c,n_se,QoE 181 | ''' 182 | 183 | # 提供初始状态 184 | def state_first(self): 185 | # u_c = [[1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.], 186 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 187 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 188 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 189 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 190 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 191 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 192 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 193 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 194 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 195 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 196 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 197 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 198 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 199 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 200 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 201 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 202 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 203 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 204 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]] 205 | u_c = [[1.]*30,[0.]*30,[0.]*30,[0.]*30,[0.]*30,[0.]*30,[0.]*30,[0.]*30,[0.]*30, 206 | [0.]*30,[0.]*30,[0.]*30,[0.]*30,[0.]*30,[0.]*30,[0.]*30,[0.]*30, 207 | [0.] * 30, [0.] * 30, [0.] * 30, [0.] * 30, [0.] * 30, [0.] * 30, [0.] * 30, [0.] * 30, 208 | [0.] * 30, [0.] * 30, [0.] * 30, [0.] * 30, [0.] * 30] 209 | u_c = np.array(u_c) 210 | u_p =[] 211 | for i in range(self.u_number): 212 | a = [0.]*self.u_number 213 | for j in range(self.u_number): 214 | if j == i: 215 | a[j] = 1. 216 | else: 217 | a[j] = 0. 218 | u_p.append(a) 219 | # u_p = [[1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 220 | # [0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 221 | # [0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 222 | # [0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 223 | # [0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 224 | # [0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 225 | # [0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 226 | # [0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 227 | # [0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 228 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 229 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 230 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0.], 231 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0.], 232 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0.], 233 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0.], 234 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0.], 235 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0.], 236 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0.], 237 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0.], 238 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1.]] 239 | u_p = np.array(u_p) 240 | # pus_snr, _ = self.pu_snr(su_p, su_c) # 获得主用户SINR 241 | 242 | # 各用户的数据率 243 | us_rate = self.u_rate(u_c, u_p) 244 | 245 | return us_rate 246 | 247 | '''用于计算每个用户空口时延 0704''' 248 | 249 | def u_latency(self, u_p, u_c, sla): 250 | # 用户空口时延计算 251 | latency = np.zeros(self.u_number) 252 | # arrive_package_rate = np.random.poisson(lam=100, size=20) 253 | # 对比 254 | arrive_package_rate = np.random.poisson(lam=1, size=self.u_number) 255 | sus_rate = self.u_rate(u_p, u_c) 256 | for i in range(self.u_number): 257 | if i < self.sep: 258 | # latency[i] = 4e7 / (sus_rate[i] - 2e5 + 1e-7) 259 | # latency[i] = 20 + 5.7e7 / (sus_rate[i] + 1e-7) #0812 260 | #latency[i] = 20 + 5.05e7 / (sus_rate[i] + 1e-7) 261 | latency[i] = 50 + 5.7e7 / (sus_rate[i] + 1e-7) 262 | # latency[i] = 50 + 3.6e7 / (sus_rate[i] + 1e-7) #0814 263 | # latency[i] = 20 + (sus_rate[i] + 1e-7)/self.rate_limit * 10 264 | if sus_rate[i] < self.rate_limit or latency[i] > self.latency_limit2: 265 | latency[i] = self.latency_limit2 266 | else: 267 | # latency[i] = 10. / (sus_rate[i] - arrive_package_rate[i] + 1e-7) 268 | # 对比算法 269 | latency[i] = 1. / (sus_rate[i] - arrive_package_rate[i] + 1e-7) 270 | if latency[i] < 0 or latency[i] > self.latency_limit: 271 | latency[i] = self.latency_limit 272 | return latency 273 | 274 | '''单纯根据不同切片空口时延比例的计算QoE 作为reward,没加入频谱效率的权重 0705''' 275 | 276 | def compute_reward(self, u_p, u_c,sla): 277 | # 网络频谱效率计算 278 | sus_rate = self.u_rate(u_p, u_c) 279 | sus_rate_sum = np.sum(sus_rate) 280 | #sla = [0.9] * self.u_number 281 | latency = self.u_latency(u_p, u_c, sla) 282 | # 频谱效率 283 | n_se = sus_rate_sum / (self.c_num * self.BW_sc) 284 | # 用户QoE计算 285 | Qoe_counter = 0 286 | # embb用户满意度 287 | # ssl_1, ssl_2 = np.zeros(self.sep), np.zeros(self.sep) 288 | ssl_1 = sus_rate[0: self.sep] 289 | ssl_1 = np.array(ssl_1) / self.rate_limit + 1 290 | # ssl_2 = np.log2(ssl_1) 291 | # ssl_2 = np.log(ssl_1) 292 | ssl_2 = np.log10(ssl_1) 293 | ssl = np.sum(ssl_2) 294 | # for i in range(self.sep): 295 | # ssl = ssl * ssl_2[i] 296 | 297 | # 对两类用户,判断满足QoE的用户数量 298 | # for i in range(self.u_number): 299 | # if i < 10: 300 | # # Qoe_counter+=1 301 | # if sus_rate[i] >= self.rate_limit: 302 | # Qoe_counter += 1 303 | # elif latency[i] <= self.latency_limit * sla[i]: 304 | # Qoe_counter += 1 305 | 306 | # 都转换成时延的约束 307 | for i in range(self.u_number): 308 | if i < self.sep: 309 | if latency[i] < self.latency_limit2 * sla[i]: 310 | Qoe_counter += 1 311 | elif i == self.sep: 312 | es = Qoe_counter 313 | if latency[i] < self.latency_limit * sla[i]: 314 | Qoe_counter += 1 315 | elif latency[i] < self.latency_limit * sla[i]: 316 | Qoe_counter += 1 317 | 318 | us = Qoe_counter - es 319 | QoE = Qoe_counter / self.u_number 320 | # SE与QoE线性组合 321 | reward_alpha = self.reward_alpha 322 | # reward = reward_alpha * n_se + (1 - reward_alpha) * QoE 323 | reward = reward_alpha * ssl + (1 - reward_alpha) * QoE 324 | return reward, n_se, QoE, latency, ssl, es, us 325 | -------------------------------------------------------------------------------- /users_plus/network_40.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | import numpy as np 3 | from scipy.spatial.distance import pdist, squareform 4 | import math 5 | from config import * 6 | from utils import * 7 | import random 8 | 9 | import matplotlib.pyplot as plt 10 | import torch 11 | 12 | 13 | class Network: 14 | 15 | def __init__(self, config, show_config=True): # 尽量搞懂这些是啥意思 16 | self.config = config 17 | try: 18 | self._attrs = config.__dict__['__flags'] 19 | except: 20 | self._attrs = class_vars(config) # 把NetworkConfig里面的变量和值 当成字典输出 21 | 22 | if show_config: 23 | print('Network configs...') 24 | pp(self._attrs) 25 | 26 | for attr in self._attrs: 27 | name = attr if not attr.startswith('_') else attr[1:] 28 | setattr(self, name, getattr(self.config, attr)) 29 | 30 | self.start() 31 | 32 | def start(self): 33 | # 用户基站距离 34 | self.mbs_u_distance = [] 35 | self.sbs_u_distance = [] 36 | 37 | # 用户基站位置 38 | self.mbs_location = [45, 55] 39 | self.sbs_location = [55, 45] 40 | # self.u_location = [[10., 55.], [25., 35.], [35., 70.], [60., 25.], [75., 45.], [80., 60.], [6., 23.], 41 | # [46., 21.], [12., 76.], [53., 50.], [75., 57.], [93., 65.], [10., 78.], [91., 51.], 42 | # [67., 91.], [15., 90.], [23., 34.], [49., 79.], [75., 14.], [12., 69.]] 43 | self.u_location = [ [10., 55.], [25., 35.], [35., 70.], [60., 25.], [75., 45.], [80., 60.], [6., 23.], 44 | [46., 21.], [12., 76.], [53., 50.], [75., 57.], [93., 65.], [10., 78.], [91., 51.], 45 | [67., 91.], [15., 90.], [23., 34.], [49., 79.], [75., 14.], [12., 69.], 46 | [55,10],[35,25],[70,35],[25,60],[45,75],[60,80],[23,6],[21,46],[76,12],[50,53], 47 | [57.,75.],[65.,93.],[78.,10.],[51.,91.],[91.,67],[90.,15.],[34.,23.],[79.,49.],[14.,75.],[69.,12.] ] 48 | 49 | self.create_topology() 50 | 51 | # 得到用户和基站的信道增益gain 52 | def create_topology(self): 53 | all_location = np.vstack((self.mbs_location, self.sbs_location, self.u_location)) 54 | all_distance = pdist(all_location, 'euclidean') 55 | 56 | self.mbs_u_distance = all_distance[1:1 + self.u_number] 57 | self.sbs_u_distance = all_distance[1 + self.u_number:1 + 2 * self.u_number] 58 | 59 | self.gain_sbs_u = self._channel_gain(self.sbs_u_distance, shape=self.u_number) # 6 60 | self.gain_mbs_u = self._channel_gain(self.mbs_u_distance, shape=self.u_number) # 6 61 | 62 | # 计算信道增益 63 | def _channel_gain(self, distance, shape): 64 | path_loss_bs_user = 37 + 30 * np.log2(distance) 65 | path_loss_bs_user = path_loss_bs_user + self.generate_shadow_fading(0, 8, shape, 1) 66 | gain = np.power(10, -path_loss_bs_user / 10) 67 | return gain 68 | 69 | def generate_shadow_fading(self, mean, sigma, num_user, num_bs): 70 | ''' 71 | 本函数生成对数正态分布的阴影衰落 72 | :param mean: 均值dB 73 | :param sigma: 标准差 dB 74 | :param num_bs: 75 | :param num_user: 76 | :return: 77 | ''' 78 | sigma = np.power(10, sigma / 10) 79 | mean = np.power(10, mean / 10) 80 | m = np.log(mean ** 2 / np.sqrt(sigma ** 2 + mean ** 2)) 81 | sigma = np.sqrt(np.log(sigma ** 2 / mean ** 2 + 1)) 82 | lognormal_fade = np.exp(np.random.randn(num_user, num_bs) * sigma + m) 83 | return lognormal_fade.reshape(num_user) 84 | 85 | def draw_net(self): 86 | '''画出PU SU分布图保存为model.jpg''' 87 | # # plt.subplot(111) 88 | # pt_location = self.pt_location 89 | # pr_location = self.pr_location 90 | # st_location = self.st_location 91 | # sr_location = self.sr_location 92 | 93 | # plt.rcParams['font.sans-serif'] = ['Arial'] # 如果要显示中文字体,则在此处设为:SimHei 94 | # plt.rcParams['axes.unicode_minus'] = False # 显示负号 95 | # plt.plot(pt_location[:, 0], pt_location[:, 1], '+', color='red', ms=15, label='PT') 96 | # plt.plot(pr_location[:, 0], pr_location[:, 1], '.r', ms=15, label='PR') 97 | # plt.plot(st_location[:, 0], st_location[:, 1], 's', color='blue', ms=10, label='ST') 98 | # plt.plot(sr_location[:, 0], sr_location[:, 1], '^b', ms=8, label='SR') 99 | # # plt.plot(su_location[:, 0], su_location[:, 1], '^b', ms=8, label='SU') 100 | # # plt.plot(30, 70, '+', color='red', ms=15, label='PBS') 101 | # # plt.plot(70, 30, 's', color='blue', ms=10, label='CBS') 102 | # plt.xlim(0, 100) 103 | # plt.ylim(0, 100) 104 | # plt.legend() 105 | # plt.savefig('model.jpg') 106 | # plt.show() 107 | 108 | '''def pu_snr(self, su_p, su_c): 109 | p_num = self.config.pu_number 110 | s_num = self.config.su_number 111 | pu_p = self.pu_p 112 | pu_c = self.pu_c 113 | pus_snr = [] 114 | pus_rate = [] 115 | for i in range(p_num): 116 | pu_signal = 0. 117 | su_signal = 0. 118 | for j in range(self.config.c_num): 119 | if pu_c[i][j] == 1: 120 | pu_signal += pu_p[i][j] * self.gain_pbs_pu[i] 121 | for k in range(s_num): 122 | su_signal += su_p[k][j] * su_c[k][j] * self.gain_mbs_u[k] 123 | interference = su_signal + self.config.N0 124 | pu_snr = pu_signal / interference 125 | pu_rate = self.BW_sc*math.log2(1 + pu_snr) #假设带宽为1 126 | pus_snr.append(pu_snr) 127 | pus_rate.append(pu_rate) 128 | return pus_snr, pus_rate 129 | ''' 130 | 131 | def u_rate(self, u_p, u_c): 132 | u_num = self.config.u_number 133 | us_rate = [] 134 | for i in range(u_num): 135 | u_rate = 0. 136 | u_interference = 0. 137 | for j in range(self.config.c_num): 138 | if u_c[i][j] == 1.: 139 | u_signal = u_p[i][j] * self.gain_mbs_u[i] 140 | for i_ in range(u_num): 141 | if (u_c[i_][j] == 1.) and (i != i_): 142 | u_interference += u_p[i_][j] * self.gain_mbs_u[i_] 143 | # 同道干扰 144 | interference = u_interference + self.config.N0 145 | # interference = self.config.N0 146 | u_snr = u_signal / interference 147 | u_rate = self.BW_sc * math.log2(1 + u_snr) 148 | us_rate.append(u_rate) 149 | return us_rate 150 | 151 | ''' 152 | def compute_reward(self, u_p, u_c): 153 | # 网络频谱效率计算 154 | sus_rate = self.u_rate(u_p, u_c) 155 | sus_rate_sum = np.sum(sus_rate) 156 | #频谱效率 157 | n_se = sus_rate_sum/(self.c_num*self.BW_sc) 158 | # 感知用户QoE计算 159 | latency = np.zeros(20) 160 | latency_limit = 10000 161 | rate_limit = 0.5e3 162 | Qoe_counter = 0 163 | arrive_package_rate = np.random.poisson(lam=1,size=10) 164 | #对两类用户,判断满足QoE的用户数量 165 | for i in range(self.u_number): 166 | if i < 10: 167 | # Qoe_counter+=1 168 | if sus_rate[i] >= rate_limit: 169 | Qoe_counter+=1 170 | else: 171 | latency[i] = 1./(sus_rate[i] - arrive_package_rate[i-10]+1e-7) 172 | if latency[i] <= latency_limit: 173 | Qoe_counter+=1 174 | 175 | QoE = Qoe_counter/self.u_number 176 | # SE与QoE线性组合 177 | reward_alpha = 0 178 | reward = reward_alpha*n_se + (1-reward_alpha)*QoE 179 | reward_c = reward 180 | 181 | return reward_c,n_se,QoE 182 | ''' 183 | 184 | # 提供初始状态 185 | def state_first(self): 186 | # u_c = [[1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.], 187 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 188 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 189 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 190 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 191 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 192 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 193 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 194 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 195 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 196 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 197 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 198 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 199 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 200 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 201 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 202 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 203 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 204 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 205 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]] 206 | # u_c = [[1.]*30,[0.]*30,[0.]*30,[0.]*30,[0.]*30,[0.]*30,[0.]*30,[0.]*30,[0.]*30, 207 | # [0.]*30,[0.]*30,[0.]*30,[0.]*30,[0.]*30,[0.]*30,[0.]*30,[0.]*30, 208 | # [0.] * 30, [0.] * 30, [0.] * 30, [0.] * 30, [0.] * 30, [0.] * 30, [0.] * 30, [0.] * 30, 209 | # [0.] * 30, [0.] * 30, [0.] * 30, [0.] * 30, [0.] * 30] 210 | u_c = [] 211 | for i in range(self.u_number): 212 | if i == 0: 213 | u_c.append([1.]*self.u_number) 214 | else: 215 | u_c.append([0.]*self.u_number) 216 | 217 | u_c = np.array(u_c) 218 | u_p =[] 219 | for i in range(self.u_number): 220 | a = [0.]*self.u_number 221 | for j in range(self.u_number): 222 | if j == i: 223 | a[j] = 1. 224 | else: 225 | a[j] = 0. 226 | u_p.append(a) 227 | # u_p = [[1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 228 | # [0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 229 | # [0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 230 | # [0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 231 | # [0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 232 | # [0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 233 | # [0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 234 | # [0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 235 | # [0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 236 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 237 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 238 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0.], 239 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0.], 240 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0.], 241 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0.], 242 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0.], 243 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0.], 244 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0.], 245 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0.], 246 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1.]] 247 | u_p = np.array(u_p) 248 | # pus_snr, _ = self.pu_snr(su_p, su_c) # 获得主用户SINR 249 | 250 | # 各用户的数据率 251 | us_rate = self.u_rate(u_c, u_p) 252 | 253 | return us_rate 254 | 255 | '''用于计算每个用户空口时延 0704''' 256 | 257 | def u_latency(self, u_p, u_c, sla): 258 | # 用户空口时延计算 259 | latency = np.zeros(self.u_number) 260 | # arrive_package_rate = np.random.poisson(lam=100, size=20) 261 | # 对比 262 | arrive_package_rate = np.random.poisson(lam=1, size=self.u_number) 263 | sus_rate = self.u_rate(u_p, u_c) 264 | for i in range(self.u_number): 265 | if i < self.sep: 266 | # latency[i] = 4e7 / (sus_rate[i] - 2e5 + 1e-7) 267 | # latency[i] = 20 + 5.7e7 / (sus_rate[i] + 1e-7) #0812 268 | latency[i] = 50 + 5.7e7 / (sus_rate[i] + 1e-7) 269 | # latency[i] = 50 + 3.6e7 / (sus_rate[i] + 1e-7) #0814 270 | # latency[i] = 20 + (sus_rate[i] + 1e-7)/self.rate_limit * 10 271 | if sus_rate[i] < self.rate_limit or latency[i] > self.latency_limit2: 272 | latency[i] = self.latency_limit2 273 | else: 274 | # latency[i] = 10. / (sus_rate[i] - arrive_package_rate[i] + 1e-7) 275 | # 对比算法 276 | latency[i] = 1. / (sus_rate[i] - arrive_package_rate[i] + 1e-7) 277 | if latency[i] < 0 or latency[i] > self.latency_limit: 278 | latency[i] = self.latency_limit 279 | return latency 280 | 281 | '''单纯根据不同切片空口时延比例的计算QoE 作为reward,没加入频谱效率的权重 0705''' 282 | 283 | def compute_reward(self, u_p, u_c, sla): 284 | # 网络频谱效率计算 285 | sus_rate = self.u_rate(u_p, u_c) 286 | sus_rate_sum = np.sum(sus_rate) 287 | # sla = [0.9] * self.u_number 288 | latency = self.u_latency(u_p, u_c, sla) 289 | # 频谱效率 290 | n_se = sus_rate_sum / (self.c_num * self.BW_sc) 291 | # 用户QoE计算 292 | Qoe_counter = 0 293 | # embb用户满意度 294 | # ssl_1, ssl_2 = np.zeros(self.sep), np.zeros(self.sep) 295 | ssl_1 = sus_rate[0: self.sep] 296 | ssl_1 = np.array(ssl_1) / self.rate_limit + 1 297 | # ssl_2 = np.log2(ssl_1) 298 | # ssl_2 = np.log(ssl_1) 299 | ssl_2 = np.log10(ssl_1) 300 | ssl = np.sum(ssl_2) 301 | # for i in range(self.sep): 302 | # ssl = ssl * ssl_2[i] 303 | 304 | # 对两类用户,判断满足QoE的用户数量 305 | # for i in range(self.u_number): 306 | # if i < 10: 307 | # # Qoe_counter+=1 308 | # if sus_rate[i] >= self.rate_limit: 309 | # Qoe_counter += 1 310 | # elif latency[i] <= self.latency_limit * sla[i]: 311 | # Qoe_counter += 1 312 | 313 | # 都转换成时延的约束 314 | for i in range(self.u_number): 315 | if i < self.sep: 316 | if latency[i] < self.latency_limit2 * sla[i]: 317 | Qoe_counter += 1 318 | elif i == self.sep: 319 | es = Qoe_counter 320 | if latency[i] < self.latency_limit * sla[i]: 321 | Qoe_counter += 1 322 | elif latency[i] < self.latency_limit * sla[i]: 323 | Qoe_counter += 1 324 | 325 | us = Qoe_counter - es 326 | QoE = Qoe_counter / self.u_number 327 | # SE与QoE线性组合 328 | reward_alpha = self.reward_alpha 329 | # reward = reward_alpha * n_se + (1 - reward_alpha) * QoE 330 | reward = reward_alpha * ssl + (1 - reward_alpha) * QoE 331 | return reward, n_se, QoE, latency, ssl, es, us 332 | -------------------------------------------------------------------------------- /users_plus/network_50.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | import numpy as np 3 | from scipy.spatial.distance import pdist, squareform 4 | import math 5 | from config import * 6 | from utils import * 7 | import random 8 | 9 | import matplotlib.pyplot as plt 10 | import torch 11 | 12 | 13 | class Network: 14 | 15 | def __init__(self, config, show_config=True): # 尽量搞懂这些是啥意思 16 | self.config = config 17 | try: 18 | self._attrs = config.__dict__['__flags'] 19 | except: 20 | self._attrs = class_vars(config) # 把NetworkConfig里面的变量和值 当成字典输出 21 | 22 | if show_config: 23 | print('Network configs...') 24 | pp(self._attrs) 25 | 26 | for attr in self._attrs: 27 | name = attr if not attr.startswith('_') else attr[1:] 28 | setattr(self, name, getattr(self.config, attr)) 29 | 30 | self.start() 31 | 32 | def start(self): 33 | # 用户基站距离 34 | self.mbs_u_distance = [] 35 | self.sbs_u_distance = [] 36 | 37 | # 用户基站位置 38 | self.mbs_location = [45, 55] 39 | self.sbs_location = [55, 45] 40 | # self.u_location = [[10., 55.], [25., 35.], [35., 70.], [60., 25.], [75., 45.], [80., 60.], [6., 23.], 41 | # [46., 21.], [12., 76.], [53., 50.], [75., 57.], [93., 65.], [10., 78.], [91., 51.], 42 | # [67., 91.], [15., 90.], [23., 34.], [49., 79.], [75., 14.], [12., 69.]] 43 | self.u_location = [ [10., 55.], [25., 35.], [35., 70.], [60., 25.], [75., 45.], [80., 60.], [6., 23.], 44 | [46., 21.], [12., 76.], [53., 50.], [75., 57.], [93., 65.], [10., 78.], [91., 51.], 45 | [67., 91.], [15., 90.], [23., 34.], [49., 79.], [75., 14.], [12., 69.], 46 | [55,10],[35,25],[70,35],[25,60],[45,75],[60,80],[23,6],[21,46],[76,12],[50,53], 47 | [57.,75.],[65.,93.],[78.,10.],[51.,91.],[91.,67],[90.,15.],[34.,23.],[79.,49.],[14.,75.],[69.,12.], 48 | [25.,45.],[35.,45.],[25.,50.],[33.,66.],[28.,56.],[32.,64.],[39.,78.],[40.,80.],[15.,30.],[66.,33.] ] 49 | 50 | self.create_topology() 51 | 52 | # 得到用户和基站的信道增益gain 53 | def create_topology(self): 54 | all_location = np.vstack((self.mbs_location, self.sbs_location, self.u_location)) 55 | all_distance = pdist(all_location, 'euclidean') 56 | 57 | self.mbs_u_distance = all_distance[1:1 + self.u_number] 58 | self.sbs_u_distance = all_distance[1 + self.u_number:1 + 2 * self.u_number] 59 | 60 | self.gain_sbs_u = self._channel_gain(self.sbs_u_distance, shape=self.u_number) # 6 61 | self.gain_mbs_u = self._channel_gain(self.mbs_u_distance, shape=self.u_number) # 6 62 | 63 | # 计算信道增益 64 | def _channel_gain(self, distance, shape): 65 | path_loss_bs_user = 37 + 30 * np.log2(distance) 66 | path_loss_bs_user = path_loss_bs_user + self.generate_shadow_fading(0, 8, shape, 1) 67 | gain = np.power(10, -path_loss_bs_user / 10) 68 | return gain 69 | 70 | def generate_shadow_fading(self, mean, sigma, num_user, num_bs): 71 | ''' 72 | 本函数生成对数正态分布的阴影衰落 73 | :param mean: 均值dB 74 | :param sigma: 标准差 dB 75 | :param num_bs: 76 | :param num_user: 77 | :return: 78 | ''' 79 | sigma = np.power(10, sigma / 10) 80 | mean = np.power(10, mean / 10) 81 | m = np.log(mean ** 2 / np.sqrt(sigma ** 2 + mean ** 2)) 82 | sigma = np.sqrt(np.log(sigma ** 2 / mean ** 2 + 1)) 83 | lognormal_fade = np.exp(np.random.randn(num_user, num_bs) * sigma + m) 84 | return lognormal_fade.reshape(num_user) 85 | 86 | def draw_net(self): 87 | '''画出PU SU分布图保存为model.jpg''' 88 | # # plt.subplot(111) 89 | # pt_location = self.pt_location 90 | # pr_location = self.pr_location 91 | # st_location = self.st_location 92 | # sr_location = self.sr_location 93 | 94 | # plt.rcParams['font.sans-serif'] = ['Arial'] # 如果要显示中文字体,则在此处设为:SimHei 95 | # plt.rcParams['axes.unicode_minus'] = False # 显示负号 96 | # plt.plot(pt_location[:, 0], pt_location[:, 1], '+', color='red', ms=15, label='PT') 97 | # plt.plot(pr_location[:, 0], pr_location[:, 1], '.r', ms=15, label='PR') 98 | # plt.plot(st_location[:, 0], st_location[:, 1], 's', color='blue', ms=10, label='ST') 99 | # plt.plot(sr_location[:, 0], sr_location[:, 1], '^b', ms=8, label='SR') 100 | # # plt.plot(su_location[:, 0], su_location[:, 1], '^b', ms=8, label='SU') 101 | # # plt.plot(30, 70, '+', color='red', ms=15, label='PBS') 102 | # # plt.plot(70, 30, 's', color='blue', ms=10, label='CBS') 103 | # plt.xlim(0, 100) 104 | # plt.ylim(0, 100) 105 | # plt.legend() 106 | # plt.savefig('model.jpg') 107 | # plt.show() 108 | 109 | '''def pu_snr(self, su_p, su_c): 110 | p_num = self.config.pu_number 111 | s_num = self.config.su_number 112 | pu_p = self.pu_p 113 | pu_c = self.pu_c 114 | pus_snr = [] 115 | pus_rate = [] 116 | for i in range(p_num): 117 | pu_signal = 0. 118 | su_signal = 0. 119 | for j in range(self.config.c_num): 120 | if pu_c[i][j] == 1: 121 | pu_signal += pu_p[i][j] * self.gain_pbs_pu[i] 122 | for k in range(s_num): 123 | su_signal += su_p[k][j] * su_c[k][j] * self.gain_mbs_u[k] 124 | interference = su_signal + self.config.N0 125 | pu_snr = pu_signal / interference 126 | pu_rate = self.BW_sc*math.log2(1 + pu_snr) #假设带宽为1 127 | pus_snr.append(pu_snr) 128 | pus_rate.append(pu_rate) 129 | return pus_snr, pus_rate 130 | ''' 131 | 132 | def u_rate(self, u_p, u_c): 133 | u_num = self.config.u_number 134 | us_rate = [] 135 | for i in range(u_num): 136 | u_rate = 0. 137 | u_interference = 0. 138 | for j in range(self.config.c_num): 139 | if u_c[i][j] == 1.: 140 | u_signal = u_p[i][j] * self.gain_mbs_u[i] 141 | for i_ in range(u_num): 142 | if (u_c[i_][j] == 1.) and (i != i_): 143 | u_interference += u_p[i_][j] * self.gain_mbs_u[i_] 144 | # 同道干扰 145 | interference = u_interference + self.config.N0 146 | # interference = self.config.N0 147 | u_snr = u_signal / interference 148 | u_rate = self.BW_sc * math.log2(1 + u_snr) 149 | us_rate.append(u_rate) 150 | return us_rate 151 | 152 | ''' 153 | def compute_reward(self, u_p, u_c): 154 | # 网络频谱效率计算 155 | sus_rate = self.u_rate(u_p, u_c) 156 | sus_rate_sum = np.sum(sus_rate) 157 | #频谱效率 158 | n_se = sus_rate_sum/(self.c_num*self.BW_sc) 159 | # 感知用户QoE计算 160 | latency = np.zeros(20) 161 | latency_limit = 10000 162 | rate_limit = 0.5e3 163 | Qoe_counter = 0 164 | arrive_package_rate = np.random.poisson(lam=1,size=10) 165 | #对两类用户,判断满足QoE的用户数量 166 | for i in range(self.u_number): 167 | if i < 10: 168 | # Qoe_counter+=1 169 | if sus_rate[i] >= rate_limit: 170 | Qoe_counter+=1 171 | else: 172 | latency[i] = 1./(sus_rate[i] - arrive_package_rate[i-10]+1e-7) 173 | if latency[i] <= latency_limit: 174 | Qoe_counter+=1 175 | 176 | QoE = Qoe_counter/self.u_number 177 | # SE与QoE线性组合 178 | reward_alpha = 0 179 | reward = reward_alpha*n_se + (1-reward_alpha)*QoE 180 | reward_c = reward 181 | 182 | return reward_c,n_se,QoE 183 | ''' 184 | 185 | # 提供初始状态 186 | def state_first(self): 187 | # u_c = [[1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.], 188 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 189 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 190 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 191 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 192 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 193 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 194 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 195 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 196 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 197 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 198 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 199 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 200 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 201 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 202 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 203 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 204 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 205 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 206 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]] 207 | # u_c = [[1.]*30,[0.]*30,[0.]*30,[0.]*30,[0.]*30,[0.]*30,[0.]*30,[0.]*30,[0.]*30, 208 | # [0.]*30,[0.]*30,[0.]*30,[0.]*30,[0.]*30,[0.]*30,[0.]*30,[0.]*30, 209 | # [0.] * 30, [0.] * 30, [0.] * 30, [0.] * 30, [0.] * 30, [0.] * 30, [0.] * 30, [0.] * 30, 210 | # [0.] * 30, [0.] * 30, [0.] * 30, [0.] * 30, [0.] * 30] 211 | u_c = [] 212 | for i in range(self.u_number): 213 | if i == 0: 214 | u_c.append([1.]*self.u_number) 215 | else: 216 | u_c.append([0.]*self.u_number) 217 | 218 | u_c = np.array(u_c) 219 | u_p =[] 220 | for i in range(self.u_number): 221 | a = [0.]*self.u_number 222 | for j in range(self.u_number): 223 | if j == i: 224 | a[j] = 1. 225 | else: 226 | a[j] = 0. 227 | u_p.append(a) 228 | # u_p = [[1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 229 | # [0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 230 | # [0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 231 | # [0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 232 | # [0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 233 | # [0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 234 | # [0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 235 | # [0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 236 | # [0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 237 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 238 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 239 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0.], 240 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0.], 241 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0.], 242 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0.], 243 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0.], 244 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0.], 245 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0.], 246 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0.], 247 | # [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1.]] 248 | u_p = np.array(u_p) 249 | # pus_snr, _ = self.pu_snr(su_p, su_c) # 获得主用户SINR 250 | 251 | # 各用户的数据率 252 | us_rate = self.u_rate(u_c, u_p) 253 | 254 | return us_rate 255 | 256 | '''用于计算每个用户空口时延 0704''' 257 | 258 | def u_latency(self, u_p, u_c, sla): 259 | # 用户空口时延计算 260 | latency = np.zeros(self.u_number) 261 | # arrive_package_rate = np.random.poisson(lam=100, size=20) 262 | # 对比 263 | arrive_package_rate = np.random.poisson(lam=1, size=self.u_number) 264 | sus_rate = self.u_rate(u_p, u_c) 265 | for i in range(self.u_number): 266 | if i < self.sep: 267 | # latency[i] = 4e7 / (sus_rate[i] - 2e5 + 1e-7) 268 | # latency[i] = 20 + 5.7e7 / (sus_rate[i] + 1e-7) #0812 269 | latency[i] = 50 + 5.7e7 / (sus_rate[i] + 1e-7) 270 | # latency[i] = 50 + 3.6e7 / (sus_rate[i] + 1e-7) #0814 271 | # latency[i] = 20 + (sus_rate[i] + 1e-7)/self.rate_limit * 10 272 | if sus_rate[i] < self.rate_limit or latency[i] > self.latency_limit2: 273 | latency[i] = self.latency_limit2 274 | else: 275 | # latency[i] = 10. / (sus_rate[i] - arrive_package_rate[i] + 1e-7) 276 | # 对比算法 277 | latency[i] = 1. / (sus_rate[i] - arrive_package_rate[i] + 1e-7) 278 | if latency[i] < 0 or latency[i] > self.latency_limit: 279 | latency[i] = self.latency_limit 280 | return latency 281 | 282 | '''单纯根据不同切片空口时延比例的计算QoE 作为reward,没加入频谱效率的权重 0705''' 283 | 284 | def compute_reward(self, u_p, u_c, sla): 285 | # 网络频谱效率计算 286 | sus_rate = self.u_rate(u_p, u_c) 287 | sus_rate_sum = np.sum(sus_rate) 288 | # sla = [0.9] * self.u_number 289 | latency = self.u_latency(u_p, u_c, sla) 290 | # 频谱效率 291 | n_se = sus_rate_sum / (self.c_num * self.BW_sc) 292 | # 用户QoE计算 293 | Qoe_counter = 0 294 | # embb用户满意度 295 | # ssl_1, ssl_2 = np.zeros(self.sep), np.zeros(self.sep) 296 | ssl_1 = sus_rate[0: self.sep] 297 | ssl_1 = np.array(ssl_1) / self.rate_limit + 1 298 | # ssl_2 = np.log2(ssl_1) 299 | # ssl_2 = np.log(ssl_1) 300 | ssl_2 = np.log10(ssl_1) 301 | ssl = np.sum(ssl_2) 302 | # for i in range(self.sep): 303 | # ssl = ssl * ssl_2[i] 304 | 305 | # 对两类用户,判断满足QoE的用户数量 306 | # for i in range(self.u_number): 307 | # if i < 10: 308 | # # Qoe_counter+=1 309 | # if sus_rate[i] >= self.rate_limit: 310 | # Qoe_counter += 1 311 | # elif latency[i] <= self.latency_limit * sla[i]: 312 | # Qoe_counter += 1 313 | 314 | # 都转换成时延的约束 315 | for i in range(self.u_number): 316 | if i < self.sep: 317 | if latency[i] < self.latency_limit2 * sla[i]: 318 | Qoe_counter += 1 319 | elif i == self.sep: 320 | es = Qoe_counter 321 | if latency[i] < self.latency_limit * sla[i]: 322 | Qoe_counter += 1 323 | elif latency[i] < self.latency_limit * sla[i]: 324 | Qoe_counter += 1 325 | 326 | us = Qoe_counter - es 327 | QoE = Qoe_counter / self.u_number 328 | # SE与QoE线性组合 329 | reward_alpha = self.reward_alpha 330 | # reward = reward_alpha * n_se + (1 - reward_alpha) * QoE 331 | reward = reward_alpha * ssl + (1 - reward_alpha) * QoE 332 | return reward, n_se, QoE, latency, ssl, es, us 333 | -------------------------------------------------------------------------------- /users_plus/replay_memory.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | import shelve 3 | from utils import * 4 | import numpy as np 5 | import os 6 | import time as t 7 | 8 | from config import * 9 | 10 | class ReplayMemory: 11 | def __init__(self, config): 12 | self.memory_size = config.memory_size 13 | self.width = config.width 14 | self.heigth = config.heigth 15 | self.length = config.length 16 | self.batch_size = config.batch_size # 32 17 | # lin1307 18 | # 这是一个有限度的存储 19 | if not (self.is_empty()): # is_empty()是空的,返回true 20 | self.actions, self.screens, self.rewards, self.count, self.current = self.load() 21 | else: 22 | self.actions = np.empty((self.memory_size, config.action_rows, config.action_cols), 23 | dtype=np.float32) # .shape[8000, 3, 4] 24 | self.rewards = np.empty((self.memory_size, config.reward_size), 25 | dtype=np.float32) # .shape[8000, 1] 26 | self.screens = np.empty((self.memory_size, self.heigth, self.width), 27 | dtype=np.float32) # [8000, 1, 4] 28 | # print(self.screens.shape) 29 | # screens.shape = (8000, 1, 50, 1) 30 | # kkw 31 | self.count = 0 # 这个count用来跟current比较,判断是否存储器存储满了 32 | self.current = 0 # 在存储器中的顺序,有点像指针,只能是1—8000 33 | 34 | self.current_states = np.empty((self.batch_size, self.heigth, self.width), 35 | dtype=np.float64) # (32,1,4) 36 | self.next_states = np.empty((self.batch_size, self.heigth, self.width), 37 | dtype=np.float64) # (32,1,4) 38 | 39 | def add(self, screen, reward, action): # self.memory.add(s_t, reward, power) 40 | self.actions[self.current, ...] = action 41 | # print(action) 42 | # kkw 43 | self.screens[self.current, ...] = screen # s_t 44 | self.rewards[self.current, ...] = reward 45 | self.count = max(self.count, self.current + 1) 46 | # print(self.count) 47 | self.current = (self.current + 1) % self.memory_size 48 | # 保存的都是actions,screens,rewards 49 | 50 | def sample(self): # 从存储器里随机抽取 self.current_states, actions, reward, self.next_states 51 | indexes = [] 52 | # print(len(indexes)) 53 | # jjlin 54 | while len(indexes) < self.batch_size: 55 | # print(self.count) 56 | # jjlin 57 | if self.count > self.current + 1: # 说明memory_size已经满了,current重新计数了 58 | index = np.random.randint(1, self.memory_size) # 在整个满的memory_size随机抽取 59 | else: 60 | index = np.random.randint(1, self.current) # 在已存储的记忆里(记忆没满)随机抽取 61 | 62 | self.current_states[len(indexes), ...] = self.screens[index - 1, ...] 63 | self.next_states[len(indexes), ...] = self.screens[index, ...] 64 | indexes.append(index) 65 | # 以上的意思是随机抽取batch_size个记忆,并赋给current_states和next_states 66 | 67 | actions = self.actions[indexes, :] 68 | reward = self.rewards[indexes] 69 | return self.current_states, actions, reward, self.next_states 70 | 71 | # 将数据保存到硬盘 72 | def save(self): 73 | print('\n [*]Data saving...') 74 | tim = str(int(t.time())) 75 | # kkw 76 | filenames = os.listdir(Tools.memory_data) 77 | if len(filenames) != 0: 78 | for data in filenames: 79 | os.remove(Tools.memory_data + '/' + data) 80 | try: 81 | datas = shelve.open(Tools.memory_data + '/' + tim + '_.db', writeback=True, flag='c') 82 | # kkw 83 | datas['actions'] = self.actions 84 | datas['screens'] = self.screens 85 | datas['rewards'] = self.rewards 86 | datas['count'] = self.count 87 | datas['current'] = self.current 88 | print('[>^<]Data save SUCCESS') 89 | except KeyError: 90 | print('[!]Data save FAILED!!!') 91 | finally: 92 | datas.close() 93 | # kkw 94 | 95 | def is_empty(self): 96 | # jjlin 97 | filenames1 = os.listdir(Tools.memory_data) # Tools.memory_data为地址 98 | # kkw 99 | # jjlin 100 | # print(len(filenames1)) 101 | # print(filenames1) 102 | # kkw 103 | if len(filenames1) == 0: 104 | print('\n[!]There no data!!!') 105 | # kkw 106 | return True 107 | # kkw 108 | print('\n[>^<]There have data') 109 | return False 110 | 111 | def load(self): # 从已存储的数据中恢复出来 112 | try: 113 | datas = os.listdir(Tools.memory_data) # 返回指定文件列表 114 | tim = [] 115 | 116 | for i in range(len(datas)): # i代表文件的个数 117 | tim.append(int(datas[i].split('_')[0])) 118 | '''加载最新的数据''' 119 | datas = shelve.open(Tools.memory_data + '/' + str(np.max(tim)) + '_.db', writeback=True, 120 | flag='c') # writeback=true可以随时修改存储 121 | actions = datas['actions'] 122 | screens = datas['screens'] 123 | rewards = datas['rewards'] 124 | count = datas['count'] 125 | current = datas['current'] 126 | print('\n[>^<]Data load success') 127 | return actions, screens, rewards, count, current 128 | except KeyError: 129 | print('\n[!]Data load FAILED!!!') 130 | finally: 131 | datas.close() 132 | 133 | -------------------------------------------------------------------------------- /users_plus/utils.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | import os 3 | import numpy as np 4 | import tensorflow as tf 5 | # import matplotlib.pyplot as plt 6 | import inspect 7 | import pprint 8 | 9 | 10 | pp = pprint.PrettyPrinter().pprint 11 | 12 | 13 | class Tools: 14 | hetnet_data = 'HetNet_data' 15 | checkpoints = hetnet_data + '/checkpoints' 16 | summary = hetnet_data + '/summary' 17 | train_data = hetnet_data + '/train_data' 18 | image = hetnet_data + '/image' 19 | memory_data = hetnet_data + '/memory_data' 20 | processed_data = hetnet_data + '/processed_data' 21 | test_data = hetnet_data + '/test_data' 22 | 23 | @classmethod 24 | def create_dirs(cls): 25 | if not (os.path.exists(cls.hetnet_data)): 26 | os.mkdir(cls.hetnet_data) 27 | # jjlin 28 | if not (os.path.exists(cls.checkpoints)): 29 | os.mkdir(cls.checkpoints) 30 | if not (os.path.exists(cls.summary)): 31 | os.mkdir(cls.summary) 32 | if not (os.path.exists(cls.train_data)): 33 | os.mkdir(cls.train_data) 34 | if not (os.path.exists(cls.image)): 35 | os.mkdir(cls.image) 36 | if not (os.path.exists(cls.memory_data)): 37 | os.mkdir(cls.memory_data) 38 | if not (os.path.exists(cls.processed_data)): 39 | os.mkdir(cls.processed_data) 40 | if not (os.path.exists(cls.test_data)): 41 | os.mkdir(cls.test_data) 42 | 43 | def get_epoch_data(net): # network #epoch_data include gain and adjacent_matrix 44 | gain = net.gain #gain.shape=(400,9) 45 | gain = np.reshape(gain, [60, 60]) 46 | gain_mean = np.mean(gain) 47 | adjacent_matrix = net.adjacent_matrix 48 | adjacent_matrix = np.reshape(adjacent_matrix, [60, 60]) * gain_mean #adjacent不是0和1而是具体的数值 49 | epoch_data = np.zeros((1, 2, 60, 60)) 50 | epoch_data[0, 0] = gain 51 | epoch_data[0, 1] = adjacent_matrix 52 | epoch_data = np.transpose(epoch_data, (0, 2, 3, 1)) #(1,60,60,2)这是一个state的值 53 | return epoch_data 54 | 55 | 56 | def is_gpu_available(): 57 | is_gpu = tf.test.is_gpu_available(True) 58 | return is_gpu 59 | 60 | 61 | def get_available_gpus(): 62 | """ 63 | code from http://stackoverflow.com/questions/38559755/how-to-get-current-available-gpus-in-tensorflow 64 | """ 65 | from tensorflow.python.client import device_lib as _device_lib 66 | local_device_protos = _device_lib.list_local_devices() 67 | gpu_name = [x.name for x in local_device_protos if x.device_type == 'GPU'] 68 | return len(gpu_name) # 返回gpu的个数 69 | 70 | 71 | def set_gpu(): 72 | if is_gpu_available(): 73 | gpus = get_available_gpus() 74 | print('There are %d GPUS'%gpus) 75 | os.environ["CUDA_VISIBLE_DEVICES"] = ','.join(['{i}'.format(i=a) for a in range(gpus)]) # 对所有gpu可见 76 | config = tf.ConfigProto() 77 | config.gpu_options.per_process_gpu_memory_fraction = 0.6 # 设置GPU使用量,但是需求比较大时会自动多分配 78 | # config.gpu_options.allow_growth=True # 不全部占满显存,按需分配 79 | session = tf.InteractiveSession(config=config) 80 | return session 81 | else: 82 | print('There are no gpu! ') 83 | return tf.InteractiveSession() 84 | 85 | 86 | def class_vars(obj): #m,obj config 87 | return {k: v for k, v in inspect.getmembers(obj) #--return all the members in a list of object 88 | if not k.startswith('__') and not callable(k)} #String.StartsWith 用以检测字符串是否以指定的前缀开始 89 | 90 | 91 | def str_map_float(str_array): 92 | nums = [] 93 | for strs in str_array: 94 | nums.append(float(strs)) 95 | return nums 96 | 97 | 98 | def save_data(filepath, data): 99 | np.savetxt(filepath, data, delimiter=',') 100 | 101 | # def load_data(filepath): 102 | # np.loadtxt(filepath, delimiter=',') 103 | 104 | 105 | # def get_random_action(net): 106 | # number = [] 107 | # mbs_number = np.random.randint(20, 40, size=1) 108 | # pbs_number = np.random.randint(10, 20, size=4) 109 | # fbs_number = np.random.randint(5, 10, size=4) 110 | # number += (list(mbs_number)) 111 | # number += (list(pbs_number)) 112 | # number += (list(fbs_number)) 113 | # number = np.floor(number / np.sum(number) * net.UE_num) 114 | # if np.sum(number) == net.UE_num: 115 | # return number 116 | # number[0] += int(net.UE_num - np.sum(number)) 117 | # assert np.sum(number) == net.UE_num 118 | # number = [int(num) for num in number] 119 | # return np.array(number) 120 | 121 | 122 | # def number2adjacent(net, number): 123 | # if np.sum(number) != net.UE_num: 124 | # raise Exception('用户没有完全覆盖或者用户数目不对') 125 | # adjacent_matrix = np.zeros_like(net.BS_UE_distance) 126 | # index = np.argsort(net.BS_UE_distance, axis=0) # 考虑距离进行分配是否妥当? 127 | # '''先考虑FBS的选择,后考虑PBS,再考虑MBS, 后期可以考虑添加约束条件''' 128 | # bs_user = [] 129 | # for bs in range(net.expectBS-1, -1, -1): 130 | # num = 0 131 | # while np.sum(adjacent_matrix[:, bs]) < number[bs]: 132 | # bu_temp = index[:number[bs] + num, bs] 133 | # adjacent_matrix[list(set(bu_temp).difference(set(bs_user))), bs] = 1 134 | # num += 1 135 | # bs_user = np.concatenate((bs_user, bu_temp)) 136 | # return adjacent_matrix 137 | 138 | # Tools().create_dirs() --------------------------------------------------------------------------------