├── DQN_env_customized_users_final1.py
├── DQN_env_customized_users_final_test1.py
├── README.md
├── Writedata.py
├── ddpg.py
├── environment_ddpg.py
├── environment_ddpg_tra.py
├── environment_optimize1.py
├── environment_tradition.py
├── test.ipynb
├── 传入用户-窃听
├── DQN_env_customized_users_final.py
├── Writedata.py
├── __pycache__
│ ├── Writedata.cpython-38.pyc
│ ├── environment_optimize1.cpython-38.pyc
│ └── environment_tradition.cpython-38.pyc
├── environment_optimize1.py
├── environment_tradition.py
├── epoch_cost_optimize_E25_1
├── epoch_cost_tradition_E25_1
├── local_costs_epoch_E25_1
└── test.ipynb
└── 改善环境版
├── DQN_env_wu.py
├── Environment_Wu.py
├── Environment_Wu_tradition.py
├── Writedata.py
├── __pycache__
├── Environment_Wu.cpython-38.pyc
├── Environment_Wu_tradition.cpython-38.pyc
└── Writedata.cpython-38.pyc
├── dataset
├── E_max
│ ├── all_costs.xls
│ ├── local_costs.xls
│ └── optimize_cost.xls
├── E_sum
│ ├── all_costs.csv
│ ├── local_costs.csv
│ └── optimize_cost.csv
├── optimize_cost_colluding.xls
├── optimize_cost_non-colluding.xls
└── tra_opi
│ ├── all_costs.xls
│ ├── all_costs1.xls
│ ├── all_costs2.xls
│ ├── local_costs.xls
│ ├── local_costs1.xls
│ ├── local_costs2.xls
│ ├── optimize_cost.xls
│ ├── optimize_cost1.xls
│ ├── r_list.xls
│ ├── r_list1.xls
│ ├── tradition_costs.xls
│ ├── tradition_costs1.xls
│ └── tradition_costs2.xls
└── test.ipynb
/DQN_env_customized_users_final1.py:
--------------------------------------------------------------------------------
1 | #%%
2 | import os
3 | # import Writedata
4 | os.environ['KMP_DUPLICATE_LIB_OK']='True'
5 | #2021。 10。27最终版。优化了算力和功率
6 | # 输入的s为:[任务量1✖️卸载率1,任务量2✖️卸载率2, .....]
7 | # 输出的a为某个用户卸载率增加或者减少
8 |
9 | #2cap 2user
10 |
11 | import torch
12 | import numpy as np
13 |
14 | import matplotlib.pyplot as plt
15 | from environment_optimize1 import environment
16 | from environment_tradition import environment1
17 |
18 |
19 | #%%
20 |
21 | # user_num=input("please input user_num")
22 |
23 | #初始化参数-----------------
24 | user_num=2
25 | cap_num=2
26 | users_num=int(user_num)
27 |
28 | Hn = np.abs(1.1 * np.sqrt(1 / 2) * (np.random.normal(1, 1, [user_num, cap_num]) + np.complex('j') *
29 | np.random. normal(1, 1, [user_num, cap_num]))) ** 2
30 | Hn_e = np.abs(0.1 * np.sqrt(1 / 2) * (np.random.normal(1, 1, user_num) + np.complex('j') *
31 | np.random.normal(1, 1, user_num))) ** 2##窃听者,[user1,user2]
32 | Hn_0=Hn[0]
33 | Hn_1=Hn[1]
34 |
35 | user_l = np.array([[np.random.randint(10,20), np.random.randint(150,200)]])
36 |
37 |
38 | sus=2000
39 | epochs=100
40 | #----------------
41 | env=environment(user_num=2,cap_num=2,W=[5,5],
42 | f_local=np.array([[1.4*10e8,0.43*10e8]]),
43 | omega=330 / 8,
44 | F_cap=np.array([[10*10e8,3*10e8]]),p_local=1e-1,p_tran=np.array([[2,3]]),lamuda=1,
45 | noise=0.1,Hn_0=Hn_0,Hn_1=Hn_1,Hn_e=Hn_e,user_l=user_l,
46 | suspend=sus
47 | )
48 |
49 | #改
50 | #获取环境的相关参数:
51 | n_action,n_state=env.action_state_num()
52 | #其他超参数的定义:
53 | MEMORY_CAPACITY=5000#记忆库的存储大小
54 | greedy=0.9#贪婪概率
55 | discount=0.9#折扣率
56 | batch_size=64#一次训练32个数据
57 | TARGET_REPLACE_ITER=10#目标网络的更新频率
58 |
59 | #%%
60 |
61 | class Net(torch.nn.Module):
62 | def __init__(self):
63 | super(Net, self).__init__()
64 | self.linear1=torch.nn.Linear(n_state,20)#(10,20)
65 | self.linear1.weight.data.normal_(0, 0.1)
66 | self.linear2=torch.nn.Linear(20,30)
67 | self.linear2.weight.data.normal_(0, 0.1)
68 | self.linear3=torch.nn.Linear(30,18)
69 | self.linear3.weight.data.normal_(0, 0.1)
70 | self.linear4=torch.nn.Linear(18,n_action)#(30,12)
71 | self.linear4.weight.data.normal_(0, 0.1)
72 | self.relu=torch.nn.ReLU()
73 | def forward(self,x):
74 | x=self.relu(self.linear1(x))
75 | x=self.relu(self.linear2(x))
76 | x = self.relu(self.linear3(x))
77 | q_values=self.linear4(x)
78 | return q_values
79 |
80 |
81 | #%%
82 |
83 | class DQN ():
84 | def __init__(self):#可能要改成def __init__(self,n_state,n_action)
85 |
86 | #记忆库:存s,a,r,s_ 一共6维
87 | self.memory=np.zeros((MEMORY_CAPACITY,n_state*2+2))
88 | self.memory_count=0#记忆库计数,用于求index,以及当记忆库计数 > 记忆库容量时 开始学习
89 |
90 | #目标网络,参数更新慢。参数更新跟着agent_network走。用于预测q现实
91 | self.target_network=Net()
92 |
93 | #目标网络更新计数
94 | self.learn_step_counter=0
95 |
96 | #用于训练的网络,参数更新及时。用于预测q估计
97 | self.agent_network=Net()
98 |
99 | #优化器与损失器
100 | self.loss_func=torch.nn.MSELoss()
101 | self.optimizer=torch.optim.Adam(self.agent_network.parameters(),lr=0.001)
102 | def choose_action(self,s):#这里每次只输入一个样本。
103 | # 输入的s为:[任务量1✖️卸载率1,任务量2✖️卸载率2]
104 | # 输出的action为0或1或2或3
105 | if np.random.uniform() < greedy:#选择最优动作
106 | #送入神经网络前,先要处理s成为torch型,且要求shape为(1,4)
107 | #s=torch.tensor(s,dtype=float).reshape(1,4)
108 | #s=s.to(torch.float32)
109 | s=torch.FloatTensor(s).reshape(-1,n_state)
110 |
111 | #把s送入神经网络得到a_value, a_value的shape 为(4,1)。并且得到的是四个动作q值
112 | action_value=self.agent_network.forward(s)
113 | #输出每个样本中预测的最大值,输出[最大值,下标]。只要下标
114 | _,action=torch.max(action_value.data,dim=1)
115 | #在从numpy转为int值
116 | action=action.numpy()[0]
117 | #此时action可能是0、1、2、3
118 |
119 |
120 | else:#随机选择动作
121 | action = np.random.randint(0, n_action)
122 |
123 | return action
124 |
125 | def store_transition(self,s,action,r,s_):
126 | #将四个值打包在一起
127 |
128 | #action为0or 1 or 2 or 3
129 | s=s.reshape(n_state)
130 | s_=s_.reshape(n_state)
131 |
132 | self.transition=np.hstack((s,[action,r],s_))
133 |
134 | #如果记忆库满了, 就覆盖老数据
135 | index = self.memory_count % MEMORY_CAPACITY
136 |
137 | #传入记忆库
138 |
139 | self.memory[index,:]=self.transition
140 | self.memory_count+=1
141 | #print("目前记忆库存储的总数为",self.memory_count)#要删除
142 |
143 | def learn(self):#从记忆库中选择batch个数据进行训练学习
144 | #首先判断target_network是否需要更新
145 |
146 | if self.learn_step_counter % TARGET_REPLACE_ITER==0:
147 | self.target_network.load_state_dict(self.agent_network.state_dict())#更新目标网络参数
148 | self.learn_step_counter+=1
149 |
150 | #随机从memory中抽32个数据,即batch=32
151 |
152 | sample_index=np.random.choice(MEMORY_CAPACITY,batch_size)#从0-1999中抽32个数字,shape为(32,)
153 | batch_memory=self.memory[sample_index,:]#获取32个数据。 shape 为(32,6)
154 |
155 |
156 | b_s = torch.FloatTensor(batch_memory[:, :n_state])
157 | b_a = torch.LongTensor(batch_memory[:, n_state:n_state+1].astype(int))
158 | b_r = torch.FloatTensor(batch_memory[:, n_state+1:n_state+2])
159 | b_s_ = torch.FloatTensor(batch_memory[:, -n_state:])
160 | # b_memory shape (batch,6)
161 | # b_s shape (batch,2)
162 | # b_a shape (batch,1)
163 | # b_r shape (batch,1)
164 | # b_s_ shape (batch,2)
165 |
166 |
167 | #把样本state送入agent网络训练,得到q估计
168 | q_predict=self.agent_network(b_s)#shape 为 (32,4)
169 | q_predict=q_predict.gather(1,b_a)#shaoe 为 (32,1)。根据b_a找出q估计
170 |
171 |
172 | # #把样本送入target网络计算,得到Q(s+1)
173 | # q_next=self.target_network(b_s_).detach()# q_next 不进行反向传播, 所以使用detach。shape为 (32,4)
174 | # q_next,_=torch.max(q_next,dim=1)#输出每个样本中预测的最大值,输出[最大值,下标]。只要最大值
175 | # q_next=q_next.reshape((-1,1))#q_next的shape 为(32,1)
176 | # #计算q真实
177 | # q_target=b_r+discount*q_next#q_target的shape 为(32,1)
178 |
179 | #改用ddqn
180 | q_next=self.agent_network(b_s_).detach()#
181 | _,b_a_=torch.max(q_next,dim=1)#由dqn网络选出动作
182 | b_a_=b_a_.reshape((-1,1))#b_a_的shape 为(32,1)
183 | q_next_target=self.target_network(b_s_).detach()
184 | q_next=q_next_target.gather(1,b_a_)#q_next的shape 为(32,1
185 | #计算q真实
186 | q_target=b_r+discount*q_next#q_target的shape 为(32,1)
187 |
188 |
189 |
190 | loss=self.loss_func(q_predict,q_target)
191 | # if self.learn_step_counter%5000==0:
192 | # print("第",self.learn_step_counter,"次强化学习的loss为:",loss.item())
193 | self.optimizer.zero_grad()
194 | loss.backward()
195 | self.optimizer.step()
196 | return loss.item()
197 |
198 |
199 |
200 | #%%
201 |
202 | dqn=DQN()
203 | dqn_tradition=DQN()
204 | epoch_cost_optimize=[]
205 | epoch_cost_tradition=[]
206 |
207 |
208 |
209 |
210 | epoch_list=[]
211 | loss_list=[]
212 | temp_wu_list=[]
213 | local_costs_epoch=[]
214 | all_costs_epoch=[]
215 | all_costs_epoch_tra=[]
216 | count=0
217 |
218 |
219 | #每次开始游戏前,重开游戏
220 | #s=env.reset()#s是(4,)的numpy
221 | # print("开始第",epoch+1,"轮游戏")
222 | # start = time.time()
223 | for epoch in range(epochs):
224 | print("本轮epoch=",epoch,"本轮epoch=",epoch,"本轮epoch=",epoch,"本轮epoch=",epoch)
225 | step_loss = []
226 | step_loss_tradition=[]
227 | local_costs=[]
228 | all_costs=[]
229 | all_costs_traditon = []
230 |
231 |
232 | #参数随机化
233 | Hn = np.abs(1.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, [user_num, cap_num]) + np.complex('j') *
234 |
235 | np.random.normal(1, 0.1, [user_num, cap_num]))) ** 2
236 | ##窃听者,[user1,user2]
237 | Hn_e1 = np.abs(0.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, user_num) + np.complex('j') *
238 | np.random.normal(1, 0.1, user_num))) ** 2
239 | Hn_e2 = np.abs(0.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, user_num) + np.complex('j') *
240 | np.random.normal(1, 0.1, user_num))) ** 2
241 | Hn_e3 = np.abs(0.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, user_num) + np.complex('j') *
242 | np.random.normal(1, 0.1, user_num))) ** 2
243 | Hn_e4 = np.abs(0.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, user_num) + np.complex('j') *
244 | np.random.normal(1, 0.1, user_num))) ** 2
245 | Hn_e5 = np.abs(0.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, user_num) + np.complex('j') *
246 | np.random.normal(1, 0.1, user_num))) ** 2
247 | Hn_e6 = np.abs(0.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, user_num) + np.complex('j') *
248 | np.random.normal(1, 0.1, user_num))) ** 2
249 | Hn_e7 = np.abs(0.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, user_num) + np.complex('j') *
250 | np.random.normal(1, 0.1, user_num))) ** 2
251 | Hn_e8 = np.abs(0.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, user_num) + np.complex('j') *
252 | np.random.normal(1, 0.1, user_num))) ** 2
253 | Hn_e9 = np.abs(0.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, user_num) + np.complex('j') *
254 | np.random.normal(1, 0.1, user_num))) ** 2
255 | Hn_e10 = np.abs(0.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, user_num) + np.complex('j') *
256 | np.random.normal(1, 0.1, user_num))) ** 2
257 | Hn_e11 = np.abs(0.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, user_num) + np.complex('j') *
258 | np.random.normal(1, 0.1, user_num))) ** 2
259 | Hn_e12 = np.abs(0.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, user_num) + np.complex('j') *
260 | np.random.normal(1, 0.1, user_num))) ** 2
261 | Hn_e13 = np.abs(0.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, user_num) + np.complex('j') *
262 | np.random.normal(1, 0.1, user_num))) ** 2
263 | Hn_e14 = np.abs(0.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, user_num) + np.complex('j') *
264 | np.random.normal(1, 0.1, user_num))) ** 2
265 | Hn_e15 = np.abs(0.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, user_num) + np.complex('j') *
266 | np.random.normal(1, 0.1, user_num))) ** 2
267 |
268 | # Hn_e = Hn_e1 + Hn_e2 + Hn_e3 + Hn_e4 + Hn_e5 + Hn_e6 + Hn_e7 + Hn_e8 + Hn_e9 + Hn_e10+Hn_e11 + Hn_e12 + Hn_e13 + Hn_e14 + Hn_e15
269 | # Hn_e=Hn_e1+Hn_e2+Hn_e3+Hn_e4+Hn_e5+Hn_e6+Hn_e7+Hn_e8+Hn_e9+Hn_e10
270 | Hn_e=Hn_e1
271 | # Hn_e=Hn_e1
272 |
273 | # Hn_e=Hn_e1
274 | Hn_0 = Hn[0]
275 | Hn_1 = Hn[1]
276 |
277 | while((Hn_e > Hn_1).any() or (Hn_e > Hn_0).any()):
278 | Hn = np.abs(1.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, [user_num, cap_num]) + np.complex('j') *
279 | np.random.normal(1, 0.1, [user_num, cap_num]))) ** 2
280 | ##窃听者,[user1,user2]
281 |
282 | Hn_e1 = np.abs(0.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, user_num) + np.complex('j') *
283 | np.random.normal(1, 0.1, user_num))) ** 2
284 | Hn_e2 = np.abs(0.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, user_num) + np.complex('j') *
285 | np.random.normal(1, 0.1, user_num))) ** 2
286 | Hn_e3 = np.abs(0.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, user_num) + np.complex('j') *
287 | np.random.normal(1, 0.1, user_num))) ** 2
288 | Hn_e4 = np.abs(0.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, user_num) + np.complex('j') *
289 | np.random.normal(1, 0.1, user_num))) ** 2
290 | Hn_e5 = np.abs(0.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, user_num) + np.complex('j') *
291 | np.random.normal(1, 0.1, user_num))) ** 2
292 | Hn_e6 = np.abs(0.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, user_num) + np.complex('j') *
293 | np.random.normal(1, 0.1, user_num))) ** 2
294 | Hn_e7 = np.abs(0.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, user_num) + np.complex('j') *
295 | np.random.normal(1, 0.1, user_num))) ** 2
296 | Hn_e8 = np.abs(0.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, user_num) + np.complex('j') *
297 | np.random.normal(1, 0.1, user_num))) ** 2
298 | Hn_e9 = np.abs(0.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, user_num) + np.complex('j') *
299 | np.random.normal(1, 0.1, user_num))) ** 2
300 | Hn_e10 = np.abs(0.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, user_num) + np.complex('j') *
301 | np.random.normal(1, 0.1, user_num))) ** 2
302 | Hn_e11 = np.abs(0.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, user_num) + np.complex('j') *
303 | np.random.normal(1, 0.1, user_num))) ** 2
304 | Hn_e12 = np.abs(0.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, user_num) + np.complex('j') *
305 | np.random.normal(1, 0.1, user_num))) ** 2
306 | Hn_e13 = np.abs(0.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, user_num) + np.complex('j') *
307 | np.random.normal(1, 0.1, user_num))) ** 2
308 | Hn_e14 = np.abs(0.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, user_num) + np.complex('j') *
309 | np.random.normal(1, 0.1, user_num))) ** 2
310 | Hn_e15 = np.abs(0.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, user_num) + np.complex('j') *
311 | np.random.normal(1, 0.1, user_num))) ** 2
312 | # Hn_e = Hn_e1 + Hn_e2 + Hn_e3 + Hn_e4 + Hn_e5 + Hn_e6 + Hn_e7 + Hn_e8 + Hn_e9 + Hn_e10 + Hn_e11 + Hn_e12 + Hn_e13 + Hn_e14 + Hn_e15
313 | # Hn_e = Hn_e1 + Hn_e2 + Hn_e3 + Hn_e4 + Hn_e5 + Hn_e6 + Hn_e7 + Hn_e8 + Hn_e9 + Hn_e10
314 | Hn_e = Hn_e1
315 | # Hn_e = Hn_e1
316 |
317 | #共谋:sum
318 | Hn_0 = Hn[0]
319 | Hn_1 = Hn[1]
320 |
321 |
322 | # user_l = np.array([[np.random.randint(10,60), np.random.randint(550,600)]])
323 | user_l=np.array([[10,550]])
324 | #--------------------------
325 | #------------优化功率和算力-------------
326 | env = environment(user_num=2, cap_num=2, W=5.0,
327 | f_local=np.array([[1.4 * 10e8, 0.43 * 10e8]]),
328 | omega=330 / 8,
329 | F_cap=np.array([[10 * 10e8, 3 * 10e8]]), p_local=1e-1, p_tran=np.array([[2, 3]]), lamuda=1,
330 | noise=0.1, Hn_0=Hn_0, Hn_1=Hn_1,Hn_e=Hn_e,user_l=user_l,
331 | suspend=sus
332 | )
333 | s = env.reset()
334 | while True:#每次循环执行一个动作
335 |
336 | #通过神经网络,输入状态,获取动作。(不带学习)
337 | action=dqn.choose_action(s)
338 |
339 | #执行,获得环境反馈
340 | s_,r,done,tc_wald,local_cost,all_cost=env.step(action)
341 | step_loss.append(tc_wald)
342 | local_costs.append(local_cost)
343 | all_costs.append(all_cost)
344 | #将环境的反馈s,a,r,s_传入记忆库。用于经验回放
345 | dqn.store_transition(s,action,r,s_)
346 |
347 | #神经网络学习(experience replay 经验回放)
348 | if dqn.memory_count > MEMORY_CAPACITY:
349 | count+=1
350 | loss=dqn.learn()
351 |
352 |
353 | #判断是否结束
354 | if done !=0:
355 | epoch_cost_optimize.append(done)
356 | local_costs_epoch.append(local_cost)
357 | all_costs_epoch.append(all_cost)
358 | break
359 |
360 | #更新状态,进入下一次循环
361 | s=s_
362 | #--------------------------------------------
363 |
364 |
365 | # ------------传统方法-------------
366 | env_tradition = environment1(user_num=2, cap_num=2, W=5.0,
367 | f_local=np.array([[1.4 * 10e8, 0.43 * 10e8]]),
368 | omega=330 / 8,
369 | F_cap=np.array([[10 * 10e8, 3 * 10e8]]), p_local=1e-1, p_tran=np.array([[2, 3]]),
370 | lamuda=1,
371 | noise=0.1, Hn_0=Hn_0, Hn_1=Hn_1, Hn_e=Hn_e, user_l=user_l,
372 | suspend=sus
373 | )
374 | s=env_tradition.reset()
375 | while True: # 每次循环执行一个动作
376 |
377 | # 通过神经网络,输入状态,获取动作。(不带学习)
378 | action = dqn_tradition.choose_action(s)
379 |
380 | # 执行,获得环境反馈
381 | s_, r, done, tc_wald, local_cost,all_cost_traditon = env_tradition.step(action)
382 | step_loss_tradition.append(tc_wald)
383 | all_costs_traditon.append(all_cost_traditon)
384 | # local_costs.append(local_cost)
385 |
386 | # 将环境的反馈s,a,r,s_传入记忆库。用于经验回放
387 | dqn_tradition.store_transition(s, action, r, s_)
388 |
389 | # 神经网络学习(experience replay 经验回放)
390 | if dqn_tradition.memory_count > MEMORY_CAPACITY:
391 | count += 1
392 | loss = dqn_tradition.learn()
393 |
394 | # 判断是否结束
395 | if done!=0:
396 | epoch_cost_tradition.append(done)
397 | all_costs_epoch_tra.append(all_cost_traditon)
398 | break
399 |
400 | # 更新状态,进入下一次循环
401 | s = s_
402 | # --------------------------------------------
403 |
404 |
405 | plt.plot(range(sus), step_loss, color='skyblue', label='optimize_F_P')
406 | plt.plot(range(sus), step_loss_tradition, color='red', label='tradition')
407 | plt.plot(range(sus),local_costs,color="yellow",label="local")
408 | plt.plot(range(sus), all_costs_traditon, color="green", label='all_off_tra')
409 | plt.legend(loc="best")
410 |
411 | plt.xlabel("step_dqn")
412 | plt.ylabel("costs")
413 | plt.show()
414 |
415 |
416 | # plt.plot(range(epochs),local_costs_epoch, color='yellow', label='locals')
417 | plt.plot(range(epochs),epoch_cost_optimize,color='skyblue', label='optimize_F_P')
418 | plt.plot(range(epochs),epoch_cost_tradition,color='red', label='tradition')
419 | plt.plot(range(epochs),all_costs_epoch,color='purple', label="all_off")
420 | # plt.plot(range(epochs),all_costs_epoch_tra,color='mediumpurple', label="all_off_Tra")
421 |
422 | # Writedata.write_to_excel(epoch_cost_optimize,1,"epoch_cost_optimize_E5_3")
423 | # Writedata.write_to_excel(epoch_cost_tradition,1,"epoch_cost_tradition_E5_3")
424 | # Writedata.write_to_excel(local_costs_epoch,1,"local_costs_epoch_E5_3")
425 |
426 | plt.xlabel("epoch")
427 | plt.ylabel("costs")
428 | plt.legend(loc="best")
429 | plt.show()
430 |
431 | #保存数据
432 |
433 | Writedata.write_to_excel(epoch_cost_optimize,1,"./dataset/tra_opi/optimize_cost2.xls")#优化
434 | Writedata.write_to_excel(all_costs_epoch,1,"./dataset/tra_opi/all_costs2.xls")#优化的全卸载
435 | Writedata.write_to_excel(local_costs_epoch,1,"./dataset/tra_opi/local_costs2.xls")#本地
436 | Writedata.write_to_excel(epoch_cost_tradition,1,"./dataset/tra_opi/tradition_costs2.xls")#传统方法
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # offloading-optimization-and-resource-optimization-base-on-mobile-edge-computing-net
2 | 基于边缘计算网络的卸载优化及资源优化
3 |
4 | 考虑了一个多用户单窃听者的移动边缘计算(MEC)网络,通过使用深度强化学习算法,并结合凸优化,对MEC网络进行了卸载优化与资源优化。
5 |
6 | 仿真结果如下所示(部分):
7 |
8 | 
9 | 上图展示的是窃听者共谋的结果。从图中可以明显看出,仅仅跑了100epoch,DQN所跑出来的结果明显优于全本地与全卸载。并且趋近于收敛趋势(笔者自己跑的epoch太少了,跑500个epoch应该就能收敛了)。说明DQN从网络中学习到了相关知识,并将网络性能优化。
10 | 
11 | 上图展示的是窃听者非共谋的结果。由于非共谋的窃听者会对网络环境产生较大的干扰,所以从途中可以明显看出此图较上图而言存在着明显的波动。但是在如此大干扰情况下,DQN仍能从中学习到知识,并将网络性能优化。
12 |
13 | 
14 | 最后一张图展示的是,结合了传统的MEC优化算法,在这过程中,我们所提出的DQN分配卸载策略,凸优化解决资源分配的算法仍比传统的MEC优化算法更优。这说明我们所提出的算法相较于传统优化算法有着更好的优势
15 |
16 | 系统模型图如下所示:
17 |
18 |
19 | DQN的结构如下两张图所示:
20 |
21 | 
22 |
23 | 
24 |
25 |
26 |
--------------------------------------------------------------------------------
/Writedata.py:
--------------------------------------------------------------------------------
1 | import xlrd
2 | from xlwt import *
3 |
4 |
5 | # 多次实验时写入数据代码
6 | def write_data(data_list, sheet_name, iteration):
7 | for each_i in range(len(data_list)):
8 | sheet_name.write(each_i, iteration, str(data_list[each_i]))
9 |
10 |
11 | def create_csv(sheet1, data_list, iteration=1):
12 | write_data(data_list=data_list, sheet_name=sheet1, iteration=iteration)
13 |
14 |
15 | def write_to_excel(cost_list, is_one, filename):
16 | wb = Workbook()
17 | sheet1 = wb.add_sheet(sheetname='cost')
18 | if is_one:
19 | create_csv(sheet1=sheet1, data_list=cost_list)
20 | else:
21 | for index in range(len(cost_list)):
22 | create_csv(sheet1=sheet1, data_list=cost_list[index], iteration=index)
23 | wb.save(filename)
24 |
25 |
26 | def read_file(h_file, task_file):
27 | channel_uc = xlrd.open_workbook(h_file)
28 | task_file = xlrd.open_workbook(task_file)
29 | uc_sheet = channel_uc.sheets()[0]
30 | task_sheet = task_file.sheets()[0]
31 |
32 | return uc_sheet, task_sheet
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/ddpg.py:
--------------------------------------------------------------------------------
1 | #%%
2 | import os
3 | os.environ['KMP_DUPLICATE_LIB_OK']='True'
4 | # S=[任务量1✖️卸载率1,任务量2✖️卸载率2]
5 | #A=[卸载率1,卸载率2]
6 | import numpy as np
7 | import torch
8 | # from environment1_customized_users_final import environment
9 | from environment_ddpg import environment
10 | from environment_ddpg_tra import environment1
11 | import matplotlib.pyplot as plt
12 |
13 | #%%
14 |
15 | # user_num=input("please input user_num")
16 |
17 | #初始化参数-----------------
18 | user_num=2
19 | cap_num=2
20 | users_num=int(user_num)
21 |
22 | Hn = np.abs(1.1 * np.sqrt(1 / 2) * (np.random.normal(1, 1, [user_num, cap_num]) + np.complex('j') *
23 | np.random. normal(1, 1, [user_num, cap_num]))) ** 2
24 | Hn_e = np.abs(0.1 * np.sqrt(1 / 2) * (np.random.normal(1, 1, user_num) + np.complex('j') *
25 | np.random.normal(1, 1, user_num))) ** 2##窃听者,[user1,user2]
26 | Hn_0=Hn[0]
27 | Hn_1=Hn[1]
28 |
29 | user_l = np.array([[np.random.randint(10,20), np.random.randint(150,200)]])
30 |
31 |
32 | sus=2000
33 | epochs=100
34 | #----------------
35 | env=environment(user_num=2,cap_num=2,W=[5,5],
36 | f_local=np.array([[1.4*10e8,0.43*10e8]]),
37 | omega=330 / 8,
38 | F_cap=np.array([[10*10e8,3*10e8]]),p_local=1e-1,p_tran=np.array([[2,3]]),lamuda=1,
39 | noise=0.1,Hn_0=Hn_0,Hn_1=Hn_1,Hn_e=Hn_e,user_l=user_l,
40 | suspend=sus
41 | )
42 |
43 |
44 |
45 |
46 | n_action,n_state=env.action_state_num()
47 |
48 | memory_size=5000#记忆库大小
49 | batch_size=64#batch大小
50 | discount=0.9#折扣率
51 | var1=1#var为方差,用于对a添加高斯分布的噪音
52 | var=1
53 | TAU = 0.01 #用于逐步更新target网络
54 |
55 | #%%
56 |
57 | #先构建神经网络:
58 |
59 | #Actor
60 |
61 | class Aactor(torch.nn.Module):
62 | def __init__(self):
63 | super(Aactor,self).__init__()
64 | self.fc1=torch.nn.Linear(n_state,30)
65 | self.fc1.weight.data.normal_(0, 0.1)
66 |
67 | self.fc2_user1=torch.nn.Linear(30,15)#user1
68 | self.fc2_user1.weight.data.normal_(0, 0.1)
69 |
70 | self.fc2_user2=torch.nn.Linear(30,15)##user2
71 | self.fc2_user2.weight.data.normal_(0, 0.1)
72 |
73 | self.fc3_user1=torch.nn.Linear(15,8)#user1
74 | self.fc3_user1.weight.data.normal_(0, 0.1)
75 |
76 | self.fc3_user2 = torch.nn.Linear(15, 8)##user2
77 | self.fc3_user2.weight.data.normal_(0, 0.1)
78 |
79 | self.fc4_user1 = torch.nn.Linear(8, 3)#user1
80 | self.fc4_user1.weight.data.normal_(0, 0.1)
81 |
82 | self.fc4_user2 = torch.nn.Linear(8, 3)#user2
83 | self.fc4_user2.weight.data.normal_(0, 0.1)
84 |
85 | self.relu=torch.nn.ReLU()
86 | self.softmax=torch.nn.Softmax()
87 | self.sigmoid=torch.nn.Sigmoid()
88 | def forward(self,s):
89 | x=self.sigmoid(self.fc1(s))
90 | x_user1=self.sigmoid(self.fc2_user1(x))
91 | x_user1 = self.sigmoid(self.fc3_user1(x_user1))
92 | x_user1=self.fc4_user1(x_user1)
93 | x_user1 = self.softmax(x_user1)
94 |
95 | x_user2=self.sigmoid(self.fc2_user2(x))
96 | x_user2 = self.sigmoid(self.fc3_user2(x_user2))
97 | x_user2 = self.softmax(self.fc4_user2(x_user2))
98 | x = torch.cat((x_user1, x_user2), dim=1)
99 |
100 | return x
101 |
102 | class Critic(torch.nn.Module):
103 | def __init__(self):
104 | super(Critic, self).__init__()
105 | self.fc_a1=torch.nn.Linear(n_state,16)
106 | self.fc_a1.weight.data.normal_(0, 0.1)
107 |
108 | self.fc_b1=torch.nn.Linear(n_action,10)
109 | self.fc_b1.weight.data.normal_(0, 0.1)
110 |
111 | self.fc_ab1=torch.nn.Linear(26,18)#采用简单的加合
112 | self.fc_ab1.weight.data.normal_(0, 0.1)
113 |
114 | self.fc_ab2=torch.nn.Linear(18,1)
115 | self.fc_ab2.weight.data.normal_(0, 0.1)
116 |
117 | self.relu=torch.nn.ReLU()
118 | def forward(self,s,a):#输出s和a,分别输入到一开始不同的网络,然后在第二层的时候加合在一起,在一起训练
119 | s=self.fc_a1(s)
120 | a=self.fc_b1(a)
121 | x=torch.cat((s,a),dim=1)
122 | x=self.relu(x)
123 | x=self.relu(self.fc_ab1(x))
124 | x=self.fc_ab2(x)
125 | return x
126 |
127 | #%%
128 |
129 | # criterion=torch.nn.CrossEntropyLoss()
130 | # optimizer=torch.optim.Adam(model.parameters(),lr=3e-4)
131 |
132 | class DDPG():
133 | def __init__(self):
134 | #构建记忆库
135 | self.memory=np.zeros((memory_size,n_state*2+n_action+1),dtype=np.float32)
136 | self.memory_count=0#用于标记存了多少
137 | #构建Actor网络
138 | self.Actor_eval=Aactor()
139 | self.Actor_target=Aactor()
140 | self.optimizer_Actor=torch.optim.Adam(self.Actor_eval.parameters(),lr=3e-4)
141 |
142 | #构建Critic网络
143 | self.Critic_eval=Critic()
144 | self.Critic_target=Critic()
145 | self.optimizer_Critic=torch.optim.Adam(self.Critic_eval.parameters(),lr=3e-4)
146 | self.loss_func=torch.nn.MSELoss()
147 |
148 | def choose_action(self,s):#输入状态s,输出动作
149 | # s=torch.FloatTensor(s).reshape(-1,n_state)
150 | # a=self.Actor_eval(s).detach()#a为[1,1]
151 | # a=a.numpy()[0]#a变为array([0.07249027]),因为step(a)需要传入array
152 |
153 | s = torch.FloatTensor(s)
154 | a=self.Actor_eval(s).detach()
155 | a=a.numpy()
156 | return a
157 |
158 | # return a
159 |
160 | def store_transition(self,s,a,r,s_):
161 |
162 | s=s.reshape(-1,)
163 | a=a.reshape(-1,)
164 | s_=s_.reshape(-1,)
165 |
166 | transition=np.hstack((s,a,[r],s_))
167 |
168 | #获得索引
169 | self.index=self.memory_count%memory_size
170 |
171 | #存入memory
172 | self.memory[self.index,:]=transition
173 | self.memory_count+=1
174 |
175 | # transition = np.hstack((s, a, [r], s_))
176 | # index = self.memory_count % memory_size # replace the old memory with new memory
177 | # self.memory[index, :] = transition
178 | # self.memory_count += 1
179 |
180 | if self.memory_count==memory_size:
181 | print("开始学习!!")
182 |
183 | def learn(self):
184 | #具体更新,还没看
185 | for x in self.Actor_target.state_dict().keys():
186 | eval('self.Actor_target.' + x + '.data.mul_((1-TAU))')
187 | eval('self.Actor_target.' + x + '.data.add_(TAU*self.Actor_eval.' + x + '.data)')
188 | for x in self.Critic_target.state_dict().keys():
189 | eval('self.Critic_target.' + x + '.data.mul_((1-TAU))')
190 | eval('self.Critic_target.' + x + '.data.add_(TAU*self.Critic_eval.' + x + '.data)')
191 |
192 | #随机抽样
193 | sample_index=np.random.choice(memory_size,size=batch_size)#从0-1999中抽batch_size个数,shape为[32,]
194 | batch_memory=self.memory[sample_index,:]#batch_memory的shape为[32,8]
195 |
196 | b_s = torch.FloatTensor(batch_memory[:, :n_state])#shape为[32,4]
197 | b_a = torch.FloatTensor(batch_memory[:, n_state:n_state+n_action])#shape为[32,4]
198 | b_r = torch.FloatTensor(batch_memory[:, n_state+n_action:n_state+n_action+1])#shape为[32,1]
199 | b_s_ = torch.FloatTensor(batch_memory[:, -n_state:])#shape为[32,3]
200 |
201 |
202 | #计算由Actor网络计算出来的S的a值,并打分
203 | a=self.Actor_eval(b_s)#shape:[32,1]
204 | q=self.Critic_eval(b_s,a)#shape:[32,1]
205 |
206 | #更新Actor_eval网络
207 | loss2=-torch.mean(q)
208 | self.optimizer_Actor.zero_grad()
209 | loss2.backward()
210 | self.optimizer_Actor.step()
211 |
212 | #计算St的q_eval
213 | q_eval=self.Critic_eval(b_s,b_a)
214 | #计算St+1的q_target
215 | a_=self.Actor_target(b_s_).detach()#shape:[32,1]
216 | q_target=self.Critic_target(b_s_,a_).detach()#shape:[32,1]
217 | q_target=b_r+discount*q_target#shape:[32,1]
218 |
219 | #
220 | q_eval=q_eval.reshape(-1,1)
221 | q_target=q_target.reshape(-1,1)
222 |
223 | #更新critic_eval网络
224 | loss=self.loss_func(q_eval, q_target)
225 | self.optimizer_Critic.zero_grad()
226 | loss.backward()
227 | self.optimizer_Critic.step()
228 |
229 |
230 | ddpg=DDPG()
231 | ddpg_tradition=DDPG()
232 | epoch_cost_optimize=[]
233 | epoch_cost_tradition=[]
234 |
235 | epoch_list=[]
236 | loss_list=[]
237 | temp_wu_list=[]
238 | local_costs_epoch=[]
239 | all_costs_epoch=[]
240 | all_costs_epoch_tra=[]
241 | count=0
242 |
243 |
244 | #%%
245 |
246 | for epoch in range(epochs):
247 | print("本轮epoch=",epoch,"本轮epoch=",epoch,"本轮epoch=",epoch,"本轮epoch=",epoch)
248 | step_loss = []
249 | step_loss_tradition = []
250 | local_costs = []
251 | all_costs = []
252 | all_costs_traditon = []
253 |
254 | # 参数随机化
255 | Hn = np.abs(1.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, [user_num, cap_num]) + np.complex('j') *
256 |
257 | np.random.normal(1, 0.1, [user_num, cap_num]))) ** 2
258 | ##窃听者,[user1,user2]
259 | Hn_e1 = np.abs(0.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, user_num) + np.complex('j') *
260 | np.random.normal(1, 0.1, user_num))) ** 2
261 | Hn_e2 = np.abs(0.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, user_num) + np.complex('j') *
262 | np.random.normal(1, 0.1, user_num))) ** 2
263 | Hn_e3 = np.abs(0.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, user_num) + np.complex('j') *
264 | np.random.normal(1, 0.1, user_num))) ** 2
265 | Hn_e4 = np.abs(0.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, user_num) + np.complex('j') *
266 | np.random.normal(1, 0.1, user_num))) ** 2
267 | Hn_e5 = np.abs(0.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, user_num) + np.complex('j') *
268 | np.random.normal(1, 0.1, user_num))) ** 2
269 | Hn_e6 = np.abs(0.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, user_num) + np.complex('j') *
270 | np.random.normal(1, 0.1, user_num))) ** 2
271 | Hn_e7 = np.abs(0.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, user_num) + np.complex('j') *
272 | np.random.normal(1, 0.1, user_num))) ** 2
273 | Hn_e8 = np.abs(0.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, user_num) + np.complex('j') *
274 | np.random.normal(1, 0.1, user_num))) ** 2
275 | Hn_e9 = np.abs(0.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, user_num) + np.complex('j') *
276 | np.random.normal(1, 0.1, user_num))) ** 2
277 | Hn_e10 = np.abs(0.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, user_num) + np.complex('j') *
278 | np.random.normal(1, 0.1, user_num))) ** 2
279 | Hn_e11 = np.abs(0.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, user_num) + np.complex('j') *
280 | np.random.normal(1, 0.1, user_num))) ** 2
281 | Hn_e12 = np.abs(0.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, user_num) + np.complex('j') *
282 | np.random.normal(1, 0.1, user_num))) ** 2
283 | Hn_e13 = np.abs(0.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, user_num) + np.complex('j') *
284 | np.random.normal(1, 0.1, user_num))) ** 2
285 | Hn_e14 = np.abs(0.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, user_num) + np.complex('j') *
286 | np.random.normal(1, 0.1, user_num))) ** 2
287 | Hn_e15 = np.abs(0.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, user_num) + np.complex('j') *
288 | np.random.normal(1, 0.1, user_num))) ** 2
289 |
290 | # Hn_e = Hn_e1 + Hn_e2 + Hn_e3 + Hn_e4 + Hn_e5 + Hn_e6 + Hn_e7 + Hn_e8 + Hn_e9 + Hn_e10+Hn_e11 + Hn_e12 + Hn_e13 + Hn_e14 + Hn_e15
291 | # Hn_e=Hn_e1+Hn_e2+Hn_e3+Hn_e4+Hn_e5+Hn_e6+Hn_e7+Hn_e8+Hn_e9+Hn_e10
292 | Hn_e = Hn_e1 + Hn_e2 + Hn_e3 + Hn_e4 + Hn_e5
293 | # Hn_e=Hn_e1
294 |
295 | # Hn_e=Hn_e1
296 | Hn_0 = Hn[0]
297 | Hn_1 = Hn[1]
298 |
299 | while ((Hn_e > Hn_1).any() or (Hn_e > Hn_0).any()):
300 | Hn = np.abs(1.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, [user_num, cap_num]) + np.complex('j') *
301 | np.random.normal(1, 0.1, [user_num, cap_num]))) ** 2
302 | ##窃听者,[user1,user2]
303 |
304 | Hn_e1 = np.abs(0.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, user_num) + np.complex('j') *
305 | np.random.normal(1, 0.1, user_num))) ** 2
306 | Hn_e2 = np.abs(0.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, user_num) + np.complex('j') *
307 | np.random.normal(1, 0.1, user_num))) ** 2
308 | Hn_e3 = np.abs(0.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, user_num) + np.complex('j') *
309 | np.random.normal(1, 0.1, user_num))) ** 2
310 | Hn_e4 = np.abs(0.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, user_num) + np.complex('j') *
311 | np.random.normal(1, 0.1, user_num))) ** 2
312 | Hn_e5 = np.abs(0.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, user_num) + np.complex('j') *
313 | np.random.normal(1, 0.1, user_num))) ** 2
314 | Hn_e6 = np.abs(0.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, user_num) + np.complex('j') *
315 | np.random.normal(1, 0.1, user_num))) ** 2
316 | Hn_e7 = np.abs(0.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, user_num) + np.complex('j') *
317 | np.random.normal(1, 0.1, user_num))) ** 2
318 | Hn_e8 = np.abs(0.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, user_num) + np.complex('j') *
319 | np.random.normal(1, 0.1, user_num))) ** 2
320 | Hn_e9 = np.abs(0.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, user_num) + np.complex('j') *
321 | np.random.normal(1, 0.1, user_num))) ** 2
322 | Hn_e10 = np.abs(0.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, user_num) + np.complex('j') *
323 | np.random.normal(1, 0.1, user_num))) ** 2
324 | Hn_e11 = np.abs(0.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, user_num) + np.complex('j') *
325 | np.random.normal(1, 0.1, user_num))) ** 2
326 | Hn_e12 = np.abs(0.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, user_num) + np.complex('j') *
327 | np.random.normal(1, 0.1, user_num))) ** 2
328 | Hn_e13 = np.abs(0.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, user_num) + np.complex('j') *
329 | np.random.normal(1, 0.1, user_num))) ** 2
330 | Hn_e14 = np.abs(0.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, user_num) + np.complex('j') *
331 | np.random.normal(1, 0.1, user_num))) ** 2
332 | Hn_e15 = np.abs(0.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, user_num) + np.complex('j') *
333 | np.random.normal(1, 0.1, user_num))) ** 2
334 | # Hn_e = Hn_e1 + Hn_e2 + Hn_e3 + Hn_e4 + Hn_e5 + Hn_e6 + Hn_e7 + Hn_e8 + Hn_e9 + Hn_e10 + Hn_e11 + Hn_e12 + Hn_e13 + Hn_e14 + Hn_e15
335 | # Hn_e = Hn_e1 + Hn_e2 + Hn_e3 + Hn_e4 + Hn_e5 + Hn_e6 + Hn_e7 + Hn_e8 + Hn_e9 + Hn_e10
336 | Hn_e = Hn_e1 + Hn_e2 + Hn_e3 + Hn_e4 + Hn_e5
337 | # Hn_e = Hn_e1
338 |
339 | # 共谋:sum
340 | Hn_0 = Hn[0]
341 | Hn_1 = Hn[1]
342 |
343 | user_l = np.array([[np.random.randint(10, 60), np.random.randint(550, 600)]])
344 | # ------------优化功率和算力-------------
345 | env = environment(user_num=2, cap_num=2, W=5.0,
346 | f_local=np.array([[1.4 * 10e8, 0.43 * 10e8]]),
347 | omega=330 / 8,
348 | F_cap=np.array([[10 * 10e8, 3 * 10e8]]), p_local=1e-1, p_tran=np.array([[2, 3]]), lamuda=1,
349 | noise=0.1, Hn_0=Hn_0, Hn_1=Hn_1, Hn_e=Hn_e, user_l=user_l,
350 | suspend=sus
351 | )
352 | s = env.reset()
353 | while True:
354 |
355 | #选择动作
356 | action=ddpg.choose_action(s)
357 |
358 | # 让动作加入高斯分布后输入环境
359 | # action = np.clip(np.random.normal(action, var1), 0, 1)
360 |
361 | # 执行,获得环境反馈
362 | s_, r, done, tc_wald, local_cost, all_cost = env.step(action)
363 | step_loss.append(tc_wald)
364 | local_costs.append(local_cost)
365 | all_costs.append(all_cost)
366 |
367 | #存入记忆库
368 | ddpg.store_transition(s,action,r,s_)
369 |
370 | #学习
371 | if ddpg.memory_count>memory_size:
372 | count+=1
373 | va1r=var1*0.9995 #逐步减少噪音
374 | ddpg.learn()
375 |
376 | #判断是否结束
377 | if done:
378 | epoch_cost_optimize.append(done)
379 | local_costs_epoch.append(local_cost)
380 | all_costs_epoch.append(all_cost)
381 | break
382 |
383 | s=s_
384 | # ------------传统方法-------------
385 | env_tradition = environment1(user_num=2, cap_num=2, W=5.0,
386 | f_local=np.array([[1.4 * 10e8, 0.43 * 10e8]]),
387 | omega=330 / 8,
388 | F_cap=np.array([[10 * 10e8, 3 * 10e8]]), p_local=1e-1, p_tran=np.array([[2, 3]]),
389 | lamuda=1,
390 | noise=0.1, Hn_0=Hn_0, Hn_1=Hn_1, Hn_e=Hn_e, user_l=user_l,
391 | suspend=sus
392 | )
393 | s = env_tradition.reset()
394 | while True:
395 |
396 | # 选择动作
397 | action = ddpg_tradition.choose_action(s)
398 |
399 | # 让动作加入高斯分布后输入环境
400 | # action = np.clip(np.random.normal(action, var), 0, 1)
401 |
402 | # 执行,获得环境反馈
403 | s_, r, done, tc_wald, local_cost,all_cost_traditon = env_tradition.step(action)
404 | step_loss_tradition.append(tc_wald)
405 | all_costs_traditon.append(all_cost_traditon)
406 |
407 | # 存入记忆库
408 | ddpg_tradition.store_transition(s, action, r, s_)
409 |
410 | # 学习
411 | if ddpg_tradition.memory_count > memory_size:
412 | count += 1
413 | ddpg_tradition.learn()
414 |
415 | # 判断是否结束
416 | if done:
417 | epoch_cost_tradition.append(done)
418 | all_costs_epoch_tra.append(all_cost_traditon)
419 | break
420 |
421 | s = s_
422 |
423 |
424 | plt.plot(range(sus), step_loss, color='skyblue', label='optimize_F_P')
425 | plt.plot(range(sus), step_loss_tradition, color='red', label='tradition')
426 | # plt.plot(range(sus),local_costs,color="yellow",label="local")
427 | # plt.plot(range(sus),all_costs,color="purple",label="all_off")
428 | # plt.plot(range(sus), all_costs_traditon, color="green", label='all_off_tra')
429 | plt.legend(loc="best")
430 |
431 | plt.xlabel("step_dqn_15")
432 | plt.ylabel("costs")
433 | plt.show()
434 |
435 |
436 | plt.plot(range(epochs),local_costs_epoch, color='yellow', label='locals')
437 | plt.plot(range(epochs),epoch_cost_optimize,color='skyblue', label='optimize_F_P')
438 | plt.plot(range(epochs),epoch_cost_tradition,color='red', label='tradition')
439 | plt.plot(range(epochs),all_costs_epoch,color='purple', label="all_off")
440 | plt.plot(range(epochs),all_costs_epoch_tra,color='mediumpurple', label="all_off_Tra")
441 |
442 | # Writedata.write_to_excel(epoch_cost_optimize,1,"epoch_cost_optimize_E5_3")
443 | # Writedata.write_to_excel(epoch_cost_tradition,1,"epoch_cost_tradition_E5_3")
444 | # Writedata.write_to_excel(local_costs_epoch,1,"local_costs_epoch_E5_3")
445 |
446 | plt.xlabel("epoch_e15")
447 | plt.ylabel("costs")
448 | plt.legend(loc="best")
449 | plt.show()
450 |
--------------------------------------------------------------------------------
/environment_ddpg.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | import pandas as pd
3 | import copy
4 | import math
5 |
6 | # S=[任务量✖️卸载率,总算力,总功率]
7 | # A=[卸载率1增,卸载率1减,卸载率2增,卸载率2减,。。。]
8 |
9 |
10 | class environment(object): # 奖励r由tc与tc-1比较大小得出。Hn:0.992912817258564, 0.992299817945962
11 | def __init__(self, user_num, cap_num, W, f_local, omega, F_cap, p_local, p_tran, lamuda, noise, Hn_0,Hn_1,Hn_e,user_l, suspend):
12 | # user_num:用户总数, cap_num:cap总数,W:单个CAP的总带宽,f_local为本地用户计算能力,omega:计算时间T的w
13 | # C为计算时间的传输速率,F_cap:分配给user的计算能力,p_local:本地计算功率,p_tran:传输功率;lamuda:时间与能耗之间的比例系数
14 | # noise:噪音的方差,用于计算香农公式的C;Hn:香农公式的hnm,用于计算C。suspend:用于判断执行多少次动作后停止
15 | self.user_num = user_num
16 | self.cap_num = cap_num
17 |
18 | self.f = f_local
19 | self.omega = omega
20 |
21 | #W为总带宽,[capA,capB],需要取出来
22 | self.W0 = W
23 | self.W1 = W
24 |
25 | # F_cap为算力(优化对象),[CAPA,CAPB],需分别均分给n个设备
26 |
27 | self.F_cap=F_cap
28 | self.F_0 = F_cap[0][0] / self.user_num#均分算力
29 | self.F_1 = F_cap[0][1] / self.user_num#均分算力
30 |
31 |
32 |
33 | self.F_capA = np.full(shape=(1,self.user_num),fill_value=self.F_0)#capA均分给每一个user的算力
34 | self.F_capB = np.full(shape=(1, self.user_num), fill_value=self.F_1) #capB均分给每一个user的算力
35 |
36 | #传输带宽(优化对象),p_tran总传输功率[user1,user2]
37 | self.p_tran=p_tran
38 | p_tran_0 = self.p_tran[0][0] / self.cap_num
39 | p_tran_1 = self.p_tran[0][1] / self.cap_num
40 |
41 | self.p_tran_user1 = np.full(shape=(1, self.cap_num), fill_value=p_tran_0) # 第一个user分给不同信道的传输功率
42 | self.p_tran_user2 = np.full(shape=(1, self.cap_num), fill_value=p_tran_1) # 第二个user分给不同信道的传输功率
43 |
44 | self.p_tran_capA = np.array([[self.p_tran_user1[0][0], self.p_tran_user2[0][0]]])# 第一个cap对应每一个user的传输功率
45 | self.p_tran_capB = np.array([[self.p_tran_user1[0][1], self.p_tran_user2[0][1]]])# 第二个cap对应每一个user的传输功率
46 |
47 |
48 | #信道,Hn为总信道CAPA分给两个用户的信道
49 | self.Hn_0=Hn_0.reshape(1,2)
50 | self.Hn_1=Hn_1.reshape(1,2)
51 |
52 | self.suspend = suspend
53 |
54 | #分配任务量
55 | self.user_l = user_l#用户最少2个
56 |
57 | #窃听者
58 | self.Hn_e=Hn_e.reshape(1,2)
59 |
60 | #卸载率初始化:
61 |
62 | self.user_offrate = np.zeros(shape=(1,(cap_num + 1)*user_num))#user_offrate的shape[1,(cap_num + 1)*user_num]
63 | for i in range((cap_num + 1)*user_num):
64 | if i % (cap_num + 1)==0:
65 | self.user_offrate[0][i] = 1.0
66 | self.judge=copy.deepcopy(self.user_offrate)
67 | self.all_off=np.array([[0.0,0.5,0.5,0.0,0.5,0.5]])
68 | # print("初始化时的卸载率为:", self.user_offrate)
69 |
70 | # self.user_offrate_ABC=copy.deepcopy(self.user_offrate)
71 |
72 | self.lamuda = lamuda
73 | self.noise = noise
74 | self.i = 0
75 | self.cost_list = [] # 记录成本
76 | self.epoch_list = []
77 | self.quancost_list = []
78 | self.wucost_list = []
79 |
80 | self.task_action = 1 # 任务每次变化率(任务卸载率)
81 | self.Mb_to_bit = 2 ** 20 # Mb to bit 1MB = 1024KB = 1024*1024B = 1024 * 1024 *8 bit =2^23
82 | # self.Mb_to_bit = 1 # Mb to bit 1MB = 1024KB = 1024*1024B = 1024 * 1024 *8 bit =2^23
83 | self.p_local = p_local
84 |
85 |
86 |
87 | # self.l1=np.full(shape=(1, self.cap_num + 1), fill_value=self.user_l[0][0])
88 | # self.l2 = np.full(shape=(1, self.cap_num + 1), fill_value=self.user_l[0][1])
89 | self.l=np.append(np.full(shape=(1, self.cap_num + 1), fill_value=self.user_l[0][0]),np.full(shape=(1, self.cap_num + 1), fill_value=self.user_l[0][1]),axis=1)
90 | self.A = 1.0
91 | self.B = 0.0
92 | self.C = 0.0
93 | self.D = 1.0
94 | self.E = 0.0
95 | self.F = 0.0
96 |
97 | self.temp_tc1 = self.total_cost(self.user_offrate)#本地
98 | self.tc_wald = self.total_cost(self.user_offrate)
99 | self.all_cost=self.total_cost(self.all_off)#全卸载
100 | # print("本地的cost为:", self.temp_tc1)
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | def reset(self): # 重开,返回初始化s
110 |
111 | self.user_S = self.l * self.user_offrate #任务量,1x6
112 | #总功率和总算力:p_tran[0],p_tran[1],F_cap[0],F_cap[1]
113 | self.P_F=np.append(self.p_tran,self.F_cap,axis=1)
114 | S_=np.append(self.user_S,self.P_F,axis=1)
115 | return S_
116 |
117 | def step(self, action):
118 | # 输入动作,输出下一步状态s_,奖励r,是否结束done。得根据给的动作,得出下一步s_,还有r,并且r需要求出当前状态下的成本
119 | self.i+=1
120 | self.user_offrate=action
121 |
122 |
123 |
124 | s_ = self.l * self.user_offrate
125 | self.P_F = np.append(self.p_tran, self.F_cap, axis=1)
126 | s_ = np.append(s_, self.P_F, axis=1)
127 |
128 | # 计算更新卸载率后的成本
129 | tc = self.total_cost(self.user_offrate)
130 |
131 | #本地
132 | self.temp_tc1=self.total_cost(self.judge)
133 |
134 |
135 | # if tc > self.tc_wald: # tc为更新后的成本,tc_wald为更新前的成本
136 | # r = -100
137 | # elif tc < self.tc_wald:
138 | # r = 100
139 | # else:
140 | # r = -100
141 | tc_diff=tc - self.tc_wald
142 | if tc_diff>=5.0:
143 | r=-200
144 | elif tc_diff>0.0 and tc_diff<5.0:
145 | r=-100
146 | elif tc_diff<=-5.0:
147 | r=200
148 | elif tc_diff<0.0 and tc_diff>-5.0:
149 | r=100
150 | elif tc_diff==0.0:
151 | r=-200
152 |
153 | self.user_S = s_ # 更新状态
154 | if self.i % 1000==0:
155 | print("----------------------------------")
156 | print("执行了第", self.i, "次动作")
157 | print("此轮更新卸载率后的成本为:", tc)
158 | print("此时卸载率为:", self.user_offrate)
159 |
160 |
161 | self.tc_wald = tc
162 |
163 | done = 0 # 不知道什么情况 done输出Ture,代码也没写
164 | if self.i == self.suspend:
165 | done = self.tc_wald
166 | self.i=0
167 |
168 |
169 |
170 | return s_, r, done, self.tc_wald,self.temp_tc1,self.all_cost
171 |
172 | #根据动作,改变对应的卸载率
173 | def offrate_normalization(self,number):#如增加,add_subtraction=1
174 | # w=self.i/5.0
175 | global w
176 | if self.i<500:
177 | w=1.0
178 | if self.i<1000:
179 | w=2.0
180 | if self.i<1500:
181 | w=3.0
182 | if self.i<2000:
183 | w=4.0
184 | if number==0:
185 | self.A+=w
186 | elif number==1:
187 | self.B+=w
188 | elif number==2:
189 | self.C+=w
190 | elif number==3:
191 | self.D+=w
192 | elif number==4:
193 | self.E+=w
194 | else:
195 | self.F+=w
196 |
197 |
198 | self.user_offrate[0][0] = self.A/ (self.A+self.B+self.C)
199 | self.user_offrate[0][1] = self.B / (self.A + self.B + self.C)
200 | self.user_offrate[0][2] = self.C / (self.A + self.B + self.C)
201 | self.user_offrate[0][3] = self.D / (self.D + self.E + self.F)
202 | self.user_offrate[0][4] = self.E / (self.D + self.E + self.F)
203 | self.user_offrate[0][5] = self.F / (self.D + self.E + self.F)
204 |
205 |
206 |
207 | def action_state_num(self): # 返回动作与环境个数
208 | n_action = self.user_num * (self.cap_num+1)#dqn
209 | n_state = self.user_num*(self.cap_num +1) +self.cap_num*2
210 | return n_action, n_state
211 |
212 | def Time(self, user_offrate):
213 | # 计算香农公式Wn
214 |
215 | # # #-----优化带宽-------------
216 | # if self.user_offrate.all()!=0:
217 | # W_user=np.sqrt((self.user_l*self.user_offrate*self.p_tran)/np.log2(1+(self.p_tran*np.square(self.Hn))/pow(self.noise, 2)))*self.W/np.sum(np.sqrt((self.user_l*self.user_offrate*self.p_tran)/np.log2(1+(self.p_tran*np.square(self.Hn))/pow(self.noise, 2))))
218 | # else:
219 | # w_ = self.W / self.user_num
220 | # W_user = np.full(shape=(1,self.user_num),fill_value=w_)
221 | # #-------------------
222 |
223 | #--------均分带宽--------------
224 | # w_0 = self.W0 / self.user_num#shape[1,2]
225 | # w_1 = self.W1 / self.user_num#shape[1,2]
226 | W_A_user = np.full(shape=(1, self.user_num), fill_value=self.W0)
227 | W_B_user = np.full(shape=(1, self.user_num), fill_value=self.W1)
228 | #-----------------------------
229 |
230 |
231 |
232 |
233 | if (user_offrate!=self.judge).any():
234 |
235 | #----解析-------
236 | a_A=W_A_user*np.log2(self.Hn_0/self.Hn_e)
237 | a_B=W_B_user*np.log2(self.Hn_1/self.Hn_e)
238 |
239 | b_A=W_A_user * pow(self.noise, 2) * (1/self.Hn_e - 1/self.Hn_0) / math.log(2)
240 | b_B=W_B_user * pow(self.noise, 2) * (1/self.Hn_e - 1/self.Hn_1) / math.log(2)
241 |
242 |
243 |
244 | #按user分
245 |
246 |
247 | b_user1=np.array([[b_A[0][0],b_B[0][0]]])
248 | b_user2 = np.array([[b_A[0][1], b_B[0][1]]])
249 |
250 | self.l1=self.l[0][1:3]#传输与cap计算的任务量
251 | self.l2=self.l[0][4:]
252 | user_offrate_user1=user_offrate[0][1:3]#user1的传输与cap计算的卸载率
253 | user_offrate_user2=user_offrate[0][4:]
254 |
255 | a_user1 =np.array([[a_A[0][0], a_B[0][0]]])
256 | a_user2 = np.array([[a_A[0][1], a_B[0][1]]])
257 |
258 | # A_users=np.append(A_user1,A_user2,axis=1)
259 | A_users=a_A*a_B
260 | A_user1=A_users[0][0]#数字
261 | A_user2=A_users[0][1]#数字
262 |
263 | lumuda_user1=pow(np.sum(np.sqrt(self.l1*user_offrate_user1*b_user1)/a_user1)/(self.p_tran[0][0]-np.sum(b_user1/a_user1)),2)
264 | lumuda_user2=pow(np.sum(np.sqrt(self.l2*user_offrate_user2*b_user2)/a_user2)/(self.p_tran[0][1]-np.sum(b_user2/a_user2)),2)
265 | lumuda_users=np.array([[lumuda_user1,lumuda_user2]])
266 |
267 |
268 | self.offrate_A = np.array([[user_offrate[0][1], user_offrate[0][4]]]) # shape:[用户1到capA的卸载率,用户2到capA的卸载率]
269 | self.offrate_B = np.array([[user_offrate[0][2], user_offrate[0][5]]]) # shape:[用户1到capA的卸载率,用户2到capA的卸载率]
270 |
271 | mu_capA = pow(np.sum(np.sqrt(self.offrate_A*self.user_l))/self.F_cap[0][0],2)#检查到这
272 | mu_capB = pow(np.sum(np.sqrt(self.offrate_B * self.user_l)) / self.F_cap[0][1],2)
273 | mu_cpas = np.array([[mu_capA, mu_capB]])
274 |
275 | #分配传输功率
276 |
277 | self.p_tran_user1=(np.sqrt(self.l1*user_offrate_user1*b_user1/lumuda_user1)+b_user1)/a_user1
278 | self.p_tran_user2=(np.sqrt(self.l2*user_offrate_user2*b_user2/lumuda_user2)+b_user2)/a_user2
279 |
280 | self.p_tran_capA=np.array([[self.p_tran_user1[0][0],self.p_tran_user2[0][0]]])
281 | self.p_tran_capB = np.array([[self.p_tran_user1[0][1], self.p_tran_user2[0][1]]])
282 | # else:
283 | # p_tran_1 = self.p_tran[0][1] / self.cap_num
284 | # self.p_tran_user2 = np.full(shape=(1, self.cap_num), fill_value=p_tran_1)
285 | # self.p_tran_capB = np.array([[self.p_tran_user1[0][1], self.p_tran_user2[0][1]]])
286 |
287 | #分配算力
288 | self.F_capA = np.sqrt(self.offrate_A * self.user_l / mu_capA)
289 | self.F_capB = np.sqrt(self.offrate_B * self.user_l / mu_capB)
290 |
291 |
292 | else:
293 | self.offrate_A = np.array([[user_offrate[0][1], user_offrate[0][4]]]) # shape:[用户1到capA的卸载率,用户2到capA的卸载率]
294 | self.offrate_B = np.array([[user_offrate[0][2], user_offrate[0][5]]]) # shape:[用户1到capA的卸载率,用户2到capA的卸载率]
295 |
296 | #均分传输功率
297 | p_tran_0 = self.p_tran[0][0] / self.cap_num
298 | p_tran_1 = self.p_tran[0][1] / self.cap_num
299 |
300 | self.p_tran_user1 = np.full(shape=(1, self.cap_num), fill_value=p_tran_0) # 第一个user分给不同信道的传输功率
301 | self.p_tran_user2 = np.full(shape=(1, self.cap_num), fill_value=p_tran_1) # 第二个user分给不同信道的传输功率
302 |
303 | self.p_tran_capA = np.array([[self.p_tran_user1[0][0], self.p_tran_user2[0][0]]]) # 第一个cap均分给每一个user的传输功率
304 | self.p_tran_capB = np.array([[self.p_tran_user1[0][1], self.p_tran_user2[0][1]]]) # 第二个cap均分给每一个user的传输功率
305 |
306 | #均分算力
307 | self.F_capA = np.full(shape=(1, self.user_num), fill_value=self.F_0) # capA均分给每一个user的算力
308 | self.F_capB = np.full(shape=(1, self.user_num), fill_value=self.F_1) # capB均分给每一个user的算力
309 |
310 | C_A1 = W_A_user * np.log2(1 + self.p_tran_capA * self.Hn_0 / pow(self.noise, 2)) # [cap_A_user1,cap_A_user2]
311 | C_B1 = W_B_user * np.log2(1 + self.p_tran_capB * self.Hn_1 / pow(self.noise, 2))
312 |
313 | # 窃听者
314 | C_A_E = W_A_user * np.log2(1 + self.p_tran_capA * self.Hn_e / pow(self.noise, 2))
315 | C_B_E = W_B_user * np.log2(1 + self.p_tran_capB * self.Hn_e / pow(self.noise, 2))
316 |
317 | # 更新速率
318 | C_A = C_A1 - C_A_E
319 | C_B = C_B1 - C_B_E
320 |
321 |
322 | #本地
323 | self.offrate_local=np.array([[user_offrate[0][0],user_offrate[0][3]]])#shape:[本地用户1的卸载率,本地用户2的卸载率]
324 | self.T_local=self.user_l*self.offrate_local * self.omega * self.Mb_to_bit / self.f#shape[1,2]
325 |
326 | # ----------CAPA--------------
327 | #传输
328 | self.T_tran_A=np.zeros(shape=(1,2))
329 | for i in range(self.user_num):
330 | if(self.offrate_A[0][i]):
331 | self.T_tran_A[0][i]=self.user_l[0][i] * self.offrate_A[0][i] / C_A[0][i]#shape[1,2]
332 | #CAP端
333 |
334 | self.T_cap_A=np.zeros(shape=(1,2))
335 | for i in range(self.user_num):
336 | if(self.offrate_A[0][i]):
337 | self.T_cap_A[0][i]=self.user_l[0][i] * self.offrate_A[0][i] * self.omega * self.Mb_to_bit / self.F_capA[0][i]#shape[1,2]
338 |
339 | #----------CAPB--------------
340 | #传输
341 |
342 | self.T_tran_B = np.zeros(shape=(1, 2))
343 | for i in range(self.user_num):
344 | if (self.offrate_B[0][i]):
345 | self.T_tran_B[0][i] = self.user_l[0][i] * self.offrate_B[0][i] / C_B[0][i] # shape[1,2]
346 |
347 | #CAP端
348 |
349 | # self.T_cap_B=self.user_l * self.offrate_B * self.omega * self.Mb_to_bit / self.F_capB#shape[1,2]
350 | self.T_cap_B = np.zeros(shape=(1, 2))
351 | for i in range(self.user_num):
352 | if (self.offrate_B[0][i]):
353 | self.T_cap_B[0][i] = self.user_l[0][i] * self.offrate_B[0][i] * self.omega * self.Mb_to_bit / self.F_capB[0][i] # shape[1,2]
354 |
355 | # -----------------------------
356 |
357 | #求T
358 | T=np.sum(self.T_local)+np.sum(self.T_tran_A)+np.sum(self.T_cap_A)+np.sum(self.T_tran_B)+np.sum(self.T_cap_B)
359 |
360 |
361 | # C = W_user * np.log2(1 + self.p_tran * self.Hn / pow(self.noise, 2))
362 | # temp = 1 - user_offrate
363 | # self.T_local = self.user_l * temp * self.omega * self.Mb_to_bit / self.f # shape(1,num)
364 | # self.T_tran = self.user_l * user_offrate * self.omega * self.Mb_to_bit / C # shape(1,num)
365 | # self.T_cap = self.user_l * user_offrate * self.omega * self.Mb_to_bit / self.F # shape(1,num)
366 | # T_temp = self.T_tran + self.T_cap
367 | #
368 | # T_max = np.max(T_temp)
369 | # T_max1 = np.max(self.T_local)
370 | # T = max(T_max, T_max1)
371 |
372 | return T
373 |
374 | def Energy(self, ):
375 | self.E_local=self.T_local * self.p_local
376 | self.E_tran_A=self.T_tran_A * self.p_tran_capA
377 | self.E_tran_B=self.T_tran_B * self.p_tran_capB
378 | E=np.sum(self.E_local)+np.sum(self.E_tran_A)+np.sum(self.E_tran_B)
379 |
380 | # self.E_local = self.T_local * self.p_local
381 | # self.E_tran = self.T_tran * self.p_tran
382 | # self.E_total = self.E_tran + self.E_local
383 | # E = np.sum(self.E_total)
384 | return E
385 |
386 | def total_cost(self, user_offrate): # total_cost 由T与E决定,返回当前时刻的成本
387 | T = self.Time(user_offrate)
388 | # E = self.Energy()
389 | total_cost = T
390 | return total_cost
391 |
392 | def cost_print(self):
393 | self.cost_list1 = self.cost_list # 记录成本
394 | self.epoch_list1 = self.epoch_list
395 | self.quancost_list1 = self.quancost_list
396 | self.wucost_list1 = self.wucost_list
397 | self.cost_list = [] # 记录成本
398 | self.epoch_list = []
399 | self.quancost_list = []
400 | self.wucost_list = []
401 | return self.cost_list1, self.epoch_list1, self.quancost_list1, self.wucost_list1
402 |
--------------------------------------------------------------------------------
/environment_ddpg_tra.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | import pandas as pd
3 | import copy
4 | import math
5 |
6 | # S=[任务量✖️卸载率,总算力,总功率]
7 | # A=[卸载率1增,卸载率1减,卸载率2增,卸载率2减,。。。]
8 |
9 |
10 | class environment1(object): # 奖励r由tc与tc-1比较大小得出。Hn:0.992912817258564, 0.992299817945962
11 | def __init__(self, user_num, cap_num, W, f_local, omega, F_cap, p_local, p_tran, lamuda, noise, Hn_0,Hn_1,Hn_e,user_l, suspend):
12 | # user_num:用户总数, cap_num:cap总数,W:单个CAP的总带宽,f_local为本地用户计算能力,omega:计算时间T的w
13 | # C为计算时间的传输速率,F_cap:分配给user的计算能力,p_local:本地计算功率,p_tran:传输功率;lamuda:时间与能耗之间的比例系数
14 | # noise:噪音的方差,用于计算香农公式的C;Hn:香农公式的hnm,用于计算C。suspend:用于判断执行多少次动作后停止
15 | self.user_num = user_num
16 | self.cap_num = cap_num
17 |
18 | self.f = f_local
19 | self.omega = omega
20 |
21 | #W为总带宽,[capA,capB],需要取出来
22 | self.W0 = W
23 | self.W1 = W
24 |
25 | # F_cap为算力(优化对象),[CAPA,CAPB],需分别均分给n个设备
26 |
27 | self.F_cap=F_cap
28 | self.F_0 = F_cap[0][0] / self.user_num#均分算力
29 | self.F_1 = F_cap[0][1] / self.user_num#均分算力
30 |
31 |
32 |
33 | self.F_capA = np.full(shape=(1,self.user_num),fill_value=self.F_0)#capA均分给每一个user的算力
34 | self.F_capB = np.full(shape=(1, self.user_num), fill_value=self.F_1) #capB均分给每一个user的算力
35 |
36 | #传输带宽(优化对象),p_tran总传输功率[user1,user2]
37 | self.p_tran=p_tran
38 | p_tran_0 = self.p_tran[0][0] / self.cap_num
39 | p_tran_1 = self.p_tran[0][1] / self.cap_num
40 |
41 | self.p_tran_user1 = np.full(shape=(1, self.cap_num), fill_value=p_tran_0) # 第一个user分给不同信道的传输功率
42 | self.p_tran_user2 = np.full(shape=(1, self.cap_num), fill_value=p_tran_1) # 第二个user分给不同信道的传输功率
43 |
44 | self.p_tran_capA = np.array([[self.p_tran_user1[0][0], self.p_tran_user2[0][0]]])# 第一个cap对应每一个user的传输功率
45 | self.p_tran_capB = np.array([[self.p_tran_user1[0][1], self.p_tran_user2[0][1]]])# 第二个cap对应每一个user的传输功率
46 |
47 |
48 | #信道,Hn为总信道CAPA分给两个用户的信道
49 | self.Hn_0=Hn_0.reshape(1,2)
50 | self.Hn_1=Hn_1.reshape(1,2)
51 |
52 | self.suspend = suspend
53 |
54 | #分配任务量
55 | self.user_l = user_l#用户最少2个
56 |
57 | #窃听者
58 | self.Hn_e=Hn_e.reshape(1,2)
59 |
60 | #卸载率初始化:
61 |
62 | self.user_offrate = np.zeros(shape=(1,(cap_num + 1)*user_num))#user_offrate的shape[1,(cap_num + 1)*user_num]
63 | for i in range((cap_num + 1)*user_num):
64 | if i % (cap_num + 1)==0:
65 | self.user_offrate[0][i] = 1.0
66 | self.judge=copy.deepcopy(self.user_offrate)
67 | self.all_off=np.array([[0.0,0.5,0.5,0.0,0.5,0.5]])
68 | # print("初始化时的卸载率为:", self.user_offrate)
69 |
70 | # self.user_offrate_ABC=copy.deepcopy(self.user_offrate)
71 |
72 | self.lamuda = lamuda
73 | self.noise = noise
74 | self.i = 0
75 | self.cost_list = [] # 记录成本
76 | self.epoch_list = []
77 | self.quancost_list = []
78 | self.wucost_list = []
79 |
80 | self.task_action = 1 # 任务每次变化率(任务卸载率)
81 | self.Mb_to_bit = 2 ** 20 # Mb to bit 1MB = 1024KB = 1024*1024B = 1024 * 1024 *8 bit =2^23
82 | # self.Mb_to_bit = 1 # Mb to bit 1MB = 1024KB = 1024*1024B = 1024 * 1024 *8 bit =2^23
83 | self.p_local = p_local
84 |
85 |
86 |
87 | # self.l1=np.full(shape=(1, self.cap_num + 1), fill_value=self.user_l[0][0])
88 | # self.l2 = np.full(shape=(1, self.cap_num + 1), fill_value=self.user_l[0][1])
89 | self.l=np.append(np.full(shape=(1, self.cap_num + 1), fill_value=self.user_l[0][0]),np.full(shape=(1, self.cap_num + 1), fill_value=self.user_l[0][1]),axis=1)
90 | self.A = 1.0
91 | self.B = 0.0
92 | self.C = 0.0
93 | self.D = 1.0
94 | self.E = 0.0
95 | self.F = 0.0
96 |
97 | self.temp_tc1 = self.total_cost(self.user_offrate)#本地
98 | self.tc_wald = self.total_cost(self.user_offrate)
99 | self.all_cost=self.total_cost(self.all_off)#全卸载
100 | # print("本地的cost为:", self.temp_tc1)
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | def reset(self): # 重开,返回初始化s
110 |
111 | self.user_S = self.l * self.user_offrate #任务量,1x6
112 | #总功率和总算力:p_tran[0],p_tran[1],F_cap[0],F_cap[1]
113 | self.P_F=np.append(self.p_tran,self.F_cap,axis=1)
114 | S_=np.append(self.user_S,self.P_F,axis=1)
115 | return S_
116 |
117 | def step(self, action):
118 | # 输入动作,输出下一步状态s_,奖励r,是否结束done。得根据给的动作,得出下一步s_,还有r,并且r需要求出当前状态下的成本
119 |
120 |
121 | self.i+=1
122 | self.user_offrate=action
123 |
124 |
125 |
126 | s_ = self.l * self.user_offrate
127 | self.P_F = np.append(self.p_tran, self.F_cap, axis=1)
128 | s_ = np.append(s_, self.P_F, axis=1)
129 |
130 | # 计算更新卸载率后的成本
131 | tc = self.total_cost(self.user_offrate)
132 |
133 | #本地
134 | self.temp_tc1=self.total_cost(self.judge)
135 |
136 |
137 | # if tc > self.tc_wald: # tc为更新后的成本,tc_wald为更新前的成本
138 | # r = -100
139 | # elif tc < self.tc_wald:
140 | # r = 100
141 | # else:
142 | # r = -100
143 | tc_diff=tc - self.tc_wald
144 | if tc_diff>=5.0:
145 | r=-200
146 | elif tc_diff>0.0 and tc_diff<5.0:
147 | r=-100
148 | elif tc_diff<=-5.0:
149 | r=200
150 | elif tc_diff<0.0 and tc_diff>-5.0:
151 | r=100
152 | elif tc_diff==0.0:
153 | r=-200
154 |
155 | self.user_S = s_ # 更新状态
156 | if self.i % 2000==0:
157 | print("----------------------------------")
158 | print("执行了第", self.i, "次动作")
159 | print("此轮更新卸载率后的成本为:", tc)
160 | print("此时卸载率为:", self.user_offrate)
161 |
162 |
163 | self.tc_wald = tc
164 |
165 | done = 0 # 不知道什么情况 done输出Ture,代码也没写
166 | if self.i == self.suspend:
167 | done = self.tc_wald
168 | self.i=0
169 |
170 |
171 |
172 | return s_, r, done, self.tc_wald,self.temp_tc1,self.all_cost
173 |
174 | #根据动作,改变对应的卸载率
175 | def offrate_normalization(self,number):#如增加,add_subtraction=1
176 | # w=self.i/5.0
177 | global w
178 | if self.i<500:
179 | w=1.0
180 | if self.i<1000:
181 | w=2.0
182 | if self.i<1500:
183 | w=3.0
184 | if self.i<2000:
185 | w=4.0
186 | if number==0:
187 | self.A+=w
188 | elif number==1:
189 | self.B+=w
190 | elif number==2:
191 | self.C+=w
192 | elif number==3:
193 | self.D+=w
194 | elif number==4:
195 | self.E+=w
196 | else:
197 | self.F+=w
198 |
199 |
200 | self.user_offrate[0][0] = self.A/ (self.A+self.B+self.C)
201 | self.user_offrate[0][1] = self.B / (self.A + self.B + self.C)
202 | self.user_offrate[0][2] = self.C / (self.A + self.B + self.C)
203 | self.user_offrate[0][3] = self.D / (self.D + self.E + self.F)
204 | self.user_offrate[0][4] = self.E / (self.D + self.E + self.F)
205 | self.user_offrate[0][5] = self.F / (self.D + self.E + self.F)
206 |
207 |
208 |
209 | def action_state_num(self): # 返回动作与环境个数
210 | n_action = self.user_num * (self.cap_num + 1) # dqn
211 | n_state = self.user_num * (self.cap_num + 1) + self.cap_num * 2
212 | return n_action, n_state
213 |
214 | def Time(self, user_offrate):
215 | # 计算香农公式Wn
216 |
217 | # # #-----优化带宽-------------
218 | # if self.user_offrate.all()!=0:
219 | # W_user=np.sqrt((self.user_l*self.user_offrate*self.p_tran)/np.log2(1+(self.p_tran*np.square(self.Hn))/pow(self.noise, 2)))*self.W/np.sum(np.sqrt((self.user_l*self.user_offrate*self.p_tran)/np.log2(1+(self.p_tran*np.square(self.Hn))/pow(self.noise, 2))))
220 | # else:
221 | # w_ = self.W / self.user_num
222 | # W_user = np.full(shape=(1,self.user_num),fill_value=w_)
223 | # #-------------------
224 |
225 | #--------均分带宽--------------
226 | # w_0 = self.W0 / self.user_num#shape[1,2]
227 | # w_1 = self.W1 / self.user_num#shape[1,2]
228 | W_A_user = np.full(shape=(1, self.user_num), fill_value=self.W0)
229 | W_B_user = np.full(shape=(1, self.user_num), fill_value=self.W1)
230 | #-----------------------------
231 |
232 |
233 |
234 |
235 | if (user_offrate!=self.judge).any():
236 |
237 | #----解析-------
238 | a_A=W_A_user*np.log2(self.Hn_0/self.Hn_e)
239 | a_B=W_B_user*np.log2(self.Hn_1/self.Hn_e)
240 |
241 | b_A=W_A_user * pow(self.noise, 2) * (1/self.Hn_e - 1/self.Hn_0) / math.log(2)
242 | b_B=W_B_user * pow(self.noise, 2) * (1/self.Hn_e - 1/self.Hn_1) / math.log(2)
243 |
244 |
245 |
246 | #按user分
247 |
248 |
249 | b_user1=np.array([[b_A[0][0],b_B[0][0]]])
250 | b_user2 = np.array([[b_A[0][1], b_B[0][1]]])
251 |
252 | self.l1=self.l[0][1:3]#传输与cap计算的任务量
253 | self.l2=self.l[0][4:]
254 | user_offrate_user1=user_offrate[0][1:3]#user1的传输与cap计算的卸载率
255 | user_offrate_user2=user_offrate[0][4:]
256 |
257 | a_user1 =np.array([[a_A[0][0], a_B[0][0]]])
258 | a_user2 = np.array([[a_A[0][1], a_B[0][1]]])
259 |
260 | # A_users=np.append(A_user1,A_user2,axis=1)
261 | A_users=a_A*a_B
262 | A_user1=A_users[0][0]#数字
263 | A_user2=A_users[0][1]#数字
264 |
265 | lumuda_user1=pow(np.sum(np.sqrt(self.l1*user_offrate_user1*b_user1)/a_user1)/(self.p_tran[0][0]-np.sum(b_user1/a_user1)),2)
266 | lumuda_user2=pow(np.sum(np.sqrt(self.l2*user_offrate_user2*b_user2)/a_user2)/(self.p_tran[0][1]-np.sum(b_user2/a_user2)),2)
267 | lumuda_users=np.array([[lumuda_user1,lumuda_user2]])
268 |
269 |
270 | self.offrate_A = np.array([[user_offrate[0][1], user_offrate[0][4]]]) # shape:[用户1到capA的卸载率,用户2到capA的卸载率]
271 | self.offrate_B = np.array([[user_offrate[0][2], user_offrate[0][5]]]) # shape:[用户1到capA的卸载率,用户2到capA的卸载率]
272 |
273 | mu_capA = pow(np.sum(np.sqrt(self.offrate_A*self.user_l))/self.F_cap[0][0],2)#检查到这
274 | mu_capB = pow(np.sum(np.sqrt(self.offrate_B * self.user_l)) / self.F_cap[0][1],2)
275 | mu_cpas = np.array([[mu_capA, mu_capB]])
276 |
277 | #分配传输功率
278 |
279 | self.p_tran_user1=(np.sqrt(self.l1*user_offrate_user1*b_user1/lumuda_user1)+b_user1)/a_user1
280 | self.p_tran_user2=(np.sqrt(self.l2*user_offrate_user2*b_user2/lumuda_user2)+b_user2)/a_user2
281 |
282 |
283 | self.p_tran_capA=np.array([[self.p_tran_user1[0][0],self.p_tran_user2[0][0]]])
284 | self.p_tran_capB = np.array([[self.p_tran_user1[0][1], self.p_tran_user2[0][1]]])
285 | # else:
286 | # p_tran_1 = self.p_tran[0][1] / self.cap_num
287 | # self.p_tran_user2 = np.full(shape=(1, self.cap_num), fill_value=p_tran_1)
288 | # self.p_tran_capB = np.array([[self.p_tran_user1[0][1], self.p_tran_user2[0][1]]])
289 |
290 | #分配算力
291 | self.F_capA = np.sqrt(self.offrate_A * self.user_l / mu_capA)
292 | self.F_capB = np.sqrt(self.offrate_B * self.user_l / mu_capB)
293 |
294 |
295 | else:
296 | self.offrate_A = np.array([[user_offrate[0][1], user_offrate[0][4]]]) # shape:[用户1到capA的卸载率,用户2到capA的卸载率]
297 | self.offrate_B = np.array([[user_offrate[0][2], user_offrate[0][5]]]) # shape:[用户1到capA的卸载率,用户2到capA的卸载率]
298 |
299 | #均分传输功率
300 | p_tran_0 = self.p_tran[0][0] / self.cap_num
301 | p_tran_1 = self.p_tran[0][1] / self.cap_num
302 |
303 | self.p_tran_user1 = np.full(shape=(1, self.cap_num), fill_value=p_tran_0) # 第一个user分给不同信道的传输功率
304 | self.p_tran_user2 = np.full(shape=(1, self.cap_num), fill_value=p_tran_1) # 第二个user分给不同信道的传输功率
305 |
306 | self.p_tran_capA = np.array([[self.p_tran_user1[0][0], self.p_tran_user2[0][0]]]) # 第一个cap均分给每一个user的传输功率
307 | self.p_tran_capB = np.array([[self.p_tran_user1[0][1], self.p_tran_user2[0][1]]]) # 第二个cap均分给每一个user的传输功率
308 |
309 | #均分算力
310 | self.F_capA = np.full(shape=(1, self.user_num), fill_value=self.F_0) # capA均分给每一个user的算力
311 | self.F_capB = np.full(shape=(1, self.user_num), fill_value=self.F_1) # capB均分给每一个user的算力
312 |
313 | C_A1 = W_A_user * np.log2(1 + self.p_tran_capA * self.Hn_0 / pow(self.noise, 2)) # [cap_A_user1,cap_A_user2]
314 | C_B1 = W_B_user * np.log2(1 + self.p_tran_capB * self.Hn_1 / pow(self.noise, 2))
315 |
316 | # 窃听者
317 | C_A_E = W_A_user * np.log2(1 + self.p_tran_capA * self.Hn_e / pow(self.noise, 2))
318 | C_B_E = W_B_user * np.log2(1 + self.p_tran_capB * self.Hn_e / pow(self.noise, 2))
319 |
320 | # 更新速率
321 | C_A = C_A1 - C_A_E
322 | C_B = C_B1 - C_B_E
323 |
324 |
325 | #本地
326 | self.offrate_local=np.array([[user_offrate[0][0],user_offrate[0][3]]])#shape:[本地用户1的卸载率,本地用户2的卸载率]
327 | self.T_local=self.user_l*self.offrate_local * self.omega * self.Mb_to_bit / self.f#shape[1,2]
328 |
329 | # ----------CAPA--------------
330 | #传输
331 | self.T_tran_A=np.zeros(shape=(1,2))
332 | for i in range(self.user_num):
333 | if(self.offrate_A[0][i]):
334 | self.T_tran_A[0][i]=self.user_l[0][i] * self.offrate_A[0][i] / C_A[0][i]#shape[1,2]
335 | #CAP端
336 |
337 | self.T_cap_A=np.zeros(shape=(1,2))
338 | for i in range(self.user_num):
339 | if(self.offrate_A[0][i]):
340 | self.T_cap_A[0][i]=self.user_l[0][i] * self.offrate_A[0][i] * self.omega * self.Mb_to_bit / self.F_capA[0][i]#shape[1,2]
341 |
342 | #----------CAPB--------------
343 | #传输
344 |
345 | self.T_tran_B = np.zeros(shape=(1, 2))
346 | for i in range(self.user_num):
347 | if (self.offrate_B[0][i]):
348 | self.T_tran_B[0][i] = self.user_l[0][i] * self.offrate_B[0][i] / C_B[0][i] # shape[1,2]
349 |
350 | #CAP端
351 |
352 | # self.T_cap_B=self.user_l * self.offrate_B * self.omega * self.Mb_to_bit / self.F_capB#shape[1,2]
353 | self.T_cap_B = np.zeros(shape=(1, 2))
354 | for i in range(self.user_num):
355 | if (self.offrate_B[0][i]):
356 | self.T_cap_B[0][i] = self.user_l[0][i] * self.offrate_B[0][i] * self.omega * self.Mb_to_bit / self.F_capB[0][i] # shape[1,2]
357 |
358 | # -----------------------------
359 |
360 | #求T
361 | T=np.sum(self.T_local)+np.sum(self.T_tran_A)+np.sum(self.T_cap_A)+np.sum(self.T_tran_B)+np.sum(self.T_cap_B)
362 |
363 |
364 | # C = W_user * np.log2(1 + self.p_tran * self.Hn / pow(self.noise, 2))
365 | # temp = 1 - user_offrate
366 | # self.T_local = self.user_l * temp * self.omega * self.Mb_to_bit / self.f # shape(1,num)
367 | # self.T_tran = self.user_l * user_offrate * self.omega * self.Mb_to_bit / C # shape(1,num)
368 | # self.T_cap = self.user_l * user_offrate * self.omega * self.Mb_to_bit / self.F # shape(1,num)
369 | # T_temp = self.T_tran + self.T_cap
370 | #
371 | # T_max = np.max(T_temp)
372 | # T_max1 = np.max(self.T_local)
373 | # T = max(T_max, T_max1)
374 |
375 | return T
376 |
377 | def Energy(self, ):
378 | self.E_local=self.T_local * self.p_local
379 | self.E_tran_A=self.T_tran_A * self.p_tran_capA
380 | self.E_tran_B=self.T_tran_B * self.p_tran_capB
381 | E=np.sum(self.E_local)+np.sum(self.E_tran_A)+np.sum(self.E_tran_B)
382 |
383 | # self.E_local = self.T_local * self.p_local
384 | # self.E_tran = self.T_tran * self.p_tran
385 | # self.E_total = self.E_tran + self.E_local
386 | # E = np.sum(self.E_total)
387 | return E
388 |
389 | def total_cost(self, user_offrate): # total_cost 由T与E决定,返回当前时刻的成本
390 | T = self.Time(user_offrate)
391 | # E = self.Energy()
392 | total_cost = T
393 | return total_cost
394 |
395 | def cost_print(self):
396 | self.cost_list1 = self.cost_list # 记录成本
397 | self.epoch_list1 = self.epoch_list
398 | self.quancost_list1 = self.quancost_list
399 | self.wucost_list1 = self.wucost_list
400 | self.cost_list = [] # 记录成本
401 | self.epoch_list = []
402 | self.quancost_list = []
403 | self.wucost_list = []
404 | return self.cost_list1, self.epoch_list1, self.quancost_list1, self.wucost_list1
405 |
--------------------------------------------------------------------------------
/environment_optimize1.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | import pandas as pd
3 | import copy
4 | import math
5 |
6 | # S=[任务量✖️卸载率,总算力,总功率]
7 | # A=[卸载率1增,卸载率1减,卸载率2增,卸载率2减,。。。]
8 |
9 |
10 | class environment(object): # 奖励r由tc与tc-1比较大小得出。Hn:0.992912817258564, 0.992299817945962
11 | def __init__(self, user_num, cap_num, W, f_local, omega, F_cap, p_local, p_tran, lamuda, noise, Hn_0,Hn_1,Hn_e,user_l, suspend):
12 | # user_num:用户总数, cap_num:cap总数,W:单个CAP的总带宽,f_local为本地用户计算能力,omega:计算时间T的w
13 | # C为计算时间的传输速率,F_cap:分配给user的计算能力,p_local:本地计算功率,p_tran:传输功率;lamuda:时间与能耗之间的比例系数
14 | # noise:噪音的方差,用于计算香农公式的C;Hn:香农公式的hnm,用于计算C。suspend:用于判断执行多少次动作后停止
15 | self.user_num = user_num
16 | self.cap_num = cap_num
17 |
18 | self.f = f_local
19 | self.omega = omega
20 |
21 | #W为总带宽,[capA,capB],需要取出来
22 | self.W0 = W
23 | self.W1 = W
24 |
25 | # F_cap为算力(优化对象),[CAPA,CAPB],需分别均分给n个设备
26 |
27 | self.F_cap=F_cap
28 | self.F_0 = F_cap[0][0] / self.user_num#均分算力
29 | self.F_1 = F_cap[0][1] / self.user_num#均分算力
30 |
31 |
32 |
33 | self.F_capA = np.full(shape=(1,self.user_num),fill_value=self.F_0)#capA均分给每一个user的算力
34 | self.F_capB = np.full(shape=(1, self.user_num), fill_value=self.F_1) #capB均分给每一个user的算力
35 |
36 | #传输带宽(优化对象),p_tran总传输功率[user1,user2]
37 | self.p_tran=p_tran
38 | p_tran_0 = self.p_tran[0][0] / self.cap_num
39 | p_tran_1 = self.p_tran[0][1] / self.cap_num
40 |
41 | self.p_tran_user1 = np.full(shape=(1, self.cap_num), fill_value=p_tran_0) # 第一个user分给不同信道的传输功率
42 | self.p_tran_user2 = np.full(shape=(1, self.cap_num), fill_value=p_tran_1) # 第二个user分给不同信道的传输功率
43 |
44 | self.p_tran_capA = np.array([[self.p_tran_user1[0][0], self.p_tran_user2[0][0]]])# 第一个cap对应每一个user的传输功率
45 | self.p_tran_capB = np.array([[self.p_tran_user1[0][1], self.p_tran_user2[0][1]]])# 第二个cap对应每一个user的传输功率
46 |
47 |
48 | #信道,Hn为总信道CAPA分给两个用户的信道
49 | self.Hn_0=Hn_0.reshape(1,2)
50 | self.Hn_1=Hn_1.reshape(1,2)
51 |
52 | self.suspend = suspend
53 |
54 | #分配任务量
55 | self.user_l = user_l#用户最少2个
56 |
57 | #窃听者
58 | self.Hn_e=Hn_e.reshape(1,2)
59 |
60 | #卸载率初始化:
61 |
62 | self.user_offrate = np.zeros(shape=(1,(cap_num + 1)*user_num))#user_offrate的shape[1,(cap_num + 1)*user_num]
63 | for i in range((cap_num + 1)*user_num):
64 | if i % (cap_num + 1)==0:
65 | self.user_offrate[0][i] = 1.0
66 | self.judge=copy.deepcopy(self.user_offrate)
67 | self.all_off=np.array([[0.0,0.5,0.5,0.0,0.5,0.5]])
68 | # print("初始化时的卸载率为:", self.user_offrate)
69 |
70 | # self.user_offrate_ABC=copy.deepcopy(self.user_offrate)
71 |
72 | self.lamuda = lamuda
73 | self.noise = noise
74 | self.i = 0
75 | self.cost_list = [] # 记录成本
76 | self.epoch_list = []
77 | self.quancost_list = []
78 | self.wucost_list = []
79 |
80 | self.task_action = 1 # 任务每次变化率(任务卸载率)
81 | self.Mb_to_bit = 2 ** 20 # Mb to bit 1MB = 1024KB = 1024*1024B = 1024 * 1024 *8 bit =2^23
82 | # self.Mb_to_bit = 1 # Mb to bit 1MB = 1024KB = 1024*1024B = 1024 * 1024 *8 bit =2^23
83 | self.p_local = p_local
84 |
85 |
86 |
87 | # self.l1=np.full(shape=(1, self.cap_num + 1), fill_value=self.user_l[0][0])
88 | # self.l2 = np.full(shape=(1, self.cap_num + 1), fill_value=self.user_l[0][1])
89 | self.l=np.append(np.full(shape=(1, self.cap_num + 1), fill_value=self.user_l[0][0]),np.full(shape=(1, self.cap_num + 1), fill_value=self.user_l[0][1]),axis=1)
90 | self.A = 1.0
91 | self.B = 0.01
92 | self.C = 0.01
93 | self.D = 1.0
94 | self.E = 0.01
95 | self.F = 0.01
96 |
97 | self.temp_tc1 = self.total_cost(self.user_offrate)#本地
98 | self.tc_wald = self.total_cost(self.user_offrate)
99 | self.all_cost=self.total_cost(self.all_off)#全卸载
100 | # print("本地的cost为:", self.temp_tc1)
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | def reset(self): # 重开,返回初始化s
110 |
111 | self.user_S = self.l * self.user_offrate #任务量,1x6
112 | #总功率和总算力:p_tran[0],p_tran[1],F_cap[0],F_cap[1]
113 | self.P_F=np.append(self.p_tran,self.F_cap,axis=1)
114 | S_=np.append(self.user_S,self.P_F,axis=1)
115 | return S_
116 |
117 | def step(self, action):
118 | # 输入动作,输出下一步状态s_,奖励r,是否结束done。得根据给的动作,得出下一步s_,还有r,并且r需要求出当前状态下的成本
119 |
120 |
121 | self.i = self.i + 1
122 |
123 | # 判断action执行什么动作,action为一个值
124 |
125 | # self.actions=int(action/2)#对应到卸载率的下标
126 |
127 | # if action%2==0:#增加
128 | # self.offrate_normalization(self.actions,1)
129 | # else:#减少
130 | # self.offrate_normalization(self.actions,0)
131 |
132 | #self.offrate_normalization(1,1)、
133 |
134 | if action==0:#user1本地增加
135 | self.offrate_normalization(0)
136 | elif action==1:
137 | self.offrate_normalization(1)
138 | elif action == 2: # user1-capA增加
139 | self.offrate_normalization(2)
140 | elif action == 3:
141 | self.offrate_normalization(3)
142 | elif action == 4: # user1-capB增加
143 | self.offrate_normalization(4)
144 | else:
145 | self.offrate_normalization(5)
146 |
147 |
148 |
149 | s_ = self.l * self.user_offrate
150 | self.P_F = np.append(self.p_tran, self.F_cap, axis=1)
151 | s_ = np.append(s_, self.P_F, axis=1)
152 |
153 | # 计算更新卸载率后的成本
154 | tc = self.total_cost(self.user_offrate)
155 |
156 | #本地
157 | self.temp_tc1=self.total_cost(self.judge)
158 |
159 |
160 | # if tc > self.tc_wald: # tc为更新后的成本,tc_wald为更新前的成本
161 | # r = -100
162 | # elif tc < self.tc_wald:
163 | # r = 100
164 | # else:
165 | # r = -100
166 | tc_diff=tc - self.tc_wald
167 | if tc_diff>=5.0:
168 | r=-200
169 | elif tc_diff>0.0 and tc_diff<5.0:
170 | r=-100
171 | elif tc_diff<=-5.0:
172 | r=200
173 | elif tc_diff<0.0 and tc_diff>-5.0:
174 | r=100
175 | elif tc_diff==0.0:
176 | r=-200
177 |
178 | self.user_S = s_ # 更新状态
179 | if self.i % 2000==0:
180 | print("----------------------------------")
181 | print("执行了第", self.i, "次动作")
182 | print("此轮更新卸载率后的成本为:", tc)
183 | print("此时卸载率为:", self.user_offrate)
184 |
185 |
186 | self.tc_wald = tc
187 |
188 | done = 0 # 不知道什么情况 done输出Ture,代码也没写
189 | if self.i == self.suspend:
190 | done = self.tc_wald
191 | self.i=0
192 |
193 |
194 |
195 | return s_, r, done, self.tc_wald,self.temp_tc1,self.all_cost
196 |
197 | #根据动作,改变对应的卸载率
198 | def offrate_normalization(self,number):#如增加,add_subtraction=1
199 | # w=self.i/5.0
200 | global w
201 | if self.i<500:
202 | w=1.0
203 | if self.i<1000:
204 | w=2.0
205 | if self.i<1500:
206 | w=3.0
207 | if self.i<2000:
208 | w=4.0
209 | if number==0:
210 | self.A+=w
211 | elif number==1:
212 | self.B+=w
213 | elif number==2:
214 | self.C+=w
215 | elif number==3:
216 | self.D+=w
217 | elif number==4:
218 | self.E+=w
219 | else:
220 | self.F+=w
221 |
222 |
223 | self.user_offrate[0][0] = self.A/ (self.A+self.B+self.C)
224 | self.user_offrate[0][1] = self.B / (self.A + self.B + self.C)
225 | self.user_offrate[0][2] = self.C / (self.A + self.B + self.C)
226 | self.user_offrate[0][3] = self.D / (self.D + self.E + self.F)
227 | self.user_offrate[0][4] = self.E / (self.D + self.E + self.F)
228 | self.user_offrate[0][5] = self.F / (self.D + self.E + self.F)
229 |
230 |
231 |
232 | def action_state_num(self): # 返回动作与环境个数
233 | action_n = self.user_num * (self.cap_num+1)#dqn
234 | state_num = self.user_num*(self.cap_num +1) +self.cap_num+self.user_num
235 | return action_n, state_num
236 |
237 | def Time(self, user_offrate):
238 | # 计算香农公式Wn
239 |
240 | # # #-----优化带宽-------------
241 | # if self.user_offrate.all()!=0:
242 | # W_user=np.sqrt((self.user_l*self.user_offrate*self.p_tran)/np.log2(1+(self.p_tran*np.square(self.Hn))/pow(self.noise, 2)))*self.W/np.sum(np.sqrt((self.user_l*self.user_offrate*self.p_tran)/np.log2(1+(self.p_tran*np.square(self.Hn))/pow(self.noise, 2))))
243 | # else:
244 | # w_ = self.W / self.user_num
245 | # W_user = np.full(shape=(1,self.user_num),fill_value=w_)
246 | # #-------------------
247 |
248 | #--------均分带宽--------------
249 | # w_0 = self.W0 / self.user_num#shape[1,2]
250 | # w_1 = self.W1 / self.user_num#shape[1,2]
251 | W_A_user = np.full(shape=(1, self.user_num), fill_value=self.W0)
252 | W_B_user = np.full(shape=(1, self.user_num), fill_value=self.W1)
253 | #-----------------------------
254 |
255 |
256 |
257 |
258 | if (user_offrate!=self.judge).any():
259 |
260 | #----解析-------
261 | a_A=W_A_user*np.log2(self.Hn_0/self.Hn_e)
262 | a_B=W_B_user*np.log2(self.Hn_1/self.Hn_e)
263 |
264 | b_A=W_A_user * pow(self.noise, 2) * (1/self.Hn_e - 1/self.Hn_0) / math.log(2)
265 | b_B=W_B_user * pow(self.noise, 2) * (1/self.Hn_e - 1/self.Hn_1) / math.log(2)
266 |
267 |
268 |
269 | #按user分
270 |
271 |
272 | b_user1=np.array([[b_A[0][0],b_B[0][0]]])
273 | b_user2 = np.array([[b_A[0][1], b_B[0][1]]])
274 |
275 | self.l1=self.l[0][1:3]#传输与cap计算的任务量
276 | self.l2=self.l[0][4:]
277 | user_offrate_user1=user_offrate[0][1:3]#user1的传输与cap计算的卸载率
278 | user_offrate_user2=user_offrate[0][4:]
279 |
280 | a_user1 =np.array([[a_A[0][0], a_B[0][0]]])
281 | a_user2 = np.array([[a_A[0][1], a_B[0][1]]])
282 |
283 | # A_users=np.append(A_user1,A_user2,axis=1)
284 | A_users=a_A*a_B
285 | A_user1=A_users[0][0]#数字
286 | A_user2=A_users[0][1]#数字
287 |
288 | lumuda_user1=pow(np.sum(np.sqrt(self.l1*user_offrate_user1*b_user1)/a_user1)/(self.p_tran[0][0]-np.sum(b_user1/a_user1)),2)
289 | lumuda_user2=pow(np.sum(np.sqrt(self.l2*user_offrate_user2*b_user2)/a_user2)/(self.p_tran[0][1]-np.sum(b_user2/a_user2)),2)
290 | lumuda_users=np.array([[lumuda_user1,lumuda_user2]])
291 |
292 |
293 | self.offrate_A = np.array([[user_offrate[0][1], user_offrate[0][4]]]) # shape:[用户1到capA的卸载率,用户2到capA的卸载率]
294 | self.offrate_B = np.array([[user_offrate[0][2], user_offrate[0][5]]]) # shape:[用户1到capA的卸载率,用户2到capA的卸载率]
295 |
296 | mu_capA = pow(np.sum(np.sqrt(self.offrate_A*self.user_l))/self.F_cap[0][0],2)#检查到这
297 | mu_capB = pow(np.sum(np.sqrt(self.offrate_B * self.user_l)) / self.F_cap[0][1],2)
298 | mu_cpas = np.array([[mu_capA, mu_capB]])
299 |
300 | #分配传输功率
301 |
302 | self.p_tran_user1=(np.sqrt(self.l1*user_offrate_user1*b_user1/lumuda_user1)+b_user1)/a_user1
303 | self.p_tran_user2=(np.sqrt(self.l2*user_offrate_user2*b_user2/lumuda_user2)+b_user2)/a_user2
304 |
305 | if np.isnan(self.p_tran_user2).any():
306 | print("yesssss!")
307 | print(user_offrate)
308 |
309 | self.p_tran_capA=np.array([[self.p_tran_user1[0][0],self.p_tran_user2[0][0]]])
310 | self.p_tran_capB = np.array([[self.p_tran_user1[0][1], self.p_tran_user2[0][1]]])
311 | # else:
312 | # p_tran_1 = self.p_tran[0][1] / self.cap_num
313 | # self.p_tran_user2 = np.full(shape=(1, self.cap_num), fill_value=p_tran_1)
314 | # self.p_tran_capB = np.array([[self.p_tran_user1[0][1], self.p_tran_user2[0][1]]])
315 |
316 | #分配算力
317 | self.F_capA = np.sqrt(self.offrate_A * self.user_l / mu_capA)
318 | self.F_capB = np.sqrt(self.offrate_B * self.user_l / mu_capB)
319 |
320 | if np.isnan(self.F_capA).any():
321 | print("yesssss!self.F_capA")
322 | print(user_offrate)
323 |
324 | else:
325 | self.offrate_A = np.array([[user_offrate[0][1], user_offrate[0][4]]]) # shape:[用户1到capA的卸载率,用户2到capA的卸载率]
326 | self.offrate_B = np.array([[user_offrate[0][2], user_offrate[0][5]]]) # shape:[用户1到capA的卸载率,用户2到capA的卸载率]
327 |
328 | #均分传输功率
329 | p_tran_0 = self.p_tran[0][0] / self.cap_num
330 | p_tran_1 = self.p_tran[0][1] / self.cap_num
331 |
332 | self.p_tran_user1 = np.full(shape=(1, self.cap_num), fill_value=p_tran_0) # 第一个user分给不同信道的传输功率
333 | self.p_tran_user2 = np.full(shape=(1, self.cap_num), fill_value=p_tran_1) # 第二个user分给不同信道的传输功率
334 |
335 | self.p_tran_capA = np.array([[self.p_tran_user1[0][0], self.p_tran_user2[0][0]]]) # 第一个cap均分给每一个user的传输功率
336 | self.p_tran_capB = np.array([[self.p_tran_user1[0][1], self.p_tran_user2[0][1]]]) # 第二个cap均分给每一个user的传输功率
337 |
338 | #均分算力
339 | self.F_capA = np.full(shape=(1, self.user_num), fill_value=self.F_0) # capA均分给每一个user的算力
340 | self.F_capB = np.full(shape=(1, self.user_num), fill_value=self.F_1) # capB均分给每一个user的算力
341 |
342 | C_A1 = W_A_user * np.log2(1 + self.p_tran_capA * self.Hn_0 / pow(self.noise, 2)) # [cap_A_user1,cap_A_user2]
343 | C_B1 = W_B_user * np.log2(1 + self.p_tran_capB * self.Hn_1 / pow(self.noise, 2))
344 |
345 | # 窃听者
346 | C_A_E = W_A_user * np.log2(1 + self.p_tran_capA * self.Hn_e / pow(self.noise, 2))
347 | C_B_E = W_B_user * np.log2(1 + self.p_tran_capB * self.Hn_e / pow(self.noise, 2))
348 |
349 | # 更新速率
350 | C_A = C_A1 - C_A_E
351 | C_B = C_B1 - C_B_E
352 |
353 |
354 | #本地
355 | self.offrate_local=np.array([[user_offrate[0][0],user_offrate[0][3]]])#shape:[本地用户1的卸载率,本地用户2的卸载率]
356 | self.T_local=self.user_l*self.offrate_local * self.omega * self.Mb_to_bit / self.f#shape[1,2]
357 |
358 | # ----------CAPA--------------
359 | #传输
360 | self.T_tran_A=np.zeros(shape=(1,2))
361 | for i in range(self.user_num):
362 | if(self.offrate_A[0][i]):
363 | self.T_tran_A[0][i]=self.user_l[0][i] * self.offrate_A[0][i] / C_A[0][i]#shape[1,2]
364 | #CAP端
365 |
366 | self.T_cap_A=np.zeros(shape=(1,2))
367 | for i in range(self.user_num):
368 | if(self.offrate_A[0][i]):
369 | self.T_cap_A[0][i]=self.user_l[0][i] * self.offrate_A[0][i] * self.omega * self.Mb_to_bit / self.F_capA[0][i]#shape[1,2]
370 |
371 | #----------CAPB--------------
372 | #传输
373 |
374 | self.T_tran_B = np.zeros(shape=(1, 2))
375 | for i in range(self.user_num):
376 | if (self.offrate_B[0][i]):
377 | self.T_tran_B[0][i] = self.user_l[0][i] * self.offrate_B[0][i] / C_B[0][i] # shape[1,2]
378 |
379 | #CAP端
380 |
381 | # self.T_cap_B=self.user_l * self.offrate_B * self.omega * self.Mb_to_bit / self.F_capB#shape[1,2]
382 | self.T_cap_B = np.zeros(shape=(1, 2))
383 | for i in range(self.user_num):
384 | if (self.offrate_B[0][i]):
385 | self.T_cap_B[0][i] = self.user_l[0][i] * self.offrate_B[0][i] * self.omega * self.Mb_to_bit / self.F_capB[0][i] # shape[1,2]
386 |
387 | # -----------------------------
388 |
389 | #求T
390 | T=np.sum(self.T_local)+np.sum(self.T_tran_A)+np.sum(self.T_cap_A)+np.sum(self.T_tran_B)+np.sum(self.T_cap_B)
391 |
392 |
393 | # C = W_user * np.log2(1 + self.p_tran * self.Hn / pow(self.noise, 2))
394 | # temp = 1 - user_offrate
395 | # self.T_local = self.user_l * temp * self.omega * self.Mb_to_bit / self.f # shape(1,num)
396 | # self.T_tran = self.user_l * user_offrate * self.omega * self.Mb_to_bit / C # shape(1,num)
397 | # self.T_cap = self.user_l * user_offrate * self.omega * self.Mb_to_bit / self.F # shape(1,num)
398 | # T_temp = self.T_tran + self.T_cap
399 | #
400 | # T_max = np.max(T_temp)
401 | # T_max1 = np.max(self.T_local)
402 | # T = max(T_max, T_max1)
403 |
404 | return T
405 |
406 | def Energy(self, ):
407 | self.E_local=self.T_local * self.p_local
408 | self.E_tran_A=self.T_tran_A * self.p_tran_capA
409 | self.E_tran_B=self.T_tran_B * self.p_tran_capB
410 | E=np.sum(self.E_local)+np.sum(self.E_tran_A)+np.sum(self.E_tran_B)
411 |
412 | # self.E_local = self.T_local * self.p_local
413 | # self.E_tran = self.T_tran * self.p_tran
414 | # self.E_total = self.E_tran + self.E_local
415 | # E = np.sum(self.E_total)
416 | return E
417 |
418 | def total_cost(self, user_offrate): # total_cost 由T与E决定,返回当前时刻的成本
419 | T = self.Time(user_offrate)
420 | # E = self.Energy()
421 | total_cost = T
422 | return total_cost
423 |
424 | def cost_print(self):
425 | self.cost_list1 = self.cost_list # 记录成本
426 | self.epoch_list1 = self.epoch_list
427 | self.quancost_list1 = self.quancost_list
428 | self.wucost_list1 = self.wucost_list
429 | self.cost_list = [] # 记录成本
430 | self.epoch_list = []
431 | self.quancost_list = []
432 | self.wucost_list = []
433 | return self.cost_list1, self.epoch_list1, self.quancost_list1, self.wucost_list1
434 |
--------------------------------------------------------------------------------
/environment_tradition.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | import pandas as pd
3 | import copy
4 | import math
5 |
6 | # S=[任务量✖️卸载率,总算力,总功率]
7 | # A=[卸载率1增,卸载率1减,卸载率2增,卸载率2减,。。。]
8 |
9 |
10 | class environment1(object): # 奖励r由tc与tc-1比较大小得出。Hn:0.992912817258564, 0.992299817945962
11 | def __init__(self, user_num, cap_num, W, f_local, omega, F_cap, p_local, p_tran, lamuda, noise, Hn_0,Hn_1,Hn_e,user_l, suspend):
12 | # user_num:用户总数, cap_num:cap总数,W:单个CAP的总带宽,f_local为本地用户计算能力,omega:计算时间T的w
13 | # C为计算时间的传输速率,F_cap:分配给user的计算能力,p_local:本地计算功率,p_tran:传输功率;lamuda:时间与能耗之间的比例系数
14 | # noise:噪音的方差,用于计算香农公式的C;Hn:香农公式的hnm,用于计算C。suspend:用于判断执行多少次动作后停止
15 | self.user_num = user_num
16 | self.cap_num = cap_num
17 |
18 | self.f = f_local
19 | self.omega = omega
20 |
21 | #W为总带宽,[capA,capB],需要取出来
22 | self.W0 = W
23 | self.W1 = W
24 |
25 | # F_cap为算力(优化对象),[CAPA,CAPB],需分别均分给n个设备
26 |
27 | self.F_cap=F_cap
28 | self.F_0 = F_cap[0][0] / self.user_num#均分算力
29 | self.F_1 = F_cap[0][1] / self.user_num#均分算力
30 |
31 |
32 |
33 | self.F_capA = np.full(shape=(1,self.user_num),fill_value=self.F_0)#capA均分给每一个user的算力
34 | self.F_capB = np.full(shape=(1, self.user_num), fill_value=self.F_1) #capB均分给每一个user的算力
35 |
36 | #传输带宽(优化对象),p_tran总传输功率[user1,user2]
37 | self.p_tran = p_tran
38 | p_tran_0 = self.p_tran[0][0] / self.cap_num
39 | p_tran_1 = self.p_tran[0][1] / self.cap_num
40 |
41 | self.p_tran_user1 = np.full(shape=(1, self.cap_num), fill_value=p_tran_0) # 第一个user分给不同信道的传输功率
42 | self.p_tran_user2 = np.full(shape=(1, self.cap_num), fill_value=p_tran_1) # 第二个user分给不同信道的传输功率
43 |
44 | self.p_tran_capA = np.array([[self.p_tran_user1[0][0], self.p_tran_user2[0][0]]]) # 第一个cap对应每一个user的传输功率
45 | self.p_tran_capB = np.array([[self.p_tran_user1[0][1], self.p_tran_user2[0][1]]]) # 第二个cap对应每一个user的传输功率
46 |
47 |
48 | #信道,Hn为总信道[CAP]
49 | self.Hn_0=Hn_0.reshape(1,2)
50 | self.Hn_1=Hn_1.reshape(1,2)
51 |
52 | self.suspend = suspend
53 |
54 | #分配任务量
55 | self.user_l = user_l#用户最少2个
56 |
57 | #窃听者
58 | self.Hn_e=Hn_e.reshape(1,2)
59 |
60 | #卸载率初始化:
61 |
62 | self.user_offrate = np.zeros(shape=(1,(cap_num + 1)*user_num))#user_offrate的shape[1,(cap_num + 1)*user_num]
63 | for i in range((cap_num + 1)*user_num):
64 | if i % (cap_num + 1)==0:
65 | self.user_offrate[0][i] = 1.0
66 | self.judge=self.user_offrate
67 | self.all_off = np.array([[0.0, 0.5, 0.5, 0.0, 0.5, 0.5]])
68 | # print("初始化时的卸载率为:", self.user_offrate)
69 |
70 | # self.user_offrate_ABC=copy.deepcopy(self.user_offrate)
71 |
72 | self.lamuda = lamuda
73 | self.noise = noise
74 | self.i = 0
75 | self.cost_list = [] # 记录成本
76 | self.epoch_list = []
77 | self.quancost_list = []
78 | self.wucost_list = []
79 |
80 | self.task_action = 1 # 任务每次变化率(任务卸载率)
81 | self.Mb_to_bit = 2 ** 20 # Mb to bit 1MB = 1024KB = 1024*1024B = 1024 * 1024 *8 bit =2^23
82 | # self.Mb_to_bit = 1 # Mb to bit 1MB = 1024KB = 1024*1024B = 1024 * 1024 *8 bit =2^23
83 | self.p_local = p_local
84 |
85 | #--------------------------
86 | #窃听者
87 |
88 |
89 | #-------------------------
90 |
91 |
92 |
93 |
94 |
95 |
96 | # self.l1=np.full(shape=(1, self.cap_num + 1), fill_value=self.user_l[0][0])
97 | # self.l2 = np.full(shape=(1, self.cap_num + 1), fill_value=self.user_l[0][1])
98 | self.l=np.append(np.full(shape=(1, self.cap_num + 1), fill_value=self.user_l[0][0]),np.full(shape=(1, self.cap_num + 1), fill_value=self.user_l[0][1]),axis=1)
99 | self.A = 1.0
100 | self.B = 0.01
101 | self.C = 0.01
102 | self.D = 1.0
103 | self.E = 0.01
104 | self.F = 0.01
105 |
106 | self.temp_tc1 = self.total_cost(self.user_offrate)
107 | self.tc_wald = self.total_cost(self.user_offrate)
108 | self.all_cost=self.total_cost(self.all_off)
109 | # print("本地的cost为:", self.temp_tc1)
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 | def reset(self): # 重开,返回初始化s
119 |
120 | self.user_S = self.l * self.user_offrate #任务量,1x6
121 | #总功率和总算力:p_tran[0],p_tran[1],F_cap[0],F_cap[1]
122 | self.P_F=np.append(self.p_tran,self.F_cap,axis=1)
123 | S_=np.append(self.user_S,self.P_F,axis=1)
124 | return S_
125 |
126 | def step(self, action):
127 | # 输入动作,输出下一步状态s_,奖励r,是否结束done。得根据给的动作,得出下一步s_,还有r,并且r需要求出当前状态下的成本
128 |
129 |
130 | self.i = self.i + 1
131 |
132 | # 判断action执行什么动作,action为一个值
133 |
134 | # self.actions=int(action/2)#对应到卸载率的下标
135 |
136 | # if action%2==0:#增加
137 | # self.offrate_normalization(self.actions,1)
138 | # else:#减少
139 | # self.offrate_normalization(self.actions,0)
140 |
141 | if action == 0: # user1本地增加
142 | self.offrate_normalization(0)
143 | elif action == 1:
144 | self.offrate_normalization(1)
145 | elif action == 2: # user1-capB增加
146 | self.offrate_normalization(2)
147 | elif action == 3:
148 | self.offrate_normalization(3)
149 | elif action == 4: # user2-capA增加
150 | self.offrate_normalization(4)
151 | else:
152 | self.offrate_normalization(5)
153 |
154 |
155 | s_ = self.l * self.user_offrate
156 | self.P_F = np.append(self.p_tran, self.F_cap, axis=1)
157 | s_ = np.append(s_, self.P_F, axis=1)
158 | tc = self.total_cost(self.user_offrate) # 更新后的卸载率的成本
159 |
160 | # if tc > self.tc_wald: # tc为更新后的成本,tc_wald为更新前的成本
161 | # r = -100
162 | # elif tc < self.tc_wald:
163 | # r = 100
164 | # else:
165 | # r = -100
166 | tc_diff = tc - self.tc_wald
167 | if tc_diff >= 5.0:
168 | r = -200
169 | elif tc_diff > 0.0 and tc_diff < 5.0:
170 | r = -100
171 | elif tc_diff <= -5.0:
172 | r = 200
173 | elif tc_diff < 0.0 and tc_diff > -5.0:
174 | r = 100
175 | elif tc_diff == 0.0:
176 | r = -200
177 |
178 |
179 | self.tc_wald = tc
180 |
181 | done = 0 # 不知道什么情况 done输出Ture,代码也没写
182 | if self.i == self.suspend:
183 | done = self.tc_wald
184 | self.i = 0
185 |
186 |
187 |
188 | return s_, r, done, self.tc_wald,self.temp_tc1,self.all_cost
189 |
190 | #根据动作,改变对应的卸载率
191 | def offrate_normalization(self,number):#如增加,add_subtraction=1
192 | # w = self.i / 5.0
193 | global w
194 | if self.i < 500:
195 | w = 1.0
196 | if self.i < 1000:
197 | w = 2.0
198 | if self.i < 1500:
199 | w = 3.0
200 | if self.i < 2000:
201 | w = 4.0
202 | if number == 0:
203 | self.A += w
204 | elif number == 1:
205 | self.B += w
206 | elif number == 2:
207 | self.C += w
208 | elif number == 3:
209 | self.D += w
210 | elif number == 4:
211 | self.E += w
212 | else:
213 | self.F += w
214 | self.user_offrate[0][0] = self.A/ (self.A+self.B+self.C)
215 | self.user_offrate[0][1] = self.B / (self.A + self.B + self.C)
216 | self.user_offrate[0][2] = self.C / (self.A + self.B + self.C)
217 | self.user_offrate[0][3] = self.D / (self.D + self.E + self.F)
218 | self.user_offrate[0][4] = self.E / (self.D + self.E + self.F)
219 | self.user_offrate[0][5] = self.F / (self.D + self.E + self.F)
220 |
221 |
222 |
223 | def action_state_num(self): # 返回动作与环境个数
224 | action_n = self.user_num * (self.cap_num+1)#dqn
225 | state_num = self.user_num*(self.cap_num +1) +self.cap_num*2
226 | return action_n, state_num
227 |
228 | def Time(self, user_offrate):
229 | # 计算香农公式Wn
230 |
231 | # # #-----优化带宽-------------
232 | # if self.user_offrate.all()!=0:
233 | # W_user=np.sqrt((self.user_l*self.user_offrate*self.p_tran)/np.log2(1+(self.p_tran*np.square(self.Hn))/pow(self.noise, 2)))*self.W/np.sum(np.sqrt((self.user_l*self.user_offrate*self.p_tran)/np.log2(1+(self.p_tran*np.square(self.Hn))/pow(self.noise, 2))))
234 | # else:
235 | # w_ = self.W / self.user_num
236 | # W_user = np.full(shape=(1,self.user_num),fill_value=w_)
237 | # #-------------------
238 |
239 | #--------均分带宽--------------
240 | # w_0 = self.W0 / self.user_num#shape[1,2]
241 | # w_1 = self.W1 / self.user_num#shape[1,2]
242 | W_A_user = np.full(shape=(1, self.user_num), fill_value=self.W0)
243 | W_B_user = np.full(shape=(1, self.user_num), fill_value=self.W1)
244 | #-----------------------------
245 |
246 | C_A1=W_A_user*np.log2(1 + self.p_tran_capA * self.Hn_0 / pow(self.noise, 2))#[cap_A_user1,cap_A_user2]
247 | C_B1=W_B_user*np.log2(1 + self.p_tran_capB * self.Hn_1 / pow(self.noise, 2))
248 |
249 | #窃听者
250 | C_A_E=W_A_user*np.log2(1+self.p_tran_capA*self.Hn_e / pow(self.noise, 2))
251 | C_B_E = W_B_user * np.log2(1 + self.p_tran_capB * self.Hn_e / pow(self.noise, 2))
252 |
253 | #更新速率
254 | C_A=C_A1 - C_A_E
255 | C_B=C_B1 - C_B_E
256 |
257 | self.offrate_A = np.array([[user_offrate[0][1], user_offrate[0][4]]]) # shape:[用户1到capA的卸载率,用户2到capA的卸载率]
258 | self.offrate_B = np.array([[user_offrate[0][2], user_offrate[0][5]]]) # shape:[用户1到capA的卸载率,用户2到capA的卸载率]
259 |
260 | #本地
261 | self.offrate_local=np.array([[user_offrate[0][0],user_offrate[0][3]]])#shape:[本地用户1的卸载率,本地用户2的卸载率]
262 | self.T_local=self.user_l*self.offrate_local * self.omega * self.Mb_to_bit / self.f#shape[1,2]
263 |
264 | # ----------CAPA--------------
265 | #传输
266 |
267 | self.T_tran_A=self.user_l * self.offrate_A / C_A#shape[1,2]
268 | #CAP端
269 | self.T_cap_A=self.user_l * self.offrate_A * self.omega * self.Mb_to_bit / self.F_capA#shape[1,2]
270 | #----------CAPB--------------
271 | #传输
272 |
273 | self.T_tran_B=self.user_l * self.offrate_B / C_B#shape[1,2]
274 | #CAP端
275 | self.T_cap_B=self.user_l * self.offrate_B * self.omega * self.Mb_to_bit / self.F_capB#shape[1,2]
276 | # -----------------------------
277 |
278 | #求T
279 | T=np.sum(self.T_local)+np.sum(self.T_tran_A)+np.sum(self.T_cap_A)+np.sum(self.T_tran_B)+np.sum(self.T_cap_B)
280 |
281 | T_off_A=self.T_tran_A+self.T_cap_A
282 |
283 | # C = W_user * np.log2(1 + self.p_tran * self.Hn / pow(self.noise, 2))
284 | # temp = 1 - user_offrate
285 | # self.T_local = self.user_l * temp * self.omega * self.Mb_to_bit / self.f # shape(1,num)
286 | # self.T_tran = self.user_l * user_offrate * self.omega * self.Mb_to_bit / C # shape(1,num)
287 | # self.T_cap = self.user_l * user_offrate * self.omega * self.Mb_to_bit / self.F # shape(1,num)
288 | # T_temp = self.T_tran + self.T_cap
289 | #
290 | # T_max = np.max(T_temp)
291 | # T_max1 = np.max(self.T_local)
292 | # T = max(T_max, T_max1)
293 |
294 | return T
295 |
296 | def Energy(self, ):
297 | self.E_local=self.T_local * self.p_local
298 | self.E_tran_A=self.T_tran_A * self.p_tran_capA
299 | self.E_tran_B=self.T_tran_B * self.p_tran_capB
300 | E=np.sum(self.E_local)+np.sum(self.E_tran_A)+np.sum(self.E_tran_B)
301 |
302 | # self.E_local = self.T_local * self.p_local
303 | # self.E_tran = self.T_tran * self.p_tran
304 | # self.E_total = self.E_tran + self.E_local
305 | # E = np.sum(self.E_total)
306 | return E
307 |
308 | def total_cost(self, user_offrate): # total_cost 由T与E决定,返回当前时刻的成本
309 | T = self.Time(user_offrate)
310 | # E = self.Energy()
311 | total_cost = T
312 | return total_cost
313 |
314 | def cost_print(self):
315 | self.cost_list1 = self.cost_list # 记录成本
316 | self.epoch_list1 = self.epoch_list
317 | self.quancost_list1 = self.quancost_list
318 | self.wucost_list1 = self.wucost_list
319 | self.cost_list = [] # 记录成本
320 | self.epoch_list = []
321 | self.quancost_list = []
322 | self.wucost_list = []
323 | return self.cost_list1, self.epoch_list1, self.quancost_list1, self.wucost_list1
324 |
--------------------------------------------------------------------------------
/test.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": 1,
6 | "metadata": {
7 | "collapsed": true
8 | },
9 | "outputs": [],
10 | "source": [
11 | "import numpy as np\n",
12 | "import torch"
13 | ]
14 | },
15 | {
16 | "cell_type": "code",
17 | "execution_count": 9,
18 | "outputs": [
19 | {
20 | "data": {
21 | "text/plain": "tensor([[0., 0., 0., 0.],\n [0., 0., 0., 0.],\n [0., 0., 0., 0.]])"
22 | },
23 | "execution_count": 9,
24 | "metadata": {},
25 | "output_type": "execute_result"
26 | }
27 | ],
28 | "source": [
29 | "w = torch.Tensor(3,4)\n",
30 | "w"
31 | ],
32 | "metadata": {
33 | "collapsed": false,
34 | "pycharm": {
35 | "name": "#%%\n"
36 | }
37 | }
38 | },
39 | {
40 | "cell_type": "code",
41 | "execution_count": 34,
42 | "outputs": [
43 | {
44 | "data": {
45 | "text/plain": "Parameter containing:\ntensor([[-0.4534, 0.3025, -0.2776],\n [-0.4067, -0.0642, -0.1638],\n [ 0.1921, -0.2198, -0.5003],\n [-0.1345, -0.3511, -0.5041],\n [ 0.3314, -0.4759, 0.1622]], requires_grad=True)"
46 | },
47 | "execution_count": 34,
48 | "metadata": {},
49 | "output_type": "execute_result"
50 | }
51 | ],
52 | "source": [
53 | "# tensor([[-37955820.0000, -1592520.5000, -203957.0000]]\n",
54 | "\n",
55 | "a=torch.tensor([[-37955820.0000, -1592520.5000, -203957.0000]])/1000000\n",
56 | "softmax=torch.nn.Softmax()\n",
57 | "relu=torch.nn.ReLU()\n",
58 | "fc1=torch.nn.Linear(3,5)\n",
59 | "fc1.weight"
60 | ],
61 | "metadata": {
62 | "collapsed": false,
63 | "pycharm": {
64 | "name": "#%%\n"
65 | }
66 | }
67 | },
68 | {
69 | "cell_type": "code",
70 | "execution_count": 32,
71 | "outputs": [
72 | {
73 | "name": "stderr",
74 | "output_type": "stream",
75 | "text": [
76 | ":1: UserWarning: Implicit dimension choice for softmax has been deprecated. Change the call to include dim=X as an argument.\n",
77 | " softmax(a)\n"
78 | ]
79 | },
80 | {
81 | "data": {
82 | "text/plain": "tensor([[3.2200e-17, 1.9964e-01, 8.0036e-01]])"
83 | },
84 | "execution_count": 32,
85 | "metadata": {},
86 | "output_type": "execute_result"
87 | }
88 | ],
89 | "source": [
90 | "softmax(a)"
91 | ],
92 | "metadata": {
93 | "collapsed": false,
94 | "pycharm": {
95 | "name": "#%%\n"
96 | }
97 | }
98 | },
99 | {
100 | "cell_type": "code",
101 | "execution_count": 7,
102 | "outputs": [
103 | {
104 | "data": {
105 | "text/plain": "tensor([2, 3, 4])"
106 | },
107 | "execution_count": 7,
108 | "metadata": {},
109 | "output_type": "execute_result"
110 | }
111 | ],
112 | "source": [
113 | "a=torch.tensor([2,3,4])\n",
114 | "a"
115 | ],
116 | "metadata": {
117 | "collapsed": false,
118 | "pycharm": {
119 | "name": "#%%\n"
120 | }
121 | }
122 | },
123 | {
124 | "cell_type": "code",
125 | "execution_count": 30,
126 | "outputs": [
127 | {
128 | "ename": "RuntimeError",
129 | "evalue": "\"normal_kernel_cpu\" not implemented for 'Long'",
130 | "output_type": "error",
131 | "traceback": [
132 | "\u001B[0;31m---------------------------------------------------------------------------\u001B[0m",
133 | "\u001B[0;31mRuntimeError\u001B[0m Traceback (most recent call last)",
134 | "\u001B[0;32m\u001B[0m in \u001B[0;36m\u001B[0;34m\u001B[0m\n\u001B[0;32m----> 1\u001B[0;31m \u001B[0mtorch\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0mnormal\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0mmean\u001B[0m\u001B[0;34m=\u001B[0m\u001B[0;36m0.5\u001B[0m\u001B[0;34m,\u001B[0m \u001B[0mstd\u001B[0m\u001B[0;34m=\u001B[0m\u001B[0mtorch\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0marange\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0;36m1\u001B[0m\u001B[0;34m,\u001B[0m \u001B[0;36m6\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[0m\u001B[1;32m 2\u001B[0m \u001B[0;34m\u001B[0m\u001B[0m\n",
135 | "\u001B[0;31mRuntimeError\u001B[0m: \"normal_kernel_cpu\" not implemented for 'Long'"
136 | ]
137 | }
138 | ],
139 | "source": [
140 | "torch.normal(mean=0.5, std=torch.arange(1, 6))"
141 | ],
142 | "metadata": {
143 | "collapsed": false,
144 | "pycharm": {
145 | "name": "#%%\n"
146 | }
147 | }
148 | },
149 | {
150 | "cell_type": "code",
151 | "execution_count": 6,
152 | "outputs": [
153 | {
154 | "data": {
155 | "text/plain": "array([[0. , 0.5, 0.5, 0.3, 0.2, 0.5]])"
156 | },
157 | "execution_count": 6,
158 | "metadata": {},
159 | "output_type": "execute_result"
160 | }
161 | ],
162 | "source": [
163 | "a=np.array([[0,0.5,0.5,0.3,0.2,0.5]])\n",
164 | "a"
165 | ],
166 | "metadata": {
167 | "collapsed": false,
168 | "pycharm": {
169 | "name": "#%%\n"
170 | }
171 | }
172 | },
173 | {
174 | "cell_type": "code",
175 | "execution_count": 13,
176 | "outputs": [
177 | {
178 | "data": {
179 | "text/plain": "array([[-0.76937837, 2.09532264, 0.18429382, 4.27775308, -2.91123644,\n -1.65041654]])"
180 | },
181 | "execution_count": 13,
182 | "metadata": {},
183 | "output_type": "execute_result"
184 | }
185 | ],
186 | "source": [
187 | "np.random.normal(a,3)"
188 | ],
189 | "metadata": {
190 | "collapsed": false,
191 | "pycharm": {
192 | "name": "#%%\n"
193 | }
194 | }
195 | },
196 | {
197 | "cell_type": "code",
198 | "execution_count": 4,
199 | "outputs": [
200 | {
201 | "data": {
202 | "text/plain": "array([[0.10981178, 0. , 1. , 0.2740658 , 1. ,\n 1. ]])"
203 | },
204 | "execution_count": 4,
205 | "metadata": {},
206 | "output_type": "execute_result"
207 | }
208 | ],
209 | "source": [
210 | "a=np.clip(np.random.normal(a,3),0,1)\n",
211 | "a"
212 | ],
213 | "metadata": {
214 | "collapsed": false,
215 | "pycharm": {
216 | "name": "#%%\n"
217 | }
218 | }
219 | }
220 | ],
221 | "metadata": {
222 | "kernelspec": {
223 | "display_name": "Python 3",
224 | "language": "python",
225 | "name": "python3"
226 | },
227 | "language_info": {
228 | "codemirror_mode": {
229 | "name": "ipython",
230 | "version": 2
231 | },
232 | "file_extension": ".py",
233 | "mimetype": "text/x-python",
234 | "name": "python",
235 | "nbconvert_exporter": "python",
236 | "pygments_lexer": "ipython2",
237 | "version": "2.7.6"
238 | }
239 | },
240 | "nbformat": 4,
241 | "nbformat_minor": 0
242 | }
--------------------------------------------------------------------------------
/传入用户-窃听/DQN_env_customized_users_final.py:
--------------------------------------------------------------------------------
1 | #%%
2 | import os
3 | import Writedata
4 | os.environ['KMP_DUPLICATE_LIB_OK']='True'
5 | #2021。9。27最终版。可以自定义用户版。优化了带宽
6 | # 输入的s为:[任务量1✖️卸载率1,任务量2✖️卸载率2, .....]
7 | # 输出的a为某个用户卸载率增加或者减少
8 |
9 | #2cap 2user
10 |
11 | import torch
12 | import numpy as np
13 |
14 | import matplotlib.pyplot as plt
15 | from environment_optimize1 import environment
16 | from environment_tradition import environment1
17 |
18 |
19 | #%%
20 |
21 | # user_num=input("please input user_num")
22 |
23 | #初始化参数-----------------
24 | user_num=2
25 | cap_num=2
26 | users_num=int(user_num)
27 |
28 | Hn = np.abs(1.1 * np.sqrt(1 / 2) * (np.random.normal(1, 1, [user_num, cap_num]) + np.complex('j') *
29 | np.random.normal(1, 1, [user_num, cap_num]))) ** 2
30 | Hn_e = np.abs(0.1 * np.sqrt(1 / 2) * (np.random.normal(1, 1, user_num) + np.complex('j') *
31 | np.random.normal(1, 1, user_num))) ** 2##窃听者,[user1,user2]
32 | Hn_0=Hn[0]
33 | Hn_1=Hn[1]
34 |
35 | user_l = np.array([[np.random.randint(10,20), np.random.randint(150,200)]])
36 |
37 | e_number=5
38 | sus=2000
39 | epochs=200
40 | #----------------
41 | env=environment(user_num=2,cap_num=2,W=[5,5],
42 | f_local=np.array([[1.4*10e8,0.43*10e8]]),
43 | omega=330 / 8,
44 | F_cap=np.array([[10*10e8,3*10e8]]),p_local=1e-1,p_tran=np.array([[2,3]]),lamuda=1,
45 | noise=0.1,Hn_0=Hn_0,Hn_1=Hn_1,Hn_e=Hn_e,user_l=user_l,
46 | suspend=sus
47 | )
48 |
49 | #改
50 | #获取环境的相关参数:
51 | n_action,n_state=env.action_state_num()
52 | #其他超参数的定义:
53 | MEMORY_CAPACITY=5000#记忆库的存储大小
54 | greedy=0.9#贪婪概率
55 | discount=0.9#折扣率
56 | batch_size=64#一次训练32个数据
57 | TARGET_REPLACE_ITER=10#目标网络的更新频率
58 |
59 | #%%
60 |
61 | class Net(torch.nn.Module):
62 | def __init__(self):
63 | super(Net, self).__init__()
64 | self.linear1=torch.nn.Linear(n_state,20)#(10,20)
65 | self.linear1.weight.data.normal_(0, 0.1)
66 | self.linear2=torch.nn.Linear(20,30)
67 | self.linear2.weight.data.normal_(0, 0.1)
68 | self.linear3=torch.nn.Linear(30,18)
69 | self.linear3.weight.data.normal_(0, 0.1)
70 | self.linear4=torch.nn.Linear(18,n_action)#(30,12)
71 | self.linear4.weight.data.normal_(0, 0.1)
72 | self.relu=torch.nn.ReLU()
73 | def forward(self,x):
74 | x=self.relu(self.linear1(x))
75 | x=self.relu(self.linear2(x))
76 | x = self.relu(self.linear3(x))
77 | q_values=self.linear4(x)
78 | return q_values
79 |
80 |
81 | #%%
82 |
83 | class DQN ():
84 | def __init__(self):#可能要改成def __init__(self,n_state,n_action)
85 |
86 | #记忆库:存s,a,r,s_ 一共6维
87 | self.memory=np.zeros((MEMORY_CAPACITY,n_state*2+2))
88 | self.memory_count=0#记忆库计数,用于求index,以及当记忆库计数 > 记忆库容量时 开始学习
89 |
90 | #目标网络,参数更新慢。参数更新跟着agent_network走。用于预测q现实
91 | self.target_network=Net()
92 |
93 | #目标网络更新计数
94 | self.learn_step_counter=0
95 |
96 | #用于训练的网络,参数更新及时。用于预测q估计
97 | self.agent_network=Net()
98 |
99 | #优化器与损失器
100 | self.loss_func=torch.nn.MSELoss()
101 | self.optimizer=torch.optim.Adam(self.agent_network.parameters(),lr=0.001)
102 | def choose_action(self,s):#这里每次只输入一个样本。
103 | # 输入的s为:[任务量1✖️卸载率1,任务量2✖️卸载率2]
104 | # 输出的action为0或1或2或3
105 | if np.random.uniform() < greedy:#选择最优动作
106 | #送入神经网络前,先要处理s成为torch型,且要求shape为(1,4)
107 | #s=torch.tensor(s,dtype=float).reshape(1,4)
108 | #s=s.to(torch.float32)
109 | s=torch.FloatTensor(s).reshape(-1,n_state)
110 |
111 | #把s送入神经网络得到a_value, a_value的shape 为(4,1)。并且得到的是四个动作q值
112 | action_value=self.agent_network.forward(s)
113 |
114 | #输出每个样本中预测的最大值,输出[最大值,下标]。只要下标
115 | _,action=torch.max(action_value.data,dim=1)
116 | #在从numpy转为int值
117 | action=action.numpy()[0]
118 | #此时action可能是0、1、2、3
119 |
120 |
121 | else:#随机选择动作
122 | action = np.random.randint(0, n_action)
123 |
124 | return action
125 |
126 | def store_transition(self,s,action,r,s_):
127 | #将四个值打包在一起
128 |
129 | #action为0or 1 or 2 or 3
130 | s=s.reshape(n_state)
131 | s_=s_.reshape(n_state)
132 |
133 | self.transition=np.hstack((s,[action,r],s_))
134 |
135 | #如果记忆库满了, 就覆盖老数据
136 | index = self.memory_count % MEMORY_CAPACITY
137 |
138 | #传入记忆库
139 |
140 | self.memory[index,:]=self.transition
141 | self.memory_count+=1
142 | #print("目前记忆库存储的总数为",self.memory_count)#要删除
143 |
144 | def learn(self):#从记忆库中选择batch个数据进行训练学习
145 | #首先判断target_network是否需要更新
146 |
147 | if self.learn_step_counter % TARGET_REPLACE_ITER==0:
148 | self.target_network.load_state_dict(self.agent_network.state_dict())#更新目标网络参数
149 | self.learn_step_counter+=1
150 |
151 | #随机从memory中抽32个数据,即batch=32
152 |
153 | sample_index=np.random.choice(MEMORY_CAPACITY,batch_size)#从0-1999中抽32个数字,shape为(32,)
154 | batch_memory=self.memory[sample_index,:]#获取32个数据。 shape 为(32,6)
155 |
156 |
157 | b_s = torch.FloatTensor(batch_memory[:, :n_state])
158 | b_a = torch.LongTensor(batch_memory[:, n_state:n_state+1].astype(int))
159 | b_r = torch.FloatTensor(batch_memory[:, n_state+1:n_state+2])
160 | b_s_ = torch.FloatTensor(batch_memory[:, -n_state:])
161 | # b_memory shape (batch,6)
162 | # b_s shape (batch,2)
163 | # b_a shape (batch,1)
164 | # b_r shape (batch,1)
165 | # b_s_ shape (batch,2)
166 |
167 |
168 | #把样本state送入agent网络训练,得到q估计
169 | q_predict=self.agent_network(b_s)#shape 为 (32,4)
170 | q_predict=q_predict.gather(1,b_a)#shaoe 为 (32,1)。根据b_a找出q估计
171 |
172 |
173 | # #把样本送入target网络计算,得到Q(s+1)
174 | # q_next=self.target_network(b_s_).detach()# q_next 不进行反向传播, 所以使用detach。shape为 (32,4)
175 | # q_next,_=torch.max(q_next,dim=1)#输出每个样本中预测的最大值,输出[最大值,下标]。只要最大值
176 | # q_next=q_next.reshape((-1,1))#q_next的shape 为(32,1)
177 | # #计算q真实
178 | # q_target=b_r+discount*q_next#q_target的shape 为(32,1)
179 |
180 | #改用ddqn
181 | q_next=self.agent_network(b_s_).detach()#
182 | _,b_a_=torch.max(q_next,dim=1)#由dqn网络选出动作
183 | b_a_=b_a_.reshape((-1,1))#b_a_的shape 为(32,1)
184 | q_next_target=self.target_network(b_s_).detach()
185 | q_next=q_next_target.gather(1,b_a_)#q_next的shape 为(32,1
186 | #计算q真实
187 | q_target=b_r+discount*q_next#q_target的shape 为(32,1)
188 |
189 |
190 |
191 | loss=self.loss_func(q_predict,q_target)
192 | # if self.learn_step_counter%5000==0:
193 | # print("第",self.learn_step_counter,"次强化学习的loss为:",loss.item())
194 | self.optimizer.zero_grad()
195 | loss.backward()
196 | self.optimizer.step()
197 | return loss.item()
198 |
199 |
200 |
201 | #%%
202 |
203 | dqn=DQN()
204 | dqn_tradition=DQN()
205 | epoch_cost_optimize=[]
206 | epoch_cost_tradition=[]
207 |
208 |
209 |
210 |
211 | epoch_list=[]
212 | loss_list=[]
213 | temp_wu_list=[]
214 | local_costs_epoch=[]
215 | count=0
216 |
217 |
218 |
219 | cost=np.zeros([epochs,sus])
220 | #每次开始游戏前,重开游戏
221 | #s=env.reset()#s是(4,)的numpy
222 | # print("开始第",epoch+1,"轮游戏")
223 | # start = time.time()
224 | e_number=5
225 | for epoch in range(epochs):
226 | print("本轮epoch=",epoch,"本轮epoch=",epoch,"本轮epoch=",epoch,"本轮epoch=",epoch)
227 | step_loss = []
228 | step_loss_tradition=[]
229 | local_costs=[]
230 |
231 | #参数随机化
232 | Hn = np.abs(1.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, [user_num, cap_num]) + np.complex('j') *
233 | np.random.normal(1, 0.1, [user_num, cap_num]))) ** 2
234 |
235 |
236 | ##窃听者,[user1,user2]
237 |
238 | Hn_e1 = np.abs(0.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, user_num) + np.complex('j') *
239 | np.random.normal(1, 0.1, user_num))) ** 2
240 | Hn_e2 = np.abs(0.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, user_num) + np.complex('j') *
241 | np.random.normal(1, 0.1, user_num))) ** 2
242 | Hn_e3 = np.abs(0.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, user_num) + np.complex('j') *
243 | np.random.normal(1, 0.1, user_num))) ** 2
244 | Hn_e4 = np.abs(0.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, user_num) + np.complex('j') *
245 | np.random.normal(1, 0.1, user_num))) ** 2
246 | Hn_e5 = np.abs(0.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, user_num) + np.complex('j') *
247 | np.random.normal(1, 0.1, user_num))) ** 2
248 | Hn_e =Hn_e1+ Hn_e2 + Hn_e3 + Hn_e4 + Hn_e5
249 |
250 | # Hn_e=Hn_e1
251 | Hn_0 = Hn[0]
252 | Hn_1 = Hn[1]
253 |
254 | while((Hn_e > Hn_1).any() or (Hn_e > Hn_0).any()):
255 | Hn = np.abs(1.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, [user_num, cap_num]) + np.complex('j') *
256 | np.random.normal(1, 0.1, [user_num, cap_num]))) ** 2
257 | ##窃听者,[user1,user2]
258 | Hn_e1 = np.abs(0.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, user_num) + np.complex('j') *
259 | np.random.normal(1, 0.1, user_num))) ** 2
260 | Hn_e2 = np.abs(0.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, user_num) + np.complex('j') *
261 | np.random.normal(1, 0.1, user_num))) ** 2
262 | Hn_e3 = np.abs(0.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, user_num) + np.complex('j') *
263 | np.random.normal(1, 0.1, user_num))) ** 2
264 | Hn_e4 = np.abs(0.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, user_num) + np.complex('j') *
265 | np.random.normal(1, 0.1, user_num))) ** 2
266 | Hn_e5 = np.abs(0.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, user_num) + np.complex('j') *
267 | np.random.normal(1, 0.1, user_num))) ** 2
268 | Hn_e =Hn_e1+ Hn_e2 + Hn_e3 + Hn_e4 + Hn_e5
269 | #共谋:sum
270 | Hn_0 = Hn[0]
271 | Hn_1 = Hn[1]
272 |
273 |
274 | user_l = np.array([[np.random.randint(10,60), np.random.randint(550,600)]])
275 | #--------------------------
276 | #------------优化功率和算力-------------
277 | env = environment(user_num=2, cap_num=2, W=5.0,
278 | f_local=np.array([[1.4 * 10e8, 0.43 * 10e8]]),
279 | omega=330 / 8,
280 | F_cap=np.array([[10 * 10e8, 3 * 10e8]]), p_local=1e-1, p_tran=np.array([[2, 3]]), lamuda=1,
281 | noise=0.1, Hn_0=Hn_0, Hn_1=Hn_1,Hn_e=Hn_e,user_l=user_l,
282 | suspend=sus
283 | )
284 | s = env.reset()
285 | while True:#每次循环执行一个动作
286 |
287 | #通过神经网络,输入状态,获取动作。(不带学习)
288 | action=dqn.choose_action(s)
289 |
290 | #执行,获得环境反馈
291 | s_,r,done,tc_wald,local_cost=env.step(action)
292 | step_loss.append(tc_wald)
293 | local_costs.append(local_cost)
294 | #将环境的反馈s,a,r,s_传入记忆库。用于经验回放
295 | dqn.store_transition(s,action,r,s_)
296 |
297 | #神经网络学习(experience replay 经验回放)
298 | if dqn.memory_count > MEMORY_CAPACITY:
299 | count+=1
300 | loss=dqn.learn()
301 |
302 |
303 | #判断是否结束
304 | if done !=0:
305 | epoch_cost_optimize.append(done)
306 | local_costs_epoch.append(local_cost)
307 | break
308 |
309 | #更新状态,进入下一次循环
310 | s=s_
311 | #--------------------------------------------
312 |
313 |
314 | # ------------传统方法-------------
315 | env_tradition = environment1(user_num=2, cap_num=2, W=5.0,
316 | f_local=np.array([[1.4 * 10e8, 0.43 * 10e8]]),
317 | omega=330 / 8,
318 | F_cap=np.array([[10 * 10e8, 3 * 10e8]]), p_local=1e-1, p_tran=np.array([[2, 3]]),
319 | lamuda=1,
320 | noise=0.1, Hn_0=Hn_0, Hn_1=Hn_1, Hn_e=Hn_e, user_l=user_l,
321 | suspend=sus
322 | )
323 | s=env_tradition.reset()
324 | while True: # 每次循环执行一个动作
325 |
326 | # 通过神经网络,输入状态,获取动作。(不带学习)
327 | action = dqn_tradition.choose_action(s)
328 |
329 | # 执行,获得环境反馈
330 | s_, r, done, tc_wald, local_cost = env_tradition.step(action)
331 | step_loss_tradition.append(tc_wald)
332 | # local_costs.append(local_cost)
333 |
334 | # 将环境的反馈s,a,r,s_传入记忆库。用于经验回放
335 | dqn_tradition.store_transition(s, action, r, s_)
336 |
337 | # 神经网络学习(experience replay 经验回放)
338 | if dqn_tradition.memory_count > MEMORY_CAPACITY:
339 | count += 1
340 | loss = dqn_tradition.learn()
341 |
342 | # 判断是否结束
343 | if done!=0:
344 | epoch_cost_tradition.append(done)
345 | break
346 |
347 | # 更新状态,进入下一次循环
348 | s = s_
349 | # --------------------------------------------
350 |
351 |
352 | plt.plot(range(sus), step_loss, color='skyblue', label='optimize_F_P')
353 | plt.plot(range(sus), step_loss_tradition, color='red', label='tradition')
354 | plt.plot(range(sus),local_costs,color="yellow",label="local")
355 | plt.legend(loc="best")
356 |
357 | plt.xlabel("step_dqn_e25")
358 | plt.ylabel("costs")
359 | plt.show()
360 |
361 |
362 | plt.plot(range(epochs),local_costs_epoch, color='yellow', label='locals')
363 | plt.plot(range(epochs),epoch_cost_optimize,color='skyblue', label='optimize_F_P')
364 | plt.plot(range(epochs),epoch_cost_tradition,color='red', label='tradition')
365 |
366 | # Writedata.write_to_excel(epoch_cost_optimize,1,"epoch_cost_optimize_E25_1")
367 | # Writedata.write_to_excel(epoch_cost_tradition,1,"epoch_cost_tradition_E25_1")
368 | # Writedata.write_to_excel(local_costs_epoch,1,"local_costs_epoch_E25_1")
369 |
370 | plt.xlabel("epoch_e25")
371 | plt.ylabel("costs")
372 | plt.legend(loc="best")
373 | plt.show()
374 |
--------------------------------------------------------------------------------
/传入用户-窃听/Writedata.py:
--------------------------------------------------------------------------------
1 | import xlrd
2 | from xlwt import *
3 |
4 |
5 | # 多次实验时写入数据代码
6 | def write_data(data_list, sheet_name, iteration):
7 | for each_i in range(len(data_list)):
8 | sheet_name.write(each_i, iteration, str(data_list[each_i]))
9 |
10 |
11 | def create_csv(sheet1, data_list, iteration=1):
12 | write_data(data_list=data_list, sheet_name=sheet1, iteration=iteration)
13 |
14 |
15 | def write_to_excel(cost_list, is_one, filename):
16 | wb = Workbook()
17 | sheet1 = wb.add_sheet(sheetname='cost')
18 | if is_one:
19 | create_csv(sheet1=sheet1, data_list=cost_list)
20 | else:
21 | for index in range(len(cost_list)):
22 | create_csv(sheet1=sheet1, data_list=cost_list[index], iteration=index)
23 | wb.save(filename)
24 |
25 |
26 | def read_file(h_file, task_file):
27 | channel_uc = xlrd.open_workbook(h_file)
28 | task_file = xlrd.open_workbook(task_file)
29 | uc_sheet = channel_uc.sheets()[0]
30 | task_sheet = task_file.sheets()[0]
31 |
32 | return uc_sheet, task_sheet
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/传入用户-窃听/__pycache__/Writedata.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiong1998/offloading-optimization-and-resource-optimization-base-on-mobile-edge-computing-net/0c90c5809c0a665f7c9ee2afc74436f2562a789f/传入用户-窃听/__pycache__/Writedata.cpython-38.pyc
--------------------------------------------------------------------------------
/传入用户-窃听/__pycache__/environment_optimize1.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiong1998/offloading-optimization-and-resource-optimization-base-on-mobile-edge-computing-net/0c90c5809c0a665f7c9ee2afc74436f2562a789f/传入用户-窃听/__pycache__/environment_optimize1.cpython-38.pyc
--------------------------------------------------------------------------------
/传入用户-窃听/__pycache__/environment_tradition.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiong1998/offloading-optimization-and-resource-optimization-base-on-mobile-edge-computing-net/0c90c5809c0a665f7c9ee2afc74436f2562a789f/传入用户-窃听/__pycache__/environment_tradition.cpython-38.pyc
--------------------------------------------------------------------------------
/传入用户-窃听/environment_optimize1.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | import pandas as pd
3 | import copy
4 | import math
5 |
6 | # S=[任务量✖️卸载率,总算力,总功率]
7 | # A=[卸载率1增,卸载率1减,卸载率2增,卸载率2减,。。。]
8 |
9 |
10 | class environment(object): # 奖励r由tc与tc-1比较大小得出。Hn:0.992912817258564, 0.992299817945962
11 | def __init__(self, user_num, cap_num, W, f_local, omega, F_cap, p_local, p_tran, lamuda, noise, Hn_0,Hn_1,Hn_e,user_l, suspend):
12 | # user_num:用户总数, cap_num:cap总数,W:单个CAP的总带宽,f_local为本地用户计算能力,omega:计算时间T的w
13 | # C为计算时间的传输速率,F_cap:分配给user的计算能力,p_local:本地计算功率,p_tran:传输功率;lamuda:时间与能耗之间的比例系数
14 | # noise:噪音的方差,用于计算香农公式的C;Hn:香农公式的hnm,用于计算C。suspend:用于判断执行多少次动作后停止
15 | self.user_num = user_num
16 | self.cap_num = cap_num
17 |
18 | self.f = f_local
19 | self.omega = omega
20 |
21 | #W为总带宽,[capA,capB],需要取出来
22 | self.W0 = W
23 | self.W1 = W
24 |
25 | # F_cap为算力(优化对象),[CAPA,CAPB],需分别均分给n个设备
26 |
27 | self.F_cap=F_cap
28 | self.F_0 = F_cap[0][0] / self.user_num#均分算力
29 | self.F_1 = F_cap[0][1] / self.user_num#均分算力
30 |
31 |
32 |
33 | self.F_capA = np.full(shape=(1,self.user_num),fill_value=self.F_0)#capA均分给每一个user的算力
34 | self.F_capB = np.full(shape=(1, self.user_num), fill_value=self.F_1) #capB均分给每一个user的算力
35 |
36 | #传输带宽(优化对象),p_tran总传输功率[user1,user2]
37 | self.p_tran=p_tran
38 | p_tran_0 = self.p_tran[0][0] / self.cap_num
39 | p_tran_1 = self.p_tran[0][1] / self.cap_num
40 |
41 | self.p_tran_user1 = np.full(shape=(1, self.cap_num), fill_value=p_tran_0) # 第一个user分给不同信道的传输功率
42 | self.p_tran_user2 = np.full(shape=(1, self.cap_num), fill_value=p_tran_1) # 第二个user分给不同信道的传输功率
43 |
44 | self.p_tran_capA = np.array([[self.p_tran_user1[0][0], self.p_tran_user2[0][0]]])# 第一个cap对应每一个user的传输功率
45 | self.p_tran_capB = np.array([[self.p_tran_user1[0][1], self.p_tran_user2[0][1]]])# 第二个cap对应每一个user的传输功率
46 |
47 |
48 | #信道,Hn为总信道CAPA分给两个用户的信道
49 | self.Hn_0=Hn_0.reshape(1,2)
50 | self.Hn_1=Hn_1.reshape(1,2)
51 |
52 | self.suspend = suspend
53 |
54 | #分配任务量
55 | self.user_l = user_l#用户最少2个
56 |
57 | #窃听者
58 | self.Hn_e=Hn_e.reshape(1,2)
59 |
60 | #卸载率初始化:
61 |
62 | self.user_offrate = np.zeros(shape=(1,(cap_num + 1)*user_num))#user_offrate的shape[1,(cap_num + 1)*user_num]
63 | for i in range((cap_num + 1)*user_num):
64 | if i % (cap_num + 1)==0:
65 | self.user_offrate[0][i] = 1.0
66 | self.judge=copy.deepcopy(self.user_offrate)
67 | # print("初始化时的卸载率为:", self.user_offrate)
68 |
69 | # self.user_offrate_ABC=copy.deepcopy(self.user_offrate)
70 |
71 | self.lamuda = lamuda
72 | self.noise = noise
73 | self.i = 0
74 | self.cost_list = [] # 记录成本
75 | self.epoch_list = []
76 | self.quancost_list = []
77 | self.wucost_list = []
78 |
79 | self.task_action = 1 # 任务每次变化率(任务卸载率)
80 | self.Mb_to_bit = 2 ** 20 # Mb to bit 1MB = 1024KB = 1024*1024B = 1024 * 1024 *8 bit =2^23
81 | # self.Mb_to_bit = 1 # Mb to bit 1MB = 1024KB = 1024*1024B = 1024 * 1024 *8 bit =2^23
82 | self.p_local = p_local
83 |
84 |
85 |
86 | # self.l1=np.full(shape=(1, self.cap_num + 1), fill_value=self.user_l[0][0])
87 | # self.l2 = np.full(shape=(1, self.cap_num + 1), fill_value=self.user_l[0][1])
88 | self.l=np.append(np.full(shape=(1, self.cap_num + 1), fill_value=self.user_l[0][0]),np.full(shape=(1, self.cap_num + 1), fill_value=self.user_l[0][1]),axis=1)
89 | self.A = 1.0
90 | self.B = 0.0
91 | self.C = 0.0
92 | self.D = 1.0
93 | self.E = 0.0
94 | self.F = 0.0
95 |
96 | self.temp_tc1 = self.total_cost(self.user_offrate)
97 | self.tc_wald = self.total_cost(self.user_offrate)
98 | # print("本地的cost为:", self.temp_tc1)
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 | def reset(self): # 重开,返回初始化s
108 |
109 | # 卸载率✖️任务量
110 | self.user_S = self.l * self.user_offrate # 任务量,1x6
111 | # 总功率和总算力:p_tran[0],p_tran[1],F_cap[0],F_cap[1]
112 | self.P_F = np.append(self.p_tran, self.F_cap, axis=1)
113 | # 信道差
114 | self.Hn0_diff = self.Hn_0 - self.Hn_e
115 | self.Hn1_diff = self.Hn_1 - self.Hn_e
116 | self.Hn_diff = np.append(self.Hn0_diff, self.Hn1_diff, axis=1)
117 |
118 | S_ = np.append(self.user_S, self.P_F, axis=1)
119 |
120 | S_ = np.append(S_, self.Hn_diff, axis=1)
121 | return S_
122 |
123 | def step(self, action):
124 | # 输入动作,输出下一步状态s_,奖励r,是否结束done。得根据给的动作,得出下一步s_,还有r,并且r需要求出当前状态下的成本
125 |
126 |
127 | self.i = self.i + 1
128 |
129 | # 判断action执行什么动作,action为一个值
130 |
131 | # self.actions=int(action/2)#对应到卸载率的下标
132 |
133 | # if action%2==0:#增加
134 | # self.offrate_normalization(self.actions,1)
135 | # else:#减少
136 | # self.offrate_normalization(self.actions,0)
137 |
138 | #self.offrate_normalization(1,1)、
139 |
140 | if action==0:#user1本地增加
141 | self.offrate_normalization(0,1)
142 | elif action==1:
143 | self.offrate_normalization(1,1)
144 | elif action == 2: # user1-capA增加
145 | self.offrate_normalization(2,1)
146 | elif action == 3:
147 | self.offrate_normalization(3,1)
148 | elif action == 4: # user1-capB增加
149 | self.offrate_normalization(4,1)
150 | else:
151 | self.offrate_normalization(5,1)
152 |
153 |
154 | s_ = self.l * self.user_offrate
155 | self.P_F = np.append(self.p_tran, self.F_cap, axis=1)
156 | s_ = np.append(s_, self.P_F, axis=1)
157 | s_ = np.append(s_, self.Hn_diff, axis=1)
158 |
159 | # 计算更新卸载率后的成本
160 | tc = self.total_cost(self.user_offrate)
161 |
162 | #本地
163 | self.temp_tc1=self.total_cost(self.judge)
164 |
165 |
166 | if tc > self.tc_wald: # tc为更新后的成本,tc_wald为更新前的成本
167 | r = -100
168 | elif tc < self.tc_wald:
169 | r = 100
170 | else:
171 | r = -100
172 | self.user_S = s_ # 更新状态
173 | if self.i % 2000==0:
174 | print("----------------------------------")
175 | print("执行了第", self.i, "次动作")
176 | print("此轮更新卸载率后的成本为:", tc)
177 | print("此时卸载率为:", self.user_offrate)
178 |
179 |
180 | self.tc_wald = tc
181 |
182 | done = 0 # 不知道什么情况 done输出Ture,代码也没写
183 | if self.i == self.suspend:
184 | done = self.tc_wald
185 | self.i=0
186 |
187 |
188 |
189 | return s_, r, done, self.tc_wald,self.temp_tc1
190 |
191 | #根据动作,改变对应的卸载率
192 | def offrate_normalization(self,number,add_subtraction):#如增加,add_subtraction=1
193 | if add_subtraction:
194 | if number==0:
195 | self.A+=1.0
196 | elif number==1:
197 | self.B+=1.0
198 | elif number==2:
199 | self.C+=1.0
200 | elif number==3:
201 | self.D+=1.0
202 | elif number==4:
203 | self.E+=1.0
204 | else:
205 | self.F+=1.0
206 | else:
207 | if number==0:
208 | if self.A>1:
209 | self.A-=1.0
210 | elif number==1:
211 | if self.B>1:
212 | self.B-=1.0
213 | elif number==2:
214 | if self.C>1:
215 | self.C-=1.0
216 | elif number==3:
217 | if self.D>1:
218 | self.D-=1.0
219 | elif number==4:
220 | if self.E>1:
221 | self.E-=1.0
222 | else:
223 | if self.F>1:
224 | self.F-=1.0
225 | self.user_offrate[0][0] = self.A/ (self.A+self.B+self.C)
226 | self.user_offrate[0][1] = self.B / (self.A + self.B + self.C)
227 | self.user_offrate[0][2] = self.C / (self.A + self.B + self.C)
228 | self.user_offrate[0][3] = self.D / (self.D + self.E + self.F)
229 | self.user_offrate[0][4] = self.E / (self.D + self.E + self.F)
230 | self.user_offrate[0][5] = self.F / (self.D + self.E + self.F)
231 |
232 |
233 |
234 | def action_state_num(self): # 返回动作与环境个数
235 | #动作个数
236 | action_n = self.user_num * (self.cap_num+1)#dqn
237 |
238 | #
239 | Hn_num = self.cap_num * self.user_num
240 | state_num = self.user_num*(self.cap_num +1) +self.cap_num*2+Hn_num
241 |
242 | return action_n, state_num
243 |
244 | def Time(self, user_offrate):
245 | # 计算香农公式Wn
246 |
247 | # # #-----优化带宽-------------
248 | # if self.user_offrate.all()!=0:
249 | # W_user=np.sqrt((self.user_l*self.user_offrate*self.p_tran)/np.log2(1+(self.p_tran*np.square(self.Hn))/pow(self.noise, 2)))*self.W/np.sum(np.sqrt((self.user_l*self.user_offrate*self.p_tran)/np.log2(1+(self.p_tran*np.square(self.Hn))/pow(self.noise, 2))))
250 | # else:
251 | # w_ = self.W / self.user_num
252 | # W_user = np.full(shape=(1,self.user_num),fill_value=w_)
253 | # #-------------------
254 |
255 | #--------均分带宽--------------
256 | # w_0 = self.W0 / self.user_num#shape[1,2]
257 | # w_1 = self.W1 / self.user_num#shape[1,2]
258 | W_A_user = np.full(shape=(1, self.user_num), fill_value=self.W0)
259 | W_B_user = np.full(shape=(1, self.user_num), fill_value=self.W1)
260 | #-----------------------------
261 |
262 |
263 |
264 |
265 | if (user_offrate!=self.judge).any():
266 |
267 | #----解析-------
268 | a_A=W_A_user*np.log2(self.Hn_0/self.Hn_e)
269 | a_B=W_B_user*np.log2(self.Hn_1/self.Hn_e)
270 |
271 | b_A=W_A_user * pow(self.noise, 2) * (1/self.Hn_e - 1/self.Hn_0) / math.log(2)
272 | b_B=W_B_user * pow(self.noise, 2) * (1/self.Hn_e - 1/self.Hn_1) / math.log(2)
273 |
274 |
275 |
276 | #按user分
277 |
278 |
279 | b_user1=np.array([[b_A[0][0],b_B[0][0]]])
280 | b_user2 = np.array([[b_A[0][1], b_B[0][1]]])
281 |
282 | self.l1=self.l[0][1:3]#传输与cap计算的任务量
283 | self.l2=self.l[0][4:]
284 | user_offrate_user1=user_offrate[0][1:3]#user1的传输与cap计算的卸载率
285 | user_offrate_user2=user_offrate[0][4:]
286 |
287 | a_user1 =np.array([[a_A[0][0], a_B[0][0]]])
288 | a_user2 = np.array([[a_A[0][1], a_B[0][1]]])
289 |
290 | # A_users=np.append(A_user1,A_user2,axis=1)
291 | A_users=a_A*a_B
292 | A_user1=A_users[0][0]#数字
293 | A_user2=A_users[0][1]#数字
294 |
295 | lumuda_user1=pow(np.sum(A_user1*np.sqrt(self.l1*user_offrate_user1*b_user1)/a_user1)/(self.p_tran[0][0]*A_user1-np.sum(b_user1*A_user1/a_user1)),2)
296 | lumuda_user2=pow(np.sum(A_user2*np.sqrt(self.l2*user_offrate_user2*b_user2)/a_user2)/(self.p_tran[0][1]*A_user2-np.sum(b_user2*A_user2/a_user2)),2)
297 | lumuda_users=np.array([[lumuda_user1,lumuda_user2]])
298 |
299 |
300 | self.offrate_A = np.array([[user_offrate[0][1], user_offrate[0][4]]]) # shape:[用户1到capA的卸载率,用户2到capA的卸载率]
301 | self.offrate_B = np.array([[user_offrate[0][2], user_offrate[0][5]]]) # shape:[用户1到capA的卸载率,用户2到capA的卸载率]
302 |
303 | mu_capA = pow(np.sum(np.sqrt(self.offrate_A*self.user_l))/self.F_cap[0][0],2)#检查到这
304 | mu_capB = pow(np.sum(np.sqrt(self.offrate_B * self.user_l)) / self.F_cap[0][1],2)
305 | mu_cpas = np.array([[mu_capA, mu_capB]])
306 |
307 | #分配传输功率
308 |
309 | self.p_tran_user1=(np.sqrt(self.l1*user_offrate_user1*b_user1/lumuda_user1)+b_user1)/a_user1
310 | self.p_tran_user2=(np.sqrt(self.l2*user_offrate_user2*b_user2/lumuda_user2)+b_user2)/a_user2
311 |
312 | self.p_tran_capA=np.array([[self.p_tran_user1[0][0],self.p_tran_user2[0][0]]])
313 | self.p_tran_capB = np.array([[self.p_tran_user1[0][1], self.p_tran_user2[0][1]]])
314 | # else:
315 | # p_tran_1 = self.p_tran[0][1] / self.cap_num
316 | # self.p_tran_user2 = np.full(shape=(1, self.cap_num), fill_value=p_tran_1)
317 | # self.p_tran_capB = np.array([[self.p_tran_user1[0][1], self.p_tran_user2[0][1]]])
318 |
319 | #分配算力
320 | self.F_capA = np.sqrt(self.offrate_A * self.user_l / mu_capA)
321 | self.F_capB = np.sqrt(self.offrate_B * self.user_l / mu_capB)
322 |
323 |
324 | else:
325 | self.offrate_A = np.array([[user_offrate[0][1], user_offrate[0][4]]]) # shape:[用户1到capA的卸载率,用户2到capA的卸载率]
326 | self.offrate_B = np.array([[user_offrate[0][2], user_offrate[0][5]]]) # shape:[用户1到capA的卸载率,用户2到capA的卸载率]
327 |
328 | #均分传输功率
329 | p_tran_0 = self.p_tran[0][0] / self.cap_num
330 | p_tran_1 = self.p_tran[0][1] / self.cap_num
331 |
332 | self.p_tran_user1 = np.full(shape=(1, self.cap_num), fill_value=p_tran_0) # 第一个user分给不同信道的传输功率
333 | self.p_tran_user2 = np.full(shape=(1, self.cap_num), fill_value=p_tran_1) # 第二个user分给不同信道的传输功率
334 |
335 | self.p_tran_capA = np.array([[self.p_tran_user1[0][0], self.p_tran_user2[0][0]]]) # 第一个cap均分给每一个user的传输功率
336 | self.p_tran_capB = np.array([[self.p_tran_user1[0][1], self.p_tran_user2[0][1]]]) # 第二个cap均分给每一个user的传输功率
337 |
338 | #均分算力
339 | self.F_capA = np.full(shape=(1, self.user_num), fill_value=self.F_0) # capA均分给每一个user的算力
340 | self.F_capB = np.full(shape=(1, self.user_num), fill_value=self.F_1) # capB均分给每一个user的算力
341 |
342 | C_A1 = W_A_user * np.log2(1 + self.p_tran_capA * self.Hn_0 / pow(self.noise, 2)) # [cap_A_user1,cap_A_user2]
343 | C_B1 = W_B_user * np.log2(1 + self.p_tran_capB * self.Hn_1 / pow(self.noise, 2))
344 |
345 | # 窃听者
346 | C_A_E = W_A_user * np.log2(1 + self.p_tran_capA * self.Hn_e / pow(self.noise, 2))
347 | C_B_E = W_B_user * np.log2(1 + self.p_tran_capB * self.Hn_e / pow(self.noise, 2))
348 |
349 | # 更新速率
350 | C_A = C_A1 - C_A_E
351 | C_B = C_B1 - C_B_E
352 |
353 |
354 | #本地
355 | self.offrate_local=np.array([[user_offrate[0][0],user_offrate[0][3]]])#shape:[本地用户1的卸载率,本地用户2的卸载率]
356 | self.T_local=self.user_l*self.offrate_local * self.omega * self.Mb_to_bit / self.f#shape[1,2]
357 |
358 | # ----------CAPA--------------
359 | #传输
360 | self.T_tran_A=np.zeros(shape=(1,2))
361 | for i in range(self.user_num):
362 | if(self.offrate_A[0][i]):
363 | self.T_tran_A[0][i]=self.user_l[0][i] * self.offrate_A[0][i] / C_A[0][i]#shape[1,2]
364 | #CAP端
365 |
366 | self.T_cap_A=np.zeros(shape=(1,2))
367 | for i in range(self.user_num):
368 | if(self.offrate_A[0][i]):
369 | self.T_cap_A[0][i]=self.user_l[0][i] * self.offrate_A[0][i] * self.omega * self.Mb_to_bit / self.F_capA[0][i]#shape[1,2]
370 |
371 | #----------CAPB--------------
372 | #传输
373 |
374 | self.T_tran_B = np.zeros(shape=(1, 2))
375 | for i in range(self.user_num):
376 | if (self.offrate_B[0][i]):
377 | self.T_tran_B[0][i] = self.user_l[0][i] * self.offrate_B[0][i] / C_B[0][i] # shape[1,2]
378 |
379 | #CAP端
380 |
381 | # self.T_cap_B=self.user_l * self.offrate_B * self.omega * self.Mb_to_bit / self.F_capB#shape[1,2]
382 | self.T_cap_B = np.zeros(shape=(1, 2))
383 | for i in range(self.user_num):
384 | if (self.offrate_B[0][i]):
385 | self.T_cap_B[0][i] = self.user_l[0][i] * self.offrate_B[0][i] * self.omega * self.Mb_to_bit / self.F_capB[0][i] # shape[1,2]
386 |
387 | # -----------------------------
388 |
389 | #求T
390 | T=np.sum(self.T_local)+np.sum(self.T_tran_A)+np.sum(self.T_cap_A)+np.sum(self.T_tran_B)+np.sum(self.T_cap_B)
391 |
392 |
393 | # C = W_user * np.log2(1 + self.p_tran * self.Hn / pow(self.noise, 2))
394 | # temp = 1 - user_offrate
395 | # self.T_local = self.user_l * temp * self.omega * self.Mb_to_bit / self.f # shape(1,num)
396 | # self.T_tran = self.user_l * user_offrate * self.omega * self.Mb_to_bit / C # shape(1,num)
397 | # self.T_cap = self.user_l * user_offrate * self.omega * self.Mb_to_bit / self.F # shape(1,num)
398 | # T_temp = self.T_tran + self.T_cap
399 | #
400 | # T_max = np.max(T_temp)
401 | # T_max1 = np.max(self.T_local)
402 | # T = max(T_max, T_max1)
403 |
404 | return T
405 |
406 | def Energy(self, ):
407 | self.E_local=self.T_local * self.p_local
408 | self.E_tran_A=self.T_tran_A * self.p_tran_capA
409 | self.E_tran_B=self.T_tran_B * self.p_tran_capB
410 | E=np.sum(self.E_local)+np.sum(self.E_tran_A)+np.sum(self.E_tran_B)
411 |
412 | # self.E_local = self.T_local * self.p_local
413 | # self.E_tran = self.T_tran * self.p_tran
414 | # self.E_total = self.E_tran + self.E_local
415 | # E = np.sum(self.E_total)
416 | return E
417 |
418 | def total_cost(self, user_offrate): # total_cost 由T与E决定,返回当前时刻的成本
419 | T = self.Time(user_offrate)
420 | # E = self.Energy()
421 | total_cost = self.lamuda * T
422 | return total_cost
423 |
424 | def cost_print(self):
425 | self.cost_list1 = self.cost_list # 记录成本
426 | self.epoch_list1 = self.epoch_list
427 | self.quancost_list1 = self.quancost_list
428 | self.wucost_list1 = self.wucost_list
429 | self.cost_list = [] # 记录成本
430 | self.epoch_list = []
431 | self.quancost_list = []
432 | self.wucost_list = []
433 | return self.cost_list1, self.epoch_list1, self.quancost_list1, self.wucost_list1
434 |
--------------------------------------------------------------------------------
/传入用户-窃听/environment_tradition.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | import pandas as pd
3 | import copy
4 | import math
5 |
6 | # S=[任务量✖️卸载率,总算力,总功率]
7 | # A=[卸载率1增,卸载率1减,卸载率2增,卸载率2减,。。。]
8 |
9 |
10 | class environment1(object): # 奖励r由tc与tc-1比较大小得出。Hn:0.992912817258564, 0.992299817945962
11 | def __init__(self, user_num, cap_num, W, f_local, omega, F_cap, p_local, p_tran, lamuda, noise, Hn_0,Hn_1,Hn_e,user_l, suspend):
12 | # user_num:用户总数, cap_num:cap总数,W:单个CAP的总带宽,f_local为本地用户计算能力,omega:计算时间T的w
13 | # C为计算时间的传输速率,F_cap:分配给user的计算能力,p_local:本地计算功率,p_tran:传输功率;lamuda:时间与能耗之间的比例系数
14 | # noise:噪音的方差,用于计算香农公式的C;Hn:香农公式的hnm,用于计算C。suspend:用于判断执行多少次动作后停止
15 | self.user_num = user_num
16 | self.cap_num = cap_num
17 |
18 | self.f = f_local
19 | self.omega = omega
20 |
21 | #W为总带宽,[capA,capB],需要取出来
22 | self.W0 = W
23 | self.W1 = W
24 |
25 | # F_cap为算力(优化对象),[CAPA,CAPB],需分别均分给n个设备
26 |
27 | self.F_cap=F_cap
28 | self.F_0 = F_cap[0][0] / self.user_num#均分算力
29 | self.F_1 = F_cap[0][1] / self.user_num#均分算力
30 |
31 |
32 |
33 | self.F_capA = np.full(shape=(1,self.user_num),fill_value=self.F_0)#capA均分给每一个user的算力
34 | self.F_capB = np.full(shape=(1, self.user_num), fill_value=self.F_1) #capB均分给每一个user的算力
35 |
36 | #传输带宽(优化对象),p_tran总传输功率[user1,user2]
37 | self.p_tran = p_tran
38 | p_tran_0 = self.p_tran[0][0] / self.cap_num
39 | p_tran_1 = self.p_tran[0][1] / self.cap_num
40 |
41 | self.p_tran_user1 = np.full(shape=(1, self.cap_num), fill_value=p_tran_0) # 第一个user分给不同信道的传输功率
42 | self.p_tran_user2 = np.full(shape=(1, self.cap_num), fill_value=p_tran_1) # 第二个user分给不同信道的传输功率
43 |
44 | self.p_tran_capA = np.array([[self.p_tran_user1[0][0], self.p_tran_user2[0][0]]]) # 第一个cap对应每一个user的传输功率
45 | self.p_tran_capB = np.array([[self.p_tran_user1[0][1], self.p_tran_user2[0][1]]]) # 第二个cap对应每一个user的传输功率
46 |
47 |
48 | #信道,Hn为总信道[CAP]
49 | self.Hn_0=Hn_0.reshape(1,2)
50 | self.Hn_1=Hn_1.reshape(1,2)
51 |
52 | self.suspend = suspend
53 |
54 | #分配任务量
55 | self.user_l = user_l#用户最少2个
56 |
57 | #窃听者
58 | self.Hn_e=Hn_e.reshape(1,2)
59 |
60 | #卸载率初始化:
61 |
62 | self.user_offrate = np.zeros(shape=(1,(cap_num + 1)*user_num))#user_offrate的shape[1,(cap_num + 1)*user_num]
63 | for i in range((cap_num + 1)*user_num):
64 | if i % (cap_num + 1)==0:
65 | self.user_offrate[0][i] = 1.0
66 | self.judge=self.user_offrate
67 | # print("初始化时的卸载率为:", self.user_offrate)
68 |
69 | # self.user_offrate_ABC=copy.deepcopy(self.user_offrate)
70 |
71 | self.lamuda = lamuda
72 | self.noise = noise
73 | self.i = 0
74 | self.cost_list = [] # 记录成本
75 | self.epoch_list = []
76 | self.quancost_list = []
77 | self.wucost_list = []
78 |
79 | self.task_action = 1 # 任务每次变化率(任务卸载率)
80 | self.Mb_to_bit = 2 ** 20 # Mb to bit 1MB = 1024KB = 1024*1024B = 1024 * 1024 *8 bit =2^23
81 | # self.Mb_to_bit = 1 # Mb to bit 1MB = 1024KB = 1024*1024B = 1024 * 1024 *8 bit =2^23
82 | self.p_local = p_local
83 |
84 | #--------------------------
85 | #窃听者
86 |
87 |
88 | #-------------------------
89 |
90 |
91 |
92 |
93 |
94 |
95 | # self.l1=np.full(shape=(1, self.cap_num + 1), fill_value=self.user_l[0][0])
96 | # self.l2 = np.full(shape=(1, self.cap_num + 1), fill_value=self.user_l[0][1])
97 | self.l=np.append(np.full(shape=(1, self.cap_num + 1), fill_value=self.user_l[0][0]),np.full(shape=(1, self.cap_num + 1), fill_value=self.user_l[0][1]),axis=1)
98 | self.A = 1.0
99 | self.B = 0.0
100 | self.C = 0.0
101 | self.D = 1.0
102 | self.E = 0.0
103 | self.F = 0.0
104 |
105 | self.temp_tc1 = self.total_cost(self.user_offrate)
106 | self.tc_wald = self.total_cost(self.user_offrate)
107 | # print("本地的cost为:", self.temp_tc1)
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 | def reset(self): # 重开,返回初始化s
117 |
118 | #卸载率✖️任务量
119 | self.user_S = self.l * self.user_offrate #任务量,1x6
120 | #总功率和总算力:p_tran[0],p_tran[1],F_cap[0],F_cap[1]
121 | self.P_F=np.append(self.p_tran,self.F_cap,axis=1)
122 | #信道差
123 | self.Hn0_diff=self.Hn_0-self.Hn_e
124 | self.Hn1_diff=self.Hn_1-self.Hn_e
125 | self.Hn_diff=np.append(self.Hn0_diff,self.Hn1_diff,axis=1)
126 |
127 | S_=np.append(self.user_S,self.P_F,axis=1)
128 |
129 | S_=np.append(S_,self.Hn_diff,axis=1)
130 | return S_
131 |
132 | def step(self, action):
133 | # 输入动作,输出下一步状态s_,奖励r,是否结束done。得根据给的动作,得出下一步s_,还有r,并且r需要求出当前状态下的成本
134 |
135 |
136 | self.i = self.i + 1
137 |
138 | # 判断action执行什么动作,action为一个值
139 |
140 | # self.actions=int(action/2)#对应到卸载率的下标
141 |
142 | # if action%2==0:#增加
143 | # self.offrate_normalization(self.actions,1)
144 | # else:#减少
145 | # self.offrate_normalization(self.actions,0)
146 |
147 | if action == 0: # user1本地增加
148 | self.offrate_normalization(0, 1)
149 | elif action == 1:
150 | self.offrate_normalization(1, 1)
151 | elif action == 2: # user1-capB增加
152 | self.offrate_normalization(2, 1)
153 | elif action == 3:
154 | self.offrate_normalization(3, 1)
155 | elif action == 4: # user2-capA增加
156 | self.offrate_normalization(4, 1)
157 | else:
158 | self.offrate_normalization(5, 1)
159 |
160 |
161 | s_ = self.l * self.user_offrate
162 | self.P_F = np.append(self.p_tran, self.F_cap, axis=1)
163 | s_ = np.append(s_, self.P_F, axis=1)
164 | s_=np.append(s_,self.Hn_diff,axis=1)
165 | tc = self.total_cost(self.user_offrate) # 更新后的卸载率的成本
166 |
167 | if tc > self.tc_wald: # tc为更新后的成本,tc_wald为更新前的成本
168 | r = -100
169 | elif tc < self.tc_wald:
170 | r = 100
171 | else:
172 | r = -100
173 | self.user_S = s_ # 更新状态
174 | # if self.i % 500==0:
175 | # print("----------------------------------")
176 | # print("执行了第", self.i, "次动作")
177 | # print("此轮更新卸载率后的成本为:", tc)
178 | # print("此时卸载率为:", self.user_offrate)
179 |
180 |
181 | self.tc_wald = tc
182 |
183 | done = 0 # 不知道什么情况 done输出Ture,代码也没写
184 | if self.i == self.suspend:
185 | done = self.tc_wald
186 | self.i = 0
187 |
188 |
189 |
190 | return s_, r, done, self.tc_wald,self.temp_tc1
191 |
192 | #根据动作,改变对应的卸载率
193 | def offrate_normalization(self,number,add_subtraction):#如增加,add_subtraction=1
194 | if add_subtraction:
195 | if number==0:
196 | self.A+=1.0
197 | elif number==1:
198 | self.B+=1.0
199 | elif number==2:
200 | self.C+=1.0
201 | elif number==3:
202 | self.D+=1.0
203 | elif number==4:
204 | self.E+=1.0
205 | else:
206 | self.F+=1.0
207 | else:
208 | if number==0:
209 | if self.A>1:
210 | self.A-=1.0
211 | elif number==1:
212 | if self.B>1:
213 | self.B-=1.0
214 | elif number==2:
215 | if self.C>1:
216 | self.C-=1.0
217 | elif number==3:
218 | if self.D>1:
219 | self.D-=1.0
220 | elif number==4:
221 | if self.E>1:
222 | self.E-=1.0
223 | else:
224 | if self.F>1:
225 | self.F-=1.0
226 | self.user_offrate[0][0] = self.A/ (self.A+self.B+self.C)
227 | self.user_offrate[0][1] = self.B / (self.A + self.B + self.C)
228 | self.user_offrate[0][2] = self.C / (self.A + self.B + self.C)
229 | self.user_offrate[0][3] = self.D / (self.D + self.E + self.F)
230 | self.user_offrate[0][4] = self.E / (self.D + self.E + self.F)
231 | self.user_offrate[0][5] = self.F / (self.D + self.E + self.F)
232 |
233 |
234 |
235 | def action_state_num(self): # 返回动作与环境个数
236 | action_n = self.user_num * (self.cap_num+1)#dqn
237 |
238 | Hn_num = self.cap_num * self.user_num
239 | state_num = self.user_num * (self.cap_num + 1) + self.cap_num * 2 + Hn_num
240 | return action_n, state_num
241 |
242 | def Time(self, user_offrate):
243 | # 计算香农公式Wn
244 |
245 | # # #-----优化带宽-------------
246 | # if self.user_offrate.all()!=0:
247 | # W_user=np.sqrt((self.user_l*self.user_offrate*self.p_tran)/np.log2(1+(self.p_tran*np.square(self.Hn))/pow(self.noise, 2)))*self.W/np.sum(np.sqrt((self.user_l*self.user_offrate*self.p_tran)/np.log2(1+(self.p_tran*np.square(self.Hn))/pow(self.noise, 2))))
248 | # else:
249 | # w_ = self.W / self.user_num
250 | # W_user = np.full(shape=(1,self.user_num),fill_value=w_)
251 | # #-------------------
252 |
253 | #--------均分带宽--------------
254 | # w_0 = self.W0 / self.user_num#shape[1,2]
255 | # w_1 = self.W1 / self.user_num#shape[1,2]
256 | W_A_user = np.full(shape=(1, self.user_num), fill_value=self.W0)
257 | W_B_user = np.full(shape=(1, self.user_num), fill_value=self.W1)
258 | #-----------------------------
259 |
260 | C_A1=W_A_user*np.log2(1 + self.p_tran_capA * self.Hn_0 / pow(self.noise, 2))#[cap_A_user1,cap_A_user2]
261 | C_B1=W_B_user*np.log2(1 + self.p_tran_capB * self.Hn_1 / pow(self.noise, 2))
262 |
263 | #窃听者
264 | C_A_E=W_A_user*np.log2(1+self.p_tran_capA*self.Hn_e / pow(self.noise, 2))
265 | C_B_E = W_B_user * np.log2(1 + self.p_tran_capB * self.Hn_e / pow(self.noise, 2))
266 |
267 | #更新速率
268 | C_A=C_A1 - C_A_E
269 | C_B=C_B1 - C_B_E
270 |
271 | self.offrate_A = np.array([[user_offrate[0][1], user_offrate[0][4]]]) # shape:[用户1到capA的卸载率,用户2到capA的卸载率]
272 | self.offrate_B = np.array([[user_offrate[0][2], user_offrate[0][5]]]) # shape:[用户1到capA的卸载率,用户2到capA的卸载率]
273 |
274 | #本地
275 | self.offrate_local=np.array([[user_offrate[0][0],user_offrate[0][3]]])#shape:[本地用户1的卸载率,本地用户2的卸载率]
276 | self.T_local=self.user_l*self.offrate_local * self.omega * self.Mb_to_bit / self.f#shape[1,2]
277 |
278 | # ----------CAPA--------------
279 | #传输
280 |
281 | self.T_tran_A=self.user_l * self.offrate_A / C_A#shape[1,2]
282 | #CAP端
283 | self.T_cap_A=self.user_l * self.offrate_A * self.omega * self.Mb_to_bit / self.F_capA#shape[1,2]
284 | #----------CAPB--------------
285 | #传输
286 |
287 | self.T_tran_B=self.user_l * self.offrate_B / C_B#shape[1,2]
288 | #CAP端
289 | self.T_cap_B=self.user_l * self.offrate_B * self.omega * self.Mb_to_bit / self.F_capB#shape[1,2]
290 | # -----------------------------
291 |
292 | #求T
293 | T=np.sum(self.T_local)+np.sum(self.T_tran_A)+np.sum(self.T_cap_A)+np.sum(self.T_tran_B)+np.sum(self.T_cap_B)
294 |
295 | T_off_A=self.T_tran_A+self.T_cap_A
296 |
297 | # C = W_user * np.log2(1 + self.p_tran * self.Hn / pow(self.noise, 2))
298 | # temp = 1 - user_offrate
299 | # self.T_local = self.user_l * temp * self.omega * self.Mb_to_bit / self.f # shape(1,num)
300 | # self.T_tran = self.user_l * user_offrate * self.omega * self.Mb_to_bit / C # shape(1,num)
301 | # self.T_cap = self.user_l * user_offrate * self.omega * self.Mb_to_bit / self.F # shape(1,num)
302 | # T_temp = self.T_tran + self.T_cap
303 | #
304 | # T_max = np.max(T_temp)
305 | # T_max1 = np.max(self.T_local)
306 | # T = max(T_max, T_max1)
307 |
308 | return T
309 |
310 | def Energy(self, ):
311 | self.E_local=self.T_local * self.p_local
312 | self.E_tran_A=self.T_tran_A * self.p_tran_capA
313 | self.E_tran_B=self.T_tran_B * self.p_tran_capB
314 | E=np.sum(self.E_local)+np.sum(self.E_tran_A)+np.sum(self.E_tran_B)
315 |
316 | # self.E_local = self.T_local * self.p_local
317 | # self.E_tran = self.T_tran * self.p_tran
318 | # self.E_total = self.E_tran + self.E_local
319 | # E = np.sum(self.E_total)
320 | return E
321 |
322 | def total_cost(self, user_offrate): # total_cost 由T与E决定,返回当前时刻的成本
323 | T = self.Time(user_offrate)
324 | E = self.Energy()
325 | total_cost = self.lamuda * T
326 | return total_cost
327 |
328 | def cost_print(self):
329 | self.cost_list1 = self.cost_list # 记录成本
330 | self.epoch_list1 = self.epoch_list
331 | self.quancost_list1 = self.quancost_list
332 | self.wucost_list1 = self.wucost_list
333 | self.cost_list = [] # 记录成本
334 | self.epoch_list = []
335 | self.quancost_list = []
336 | self.wucost_list = []
337 | return self.cost_list1, self.epoch_list1, self.quancost_list1, self.wucost_list1
338 |
--------------------------------------------------------------------------------
/传入用户-窃听/epoch_cost_optimize_E25_1:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiong1998/offloading-optimization-and-resource-optimization-base-on-mobile-edge-computing-net/0c90c5809c0a665f7c9ee2afc74436f2562a789f/传入用户-窃听/epoch_cost_optimize_E25_1
--------------------------------------------------------------------------------
/传入用户-窃听/epoch_cost_tradition_E25_1:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiong1998/offloading-optimization-and-resource-optimization-base-on-mobile-edge-computing-net/0c90c5809c0a665f7c9ee2afc74436f2562a789f/传入用户-窃听/epoch_cost_tradition_E25_1
--------------------------------------------------------------------------------
/传入用户-窃听/local_costs_epoch_E25_1:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiong1998/offloading-optimization-and-resource-optimization-base-on-mobile-edge-computing-net/0c90c5809c0a665f7c9ee2afc74436f2562a789f/传入用户-窃听/local_costs_epoch_E25_1
--------------------------------------------------------------------------------
/传入用户-窃听/test.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": 4,
6 | "metadata": {
7 | "collapsed": true
8 | },
9 | "outputs": [],
10 | "source": [
11 | "import numpy as np\n",
12 | "user_num=2"
13 | ]
14 | },
15 | {
16 | "cell_type": "code",
17 | "execution_count": 5,
18 | "outputs": [
19 | {
20 | "data": {
21 | "text/plain": "array([0.04008809, 0.03647456])"
22 | },
23 | "execution_count": 5,
24 | "metadata": {},
25 | "output_type": "execute_result"
26 | }
27 | ],
28 | "source": [
29 | "Hn_e1 = np.abs(0.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, user_num) + np.complex('j') *\n",
30 | " np.random.normal(1, 0.1, user_num))) ** 2\n",
31 | "Hn_e2 = np.abs(0.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, user_num) + np.complex('j') *\n",
32 | " np.random.normal(1, 0.1, user_num))) ** 2\n",
33 | "Hn_e3 = np.abs(0.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, user_num) + np.complex('j') *\n",
34 | " np.random.normal(1, 0.1, user_num))) ** 2\n",
35 | "Hn_e4 = np.abs(0.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, user_num) + np.complex('j') *\n",
36 | " np.random.normal(1, 0.1, user_num))) ** 2\n",
37 | "Hn_e5 = np.abs(0.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, user_num) + np.complex('j') *\n",
38 | " np.random.normal(1, 0.1, user_num))) ** 2\n",
39 | "Hn_e = Hn_e2 + Hn_e3 + Hn_e4 + Hn_e5\n",
40 | "\n",
41 | "Hn_e"
42 | ],
43 | "metadata": {
44 | "collapsed": false,
45 | "pycharm": {
46 | "name": "#%%\n"
47 | }
48 | }
49 | },
50 | {
51 | "cell_type": "code",
52 | "execution_count": 3,
53 | "outputs": [
54 | {
55 | "data": {
56 | "text/plain": "array([[0.01109678, 0.01234598]])"
57 | },
58 | "execution_count": 3,
59 | "metadata": {},
60 | "output_type": "execute_result"
61 | }
62 | ],
63 | "source": [
64 | "Hn_e=np.zeros(shape=(1,2))\n",
65 | "\n",
66 | "Hn_1=np.zeros(shape=(1,2))\n",
67 | "\n",
68 | "Hn_2=np.zeros(shape=(1,2))\n",
69 | "for i in range(1):\n",
70 | " Hn_e += (np.abs(0.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, 2) + np.complex('j') *\n",
71 | " np.random.normal(1, 0.1, 2))) ** 2).reshape(1,2)\n",
72 | "for i in range(1):\n",
73 | " Hn_1 += (np.abs(0.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, 2) + np.complex('j') *\n",
74 | " np.random.normal(1, 0.1, 2))) ** 2).reshape(1,2)\n",
75 | "for i in range(1):\n",
76 | " Hn_2 += (np.abs(0.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, 2) + np.complex('j') *\n",
77 | " np.random.normal(1, 0.1, 2))) ** 2).reshape(1,2)"
78 | ],
79 | "metadata": {
80 | "collapsed": false,
81 | "pycharm": {
82 | "name": "#%%\n"
83 | }
84 | }
85 | },
86 | {
87 | "cell_type": "code",
88 | "execution_count": 4,
89 | "outputs": [
90 | {
91 | "ename": "NameError",
92 | "evalue": "name 'Hn_1' is not defined",
93 | "output_type": "error",
94 | "traceback": [
95 | "\u001B[0;31m---------------------------------------------------------------------------\u001B[0m",
96 | "\u001B[0;31mNameError\u001B[0m Traceback (most recent call last)",
97 | "\u001B[0;32m\u001B[0m in \u001B[0;36m\u001B[0;34m\u001B[0m\n\u001B[0;32m----> 1\u001B[0;31m \u001B[0mnp\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0marray\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0mHn_e\u001B[0m\u001B[0;34m,\u001B[0m\u001B[0mHn_1\u001B[0m\u001B[0;34m,\u001B[0m\u001B[0mHn_2\u001B[0m\u001B[0;34m,\u001B[0m\u001B[0maxis\u001B[0m\u001B[0;34m=\u001B[0m\u001B[0;36m1\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[0m",
98 | "\u001B[0;31mNameError\u001B[0m: name 'Hn_1' is not defined"
99 | ]
100 | }
101 | ],
102 | "source": [
103 | "np.array(Hn_e,Hn_1,Hn_2,axis=1)"
104 | ],
105 | "metadata": {
106 | "collapsed": false,
107 | "pycharm": {
108 | "name": "#%%\n"
109 | }
110 | }
111 | }
112 | ],
113 | "metadata": {
114 | "kernelspec": {
115 | "display_name": "Python 3",
116 | "language": "python",
117 | "name": "python3"
118 | },
119 | "language_info": {
120 | "codemirror_mode": {
121 | "name": "ipython",
122 | "version": 2
123 | },
124 | "file_extension": ".py",
125 | "mimetype": "text/x-python",
126 | "name": "python",
127 | "nbconvert_exporter": "python",
128 | "pygments_lexer": "ipython2",
129 | "version": "2.7.6"
130 | }
131 | },
132 | "nbformat": 4,
133 | "nbformat_minor": 0
134 | }
--------------------------------------------------------------------------------
/改善环境版/DQN_env_wu.py:
--------------------------------------------------------------------------------
1 | #%%
2 | import os
3 | import Writedata
4 | os.environ['KMP_DUPLICATE_LIB_OK']='True'
5 | #2021年11。2。 用了裕鑫的环境,自己的模型
6 | # 输入的s为:[任务量1✖️卸载率1,任务量2✖️卸载率2, .....]
7 | # 输出的a为某个用户卸载率增加或者减少
8 |
9 | #2cap 2user
10 | import torch
11 | import numpy as np
12 | import Writedata
13 | import matplotlib.pyplot as plt
14 |
15 | from Environment_Wu import Environment
16 | from Environment_Wu_tradition import Environment1
17 |
18 | #%%
19 |
20 | # user_num=input("please input user_num")
21 |
22 | #初始化参数-----------------
23 | user_num=2
24 | cap_num=2
25 | users_num=int(user_num)
26 | MAX_EP=2000#步数
27 | epochs=100
28 | e_num=5#窃听数
29 |
30 | Hn = np.abs(1.1 * np.sqrt(1 / 2) * (np.random.normal(1, 1, [user_num, cap_num]) + np.complex('j') *
31 | np.random.normal(1, 1, [user_num, cap_num]))) ** 2
32 |
33 |
34 | Hn_e = np.abs(0.1 * np.sqrt(1 / 2) * (np.random.normal(1, 1, user_num) + np.complex('j') *
35 | np.random.normal(1, 1, user_num))) ** 2##窃听者,[user1,user2]
36 |
37 |
38 | user_l=np.array([10, 550])
39 |
40 | #----------------
41 |
42 | env = Environment(user_num=2, cap_num=2, W=5e6,
43 | f_local=np.array([1.4 * 10e8, 0.43 * 10e8]),
44 | omega=330 / 8,
45 | F_cap=np.array([10 * 10e8, 3 * 10e8]), p_local=1e-1, p_tran=np.array([2, 3]), lamda_=1.0,
46 | p_noise=0.1, Hn=Hn, Hn_e=Hn_e, user_l=user_l,Mb_to_bit=2 ** 20
47 | )
48 |
49 |
50 | #获取环境的相关参数:
51 | n_action,n_state=env.action_state_num()
52 | #其他超参数的定义:
53 | MEMORY_CAPACITY=5000#记忆库的存储大小
54 | greedy=0.57#贪婪概率
55 | discount=0.9#折扣率 ff
56 | batch_size=32#一次训练32个数据
57 | TARGET_REPLACE_ITER=100#目标网络的更新频率
58 |
59 | def get_channel_gain_sum():#共谋
60 | # Hn (2,2)
61 | while True:
62 | Hn = np.abs(1.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, [user_num, cap_num]) + np.complex('j') *
63 | np.random.normal(1, 0.1, [user_num, cap_num]))) ** 2
64 | Hn_e = np.abs(0.2 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, [user_num, e_num]) + np.complex('j') *
65 | np.random.normal(1, 0.1, [user_num, e_num]))) ** 2
66 | Hn_e = np.sum(Hn_e, axis=1) # 共谋取和
67 | if(Hn>Hn_e).all():
68 | break
69 |
70 | return Hn, Hn_e
71 |
72 | def get_channel_gain_max():#非共谋
73 | while True:
74 | Hn = np.abs(1.1 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, [user_num, cap_num]) + np.complex('j') *
75 | np.random.normal(1, 0.1, [user_num, cap_num]))) ** 2
76 |
77 | Hn_e = np.abs(0.2 * np.sqrt(1 / 2) * (np.random.normal(1, 0.1, [user_num, e_num]) + np.complex('j') *
78 | np.random.normal(1, 0.1, [user_num, e_num]))) ** 2
79 | Hn_e=np.max(Hn_e, axis=1)
80 | if (Hn > Hn_e).all():
81 | break
82 | return Hn, Hn_e
83 |
84 | #%%
85 |
86 | class Net(torch.nn.Module):
87 | def __init__(self):
88 | super(Net, self).__init__()
89 | self.linear1=torch.nn.Linear(n_state,64)#(10,20)
90 | self.linear1.weight.data.normal_(0, 0.1)
91 | self.linear2=torch.nn.Linear(64,256)
92 | self.linear2.weight.data.normal_(0, 0.1)
93 | self.linear3=torch.nn.Linear(256,64)
94 | self.linear3.weight.data.normal_(0, 0.1)
95 | self.linear4=torch.nn.Linear(64,n_action)#(30,12)
96 | self.linear4.weight.data.normal_(0, 0.1)
97 | self.relu=torch.nn.ReLU()
98 | self.dropout=torch.nn.Dropout(p=0.5)
99 | def forward(self,x):
100 | x=self.relu(self.linear1(x))
101 | x=self.dropout(x)
102 | x=self.relu(self.linear2(x))
103 | x = self.relu(self.linear3(x))
104 | q_values=self.linear4(x)
105 | return q_values
106 |
107 |
108 | #%%
109 |
110 | class DQN ():
111 | def __init__(self):#可能要改成def __init__(self,n_state,n_action)
112 |
113 | #记忆库:存s,a,r,s_ 一共6维
114 | self.memory=np.zeros((MEMORY_CAPACITY,n_state*2+2))
115 | self.memory_count=0#记忆库计数,用于求index,以及当记忆库计数 > 记忆库容量时 开始学习
116 |
117 | #目标网络,参数更新慢。参数更新跟着agent_network走。用于预测q现实
118 | self.target_network=Net()
119 |
120 | #目标网络更新计数
121 | self.learn_step_counter=0
122 |
123 | #用于训练的网络,参数更新及时。用于预测q估计
124 | self.agent_network=Net()
125 |
126 | #优化器与损失器
127 | self.loss_func=torch.nn.MSELoss()
128 | self.optimizer=torch.optim.Adam(self.agent_network.parameters(),lr=0.001)
129 | def choose_action(self,s):#这里每次只输入一个样本。
130 | # 输入的s为:[任务量1✖️卸载率1,任务量2✖️卸载率2]
131 | # 输出的action为0或1或2或3
132 | self.agent_network.eval()
133 | if np.random.uniform() < greedy:#选择最优动作
134 | #送入神经网络前,先要处理s成为torch型,且要求shape为(1,4)
135 | #s=torch.tensor(s,dtype=float).reshape(1,4)
136 | #s=s.to(torch.float32)
137 | s=torch.FloatTensor(s).reshape(-1,n_state)
138 |
139 | #把s送入神经网络得到a_value, a_value的shape 为(4,1)。并且得到的是四个动作q值
140 | action_value=self.agent_network.forward(s)
141 |
142 | #输出每个样本中预测的最大值,输出[最大值,下标]。只要下标
143 | _,action=torch.max(action_value.data,dim=1)
144 | #在从numpy转为int值
145 | action=action.numpy()[0]
146 | #此时action可能是0、1、2、3
147 |
148 |
149 | else:#随机选择动作
150 | action = np.random.randint(0, n_action)
151 |
152 | return action
153 |
154 | def store_transition(self,s,action,r,s_):
155 | #将四个值打包在一起
156 |
157 | #action为0or 1 or 2 or 3
158 | s=s.reshape(n_state)
159 | s_=s_.reshape(n_state)
160 |
161 | self.transition=np.hstack((s,[action,r],s_))
162 |
163 | #如果记忆库满了, 就覆盖老数据
164 | index = self.memory_count % MEMORY_CAPACITY
165 |
166 | #传入记忆库
167 |
168 | self.memory[index,:]=self.transition
169 | self.memory_count+=1
170 | #print("目前记忆库存储的总数为",self.memory_count)#要删除
171 |
172 | def learn(self):#从记忆库中选择batch个数据进行训练学习
173 | #首先判断target_network是否需要更新
174 |
175 | if self.learn_step_counter % TARGET_REPLACE_ITER==0:
176 | self.target_network.load_state_dict(self.agent_network.state_dict())#更新目标网络参数
177 | self.learn_step_counter+=1
178 |
179 | #随机从memory中抽32个数据,即batch=32
180 | sample_index=np.random.choice(MEMORY_CAPACITY,batch_size)#从0-1999中抽32个数字,shape为(32,)
181 | batch_memory=self.memory[sample_index,:]#获取32个数据。 shape 为(32,6)
182 |
183 | self.agent_network.train()
184 |
185 | b_s = torch.FloatTensor(batch_memory[:, :n_state])
186 | b_a = torch.LongTensor(batch_memory[:, n_state:n_state+1].astype(int))
187 | b_r = torch.FloatTensor(batch_memory[:, n_state+1:n_state+2])
188 | b_s_ = torch.FloatTensor(batch_memory[:, -n_state:])
189 | # b_memory shape (batch,6)
190 | # b_s shape (batch,2)
191 | # b_a shape (batch,1)
192 | # b_r shape (batch,1)
193 | # b_s_ shape (batch,2)
194 |
195 |
196 | #把样本state送入agent网络训练,得到q估计
197 | q_predict=self.agent_network(b_s)#shape 为 (32,4)
198 | q_predict=q_predict.gather(1,b_a)#shaoe 为 (32,1)。根据b_a找出q估计
199 |
200 |
201 | # #把样本送入target网络计算,得到Q(s+1)
202 | # q_next=self.target_network(b_s_).detach()# q_next 不进行反向传播, 所以使用detach。shape为 (32,4)
203 | # q_next,_=torch.max(q_next,dim=1)#输出每个样本中预测的最大值,输出[最大值,下标]。只要最大值
204 | # q_next=q_next.reshape((-1,1))#q_next的shape 为(32,1)
205 | # #计算q真实
206 | # q_target=b_r+discount*q_next#q_target的shape 为(32,1)
207 |
208 | #改用ddqn
209 | q_next=self.agent_network(b_s_).detach()#
210 | _,b_a_=torch.max(q_next,dim=1)#由dqn网络选出动作
211 | b_a_=b_a_.reshape((-1,1))#b_a_的shape 为(32,1)
212 | q_next_target=self.target_network(b_s_).detach()
213 | q_next=q_next_target.gather(1,b_a_)#q_next的shape 为(32,1
214 | #计算q真实
215 | q_target=b_r+discount*q_next#q_target的shape 为(32,1)
216 |
217 |
218 |
219 | loss=self.loss_func(q_predict,q_target)
220 | # if self.learn_step_counter%5000==0:
221 | # print("第",self.learn_step_counter,"次强化学习的loss为:",loss.item())
222 | self.optimizer.zero_grad()
223 | loss.backward()
224 | self.optimizer.step()
225 | return loss.item()
226 |
227 |
228 |
229 | #%%
230 |
231 | dqn=DQN()
232 | dqn_tradition=DQN()
233 | epoch_cost_optimize=[]
234 | epoch_cost_tradition=[]
235 | r_list_epoch=[]
236 |
237 | local_costs_epoch=[]
238 | all_costs_epoch=[]
239 | all_costs_epoch_tra=[]
240 | count=0
241 |
242 | #每次开始游戏 前,重开游戏
243 | #s=env.reset()#s是(4,)的numpy
244 | # print("开始第",epoch+1,"轮游戏")
245 | # start = time.time()
246 | for epoch in range(epochs):
247 |
248 | print("本轮epoch=",epoch,"本轮epoch=",epoch,"本轮epoch=",epoch,"本轮epoch=",epoch)
249 | step_loss = []
250 | step_loss_tradition=[]
251 | local_costs=[]
252 | all_costs=[]
253 | all_costs_traditon = []
254 | r_total=0
255 |
256 | Hn, Hn_e = get_channel_gain_sum()
257 | user_l = np.array([np.random.randint(10,20),np.random.randint(550,560)])
258 |
259 | #--------------------------
260 | #------------优化功率和算力-------------
261 | env = Environment(user_num=2, cap_num=2, W=5e6,
262 | f_local=np.array([1.4 * 10e8, 0.43 * 10e8]),
263 | omega=330 / 8,
264 | F_cap=np.array([10 * 10e8, 3 * 10e8]), p_local=2, p_tran=np.array([2, 3]), lamda_=1.0,
265 | p_noise=0.1, Hn=Hn, Hn_e=Hn_e, user_l=user_l, Mb_to_bit=2 ** 20
266 | )
267 |
268 | s = env.reset()
269 | episode_step = 0
270 | while episode_step MEMORY_CAPACITY:
288 | count+=1
289 | loss=dqn.learn()
290 |
291 |
292 | #判断是否结束
293 | if done !=0:
294 | break
295 |
296 | #更新状态,进入下一次循环
297 | s=s_
298 | #-------------------------------------------
299 |
300 | print("最后一个step的优化PF的cost=",tc_optimized)
301 |
302 | #------------传统方法-------------
303 | env_tradition = Environment1(user_num=2, cap_num=2, W=5e6,
304 | f_local=np.array([1.4 * 10e8, 0.43 * 10e8]),
305 | omega=330 / 8,
306 | F_cap=np.array([10 * 10e8, 3 * 10e8]), p_local=2, p_tran=np.array([2, 3]), lamda_=1.0,
307 | p_noise=0.1, Hn=Hn, Hn_e=Hn_e, user_l=user_l, Mb_to_bit=2 ** 20
308 | )
309 | s=env_tradition.reset()
310 | episode_step = 0
311 | while episode_step < MAX_EP: # 每次循环执行一个动作
312 | episode_step += 1
313 | # 通过神经网络,输入状态,获取动作。(不带学习)
314 | action = dqn_tradition.choose_action(s)
315 |
316 | # 执行,获得环境反馈
317 | #return self.state, reward, self.tc_cur, self.done
318 | s_, r, tc_tradition, done = env_tradition.step(action, episode_step)
319 | step_loss_tradition.append(tc_tradition)
320 | # 将环境的反馈s,a,r,s_传入记忆库。用于经验回放
321 | dqn_tradition.store_transition(s, action, r, s_)
322 |
323 | # 神经网络学习(experience replay 经验回放)
324 | if dqn_tradition.memory_count > MEMORY_CAPACITY:
325 | count += 1
326 | loss = dqn_tradition.learn()
327 |
328 | # 判断是否结束
329 | if done != 0:
330 | break
331 |
332 | # 更新状态,进入下一次循环
333 | s = s_
334 | #--------------------------------------------
335 | epoch_cost_optimize.append(np.mean(step_loss[-200:])) # 强化学习、优化PF、cost
336 | local_costs_epoch.append(local_latency) # 本地
337 | all_costs_epoch.append(all_cost) # 优化的all cap
338 | epoch_cost_tradition.append(np.mean(step_loss_tradition[-200:])) # 强化学习、均分PF、cost
339 | r_list_epoch.append(r_total)
340 |
341 | plt.plot(range(episode_step), step_loss, color='skyblue', label='optimize_F_P')
342 | plt.plot(range(episode_step), step_loss_tradition, color='red', label='tradition')
343 | plt.plot(range(episode_step),local_costs,color="yellow",label="local")
344 | plt.plot(range(episode_step),all_costs,color="purple",label="all_off")
345 | # plt.plot(range(episode_step), all_costs_traditon, color="green", label='all_off_tra')
346 | plt.legend(loc="best")
347 |
348 | plt.xlabel("step_dqn_e1")
349 | plt.ylabel("costs")
350 | plt.show()
351 | if epoch <20:
352 | if greedy<0.73:
353 | if epoch %5 ==0:
354 | greedy+=0.03
355 | if epoch==30:
356 | greedy=0.85
357 | if epoch >30 and epoch <=40:
358 | if epoch %5 == 0:
359 | greedy+=0.01
360 | if epoch > 40:
361 | if epoch %10 ==0:
362 | if greedy<0.98:
363 | greedy+=0.02
364 |
365 | if epoch==98:
366 | greedy=0.99
367 | print("greedy=",greedy)
368 |
369 | plt.plot(range(epochs),local_costs_epoch, color='yellow', label='locals')
370 | plt.plot(range(epochs),epoch_cost_optimize,color='skyblue', label='optimize_F_P')
371 | plt.plot(range(epochs),epoch_cost_tradition,color='red', label='tradition')
372 | plt.plot(range(epochs),all_costs_epoch,color='purple', label="all_off")
373 | # plt.plot(range(epochs),all_costs_epoch_tra,color='mediumpurple', label="all_off_Tra")
374 |
375 | plt.xlabel("epoch_colluding")
376 | plt.ylabel("costs")
377 | plt.legend(loc="best")
378 | plt.show()
379 |
380 | #保存数据
381 |
382 | Writedata.write_to_excel(epoch_cost_optimize,1,"./dataset/tra_opi/optimize_cost2.xls")#优化
383 | Writedata.write_to_excel(all_costs_epoch,1,"./dataset/tra_opi/all_costs2.xls")#优化的全卸载
384 | Writedata.write_to_excel(local_costs_epoch,1,"./dataset/tra_opi/local_costs2.xls")#本地
385 | Writedata.write_to_excel(epoch_cost_tradition,1,"./dataset/tra_opi/tradition_costs2.xls")#传统方法
386 | Writedata.write_to_excel(r_list_epoch,1,"./dataset/tra_opi/r_list.xls")#传统方法
387 |
--------------------------------------------------------------------------------
/改善环境版/Environment_Wu.py:
--------------------------------------------------------------------------------
1 | import math
2 |
3 | import numpy
4 | import numpy as np
5 |
6 |
7 | class Environment(object):
8 |
9 | def __init__(self, user_num, cap_num, W, f_local, omega,
10 | F_cap, p_local, p_tran, p_noise, Hn, Hn_e, user_l, Mb_to_bit, lamda_):
11 |
12 | self.user_num = user_num
13 | self.cap_num = cap_num
14 | # self.name = name # 进程名字
15 |
16 | self.f_local = f_local
17 | self.omega = omega
18 |
19 | # 获取信道参数
20 | self.Hn = Hn
21 | self.Hn_e = Hn_e
22 | self.Hn_A = self.Hn[0]
23 | self.Hn_B = self.Hn[1]
24 |
25 | # W为总带宽,[capA,capB],需要取出来
26 | self.W = W
27 |
28 |
29 | # F_cap为A和B总算力(优化对象),[CAPA,CAPB],需分别均分给n个设备
30 | self.F_cap = F_cap.reshape(1, -1) # (2,1)(F_A,F_B) (10*10e8,3*10e8)
31 | self.F = (np.r_[self.F_cap, self.F_cap] / 2)
32 | self.F_constant = self.F # [[5,1,5],[5,1.5]]
33 |
34 |
35 | # 传输功率 下个版本也许要利用解析解优化 如p_{i,j}
36 | self.p_tran = (p_tran / self.user_num).reshape(-1, 1)
37 | self.P = np.c_[self.p_tran, self.p_tran]
38 | self.p_tran_constant = self.p_tran # [[1, 1], [1.5, 1.5]]
39 | self.p_tran_total = p_tran.reshape(1, -1) # 该参数仅用于传入神经网络寻
40 |
41 | self.F_P_total = np.append(self.F_cap, self.p_tran_total, axis=1)
42 |
43 | self.p_noise = p_noise
44 | self.p_local = p_local
45 |
46 | self.omega = omega
47 | self.Mb_to_bit = Mb_to_bit
48 | self.lamda_ = lamda_
49 |
50 | self.user_l = user_l # (2,)
51 |
52 | # 卸载率权重 和卸载率的初始化(归一化)
53 | self.off_rate_weight = self.init_offloading_weight() # 卸载率权重(未归一化)
54 | self.offload_rate = np.zeros((self.user_num, self.cap_num + 1))
55 | self.off_rate_weight_normalization()#卸载率归一化
56 |
57 | # 环境状态
58 | self.state = self.update_state() # (6,1)
59 |
60 | self.tc_pre = self.get_total_cost()
61 | self.tc_cur = 0.0
62 |
63 | self.total_local_latency = self.tc_pre # 本地
64 | self.total_cap_offload_latency = self.get_all_cap_latency_cost() # 全卸载
65 | self.done = False
66 |
67 | # if name == 'w00':
68 | # print("all cap_cost{} all_local_cost{}".format(self.total_cap_offload_latency, self.total_local_latency))
69 |
70 | def init_offloading_weight(self):
71 | offload_weight = np.zeros((self.user_num, self.cap_num + 1))
72 | # e.g
73 | # offloading ={[1,0,0],[1,0,0]}
74 | for i in range(self.user_num):
75 | for j in range(self.cap_num+1):
76 | if j ==0:
77 | offload_weight[i][j] = 1.0
78 | else:
79 | offload_weight[i][j] = 0.1 # 全卸载在优化算力会出现问题 分母为0
80 | return offload_weight
81 |
82 | def reset(self):
83 | self.off_rate_weight = self.init_offloading_weight()
84 | self.off_rate_weight_normalization()
85 |
86 |
87 | # s = np.append(self.F_P_total, self.state.reshape(1, -1), axis=1) 加入总功率和总算力self.F_cap,self.p_tran_total
88 |
89 | return self.state
90 |
91 | def action_state_num(self):
92 | action_n = self.user_num * (self.cap_num + 1) # dqn
93 | state_num = self.user_num * (self.cap_num + 1)
94 | return action_n, state_num
95 |
96 | def step(self, a, cur_step, ):
97 | # a [0,1,2,3,4,5]中一个
98 | # [0,1,2] and [3,4,5]分别对应user_1 user2的动作
99 | # 对应a的卸载率
100 | # 总动作数量 = (cap_num+1)*user_num
101 |
102 | # 1.0 更新卸载率权重
103 | # w = (cur_step / 100)+ 1.0
104 |
105 | w = cur_step // 50 + 1.0
106 |
107 | step = w * 1.0
108 |
109 | user_index = a // (self.cap_num + 1)#选出是哪个用户
110 | action_index = a % (self.user_num + 1)#选出是本地还是capA,capB
111 |
112 | self.off_rate_weight[user_index][action_index] += step
113 |
114 | # 1.1 更新卸载率
115 | self.off_rate_weight_normalization()
116 |
117 | # 2. 更新环境状态
118 | self.state = self.update_state()
119 |
120 | # 3.1 优化P和F
121 | self.optimaztion_for_power_and_F_Cap()
122 | self.tc_cur = self.get_total_cost()
123 |
124 | if self.tc_cur > self.tc_pre:
125 | reward = -100
126 | elif self.tc_cur < self.tc_pre:
127 | reward = 100
128 | else:
129 | reward = -50
130 |
131 | # 4.缓存总代价
132 | self.tc_pre = self.tc_cur
133 |
134 | # s = np.append(self.F_P_total, self.state.reshape(1,-1), axis=1) 加入总功率和总算力self.F_cap,self.p_tran_total
135 |
136 |
137 | return self.state, reward, self.total_local_latency, self.tc_cur, self.total_cap_offload_latency, self.done#self.tc_cur为传统方法
138 |
139 | def init_P_and_F(self):
140 | self.F = np.array([[5e9, 1.5e9], [5e9, 1.5e9]])
141 | self.P = np.array([[1., 1.], [1.5, 1.5]])
142 |
143 | def update_state(self):#更新环境
144 | temp = np.zeros_like(self.offload_rate)
145 |
146 | for i in range(len(self.user_l)):
147 | temp[i] = self.offload_rate[i] * self.user_l[i]
148 |
149 | state = np.r_[temp[0], temp[1]].reshape(-1, 1).squeeze()
150 | return state
151 |
152 | def off_rate_weight_normalization(self):
153 | for i in range(self.user_num):
154 | total = np.sum(self.off_rate_weight[i])
155 | for j in range(self.cap_num + 1):
156 | self.offload_rate[i][j] = self.off_rate_weight[i][j] / total
157 |
158 | def get_all_cap_latency_cost(self):
159 | # 全卸载
160 | temp = self.offload_rate
161 | self.offload_rate = np.array([[0., 0.5, 0.5], [0., 0.5, 0.5]])
162 | all_cap_cost = self.get_total_cost()
163 | self.offload_rate = temp
164 | return all_cap_cost
165 |
166 | def get_all_local_latency(self):
167 | # 全本地计算
168 | temp = self.offload_rate
169 | self.offload_rate = np.array([[1, .0, .0], [1., .0, .0]])
170 | all_cap_cost = self.get_total_cost()
171 | self.offload_rate = temp
172 | return all_cap_cost
173 |
174 | def get_total_cost(self):
175 | a = self.F
176 | b = self.P
177 | T_total = self.get_total_latency()
178 | E_total = self.get_total_energy()
179 | Cost_total = self.lamda_ * T_total + (1.0 - self.lamda_) * E_total
180 | return Cost_total
181 |
182 | def get_total_energy(self):
183 |
184 | return 0.0
185 |
186 | def get_total_local_latency(self):
187 | # 采用∑方式
188 |
189 | sum = 0
190 | for i in range(self.user_num):
191 | t_local_i = self.user_l[i] * self.offload_rate[i][0] * self.omega * self.Mb_to_bit / self.f_local[i]
192 | sum += t_local_i
193 | return sum
194 |
195 |
196 |
197 | def get_transmit_latency(self):
198 |
199 | hn_e = self.Hn_e.reshape(-1, 1) # (2,1)
200 | hn_e = np.c_[hn_e, hn_e] # (2,2)
201 |
202 | user_l = self.user_l.reshape(-1, 1) # ( 2,1)
203 | user_l = np.c_[user_l, user_l] # (2,2)
204 |
205 | # R(i,j) -->(2,2)
206 | # Shannon formula
207 | R = self.W * np.log2(1 + self.P * self.Hn / (self.p_noise ** 2)) \
208 | - self.W * np.log2(1 + self.P * hn_e / (self.p_noise ** 2))
209 |
210 | # T_trans = l_{i,j} *a_{i,j} * Mb_to_bit / R_{i,j}
211 | T_trans = np.multiply(user_l, self.offload_rate[:, 1:]) * self.Mb_to_bit / R
212 | return T_trans
213 |
214 | def get_cap_latency(self):
215 | user_l = self.user_l.reshape(-1, 1) # ( 2,1)
216 | user_l = np.c_[user_l, user_l] # (2,2)
217 |
218 | # (2,2)
219 | T_cap = np.multiply(user_l, self.offload_rate[:, 1:]) * self.Mb_to_bit * self.omega / self.F
220 | return T_cap
221 |
222 | def get_total_latency(self):
223 | T_local = self.get_total_local_latency() # 标量
224 | T_trans = self.get_transmit_latency() # (2,2)
225 | T_cap = self.get_cap_latency() # (2,2)
226 | T_total = T_local + T_trans.sum() + T_cap.sum()
227 |
228 | return T_total
229 |
230 | def optimaztion_for_power_and_F_Cap(self):
231 | hn_e = self.Hn_e.reshape(-1, 1) # (2,1)
232 | hn_e = np.c_[hn_e, hn_e] # (2,2)
233 |
234 | user_l_padding = self.user_l.reshape(-1, 1)
235 | user_l = np.c_[user_l_padding, user_l_padding]
236 | offload_rate = self.offload_rate[:, 1:]
237 |
238 | a = self.W * np.log2((self.Hn / hn_e))
239 |
240 | b = (self.W * self.p_noise ** 2 * (1 / (hn_e) - 1 / (self.Hn))) / math.log(2)
241 |
242 | # 求lamda_i
243 | fenzi = np.sqrt(offload_rate * user_l * b) / a
244 | # 2个用户直接写死 ,按列加和
245 | row_temp = fenzi[:, 0] + fenzi[:, 1]
246 | fenzi = np.c_[(row_temp, row_temp)]
247 |
248 | row_temp = (b / a)[:, 0] + (b / a)[:, 1]
249 | fenmu = self.p_tran_constant - np.c_[row_temp, row_temp]
250 | lada = np.square(fenzi / fenmu)
251 |
252 | # 求解mu
253 | # 按照行加和
254 | fenzi = np.sqrt(offload_rate * user_l)
255 | row_temp = fenzi[0, :] + fenzi[1, :]
256 | fenzi = np.r_[row_temp.reshape(1, -1), row_temp.reshape(1, -1)]
257 | fenmu = self.F_constant * 2
258 |
259 | mu = np.square(fenzi / fenmu)
260 |
261 | if (lada == 0).any():
262 | return
263 |
264 | if (mu == 0).any():
265 | return
266 |
267 | self.P = (np.sqrt(offload_rate * user_l * b / lada) + b) / a
268 | self.F = np.sqrt(offload_rate * user_l / mu)
269 |
270 | if (offload_rate == 0).any():
271 | a = 0
272 |
273 |
274 |
--------------------------------------------------------------------------------
/改善环境版/Environment_Wu_tradition.py:
--------------------------------------------------------------------------------
1 | import math
2 |
3 | import numpy
4 | import numpy as np
5 |
6 |
7 | class Environment1(object):
8 |
9 | def __init__(self, user_num, cap_num, W, f_local, omega,
10 | F_cap, p_local, p_tran, p_noise, Hn, Hn_e, user_l, Mb_to_bit, lamda_):
11 |
12 | self.user_num = user_num
13 | self.cap_num = cap_num
14 | # self.name = name # 进程名字
15 |
16 | self.f_local = f_local
17 | self.omega = omega
18 |
19 | # 获取信道参数
20 | self.Hn = Hn
21 | self.Hn_e = Hn_e
22 | self.Hn_A = self.Hn[0]
23 | self.Hn_B = self.Hn[1]
24 |
25 | # W为总带宽,[capA,capB],需要取出来
26 | self.W = W
27 |
28 |
29 | # F_cap为A和B总算力(优化对象),[CAPA,CAPB],需分别均分给n个设备
30 | self.F_cap = F_cap.reshape(1, -1) # (2,1)(F_A,F_B) (10*10e8,3*10e8)
31 | self.F = (np.r_[self.F_cap, self.F_cap] / 2)
32 | self.F_constant = self.F # [[5,1,5],[5,1.5]]
33 |
34 |
35 | # 传输功率 下个版本也许要利用解析解优化 如p_{i,j}
36 | self.p_tran = (p_tran / self.user_num).reshape(-1, 1)
37 | self.P = np.c_[self.p_tran, self.p_tran]
38 | self.p_tran_constant = self.p_tran # [[1, 1], [1.5, 1.5]]
39 | self.p_tran_total = p_tran.reshape(1, -1) # 该参数仅用于传入神经网络寻
40 |
41 | self.F_P_total = np.append(self.F_cap, self.p_tran_total, axis=1)
42 |
43 | self.p_noise = p_noise
44 | self.p_local = p_local
45 |
46 | self.omega = omega
47 | self.Mb_to_bit = Mb_to_bit
48 | self.lamda_ = lamda_
49 |
50 | self.user_l = user_l # (2,)
51 |
52 | # 卸载率权重 和卸载率的初始化(归一化)
53 | self.off_rate_weight = self.init_offloading_weight() # 卸载率权重(未归一化)
54 | self.offload_rate = np.zeros((self.user_num, self.cap_num + 1))
55 | self.off_rate_weight_normalization()#卸载率归一化
56 |
57 | # 环境状态
58 | self.state = self.update_state() # (6,1)
59 |
60 | self.tc_pre = self.get_total_cost()
61 | self.tc_cur = 0.0
62 |
63 | self.total_local_latency = self.tc_pre # 本地
64 | self.total_cap_offload_latency = self.get_all_cap_latency_cost() # 全卸载
65 | self.done = False
66 |
67 | # if name == 'w00':
68 | # print("all cap_cost{} all_local_cost{}".format(self.total_cap_offload_latency, self.total_local_latency))
69 |
70 | def init_offloading_weight(self):
71 | offload_weight = np.zeros((self.user_num, self.cap_num + 1))
72 | # e.g
73 | # offloading ={[1,0,0],[1,0,0]}
74 | for i in range(self.user_num):
75 | for j in range(self.cap_num+1):
76 | if j ==0:
77 | offload_weight[i][j] = 1.0
78 | else:
79 | offload_weight[i][j] = 0.1 # 全卸载在优化算力会出现问题 分母为0
80 | return offload_weight
81 |
82 | def reset(self):
83 | self.off_rate_weight = self.init_offloading_weight()
84 | self.off_rate_weight_normalization()
85 |
86 |
87 | # s = np.append(self.F_P_total, self.state.reshape(1, -1), axis=1) 加入总功率和总算力self.F_cap,self.p_tran_total
88 |
89 | return self.state
90 |
91 | def action_state_num(self):
92 | action_n = self.user_num * (self.cap_num + 1) # dqn
93 | state_num = self.user_num * (self.cap_num + 1)
94 | return action_n, state_num
95 |
96 | def step(self, a, cur_step, ):
97 | # a [0,1,2,3,4,5]中一个
98 | # [0,1,2] and [3,4,5]分别对应user_1 user2的动作
99 | # 对应a的卸载率
100 | # 总动作数量 = (cap_num+1)*user_num
101 |
102 | # 1.0 更新卸载率权重
103 | # w = (cur_step / 100)+ 1.0
104 |
105 | w = cur_step // 50 + 1.0
106 |
107 | step = w * 1.0
108 |
109 | user_index = a // (self.cap_num + 1)#选出是哪个用户
110 | action_index = a % (self.user_num + 1)#选出是本地还是capA,capB
111 |
112 | self.off_rate_weight[user_index][action_index] += step
113 |
114 | # 1.1 更新卸载率
115 | self.off_rate_weight_normalization()
116 |
117 | # 2. 更新环境状态
118 | self.state = self.update_state()
119 |
120 | # 3.1 优化P和F
121 | self.tc_cur = self.get_total_cost()
122 |
123 | if self.tc_cur > self.tc_pre:
124 | reward = -100
125 | elif self.tc_cur < self.tc_pre:
126 | reward = 100
127 | else:
128 | reward = -50
129 |
130 | # 4.缓存总代价
131 | self.tc_pre = self.tc_cur
132 |
133 | # s = np.append(self.F_P_total, self.state.reshape(1,-1), axis=1) 加入总功率和总算力self.F_cap,self.p_tran_total
134 |
135 |
136 | return self.state, reward,self.tc_cur,self.done#self.tc_cur为传统方法
137 |
138 | def init_P_and_F(self):
139 | self.F = np.array([[5e9, 1.5e9], [5e9, 1.5e9]])
140 | self.P = np.array([[1., 1.], [1.5, 1.5]])
141 |
142 | def update_state(self):#更新环境
143 | temp = np.zeros_like(self.offload_rate)
144 |
145 | for i in range(len(self.user_l)):
146 | temp[i] = self.offload_rate[i] * self.user_l[i]
147 |
148 | state = np.r_[temp[0], temp[1]].reshape(-1, 1).squeeze()
149 | return state
150 |
151 | def off_rate_weight_normalization(self):
152 | for i in range(self.user_num):
153 | total = np.sum(self.off_rate_weight[i])
154 | for j in range(self.cap_num + 1):
155 | self.offload_rate[i][j] = self.off_rate_weight[i][j] / total
156 |
157 | def get_all_cap_latency_cost(self):
158 | # 全卸载
159 | temp = self.offload_rate
160 | self.offload_rate = np.array([[0., 0.5, 0.5], [0., 0.5, 0.5]])
161 | all_cap_cost = self.get_total_cost()
162 | self.offload_rate = temp
163 | return all_cap_cost
164 |
165 | def get_all_local_latency(self):
166 | # 全本地计算
167 | temp = self.offload_rate
168 | self.offload_rate = np.array([[1, .0, .0], [1., .0, .0]])
169 | all_cap_cost = self.get_total_cost()
170 | self.offload_rate = temp
171 | return all_cap_cost
172 |
173 | def get_total_cost(self):
174 | a = self.F
175 | b = self.P
176 | T_total = self.get_total_latency()
177 | E_total = self.get_total_energy()
178 | Cost_total = self.lamda_ * T_total + (1.0 - self.lamda_) * E_total
179 | return Cost_total
180 |
181 | def get_total_energy(self):
182 |
183 | return 0.0
184 |
185 | def get_total_local_latency(self):
186 | # 采用∑方式
187 |
188 | sum = 0
189 | for i in range(self.user_num):
190 | t_local_i = self.user_l[i] * self.offload_rate[i][0] * self.omega * self.Mb_to_bit / self.f_local[i]
191 | sum += t_local_i
192 | return sum
193 |
194 |
195 |
196 | def get_transmit_latency(self):
197 |
198 | hn_e = self.Hn_e.reshape(-1, 1) # (2,1)
199 | hn_e = np.c_[hn_e, hn_e] # (2,2)
200 |
201 | user_l = self.user_l.reshape(-1, 1) # ( 2,1)
202 | user_l = np.c_[user_l, user_l] # (2,2)
203 |
204 | # R(i,j) -->(2,2)
205 | # Shannon formula
206 | R = self.W * np.log2(1 + self.P * self.Hn / (self.p_noise ** 2)) \
207 | - self.W * np.log2(1 + self.P * hn_e / (self.p_noise ** 2))
208 |
209 | # T_trans = l_{i,j} *a_{i,j} * Mb_to_bit / R_{i,j}
210 | T_trans = np.multiply(user_l, self.offload_rate[:, 1:]) * self.Mb_to_bit / R
211 | return T_trans
212 |
213 | def get_cap_latency(self):
214 | user_l = self.user_l.reshape(-1, 1) # ( 2,1)
215 | user_l = np.c_[user_l, user_l] # (2,2)
216 |
217 | # (2,2)
218 | T_cap = np.multiply(user_l, self.offload_rate[:, 1:]) * self.Mb_to_bit * self.omega / self.F
219 | return T_cap
220 |
221 | def get_total_latency(self):
222 | T_local = self.get_total_local_latency() # 标量
223 | T_trans = self.get_transmit_latency() # (2,2)
224 | T_cap = self.get_cap_latency() # (2,2)
225 | T_total = T_local + T_trans.sum() + T_cap.sum()
226 |
227 | return T_total
228 |
229 | def optimaztion_for_power_and_F_Cap(self):
230 | hn_e = self.Hn_e.reshape(-1, 1) # (2,1)
231 | hn_e = np.c_[hn_e, hn_e] # (2,2)
232 |
233 | user_l_padding = self.user_l.reshape(-1, 1)
234 | user_l = np.c_[user_l_padding, user_l_padding]
235 | offload_rate = self.offload_rate[:, 1:]
236 |
237 | a = self.W * np.log2((self.Hn / hn_e))
238 |
239 | b = (self.W * self.p_noise ** 2 * (1 / (hn_e) - 1 / (self.Hn))) / math.log(2)
240 |
241 | # 求lamda_i
242 | fenzi = np.sqrt(offload_rate * user_l * b) / a
243 | # 2个用户直接写死 ,按列加和
244 | row_temp = fenzi[:, 0] + fenzi[:, 1]
245 | fenzi = np.c_[(row_temp, row_temp)]
246 |
247 | row_temp = (b / a)[:, 0] + (b / a)[:, 1]
248 | fenmu = self.p_tran_constant - np.c_[row_temp, row_temp]
249 | lada = np.square(fenzi / fenmu)
250 |
251 | # 求解mu
252 | # 按照行加和
253 | fenzi = np.sqrt(offload_rate * user_l)
254 | row_temp = fenzi[0, :] + fenzi[1, :]
255 | fenzi = np.r_[row_temp.reshape(1, -1), row_temp.reshape(1, -1)]
256 | fenmu = self.F_constant * 2
257 |
258 | mu = np.square(fenzi / fenmu)
259 |
260 | if (lada == 0).any():
261 | return
262 |
263 | if (mu == 0).any():
264 | return
265 |
266 | self.P = (np.sqrt(offload_rate * user_l * b / lada) + b) / a
267 | self.F = np.sqrt(offload_rate * user_l / mu)
268 |
269 | if (offload_rate == 0).any():
270 | a = 0
271 |
272 |
273 |
--------------------------------------------------------------------------------
/改善环境版/Writedata.py:
--------------------------------------------------------------------------------
1 | import xlrd
2 | from xlwt import *
3 |
4 |
5 | # 多次实验时写入数据代码
6 | def write_data(data_list, sheet_name, iteration):
7 | for each_i in range(len(data_list)):
8 | sheet_name.write(each_i, iteration, str(data_list[each_i]))
9 |
10 |
11 | def create_csv(sheet1, data_list, iteration=1):
12 | write_data(data_list=data_list, sheet_name=sheet1, iteration=iteration)
13 |
14 |
15 | def write_to_excel(cost_list, is_one, filename):
16 | wb = Workbook()
17 | sheet1 = wb.add_sheet(sheetname='cost')
18 | if is_one:
19 | create_csv(sheet1=sheet1, data_list=cost_list)
20 | else:
21 | for index in range(len(cost_list)):
22 | create_csv(sheet1=sheet1, data_list=cost_list[index], iteration=index)
23 | wb.save(filename)
24 |
25 |
26 | def read_file(h_file, task_file):
27 | channel_uc = xlrd.open_workbook(h_file)
28 | task_file = xlrd.open_workbook(task_file)
29 | uc_sheet = channel_uc.sheets()[0]
30 | task_sheet = task_file.sheets()[0]
31 |
32 | return uc_sheet, task_sheet
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/改善环境版/__pycache__/Environment_Wu.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiong1998/offloading-optimization-and-resource-optimization-base-on-mobile-edge-computing-net/0c90c5809c0a665f7c9ee2afc74436f2562a789f/改善环境版/__pycache__/Environment_Wu.cpython-38.pyc
--------------------------------------------------------------------------------
/改善环境版/__pycache__/Environment_Wu_tradition.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiong1998/offloading-optimization-and-resource-optimization-base-on-mobile-edge-computing-net/0c90c5809c0a665f7c9ee2afc74436f2562a789f/改善环境版/__pycache__/Environment_Wu_tradition.cpython-38.pyc
--------------------------------------------------------------------------------
/改善环境版/__pycache__/Writedata.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiong1998/offloading-optimization-and-resource-optimization-base-on-mobile-edge-computing-net/0c90c5809c0a665f7c9ee2afc74436f2562a789f/改善环境版/__pycache__/Writedata.cpython-38.pyc
--------------------------------------------------------------------------------
/改善环境版/dataset/E_max/all_costs.xls:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiong1998/offloading-optimization-and-resource-optimization-base-on-mobile-edge-computing-net/0c90c5809c0a665f7c9ee2afc74436f2562a789f/改善环境版/dataset/E_max/all_costs.xls
--------------------------------------------------------------------------------
/改善环境版/dataset/E_max/local_costs.xls:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiong1998/offloading-optimization-and-resource-optimization-base-on-mobile-edge-computing-net/0c90c5809c0a665f7c9ee2afc74436f2562a789f/改善环境版/dataset/E_max/local_costs.xls
--------------------------------------------------------------------------------
/改善环境版/dataset/E_max/optimize_cost.xls:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiong1998/offloading-optimization-and-resource-optimization-base-on-mobile-edge-computing-net/0c90c5809c0a665f7c9ee2afc74436f2562a789f/改善环境版/dataset/E_max/optimize_cost.xls
--------------------------------------------------------------------------------
/改善环境版/dataset/E_sum/all_costs.csv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiong1998/offloading-optimization-and-resource-optimization-base-on-mobile-edge-computing-net/0c90c5809c0a665f7c9ee2afc74436f2562a789f/改善环境版/dataset/E_sum/all_costs.csv
--------------------------------------------------------------------------------
/改善环境版/dataset/E_sum/local_costs.csv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiong1998/offloading-optimization-and-resource-optimization-base-on-mobile-edge-computing-net/0c90c5809c0a665f7c9ee2afc74436f2562a789f/改善环境版/dataset/E_sum/local_costs.csv
--------------------------------------------------------------------------------
/改善环境版/dataset/E_sum/optimize_cost.csv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiong1998/offloading-optimization-and-resource-optimization-base-on-mobile-edge-computing-net/0c90c5809c0a665f7c9ee2afc74436f2562a789f/改善环境版/dataset/E_sum/optimize_cost.csv
--------------------------------------------------------------------------------
/改善环境版/dataset/optimize_cost_colluding.xls:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiong1998/offloading-optimization-and-resource-optimization-base-on-mobile-edge-computing-net/0c90c5809c0a665f7c9ee2afc74436f2562a789f/改善环境版/dataset/optimize_cost_colluding.xls
--------------------------------------------------------------------------------
/改善环境版/dataset/optimize_cost_non-colluding.xls:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiong1998/offloading-optimization-and-resource-optimization-base-on-mobile-edge-computing-net/0c90c5809c0a665f7c9ee2afc74436f2562a789f/改善环境版/dataset/optimize_cost_non-colluding.xls
--------------------------------------------------------------------------------
/改善环境版/dataset/tra_opi/all_costs.xls:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiong1998/offloading-optimization-and-resource-optimization-base-on-mobile-edge-computing-net/0c90c5809c0a665f7c9ee2afc74436f2562a789f/改善环境版/dataset/tra_opi/all_costs.xls
--------------------------------------------------------------------------------
/改善环境版/dataset/tra_opi/all_costs1.xls:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiong1998/offloading-optimization-and-resource-optimization-base-on-mobile-edge-computing-net/0c90c5809c0a665f7c9ee2afc74436f2562a789f/改善环境版/dataset/tra_opi/all_costs1.xls
--------------------------------------------------------------------------------
/改善环境版/dataset/tra_opi/all_costs2.xls:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiong1998/offloading-optimization-and-resource-optimization-base-on-mobile-edge-computing-net/0c90c5809c0a665f7c9ee2afc74436f2562a789f/改善环境版/dataset/tra_opi/all_costs2.xls
--------------------------------------------------------------------------------
/改善环境版/dataset/tra_opi/local_costs.xls:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiong1998/offloading-optimization-and-resource-optimization-base-on-mobile-edge-computing-net/0c90c5809c0a665f7c9ee2afc74436f2562a789f/改善环境版/dataset/tra_opi/local_costs.xls
--------------------------------------------------------------------------------
/改善环境版/dataset/tra_opi/local_costs1.xls:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiong1998/offloading-optimization-and-resource-optimization-base-on-mobile-edge-computing-net/0c90c5809c0a665f7c9ee2afc74436f2562a789f/改善环境版/dataset/tra_opi/local_costs1.xls
--------------------------------------------------------------------------------
/改善环境版/dataset/tra_opi/local_costs2.xls:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiong1998/offloading-optimization-and-resource-optimization-base-on-mobile-edge-computing-net/0c90c5809c0a665f7c9ee2afc74436f2562a789f/改善环境版/dataset/tra_opi/local_costs2.xls
--------------------------------------------------------------------------------
/改善环境版/dataset/tra_opi/optimize_cost.xls:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiong1998/offloading-optimization-and-resource-optimization-base-on-mobile-edge-computing-net/0c90c5809c0a665f7c9ee2afc74436f2562a789f/改善环境版/dataset/tra_opi/optimize_cost.xls
--------------------------------------------------------------------------------
/改善环境版/dataset/tra_opi/optimize_cost1.xls:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiong1998/offloading-optimization-and-resource-optimization-base-on-mobile-edge-computing-net/0c90c5809c0a665f7c9ee2afc74436f2562a789f/改善环境版/dataset/tra_opi/optimize_cost1.xls
--------------------------------------------------------------------------------
/改善环境版/dataset/tra_opi/r_list.xls:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiong1998/offloading-optimization-and-resource-optimization-base-on-mobile-edge-computing-net/0c90c5809c0a665f7c9ee2afc74436f2562a789f/改善环境版/dataset/tra_opi/r_list.xls
--------------------------------------------------------------------------------
/改善环境版/dataset/tra_opi/r_list1.xls:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiong1998/offloading-optimization-and-resource-optimization-base-on-mobile-edge-computing-net/0c90c5809c0a665f7c9ee2afc74436f2562a789f/改善环境版/dataset/tra_opi/r_list1.xls
--------------------------------------------------------------------------------
/改善环境版/dataset/tra_opi/tradition_costs.xls:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiong1998/offloading-optimization-and-resource-optimization-base-on-mobile-edge-computing-net/0c90c5809c0a665f7c9ee2afc74436f2562a789f/改善环境版/dataset/tra_opi/tradition_costs.xls
--------------------------------------------------------------------------------
/改善环境版/dataset/tra_opi/tradition_costs1.xls:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiong1998/offloading-optimization-and-resource-optimization-base-on-mobile-edge-computing-net/0c90c5809c0a665f7c9ee2afc74436f2562a789f/改善环境版/dataset/tra_opi/tradition_costs1.xls
--------------------------------------------------------------------------------
/改善环境版/dataset/tra_opi/tradition_costs2.xls:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiong1998/offloading-optimization-and-resource-optimization-base-on-mobile-edge-computing-net/0c90c5809c0a665f7c9ee2afc74436f2562a789f/改善环境版/dataset/tra_opi/tradition_costs2.xls
--------------------------------------------------------------------------------