ns3-gym入门(三):在opengym基础上实现一个小小的demo

因为官方给的"opengym""opengym-2"这两个例子都很简单,所以自己改了一个demo,把reward-action-state相互影响的关系表现出来

一、准备工作

在ns3.35/scratch目录下创建一个文件夹:
(后续的运行指令后面都需要转移到这个文件夹路径下)

二、主要思路

  • Action:离散空间[0,1,2,3],使用ε-贪心策略选择
  • ExecuteActions:赋值x=action
  • Obs\State:基于action定义一组数,关于x的线性函数
  • Reward:对state中的所有数据进行处理,取平均数得到r

PS.发现一个问题,这个框架如果脱离了具体的网络环境其实并不好定义,因为这些要素相互依赖的关系非常抽象,尤其是state是通过全网状态搜集得到的,在这里没有定义具体的网络环境,所以暂时用全局变量来表示一下这种隐性关系

三、关键实现步骤

mygym.cc(定义了存储决策和状态的全局变量,增加了收集状态、执行动作、计算奖励的函数)
①全局变量

static float deci = 0.0; // 全局变量,用于存储决策
std::vector<float> state;// 全局变量,用于存储状态

②创建状态空间(只是初始化一个容器,定义好维度就行)

//初始化一般不用大改,建立一个存储空间就行
Ptr<OpenGymSpace>
MyGymEnv::GetObservationSpace()
{
  uint32_t nodeNum = 8;
  float low = 0.0;
  float high = 100.0;
  std::vector<uint32_t> shape = {nodeNum,};
  std::string dtype = TypeNameGet<uint32_t> ();
  Ptr<OpenGymBoxSpace> space = CreateObject<OpenGymBoxSpace>(low, high, shape, dtype);
  NS_LOG_UNCOND ("MyGetObservationSpace: " << space);
  return space;
}

③创建动作空间(离散)

// 离散空间[0,1,2,3]
Ptr<OpenGymSpace>
MyGymEnv::GetActionSpace()
{

  uint32_t nodeNum = 4;
  Ptr<OpenGymDiscreteSpace> space = CreateObject<OpenGymDiscreteSpace> (nodeNum);
  NS_LOG_UNCOND ("MyGetActionSpace: " << space);
  return space;
}

④执行选定的动作

// action存储到全局变量deci
bool
MyGymEnv::ExecuteActions(Ptr<OpenGymDataContainer> action)
{
  Ptr<OpenGymDiscreteContainer> discrete = DynamicCast<OpenGymDiscreteContainer>(action);
  NS_LOG_UNCOND ("MyExecuteActions: " << action);
  deci = discrete->GetValue();
  return true;
}

⑤收集网络状态

Ptr<OpenGymDataContainer>
MyGymEnv::GetObservation()
{

  uint32_t nodeNum =  8;
  std::vector<uint32_t> shape = {nodeNum,};
  Ptr<OpenGymBoxContainer<uint32_t> > box = CreateObject<OpenGymBoxContainer<uint32_t> >(shape);
  
  for (uint32_t i=0;i<nodeNum;i++){
    uint32_t value = GetValue(i);
    box->AddValue(value);
  }
 }

  // 将 box 的值放入全局变量 state
  state.clear();
  for (uint32_t i = 0; i < nodeNum; i++) {
    state.push_back(box->GetValue(i)); // 获取 box 中的值并添加到 state 中
  }

  NS_LOG_UNCOND ("MyGetObservation: " << box);
  return box;
}
// 搜集网络状态的函数
float 
MyGymEnv::GetValue(uint32_t index)
{
  float value = deci*index;
  return value;
}

⑥根据状态计算奖励

// 对state进行处理
float
MyGymEnv::GetAverage( std::vector<float> state)
{
  uint32_t sum = 0;
  for (uint32_t value : state) {
    sum += value;
  }
  return static_cast<double>(sum) / state.size();
}
/*
Define reward function
*/
float
MyGymEnv::GetReward()
{
  float reward = GetAverage(state);
  NS_LOG_UNCOND ("MyGetReward: " << reward);
  return reward;
}

mygym.h(声明全局变量,添加自定义函数到private类)

extern std::vector<float> state;// 全局变量,用于存储状态
private:
  void ScheduleNextStateRead();
  float GetValue(uint32_t index);
  float GetAverage( std::vector<float> state);

sim.cc(这一块没有什么要改的,注意总仿真时间和仿真次数的关系,相当于实际的step受到两个地方的参数影响,另一个在创建环境时定义的isGameOver函数中)

  double simulationTime = 3; //seconds, 控制仿真次数的位置2
  double envStepTime = 0.1; //seconds, ns3gym env step time interval

