Pycharm代码个人理解

代码小白整理个人笔记,不定时更新

代码1 某位学弟整理的DQN代码(无特定应用场景)

DQN

  • 初始化阶段
import random
from env import Network
import gym #创建一个虚拟环境
import numpy as np #用来解决数学问题
import torch #动态图计算
import torch.nn as nn #用于构建神经网络的模块
from agent import Agent #引入一个主体
import matplotlib.pyplot as plt #画图模块

       其中‘cart pole’是典型的摆臂车模型,此处只是借用了一下名称。

       设置初始参数:总局数、每局最大步数、ε等。

​
env = gym.make("CartPole-v1")
env = Network()

s = env.reset() #初始化

plt_n_episode = [] #空列表存储每局的局数
plt_reward = [] #空列表存储每局的奖励

n_episode = 500 #总局数
n_time_step = 200 #步数
EPSILON_DECAY = n_episode*n_time_step/2 #ε-greedy策略中的ε的衰减率
EPSILON_START = 1.0
EPSILON_END = 0.02
TARGET_UPDATE_FREQUENCY=5 #几局更新一次Q网络

REWARD_BUFFER=np.empty(shape=n_episode) #空的缓冲区,存储每局的奖励

​
  •  创建agent对象
n_state = len(s)
n_action = env.n_actions
agent = Agent(n_input=n_state,n_output=n_action)
print(REWARD_BUFFER)
  • 在每一步中,根据ε-greedy策略决定是探索还是利用

       其中 ε 的计算运用了插值算法,episode_i * n_time_step + step_i是x值,用于插值计算;

       [0, EPSILON_DECAY]是x值的范围或数组,表示插值点的x坐标;

       [EPSILON_START, EPSILON_END]是y值的范围或数组,表示对应于x值范围的值 

       这个函数会找到episode_i * n_time_step + step_i[0, EPSILON_DECAY]范围内的y值,这个y值是从[EPSILON_START, EPSILON_END]中得到的 。

for episode_i in range(n_episode):
    episode_reward = 0
    for step_i in range(n_time_step):
        #贪婪率
        epsilon = np.interp(episode_i * n_time_step + step_i, [0, EPSILON_DECAY], [EPSILON_START, EPSILON_END]) #一阶线性插值?

        random_sample = random.random()

        if random_sample<=epsilon:
            a=env.action_sample() #进行探索,随机选择动作
        else:
            a= agent.online_net.act(s) #进行利用,根据当前状态选择动作

        s_,r,done=env.step(a) #下一个状态,奖励,是否结束,未知
        agent.memo.add_memo(s,a,r,done,s_ )
        s = s_
        episode_reward += r


        if done:
            # print("时间:{}".format(step_i))
            # if (episode_i > 80):
            #     print(REWARD_BUFFER)
            s=env.reset() #如果游戏结束则重置环境
            REWARD_BUFFER[episode_i] = episode_reward# 进入经验池
            break
  • 更新过程

目标函数targets:

其中batch_done是一个布尔数(0或1),表示是否为终止状态,如果是1则1-batch_done为0,不再更新。

 batch_s,batch_a,batch_r,batch_done,batch_s_ = agent.memo.sample() #从经验池中随机抽取一批数据

#Compute targets//计算目标值
target_q_values = agent.target_net(batch_s_) #使用目标网络计算下一个状态的Q值
max_target_q_values = target_q_values.max(dim=1,keepdim=True)[0] #取Q值最大值
targets = batch_r +agent.GAMMA * (1-batch_done)*max_target_q_values #计算目标值

#计算Q_values
q_values = agent.online_net(batch_s) #使用评估网络算Q值
a_q_values = torch.gather(input=q_values,dim=1,index=batch_a)
#动作Q值,神经网路输入S 输出Q(s,a1),Q(s,a3)...Q(s,aN)找到最大的进行匹配
  •  固定搭配
#计算LOSS
loss = nn.functional.smooth_l1_loss(targets, a_q_values) #现成的计算损失的函数

#梯度下降  更新参数
agent.optimizer.zero_grad() 
#反向传播
#使损失函数尽可能小
loss.backward()
agent.optimizer.step()
  • 更新目标网络

     之前设置过5局一更新,如果是5的倍数,那么执行以下代码:

     第二行使目标网络和在线网络的权重保持一致,但目标网络的更新是相对较慢的,所以它为在线网络提供了一个稳定的比较基准。

     然后计算近10个episode的平均奖励。(如果不足10局则计算所有的均值)

     为了使结果更平滑,后续改成了计算近20个episode的奖励。

