用 python 求拥塞控制模型欧拉数值解

news2024/9/22 23:18:08

昨天使用 scipy 的 odeint 模拟了 E_best 的微分方程组模型(参见 用 python scipy 库模拟拥塞控制模型),但我觉得那个模型中处理 z 时不够优雅,只是一个负反馈,并未体现 “排队时延与 buffer 占用率成比例增长” 的事实,所以今天我直接用 inflight-in-buffer 重新建模,就优雅多了。

设 x 为 E = bw / delay,y 为 inflight-in-buffer 但不包括余量,w 为到达瓶颈的速率(等价于 sender 的 pacing rate 但又不是,具体为何,看我前面的文章),z 为排队时延,并且有以下参数,R 为传播时延,C 为瓶颈带宽,I 为 inflight 余量。新模型如下:

d x 1 d t = y 1 + I z z + R − x 1 \dfrac{dx_1}{dt}=\dfrac{\frac{y_1+I}{z}}{z+R}-x_1 dtdx1=z+Rzy1+Ix1 【E = bw / delay 表达式】
d w 1 d t = C ⋅ y 1 + I y 1 + y 2 + y 3 + 3 ⋅ I − w 1 \dfrac{dw_1}{dt}=C\cdot\dfrac{y_1+I}{y_1+y_2+y_3+3\cdot I}-w_1 dtdw1=Cy1+y2+y3+3Iy1+Iw1 【w = C * buffer 占率】
d y 1 d t = w 1 ⋅ z − y 1 \dfrac{dy_1}{dt}=w_1\cdot z-y_1 dtdy1=w1zy1 【bdp 公式】

d x 2 d t = y 2 + I z z + R − x 2 \dfrac{dx_2}{dt}=\dfrac{\frac{y_2+I}{z}}{z+R}-x_2 dtdx2=z+Rzy2+Ix2
d w 2 d t = C ⋅ y 2 + I y 1 + y 2 + y 3 + 3 ⋅ I − w 2 \dfrac{dw_2}{dt}=C\cdot\dfrac{y_2+I}{y_1+y_2+y_3+3\cdot I}-w_2 dtdw2=Cy1+y2+y3+3Iy2+Iw2
d y 2 d t = w 2 ⋅ z − y 2 \dfrac{dy_2}{dt}=w_2\cdot z-y_2 dtdy2=w2zy2

d x 3 d t = y 3 + I z z + R − x 3 \dfrac{dx_3}{dt}=\dfrac{\frac{y_3+I}{z}}{z+R}-x_3 dtdx3=z+Rzy3+Ix3
d w 3 d t = C ⋅ y 3 + I y 1 + y 2 + y 3 + 3 ⋅ I − w 3 \dfrac{dw_3}{dt}=C\cdot\dfrac{y_3+I}{y_1+y_2+y_3+3\cdot I}-w_3 dtdw3=Cy1+y2+y3+3Iy3+Iw3
d y 3 d t = w 3 ⋅ z − y 3 \dfrac{dy_3}{dt}=w_3\cdot z-y_3 dtdy3=w3zy3

d z d t = β ⋅ ( y 1 + y 2 + y 3 ) \dfrac{dz}{dt}=\beta\cdot(y_1+y_2+y_3) dtdz=β(y1+y2+y3) 【排队时延与 buffer 占率成正比】

基于这个新模型,我准备用欧拉法求数值解,先简单介绍欧拉法。给定一个常微分方程:

d y d t = f ( t , y ) , y ( t 0 ) = y 0 \frac{dy}{dt} = f(t, y), \quad y(t_0) = y_0 dtdy=f(t,y),y(t0)=y0

欧拉法求解步骤如下:

  • 离散:选一个时间步长 h,定义离散时间点 t n = t 0 + n h ( n = 0 , 1 , 2 , … ) t_n = t_0 + nh \quad (n = 0, 1, 2, \ldots) tn=t0+nh(n=0,1,2,)
  • 更新:使用欧拉法的更新公式: y n + 1 = y n + h ⋅ f ( t n , y n ) y_{n+1} = y_n + h \cdot f(t_n, y_n) yn+1=yn+hf(tn,yn)
  • 迭代:从初始条件开始,迭代计算 y n + 1 y_{n+1} yn+1 直到达到所需的时间范围。