test.py(这里主要的改动是使用了ε-贪心策略)

# Choose action
            if np.random.rand( ) < epsilon:
                 action = env.action_space.sample()
                 print("random")
            else:
                for action in range(env.action_space.n):#离散动作空间的定义
                    Q_value = estimate(action,ob_space)
                    if Q_value > best_value:
                        best_value = Q_value
                        best_action = action
                    action = best_action
                print("maximum Q")

简单模拟了一下Q值的估计(基于action估计reward)

def estimate(action,ob_space):
    state = []
    for i in range(ob_space.shape[0]):{
        state.append(action * i) 
    }
    reward = np.mean(state)
    Q_value =reward
    return Q_value

简单运行了一下:
ns3端:

python端

PS.要注意ns3-gym传递的数据类型可能无法直接用len()等函数,要去查看定义的具体数据类型

这个demo只是先按照我的理解大致实现了各个环节的衔接,但是reward对action的调整作用还没有体现出来,强化学习的精髓还没有融合进去,还有一些细节问题可能没有发现,下一个demo见

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C++字体库开发之字符显示四

freetype提取路径&#xff0c;转svg显示 std::string FontPath::toSvg(const Segment &seg) const {if (seg.pts.empty())return "";std::ostringstream strStream;for (const auto &pt : seg.pts) {if (!strStream.view().empty())strStream << &quo…

【linux】服务器重装系统之系统盘写入准备

【linux】服务器重装系统之系统盘写入准备 【创作不易&#xff0c;求点赞关注收藏】&#x1f600; 文章目录 【linux】服务器重装系统之系统盘写入准备一、前期准备1、准备一个U盘&#xff0c;并进行格式化2、下载UltralSO工具3、下载对应的Ubuntu版本 二、写入操作教程 一、…

gorm多表联合查询 Joins方法 LEFT JOIN , RIGHT JOIN , INNER JOIN, FULL JOIN 使用总结

gorm中多表联合查询&#xff0c;我们可以使用Joins来完成&#xff0c;这个Joins方法很灵活&#xff0c;我们可以非常方便的多多表进行联合查询&#xff0c; 我们先来看看这个方法的官方定义和使用示例&#xff1a; Joins方法定义和使用示例 当然我们这里要说的使用方式是官方示…

nginx生成自签名SSL证书配置HTTPS

一、安装nginx nginx必须有"--with-http_ssl_module"模块 查看nginx安装的模块&#xff1a; rootecs-7398:/usr/local/nginx# cd /usr/local/nginx/ rootecs-7398:/usr/local/nginx# ./sbin/nginx -V nginx version: nginx/1.20.2 built by gcc 9.4.0 (Ubuntu 9.4.0…

Vue.js 中的 immediate: true的作用

在使用 Vue.js 时&#xff0c;监听器 (watchers) 是一种非常重要的工具&#xff0c;它允许我们观察和响应数据的变化。 immediate: true 的作用 默认情况下&#xff0c;监听器只有在所监视的数据属性发生变化时才会触发回调函数。然而&#xff0c;有时候我们需要在组件初始化时…

Hadoop-29 ZooKeeper集群 Watcher机制 工作原理 与 ZK基本命令 测试集群效果 3台公网云服务器

章节内容 上节我们完成了&#xff1a; ZNode的基本介绍ZNode节点类型的介绍事务ID的介绍ZNode实机测试效果 背景介绍 这里是三台公网云服务器&#xff0c;每台 2C4G&#xff0c;搭建一个Hadoop的学习环境&#xff0c;供我学习。 之前已经在 VM 虚拟机上搭建过一次&#xff…

LVS+Nginx高可用集群---keepalived原理与实战

1.高可用集群架构keepalived双机主备原理 高可用&#xff1a;(HA) 部署nginx存在两台nginx。当主节点的nginx宕机停止服务的时候&#xff0c;nginx备用机起到跟nginx(主) keepalived的概念&#xff1a;解决单点故障&#xff1b;组件免费&#xff1b;可以实现高可用HA机制&…

《0基础》学习Python——第十一讲

一、lambda 匿名函数 lambda函数是一种匿名函数。它是一种快速定义单行函数的方法。与常规函数不同&#xff0c;lambda函数没有名称&#xff0c;也没有使用def关键字来定义。lambda函数通常用于一些简单的函数&#xff0c;可以在代码中快速定义和使用&#xff0c;而不需要为其定…

Hive的基本操作(查询)

1、基础查询 基本语法 select 字段列表|表达式|子查询 from 表(子查询|视图|临时表|普通表) where [not] 条件A and|or 条件B --先&#xff1a;面向原始行进行筛选 group by 字段A[,字段B,...] > 分组【去重处理】 having 聚合条件(非原始字段条件) --再&#x…

