20250306-笔记-精读class CVRPEnv:step(self, selected)

文章目录

  • 前言
  • 一、`if self.time_step<4:`
    • 控制时间步的递增
    • 判断是否在配送中心
    • 特定时间步的操作
    • 更新
      • 更新当前节点和已选择节点列表
      • 更新需求和负载
      • 更新访问标记
      • 更新负无穷掩码
      • 更新步骤状态,将更新后的状态同步到 self.step_state
  • 二、使用步骤
  • 总结


前言

class CVRPEnv:step(self, selected)函数是强化学习代码实现中的核心。
精读该代码的目标:

  1. 熟悉每一个参数的shape。
  2. 熟悉每个参数之间的关系(剪切,扩展,等)。

一、if self.time_step<4:

控制时间步的递增

            # 控制时间步的递增self.time_step=self.time_step+1self.selectex_count = self.selected_count+1

判断是否在配送中心

            #判断是否在配送中心self.at_the_depot = (selected == 0)

特定时间步的操作

            if self.time_step==3:self.last_current_node = self.current_node.clone()self.last_load = self.load.clone()if self.time_step == 4:self.last_current_node = self.current_node.clone()self.last_load = self.load.clone()self.visited_ninf_flag[:, :, self.problem_size+1][(~self.at_the_depot)&(self.last_current_node!=0)] = 0

更新

更新当前节点和已选择节点列表

            #更新当前节点和已选择节点列表self.current_node = selectedself.selected_node_list = torch.cat((self.selected_node_list, self.current_node[:, :, None]), dim=2)
参数Shape
self.current_node(batch, pomo)
self.selected_node_list(batch, pomo,0~)

注:0~表示第三维度逐渐增加

self.selected_node_list的shape:
在这里插入图片描述
self.current_node的shape:
在这里插入图片描述
self.selected_node_list = torch.cat((self.selected_node_list, self.current_node[:, :, None]), dim=2),表示先将self.current_node扩展为三维数据,再将self.current_node沿着self.selected_node_list 的第三维度(dim=2)进行依次剪切进去。

更新需求和负载

            #更新需求和负载demand_list = self.depot_node_demand[:, None, :].expand(self.batch_size, self.pomo_size, -1)gathering_index = selected[:, :, None]selected_demand = demand_list.gather(dim=2, index=gathering_index).squeeze(dim=2)self.load -= selected_demandself.load[self.at_the_depot] = 1  # refill loaded at the depot
参数Shape含义g
self.depot_node_demand(batch, problem + 1)表示每个批次中,每个问题(包括配送中心)对应的节点需求
demand_list(batch, pomo, problem + 1)包含每个节点需求的张量
selected(batch, pomo)表示每个批次中的每个智能体所选择的节点编号(这些节点是从节点集合中选择的)
selected_demand(batch, pomo)示每个智能体所选择节点的需求。

demand_list = self.depot_node_demand[:, None, :].expand(self.batch_size, self.pomo_size, -1)

  • [:, None, :]:先在self.depot_node_demand的第二维(即问题维度)上增加一个新的维度,使其变为 (batch_size, 1, problem_size + 1)
  • .expand(self.batch_size, self.pomo_size, -1):将数据self.depot_node_demand扩展为 (batch_size, pomo_size, problem_size + 1),表示每个批次中的每个 POMO 智能体都有一份相同的需求数据。

在这里插入图片描述
gathering_index = selected[:, :, None]

  • selected 进行维度扩展
    在这里插入图片描述

selected_demand = demand_list.gather(dim=2, index=gathering_index).squeeze(dim=2)

  • demand_list 的 shape 是 (batch_size, pomo_size, problem_size + 1),包含了所有节点的需求数据。
  • gather(dim=2, index=gathering_index) 会按照 gathering_index(即 selected 中存储的节点编号)从 demand_list 中选择出对应的节点需求。dim=2 表示沿着第三维(即问题维度)进行选择。
  • gather 的结果是一个 shape 为 (batch_size, pomo_size, 1) 的张量。
  • .squeeze(dim=2) 去掉了多余的第三维,最终得到 selected_demand,其 shape 是 (batch_size, pomo_size),表示每个智能体所选择节点的需求。

在这里插入图片描述

更新访问标记

            #更新访问标记(防止重复选择已访问的节点)self.visited_ninf_flag[self.BATCH_IDX, self.POMO_IDX, selected] = float('-inf')self.visited_ninf_flag[:, :, 0][~self.at_the_depot] = 0  # depot is considered unvisited, unless you are AT the depot