if episode_i %TARGET_UPDATE_FREQUENCY == 0:
    agent.target_net.load_state_dict(agent.online_net.state_dict())

    print("场数:{}".format(episode_i))
    print("奖励:{}".format(np.mean(REWARD_BUFFER[:episode_i])))
    # print(REWARD_BUFFER)
    if episode_i > 20:
        reward_step = np.mean(REWARD_BUFFER[episode_i-20:episode_i])
    else:
        reward_step = np.mean(REWARD_BUFFER[:episode_i])
    plt_reward.append(reward_step)
    plt_n_episode.append(episode_i)
  •  画图
plt.figure() #创建画布
plt.plot(plt_n_episode,plt_reward,color='k',linestyle=':') #绘制图像
plt.show() #显示图像
plt.pause(0)
  • 运行出来的图

       最后一部分有明显下滑原因为agent的参数没有调试好,后来缩小了经验池的总容量,扩大了抽取的样本量,得到了明显的改善。

       横坐标代表局数,纵坐标代表reward。 

       修改后的图:

agent

这段代码主要关注于使用强化学习来训练一个agent以解决CartPole问题

  • 定义Replaymemory类

       self.all_s(二维)的大小为self.MEMORY_SIZE,self.n_s,32位浮点数

       二维的原因:一共有self.MEMORY_SIZE个状态,每个状态有self.n_s个因素(比如位置和速  度),相比来说动作就是一个标量,这样解释比较好理解。

       self.all_a的下限是0,上限是n_a,大小是self.MEMORY_SIZE,64位整数。

       self.all_done,模拟不同结束状态的多样性,而不是用于定义环境中的真正结束状态,所以是随机的,只可能是0或1。

class Replaymemory:#记忆池
    def __init__(self,n_s,n_a):
        self.n_s = n_s
        self.n_a = n_a
        self.MEMORY_SIZE = 2000
        self.BATCH_SIZE = 256#取样数

        self.all_s = np.empty(shape=(self.MEMORY_SIZE,self.n_s),dtype=np.float32)
        self.all_a = np.random.randint(low=0,high=n_a,size = self.MEMORY_SIZE,dtype=np.int64)
        # self.all_a = np.random.randint(low=0, high=n_a, size=self.MEMORY_SIZE).tolist()
        self.all_r = np.empty(self.MEMORY_SIZE,dtype=np.float32)
        self.all_done = np.random.randint(low=0,high=2,size=self.MEMORY_SIZE,dtype=np.uint8)
        self.all_s_ = np.empty(shape=(self.MEMORY_SIZE,self.n_s),dtype=np.float32)
        self.t_memo = 0
        self.t_max = 0
  • add_demo方法:更新一个对象的状态和历史记录

        self.all_s[self.t_memo]=s: 将当前状态s存储在self.all_s数组的self.t_memo索引位置

        更新 self.t_max的值,使其不超过最大值。

        最后更新self.t_memo的值。

 def add_memo(self,s,a,r,done,s_):
        self.all_s[self.t_memo]=s
        self.all_a[self.t_memo]=a
        self.all_r[self.t_memo]=r
        self.all_done[self.t_memo]=done
        self.all_s_[self.t_memo]=s_
        self.t_max = max(self.t_max,self.t_memo+1)
        self.t_memo = (self.t_memo+1)%self.MEMORY_SIZE#填到2000个又从第一个开始填
  • sample方法:抽取数据 

     通过判断 self.t_max 是否大于等于 self.BATCH_SIZE(最开始设置好了),来确定是否需要进行抽样。如果 self.t_max 大于等于 self.BATCH_SIZE,则执行抽样操作;否则,直接使用前 self.t_max 个样本。           

 def sample(self):
        if self.t_max >=self.BATCH_SIZE:
            if self.t_max>1000:
                self.t_max=1000
            idxes = random.sample(range(0,self.t_max),self.BATCH_SIZE)
        # elif self.t_max>self.MEMORY_SIZE:
        #     idxes = range(0, self.MEMORY_SIZE)
        else:
            idxes = range(0,self.t_max)

        batch_s=[]
        batch_a =[]
        batch_r = []
        batch_done =[]
        batch_s_=[]

        for idx in idxes:
            batch_s.append(self.all_s[idx])
            batch_a.append(self.all_a[idx])
            batch_r.append(self.all_r[idx])
            batch_done.append(self.all_done[idx])
            batch_s_.append(self.all_s_[idx])

        batch_s_tensor = torch.as_tensor(np.asarray(batch_s),dtype=torch.float32)
        batch_a_tensor = torch.as_tensor(np.asarray(batch_a),dtype=torch.int64).unsqueeze(-1)
        batch_r_tensor = torch.as_tensor(np.asarray(batch_r),dtype=torch.float32).unsqueeze(-1)
        batch_done_tensor = torch.as_tensor(np.asarray(batch_done),dtype=torch.float32).unsqueeze(-1)
        batch_s__tensor = torch.as_tensor(np.asarray(batch_s_),dtype=torch.float32)

        return batch_s_tensor,batch_a_tensor,batch_r_tensor,batch_done_tensor,batch_s__tensor

 这些样本数据用于训练DQN。

  • DQN类

   首先定义了神经网络结构self.net。

   forward定义传播过程,接收输入x,传递给self.net,返回网络的输出结果。

   act方法用于执行动作选择的过程。它接收观测值obs作为输入,并首先将其转换为 PyTorch 张量。然后,使用模型进行前向传播,得到 Q 值。接着,找到具有最大 Q 值的动作索引,并将其作为agent的动作输出。