《梦醒蝶飞:释放Excel函数与公式的力量》12.3 DMIN函数

第12章&#xff1a;数据库函数 第三节 12.3 DMIN函数 12.3.1 简介 DMIN函数是Excel中的一个数据库函数&#xff0c;用于返回数据库或数据表中特定条件下某字段的最小值。DMIN函数在处理大规模数据、数据筛选和分析时非常有用。 12.3.2 语法 DMIN(database, field, criteri…

MYSQL 四、mysql进阶 9(数据库的设计规范)

一、为什么需要数据库设计 二、范 式 2.1 范式简介 在关系型数据库中&#xff0c;关于数据表设计的基本原则、规则就称为范式。 可以理解为&#xff0c;一张数据表的设计结 构需要满足的某种设计标准的 级别 。要想设计一个结构合理的关系型数据库&#xff0c;必须满足一定的…

LLM量化--AWQ论文阅读笔记

写在前面&#xff1a;近来大模型十分火爆&#xff0c;所以最近开启了一波对大模型推理优化论文的阅读&#xff0c;下面是自己的阅读笔记&#xff0c;里面对文章的理解并不全面&#xff0c;只将自己认为比较重要的部分摘了出来&#xff0c;详读的大家可以参看原文 原论文地址&am…

Leetcode—146. LRU 缓存【中等】(shared_ptr、unordered_map、list)

2024每日刷题&#xff08;143&#xff09; Leetcode—146. LRU 缓存 先验知识 list & unordered_map 实现代码 struct Node{int key;int value;Node(int key, int value): key(key), value(value) {} };class LRUCache { public:LRUCache(int capacity): m_capacity(capa…

axios以post方式提交表单形式数据

某些后端框架请求接口必须走form表单提交的那种形式&#xff0c;但前端很少有<form action"接口地址" method"post"></form>这种写法去提交表单数据&#xff0c;所以前端需要用axios模拟一个表单提交接口。 Content-Type 代表发送端&#xff0…

【.NET全栈】ASP.NET开发web应用——ASP.NET中的样式、主题和母版页

文章目录 前言一、在ASP.NET中应用CSS样式1、创建CSS样式&#xff08;1&#xff09;内联样式&#xff08;2&#xff09;内部样式表&#xff08;3&#xff09;外部样式表 2、应用CSS样式&#xff08;1&#xff09;菜鸟教程-简单例子&#xff08;2&#xff09;菜鸟教程-用户界面&…

零售门店收银系统源码

php收银系统源码-CSDN博客文章浏览阅读268次&#xff0c;点赞6次&#xff0c;收藏4次。收银系统源码https://blog.csdn.net/qh716/article/details/140431477 1.系统开发语言 核心开发语言: PHP、HTML5、Dart后台接口: PHP7.3后合管理网站: HTML5vue2.0element-uicssjs线下收…

【区块链 + 智慧政务】涉税行政事业性收费“e 链通”项目 | FISCO BCOS应用案例

国内很多城市目前划转至税务部门征收的非税收入项目已达 17 项&#xff0c;其征管方式为行政主管部门核定后交由税务 部门征收。涉税行政事业性收费受限于传统的管理模式&#xff0c;缴费人、业务主管部门、税务部门、财政部门四方处于 相对孤立的状态&#xff0c;信息的传递靠…

校园网自动登录脚本【Windows 10】

如果要使用校园网&#xff0c;必须打开浏览器输入校园网地址&#xff0c;之后输入账号密码登录。实验室电脑绝大多数情况下应该处于联网状态&#xff0c;但不幸的是&#xff0c;我深会限制校园网客户端数量&#xff0c;一旦有新设备接入&#xff0c;很可能实验室电脑就会断网。…

实现给Nginx的指定网站开启basic认证——http基本认证

一、问题描述 目前我们配置的网站内容都是没有限制&#xff0c;可以让任何人打开浏览器都能够访问&#xff0c;这样就会存在一个问题&#xff08;可能会存在一些恶意访问的用户进行恶意操作&#xff0c;直接访问到我们的敏感后台路径进行操作&#xff0c;风险就会很大&#xff…

wps批量删除空白单元格

目录 原始数据1.按ctrlg键2.选择“空值”&#xff0c;点击“定位”3. 右击&#xff0c;删除单元格修改后的数据 原始数据 1.按ctrlg键 2.选择“空值”&#xff0c;点击“定位” 如图所示&#xff0c;空值已被选中 3. 右击&#xff0c;删除单元格 修改后的数据