参数Shape含义
self.visited_ninf_flag(batch, pomo, problem+ 1)记录了每 个智能体(POMO)在每个批次中已访问的节点的信息,标记某些节点是否已经被访问(用负无穷表示)。
self.BATCH_IDX(batch, pomo)批次索引的张量
self.POMO_IDX(batch, pomo)智能体(POMO)索引的张量
selected(batch, pomo)表示每个批次中的每个智能体所选择的节点编号(这些节点是从节点集合中选择的)
self.at_the_depot(batch, pomo)一个布尔型张量,表示每个智能体是否处于配送中心(即该智能体是否在节点 0,通常是配送中心)。

self.visited_ninf_flag[self.BATCH_IDX, self.POMO_IDX, selected] 表示从 visited_ninf_flag 张量中选择出对应批次和智能体的对应位置,并设置为 float('-inf'),表示这些节点已经被访问过。

举例:
假设我们有以下参数:

  • batch_size = 2,即有 2 个批次。
  • pomo_size = 3,即每个批次有 3 个智能体(POMO)。
  • problem_size = 4,即有 4 个节点(包含配送中心)。
self.visited_ninf_flag = [[[  0.,   0.,   0.,   0.,   0.],  # 第一个批次(batch 0)[  0.,   0.,   0.,   0.,   0.],  # POMO 0, POMO 1, POMO 2 各自对节点的访问标志[  0.,   0.,   0.,   0.,   0.]],[[  0.,   0.,   0.,   0.,   0.],  # 第二个批次(batch 1)[  0.,   0.,   0.,   0.,   0.],[  0.,   0.,   0.,   0.,   0.]]
]

self.BATCH_IDX(批次索引):

self.BATCH_IDX = [[0, 0, 0],  # 第一个批次[1, 1, 1]   # 第二个批次
]

self.POMO_IDX(POMO 索引):

self.POMO_IDX = [[0, 1, 2],  # 每个批次中三个智能体的索引[0, 1, 2]
]

selected(每个智能体选择的节点):

selected = [[1, 2, 0],  # 第一个批次中,智能体选择的节点:POMO 0 选择节点 1,POMO 1 选择节点 2,POMO 2 选择节点 0[3, 1, 2]   # 第二个批次中,智能体选择的节点:POMO 0 选择节点 3,POMO 1 选择节点 1,POMO 2 选择节点 2
]

执行这一行代码 self.visited_ninf_flag[self.BATCH_IDX, self.POMO_IDX, selected] = float('-inf')
对于第一个批次(BATCH_IDX[0]),我们有三个智能体(POMO_IDX[0]),选择了节点 [1, 2, 0],分别是:

  • selected[0][0] = 1 表示 POMO 0 选择了节点 1。
  • selected[0][1] = 2 表示 POMO 1 选择了节点 2。
  • selected[0][2] = 0 表示 POMO 2 选择了节点 0。
    对于第二个批次(BATCH_IDX[1]),我们同样有三个智能体(POMO_IDX[1]),选择了节点 [3, 1, 2],分别是:
  • selected[1][0] = 3 表示 POMO 0 选择了节点 3。
  • selected[1][1] = 1 表示 POMO 1 选择了节点 1。
  • selected[1][2] = 2 表示 POMO 2 选择了节点 2。

更新 visited_ninf_flag: 根据批次索引和 POMO 索引,我们更新了对应位置的值为负无穷 -inf:

  • 对于 BATCH_IDX[0] 和 POMO_IDX[0, 1, 2],我们将 selected[0][0] = 1,selected[0][1] = 2,selected[0][2] = 0 位置标记为 -inf。
  • 对于 BATCH_IDX[1] 和 POMO_IDX[0, 1, 2],我们将 selected[1][0] = 3,selected[1][1] = 1,selected[1][2] = 2 位置标记为 -inf。

self.visited_ninf_flag[:, :, 0][~self.at_the_depot] = 0,我们将所有不在配送中心的智能体的配送中心访问标志设置为 0。
-[:, :, 0] 是一个切片操作,表示我们提取张量中的第一个节点(通常是配送中心节点)。

  • ~self.at_the_depot 是对 self.at_the_depot 张量的布尔取反操作,将 True 变为 False,将 False 变为 True。

更新负无穷掩码

            #更新负无穷掩码(屏蔽需求量超过当前负载的节点)self.ninf_mask = self.visited_ninf_flag.clone()round_error_epsilon = 0.00001demand_too_large = self.load[:, :, None] + round_error_epsilon < demand_list_2=torch.full((demand_too_large.shape[0],demand_too_large.shape[1],1),False)demand_too_large = torch.cat((demand_too_large, _2), dim=2)self.ninf_mask[demand_too_large] = float('-inf')
参数Shape含义
self.visited_ninf_flag(batch, pomo, problem+ 1)记录了每 个智能体(POMO)在每个批次中已访问的节点的信息,标记某些节点是否已经被访问(用负无穷表示)。
self.ninf_mask(batch, pomo, problem+ 1)self.visited_ninf_flag.clone()

更新步骤状态,将更新后的状态同步到 self.step_state

            #更新步骤状态,将更新后的状态同步到 self.step_stateself.step_state.selected_count = self.time_stepself.step_state.load = self.loadself.step_state.current_node = self.current_nodeself.step_state.ninf_mask = self.ninf_mask
参数Shape

二、使用步骤


总结

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/72650.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Flowable 基本入门

flowable.7z官方版下载丨最新版下载丨绿色版下载丨APP下载-123云盘 1、Flowable介绍 Flowable是BPMN的一个基于java的软件实现&#xff0c;不过Flowable不仅仅包括BPMN&#xff0c;还有DMN决策表和CMMN Case管理引擎&#xff0c;并且有自己的用户管理、微服务API等一系列功能&a…

完全背包-一维数组

52. 携带研究材料&#xff08;第七期模拟笔试&#xff09; 题目描述 小明是一位科学家&#xff0c;他需要参加一场重要的国际科学大会&#xff0c;以展示自己的最新研究成果。他需要带一些研究材料&#xff0c;但是他的行李箱空间有限。这些研究材料包括实验设备、文献资料和…

景联文科技:以专业标注赋能AI未来,驱动智能时代的精准跃迁

在人工智能技术重塑全球产业格局的今天&#xff0c;高质量训练数据已成为驱动算法进化的核心燃料。作为数据智能服务领域的领军者&#xff0c;景联文科技深耕数据标注行业多年&#xff0c;以全栈式数据解决方案为核心&#xff0c;构建起覆盖数据采集、清洗、标注、质检及算法调…

洛谷B2074 计算星期几

B2074 计算星期几 - 洛谷 代码区&#xff1a; #include<algorithm> #include<iostream> #include<unordered_map> #include<string> using namespace std; int main() {unordered_map<int, string> m { { 1,"Monday" },{2,"Tue…

协同过滤推荐算法+微信小程序的农产品团购推荐平台(程序+论文+讲解+安装+调试+售后)

感兴趣的可以先收藏起来&#xff0c;还有大家在毕设选题&#xff0c;项目以及论文编写等相关问题都可以给我留言咨询&#xff0c;我会一一回复&#xff0c;希望帮助更多的人。 系统介绍 在当今时代&#xff0c;科学技术正以令人瞩目的速度迅猛进步&#xff0c;经济社会也随之…

十大经典排序算法简介

一 概述 本文对十大经典排序算法做简要的总结(按常用分类方式排列),包含核心思想、时间/空间复杂度及特点。 二、比较类排序 1. 冒泡排序 (BUBBLE SORT) 思想:重复交换相邻逆序元素,像气泡上浮 复杂度: 时间:O(n^2)(最好情况O(n)) 空间:O(1) 特点:简单但效率低,稳…

[自然语言处理]pytorch概述--什么是张量(Tensor)和基本操作

pytorch概述 PyTorch 是⼀个开源的深度学习框架&#xff0c;由 Facebook 的⼈⼯智能研究团队开发和维护&#xff0c;于2017年在GitHub上开源&#xff0c;在学术界和⼯业界都得到了⼴泛应⽤ pytorch能做什么 GPU加速自动求导常用网络层 pytorch基础 量的概念 标量&#xf…

Spring统一格式返回

目录 一&#xff1a;统一结果返回 1&#xff1a;统一结果返回写法 2&#xff1a;String类型报错问题 解决方法 二&#xff1a;统一异常返回 统一异常返回写法 三&#xff1a;总结 同志们&#xff0c;今天咱来讲一讲统一格式返回啊&#xff0c;也是好久没有讲过统一格式返…

【无标题】四色拓扑模型与宇宙历史重构的猜想框架

### 四色拓扑模型与宇宙历史重构的猜想框架 --- #### **一、理论基础&#xff1a;四色拓扑与时空全息原理的融合** 1. **宇宙背景信息的拓扑编码** - **大尺度结构网络**&#xff1a;将星系团映射为四色顶点&#xff0c;纤维状暗物质结构作为边&#xff0c;构建宇宙尺度…

蓝桥杯 封闭图形个数

蓝桥杯 封闭图形个数 题目 链接 解答 # 数字个数 n int(input()) # 数字 ls input().split() # 统计数字的圈数 o_nums {} for i, x in enumerate(ls):o_num 0for c in x:if int(c) in [0, 4, 6, 9]:o_num 1elif c 8:o_num 2o_nums[i] o_num # 字典根据圆圈数排序 …

基于javaweb的SpringBoot学生在线考试管理系统设计和实现(源码+文档+部署讲解)

技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容&#xff1a;免费功能设计、开题报告、任务书、中期检查PPT、系统功能实现、代码编写、论文编写和辅导、论…

国产编辑器EverEdit - 超多样式设置

1 设置-编辑-样式 1.1 设置说明 1.1.1 折叠样式 默认为箭头&#xff0c;折叠样式选项如下&#xff1a; 箭头&#xff1a; 矩形和线条 五边形 圆形图标 1.1.2 光标样式 光标用于指示当前用户输入位置&#xff0c;光标样式选项如下&#xff1a; 默认 纤细 字宽 …

Linux - 线程控制

一、线程概念 1&#xff09;线程地址空间 线程与进程共享相同的虚拟地址空间&#xff0c;因此线程在访问内存时与进程没有本质的区别。但线程共享和独占的内存区域有不同的特点&#xff0c;理解这些特性对于正确使用线程至关重要。 1. 线程地址空间的组成 线程的地址空间是…

通过多线程分别获取高分辨率和低分辨率的H264码流

目录 一.RV1126 VI采集摄像头数据并同时获取高分辨率码流和低分辨率码流流程 ​编辑 1.1初始化VI模块&#xff1a; 1.2初始化RGA模块&#xff1a; 1.3初始化高分辨率VENC编码器、 低分辨率VENC编码器&#xff1a; 1.4 VI绑定高分辨率VENC编码器&#xff0c;VI绑定RGA模块…

部署RabbitMQ集群详细教程

部署RabbitMQ集群详细教程 下面是一份在 Ubuntu 环境下部署 RabbitMQ 集群的详细步骤说明&#xff0c;涉及主机名设置、Erlang & RabbitMQ 安装、管理插件启用、集群通信 Cookie 配置、节点加入集群、镜像队列策略设置以及集群验证等。为了演示方便&#xff0c;以下示例假…

【Linux】之【Bug】VMware 虚拟机开机 一直卡在黑屏左上角下划线闪烁界面

解决 参考&#xff1a; 解决Ubuntu20.04 开机黑屏光标闪烁进不去系统 Centos根目录100%解决思路 当前界面 ctrlaltf3-f6 暂时进入终端界面 df -h 查看发现根目录 磁盘空间已满 执行命令 查看当前目录占用内存明细 sudo du -h -x --max-depth1清理无用的大内存文件 或者安装…

webflux集成langchain4j基础版

伴随着大模型应用的兴起&#xff0c;webflux逐渐引起关注。为了以java的方式运行AI应用&#xff0c;让我们一起学习webflux集成langchain4j吧。 1. 项目依赖 首先&#xff0c;你需要在 pom.xml 中添加必要的依赖&#xff1a; <dependencies><!-- Spring WebFlux --…

使用GitLink个人建站服务部署Allure在线测试报告

更多技术文章&#xff0c;访问软件测试社区 文章目录 &#x1f680;前言&#x1f511;开通GitLink个人建站服务1. 前提条件2. 登录GitLink平台&#xff08;https://www.gitlink.org.cn/login&#xff09;3. 进入设置>个人建站>我的站点4. 新建站点5. 去仓部进行部署6. 安…

go数组的声明和初始化

1.数组简介 数组是可以存放多个同一类型的数据。数组也是一种数据类型&#xff0c;在go中&#xff0c;数组是值类型。数组的长度也是数组类型的一部分&#xff0c;所以[2]int和[3]int属于不同的数据类型。 2.数组的长度也是类型的一部分 var arr1 [2]intvar arr2 [3]intfmt.P…

四款GIS工具箱软件解析:满足企业多样化空间数据需求

概述 随着地理信息系统&#xff08;GIS&#xff09;在城市规划、环境监测、资源管理等领域的广泛应用&#xff0c;各种GIS工具箱软件不断涌现&#xff0c;为用户提供了强大的数据处理、空间分析和地图制图功能。本文将为大家介绍4款GIS工具箱软件&#xff0c;这些软件各具特色…