我一开始硬编码了一个 python matplotlib 实现,非常不雅,如果涉及共享瓶颈的流太多,欧拉法的写法将非常令人烦躁,所以不得不重构代码。

但我真不会编程,稍微会一点,就这个代码吭哧折腾快一下午,但还是没有做到可扩展:

#!/opt/homebrew/bin/python3

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.pyplot import MultipleLocator

class Model:
    def __init__(self, initial_conditions, T, dt, a, b, c, d, R, C, I):
        self.T = T
        self.dt = dt
        self.a = a
        self.b = b
        self.c = c
        self.d = d
        self.R = R
        self.C = C
        self.I = I
        self.len = (len(initial_conditions) - 1) / 3
        self.times = np.arange(0, T + dt, dt)

        # 初始化状态
        self.states = {name: np.zeros_like(self.times) for name in initial_conditions.keys()}
        for name, value in initial_conditions.items():
            self.states[name][0] = value

    def update(self):
        for n in range(1, len(self.times)):
            for i in range(1, int(self.len) + 1):  # 假设有三个 x, y, w
                x_name = f'x{i}'
                y_name = f'y{i}'
                w_name = f'w{i}'

                self.states[x_name][n] = self.states[x_name][n - 1] + self.dt * (
                    (self.states[y_name][n - 1] + self.I) / self.states['z'][n - 1] /
                    (self.states['z'][n - 1] + self.R) - self.states[x_name][n - 1]
                )

                self.states[w_name][n] = self.states[w_name][n - 1] + self.dt * (
                    self.a * self.C * (self.states[y_name][n - 1] + self.I) /
                    (self.states['y1'][n - 1] + self.states['y2'][n - 1] + self.states['y3'][n - 1] + 3 * self.I) - self.states[w_name][n - 1]
                )

                self.states[y_name][n] = self.states[y_name][n - 1] + self.dt * (
                    self.states[w_name][n] * self.states['z'][n] - self.states[y_name][n - 1]
                )
                print("y1", self.states[y_name][n]);

            self.states['z'][n] = self.states['z'][n - 1] + self.dt * (
                self.states['y1'][n - 1] + self.states['y2'][n - 1] + self.states['y3'][n - 1]
            )

    def plot(self):
        plt.figure(figsize = (12, 6))
        plt.subplot(2, 1, 1)
        plt.plot(self.times, self.states['z'], label = 'z(t)', linestyle = 'dotted')
        for i in range(1, int(self.len) + 1):
            plt.plot(self.times, self.states[f'y{i}'], label = f'y{i}(t)', linestyle = 'dashed')
            plt.plot(self.times, self.states[f'w{i}'], label = f'w{i}(t)', linestyle = 'dashed')
        plt.legend()

        plt.subplot(2, 1, 2)
        ax = plt.gca()
        y_major = MultipleLocator(0.2)
        ax.yaxis.set_major_locator(y_major)
        plt.ylim(top = 0.01)
        for i in range(1, int(self.len) + 1):
            plt.plot(self.times, self.states[f'x{i}'], label = f'x{i}(t)')

        plt.xlabel('time (t)')
        plt.ylabel('')
        plt.legend()
        plt.grid(linestyle = 'dotted', linewidth = 1)
        plt.tight_layout()
        plt.show()

initial_conditions = {
    'x1': 0.00002, 'y1': 6, 'x2': 0.00003, 'y2': 2,
    'x3': 0.000001, 'y3': 14, 'w1': 1, 'w2': 1,
    'w3': 3, 'z': 0.1
}

T, dt = 50, 0.1
a, b, c, d, R, C, I = 1, 1.000, 0.2, 0.03, 2, 18, 1

model = Model(initial_conditions, T, dt, a, b, c, d, R, C, I)
model.update()
model.plot()

问题在于下面这个硬编码难以重构:

self.states['y1'][n - 1] + self.states['y2'][n - 1] + self.states['y3'][n - 1] + 3 * self.I

我想改成:

sum(self.states['y'][j][n-1] for j in range(self.len)) + len * self.I

但需要重构数据存储结构,我就搞不定了。但能运行就行:
在这里插入图片描述
其实这个代码已经不错了,最开始的风格如下:

x1 = np.zeros_like(times)
y1 = np.zeros_like(times)
x2 = np.zeros_like(times)
y2 = np.zeros_like(times)
x3 = np.zeros_like(times)
y3 = np.zeros_like(times)
w1 = np.zeros_like(times)
w2 = np.zeros_like(times)
w3 = np.zeros_like(times)
z = np.zeros_like(times)

x1[0], y1[0], x2[0], y2[0], x3[0], y3[0], w1[0], w2[0], w3[0], z[0] = x10, y10, x20, y20, x30, y30, w10, w20, w30, z0
for n in range(1, len(times)):    
    x1[n] = x1[n-1] + dt * (...)
    w1[n] = w1[n-1] + dt * (...)
    y1[n] = y1[n-1] + dt * (...)
    x2[n] = x2[n-1] + dt * (...)
    w2[n] = w2[n-1] + dt * (...)
    y2[n] = y2[n-1] + dt * (...)
    x3[n] = x3[n-1] + dt * (...)
    w3[n] = w3[n-1] + dt * (...)
    y3[n] = y3[n-1] + dt * (...)
    z[n] = z[n-1] + dt * (...)
...

假努力,工整而恶心。

浙江温州皮鞋湿,下雨进水不会胖。

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

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

相关文章

基于NE555制作雾化加湿器

基于NE555制作雾化加湿器 🌼实物制作图:(只焊接了2路,进行功能验证) 📺演示效果: 🍁原理图: 🎉其他方案:基于专用加湿器芯片:富…

noVNC使用与介绍

noVNC使用与介绍报告 1. 概述 VNC(Virtual Network Console,虚拟网络控制台)是一种流行的远程桌面访问协议,它允许用户通过网络连接到远程计算机的图形界面。VNC协议的实现通常包括两个主要组件:服务器端&#xff08…

充满惊喜与欢乐的老友

在这个充满惊喜与欢笑的娱乐圈里,每一个不经意的可能成为网友热议的焦点,而《快乐老友记》的花絮,无疑为这个多彩的世界又添上了一抹亮丽的色彩。当“王栎鑫被路人认成张艺兴”这一话题如春风般拂过网络,不仅让两位才华横溢的艺人…

硬核科普:什么是网络准入控制系统|网络准入控制系统四大品牌介绍

网络准入控制系统(Network Access Control, NAC)是一种用于确保只有授权设备和用户才能接入网络的安全技术。 本文将介绍几种常用的网络准入控制系统,帮助您更好地了解如何选择适合您企业的NAC系统。 网络准入控制的重要性和作用 网络准入控…

Jenkins集成JDK、git、gitee、maven逐步实现自动拉取,自动部署,自动启动

1. jenkins集成JDK 成功登录Jenkins后,选择Manage Jenkins,选择Tools 集成JDK 2. jenkins集成git 因为Jenkins自动从git远程仓库拉取代码 首先要在Jenkins所在的linux服务器上安装git yum install -y git然后,实行集成JDK的第一步 配置g…

ElMessage自动引入,样式缺失和ts esline 报错问题解决

一. 环境 "unplugin-auto-import": "^0.17.6", "vue": "^3.3.8", "vite": "^5.0.0", "typescript": "^5.2.2",二. ElMessage样式缺失问题. 以下有两种解决方法 方法一: 配置了自动引用后…

【Java算法专场】二分查找(上)

目录 前言 什么是二分查找? 二段性 ​​​​​​​​​​​​​​​​​​​​​二分查找 算法分析 算法步骤 算法代码 算法示例 模板 在排序数组中查找元素的第一个和最后一个位置 算法分析 算法步骤 算法代码 算法示例 搜索插入位置 算法分析 算法步…

HTML常见标签——超链接a标签

一、a标签简介 二、a标签属性 href属性 target属性 三、a标签的作用 利用a标签进行页面跳转 利用a标签返回页面顶部以及跳转页面指定区域 利用a标签实现文件下载 一、a标签简介 <a>标签用于做跳转、导航&#xff0c;是双标签&#xff0c;记作<a></a>&#…

MFC开发,自定义消息

在MFC开发中&#xff0c;主要核心机制就是消息机制。QT与之类似的机制就是信号与槽。QT中的信号与槽是非常容易自定义的&#xff0c;MFC也是如此&#xff0c;自定义也是比较方便&#xff0c;况且自定义消息或者控件在整个GUI图形化界面开发中也是非常重要的部分&#xff0c;上篇…

项目都做完了,领导要求国际化????--JAVA后端篇

