【反馈】随机缓存系统

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/weixin_41374099/article/details/98477725

前言

PID控制器不仅仅用于智能硬件的控制,只要是有用到简单的反馈,那就一定用到过比例、积分、微分来对反馈量计算。一个PID反馈函数会涉及这样三个操作,一般用拉布拉斯变换后的结果表示。想到函数可能进行泰勒展开,我猜测比PID更简单的操作就是用多项式来表示反馈函数。


"准备·缓存"系统

给出这样一个例子

  1. 我们负责管理一个系统,它把item发送到下游的一个处理步骤(就是另一个模块)
  2. 下游系统有一个存放item的缓存区
  3. 在每一次操作中,下游的系统要从缓存区里拿一些item进行处理,被处理过的item将被移出缓存区(移出后的这里不考虑)
  4. 我们不能直接把item放到下游的缓存区,只能把其放入“准备区”中,这些item最终会被运输到下游缓存区
  5. item一旦被放进准备区,我们对其就不能任何控制:它们会被运输到下游缓存区,受到其他设备的控制
  6. 下游系统完成item处理的数量(第3步)以及从准备区移动到下游缓存区(第5步)的item数量都会随机波动
  7. 每个步骤,我们都需要决定放多少item到准备区,以保证下游缓存区能满负荷但又不会溢出——事实上,下游系统的管理者更希望我们保证缓存区的item数量不变

在这里插入图片描述

模拟缓存系统

1,首先,我们放入准备区的item数量只有小于准备区长度(max_wip)或者等于准备区长度(max_wip)——小于零的情况可以转换成这两种。
2,然后再从这样的长度里随机(这里用高斯分布随机)一小节长度,准备区减少这节长度,缓存区加上这节长度。
3,以缓存区长度(max_flow)为最大随机一节长度,用这节长度与缓存区已有的item数量相比,用原来的缓存区长度(queued)减去这两个比较后的最小的长度/数量就是这个缓存区的长度。

输入:情况A或情况B的长度(数量)
输出:最后情况C或情况D的长度(数量)
在这里插入图片描述


'''
buffer region and ready region
wip : the number of item  of ready region
flow : the number of item of buffer region
'''
class Buffer:
	def __init__(self,max_wip,max_flow):
		self.queued=0
		self.wip=0 #work-in-progress("ready pool")
		self.max_wip=max_wip
		self.max_flow=max_flow #avg outflow is max_flow/2

	def work(self,num):
		#add to ready pool
		num=max(0,int(round(num)))
		num=min(num,self.max_wip)
		self.wip+=num

		#transfer from ready pool to queue
		r=int(round(random.uniform(0,self.wip)))
		self.wip-=r
		self.queued+=r

		#release from queue to downstream process
		r=int(round(random.uniform(0,self.max_flow)))
		r=min(r,self.queued)
		self.queued-=r

		return self.queued  #return the value of y


不加控制器的模拟。看看自由状态下缓存系统会如何运作。

import random
import numpy as np
import matplotlib.pyplot as plt


class Buffer:
	...

def open_loop(buffer,tm=5000):
	y=0
	global yDir  #ignore the function of shadowing
	for t in range(tm):
		yDir.append(y)  #save the number which out of buffer
		r=5
		y=buffer.work(r)
		print("t=%d,r=%d,error=%d,num=%d,y=%d"%(t,r,r-y,r,y))



yDir=[]
b=Buffer(20,10)

open_loop(b,1000)


#paint the carve
#实际的输出数量的曲线
xS=np.arange(0,1000,1)
yS=yDir


plt.plot(xS,yS,color="g",linestyle="-",linewidth=1.0,label="queue's length")

plt.xlabel("time step")
plt.ylabel("number of item")
plt.show()

在这里插入图片描述

模拟控制器

中间item数量随机的,我们无法控制,最后缓存区出去的item数量也是随机的,我们也无法控制。但是有了两次随机的数值,我们可以用反馈来控制输入从而间接达到控制输出的目的。当然,一个合理的黑箱只有一个输出,所以这里我们就只以最后随机的来构造反馈函数。

所谓的PID,就是一个反馈函数里拥有比例运算,积分运算和微分运算(用拉布拉斯转换后就是乘法和除法)而已。PID不过是对这类函数的说法。

设定一个目标,减去缓存区长度,得到的就是偏差errorbias。再用偏差和充当积分项,这样得到的输入item数量公式为
i t e m ( s ) = K p e r r o r + K i e r r o r item(s) = K_p * error + K_i * \sum{error}

'''
control system
kp : proportionality  coefficient
ki : integral coefficient
self.i : cumulative deviation
'''
class Controller:
	def __init__(self,kp,ki):
		self.kp,self.ki=kp,ki
		self.i =0  #cumulative error ("integral")

	def work(self,error):
		self.i+=error
		return self.kp*error + self.ki*self.i

加入控制器,设定目标曲线之后。

import random
import numpy as np
import matplotlib.pyplot as plt


class Buffer:
	...

class Controller:
	...

def closed_loop(buffer,controller,tm=5000):
	def target(t):
		if t<100:return 0
		if t<300:return 50
		return 10
	y=0
	global yDir  #ignore the function of shadowing
	for t in range(tm):
		yDir.append(y)  #save the number which out of  buffer
		r=target(t)
		error = r-y
		num=controller.work(error)   #num=kp*error + ki*i
		y=buffer.work(num)
		print("t=%d,r=%d,error=%d,num=%d,y=%d"%(t,r,error,num,y))  #大概满足情况就不需要在浪费性能了



yDir=[]
b=Buffer(20,10)
c=Controller(1.25,0.01)    #比例系数1.25   积分系数0.01
closed_loop(b,c,1000)


#paint the carve
#实际的输出数量的曲线
xS=np.arange(0,1000,1)
yS=yDir

#目标曲线
xTarget=[0,100,100,300,300,999]
yTarget=[0,0,50,50,10,10]


plt.plot(xS,yS,color="g",linestyle="-",linewidth=1.0,label="queue's length")
plt.plot(xTarget,yTarget,color="b",linestyle="-",linewidth=1.0,label="wanted length")

plt.legend(loc="upper right",bbox_to_anchor=(0.9,0.95))

plt.xlabel("time step")
plt.ylabel("number of item")
plt.show()

在这里插入图片描述

在这个系统中,可以设定的是准备区和缓存区的长度目标曲线积分系数比例系数。上面放的两张图算是其中很优秀的结果了,两个区的长度到50左右控制器就不起什么作用了。

缓存系统长度越短,越容易稳定。越长控制器的作用就越小。

还算是有点反馈控制的意思了。


来自《企业级编程与控制理论》

猜你喜欢

转载自blog.csdn.net/weixin_41374099/article/details/98477725
今日推荐