class DQN(nn.Module):
    def __init__(self, n_input ,n_output):
        super().__init__()

        self.net = nn.Sequential(
            nn.Linear(in_features=n_input,out_features=88),
            nn.Tanh(),
            nn.Linear(in_features=88,out_features=n_output)
        )

    def forward (self,x):
        return self.net(x)

    def act(self,obs):
        obs_tensor = torch.as_tensor(obs,dtype=torch.float32)
        q_value = self(obs_tensor.unsqueeze(0))
        max_q_idx = torch.argmax(input=q_value)#取最大Q值的地方
        action = max_q_idx.detach().item()#转化成第几个动作的值
        return action
  • 最后是定义agent类(包含记忆回放和神经网络模型,优化器暂时没有放)

     包含两个网络模型:self.online_net用于实施决策,self.target_net用于计算目标Q值。

class Agent:
    def __init__(self,n_input,n_output):
        self.n_input = n_input
        self.n_output = n_output

        self.GAMMA=0.99#衰减
        self.learning_rate=0.01#学习率

        self.memo =Replaymemory(self.n_input,self.n_output)#TODO

        self.online_net =DQN(self.n_input,self.n_output)        #神经网络中现成的算法
        self.target_net =DQN(self.n_input,self.n_output)        #TODO

        self.optimizer =   torch.optim.Adam(self.online_net.parameters(),lr=self.learning_rate )

env(算力网络场景)

  • 首先设定一下二维迷宫

     设定的是五个任务发送器,所以主动设置了5组均值为0.5的泊松分布的数据。

Pt0_5_1 = [0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0,
           0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
           1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0,
           1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0,
           0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0,
           0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0]
Pt0_5_2 = [1, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1,
           0, 0,0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0,
           1, 0,0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0,
           0, 1,0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0,
           0, 0,1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0,
           1, 0,0, 0, 1, 0, 1, 0, 0, 0, 1, 0]
Pt0_5_3 = [1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0,
           0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1,
           1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1,
           0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1,
           0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1,
           1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1]
Pt0_5_4 = [1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0,
           1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1,
           0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0,
           0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0,
           1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1,
           0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0]
Pt0_5_5 = [0,1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1,
           1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0,
           0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1,
           1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1,
           1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0,
           1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0]
  • 动作表

     因为是5个任务发送器,3个任务处理器,所以action一共有A53=60个,代表从任务发送器中选择3个任务来处理(有顺序区分)。

Action_table = \
    {0: [1, 2, 3], 1: [1, 2, 4], 2: [1, 2, 5], 3: [1, 3, 2], 4: [1, 3, 4], 5: [1, 3, 5], 6: [1, 4, 2], 7: [1, 4, 3],
     8: [1, 4, 5], 9: [1, 5, 2], 10: [1, 5, 3], 11: [1, 5, 4], 12: [2, 1, 3], 13: [2, 1, 4], 14: [2, 1, 5],
     15: [2, 3, 1], 16: [2, 3, 4], 17: [2, 3, 5], 18: [2, 4, 1], 19: [2, 4, 3], 20: [2, 4, 5], 21: [2, 5, 1],
     22: [2, 5, 3], 23: [2, 5, 4], 24: [3, 1, 2], 25: [3, 1, 4], 26: [3, 1, 5], 27: [3, 2, 1], 28: [3, 2, 4],
     29: [3, 2, 5], 30: [3, 4, 1], 31: [3, 4, 2], 32: [3, 4, 5], 33: [3, 5, 1], 34: [3, 5, 2], 35: [3, 5, 4],
     36: [4, 1, 2], 37: [4, 1, 3], 38: [4, 1, 5], 39: [4, 2, 1], 40: [4, 2, 3], 41: [4, 2, 5], 42: [4, 3, 1],
     43: [4, 3, 2], 44: [4, 3, 5], 45: [4, 5, 1], 46: [4, 5, 2], 47: [4, 5, 3], 48: [5, 1, 2], 49: [5, 1, 3],
     50: [5, 1, 4], 51: [5, 2, 1], 52: [5, 2, 3], 53: [5, 2, 4], 54: [5, 3, 1], 55: [5, 3, 2], 56: [5, 3, 4],
     57: [5, 4, 1], 58: [5, 4, 2], 59: [5, 4, 3]}
  • 根据版本的不同选择Tkinter库(画图用的)