springboot项目国际化相信各位小伙伴都会&#xff0c;很简单&#xff0c;但是怎么项目都做完了&#xff0c;领导却要求国际化文件就很头疼了 国际化的SpringBoot代码&#xff1a; 第一步&#xff1a;创建工具类 /*** 获取i18n资源文件** author bims*/ public class Message…

Java Collections类

Collections是一个与有关集合的工具类&#xff0c;提供了很多对集合进行操作的方法。 常见方法 addAll&#xff1a;往集合中添加多个元素。 public static <T> boolean addAll(Collection<? super T> c, T... elements) {boolean result false;for (T element…

MongoDB教程(二十):MongoDB正则表达式

&#x1f49d;&#x1f49d;&#x1f49d;首先&#xff0c;欢迎各位来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里不仅可以有所收获&#xff0c;同时也能感受到一份轻松欢乐的氛围&#xff0c;祝你生活愉快&#xff01; 文章目录 引言一、正则表…

Python3网络爬虫开发实战(3)网页数据的解析提取

文章目录 一、XPath1. 选取节点2. 查找某个特定的节点或者包含某个指定的值的节点3. XPath 运算符4. 节点轴5. 利用 lxml 使用 XPath 二、CSS三、Beautiful Soup1. 信息提取2. 嵌套选择3. 关联选择4. 方法选择器5. css 选择器 四、PyQuery1. 初始化2. css 选择器3. 信息提取4. …

程序的机器级表示(一)汇编,汇编格式和数据传输指令

系列文章 : 深入理解计算机系统笔记 文章目录 系列文章3 程序的机器级表示3.1 历史观点3.2 程序编码3.2.1 机器级代码3.2.2 代码示例3.2.3 关于格式的注解 3.3 数据格式3.4 访问信息3.4.1 操作数指示符3.4.2 数据传送指令3.4.3 数据传送示例3.4.4 压入和弹出栈数据 3 程序的机…

如何做校园圈子小程序,需要哪些功能?可打包APP小程序H5,源码交付,支持二开!

独立学校首页 支持每个学校独立首页!每个学校都可以拥有专属首页&#xff0c;打造不同风格的学校首页展示效果 多业务覆盖 可实现校园内外卖、跑腿、超市、药店水果、快餐店等业务全覆盖!所有配送业务平台都可开展 多站点运营 支持多学校多站点运营&#xff0c;各分站管理员可独…

【日记】办个护照不至于有这种刑事罪犯一样的待遇吧……(737 字)

正文 暴晒&#xff0c;中午出去骑共享单车&#xff0c;座垫都不敢坐。 至于为什么&#xff0c;中午觉都不睡跑出去&#xff0c;是因为今天他们办承兑汇票的业务&#xff0c;搞了一天&#xff0c;中午不休息&#xff0c;说可能还会用到我的指纹&#xff0c;让我 on call。我心想…

基础IO(文件系统)

一、块组的宏观理解 1、分区和分组 首先一台电脑就一个磁盘&#xff0c;一般800GB到1TB&#xff0c;为了管理这么大的内存数据&#xff0c;我们就对磁盘进行分区&#xff0c;分区之后才是我们看到的C盘&#xff0c;D盘等。 但是其实分区之后空间还是太大不好管理&#xff0c;…

习题2.23

不解释了&#xff0c;这么简单的题目。 (defn for-each[f item](if (not (empty? item));(println (f (first item)))(f (first item)))(if (not (empty? item))(for-each f (rest item)));(f (first item)))执行结果如下

FastGPT、Dify、Coze产品功能对比分析

在当前的人工智能领域&#xff0c;模型接入、应用发布、应用构建、知识库和工作流编排等功能是衡量一个AI平台综合能力的重要指标。本文将对FastGPT、Dify和Coze这三款产品的功能进行详细对比分析&#xff0c;以帮助用户更好地了解它。 订阅模式及市场概况 在订阅模式及市场概…

CSS常见属性详解——内边距与外边距

内边距与外边距 内边距 外边距 应用场景 在网页排版布局时&#xff0c;我们经常会希望元素与元素之间有一定的间距&#xff0c;此时我们可能会用到CSS的外边距或内边距属性&#xff0c;这两个属性都能让元素之间产生距离&#xff0c;那么他们之间有什么不同呢&#xff1f; …