if sys.version_info.major == 2:
    import Tkinter as tk  # 窗口界面库
else:
    import tkinter as tk  # 窗口界面库
  • Network类 

      初始化系数后,用最初的pt0_5_1等赋值给task center,

      其中aoi的范围从2到5而不是从0开始:任务从用户处发送到服务平台会产生时延,所以此处直接给了2-5。

class Network(tk.Tk, object):  # 新类继承父类tkinter.Tk
    def __init__(self):
        super(Network, self).__init__()  # super类继承方法,初始化
        self.action_space = [1, 2, 3, 4, 5] 
        self.n_actions = 60  # len(self.action_space)
        self.n_features = 2
        self.title('算力网络场景')
        self.geometry('{0}x{1}'.format(MAZE_H * UNIT, MAZE_H * UNIT))  # format格式化函数 geometry分辨率函数 建立
        self._build_maze()
       # self.Compute_Charge = [3, 3, 2, 2, 1]  # 初始化每个计算中心当地的电力费用
       # self.Compute_Distances = [1, 1, 4, 4, 10]  # 初始化每个计算中心距离任务发布者的距离
        self.Compute_Power = [1, 2, 3]  # 初始化计算中心的计算能力#TODO
        self.Compute_Energy_Consumption = [1, 4, 9]    #超高功耗
        self.Now_Aoi=[0, 0, 0, 0, 0]
        self.Aoi_Last = [0, 0, 0, 0, 0]
        self.Task_Data_Size = [0, 0, 0, 0, 0] #任务的数据量

        self.t = 0
        self.Task_Center = [1, 1, 1, 1, 1]
        self.Task_Center[0] = Pt0_5_1[0]
        self.Task_Center[1] = Pt0_5_2[0]
        self.Task_Center[2] = Pt0_5_3[0]
        self.Task_Center[3] = Pt0_5_4[0]
        self.Task_Center[4] = Pt0_5_5[0]
        self.Now_Aoi = self.List_random_num(self.Task_Center,2,5)#第一次先生成一波aoi
        self.Task_Data_Size = self.List_random_num(self.Task_Center,1,4)

 每一场训练完,都要初始化一下

# rect reset 任务中心任务刷新
    def reset(self):
        self.update()
        # time.sleep(0.5)
        self.Task_Center[0] = Pt0_5_1[0]
        self.Task_Center[1] = Pt0_5_2[0]
        self.Task_Center[2] = Pt0_5_3[0]
        self.Task_Center[3] = Pt0_5_4[0]
        self.Task_Center[4] = Pt0_5_5[0]
        self.t = 0
        self.Now_Aoi = self.List_random_num(self.Task_Center, 2, 5)  # 第一次先生成一波aoi
        self.Task_Data_Size = self.List_random_num(self.Task_Center, 1, 4)
        return self.Now_Aoi+self.Task_Data_Size

动作结束后根据Action_table字典将action解码得到real_action

 # 生成下一状态和奖惩机制策略
    def step(self, action):#状态改成当前AOI的数值

        real_action = Action_table[action]  # 解码获得的此时动作

        Energy = self.Energy_Calculation(real_action)

        self.Now_Aoi = self.clear_numbers(real_action, self.Now_Aoi) #计算机执行任务,对要执行的aoi清零

        self.Aoi_Last=self.Now_Aoi #储存一下因为没处理,积攒下的aoi

        for i in range(len(self.Aoi_Last)): #没处理的aoi加上2
            if self.Aoi_Last[i] != 0:
                self.Aoi_Last[i] += 2

        if self.t == 199:
            done = True
            self.t=0
        else:
            done = False #不结束

        reward = 17.5-sum(self.Aoi_Last)-Energy #奖励暂时等于平均下来的aoi

 然后调用Energy_Calculation方法计算能量值,并将结果赋给Energy

energy的公式是自己定义的:self.Compute_Energy_Consumption[i] * self.Task_Data_Size[index - 1]

    def Energy_Calculation(self, indices): #计算能耗
        total_sum = 0
        for i, index in enumerate(indices[:3]):
            total_sum += self.Compute_Energy_Consumption[i] * self.Task_Data_Size[index - 1]
        return total_sum

接下来调用clear_numbers方法将要执行的real_action对应的AOI清零,并将结果赋给Now_Aoi

    def clear_numbers(self, indices, number_list): #用于计算任务清楚AOI
        for index in indices:
            number_list[index - 1] = 0
        return number_list

然后将当前的Now_Aoi值赋给Aoi_Last,接着对Aoi_Last中未处理的AOI加上2。

最后计算奖励值,奖励暂时等于17.5减去Aoi_Last的总和再减去Energy的值。 

 

  • 8
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值