在上一章中,基本完成了网络的模拟,但是设置的仿真精度是固定的0.1ms,而因为只有一个突触,其延迟是1ms,突触类的代码如下图
#ifndef SYNAPSE_H
#define SYNAPSE_H
#include <vector>
#include "Neuron.h"
#include "Params.h"
class Synapse
{
private:
double delay; //延迟
double weight; //权重
Neuron *post; //后神经元的gid
public:
Synapse(double delay_,double weight_,Neuron *post_);
~Synapse() = default;
/// @brief 将脉冲时间发送给后神经元
void send(SpikeEvent se);
};
Synapse::Synapse(double delay_,double weight_,Neuron *post_)
{
delay = delay_;
weight = weight_;
post = post_;
}
void Synapse::send(SpikeEvent se)
{
se.delay = delay;
se.weight = weight;
post->handle(se);
}
#endif
但是一个大的SNN网络中,不同的突触的延迟是不相同的,我想重新梳理一下这种机制,当SNN网络中一个神经元发射脉冲时,假设此时的时间为T,而网络中的最大延迟和最小延迟分别为max_delay和min_delay,这意味该脉冲的最早交付时间为T+min_delay,而最晚的交付时间为T+(min_delay-1)+max_delay。应该如何理解这个最大交付时间呢,我琢磨很久,我不理解为什么最晚交付时间为什么不是T+max_delay。下面展示了一个最晚交付时间的案例,假设最小延迟为5,最大延迟为7,那么从T时刻开始,最晚交付时间为T+(min_delay-1)+max_delay=11,而T+max_delay代表的时脉冲之间的交付时间
理论上来说,每一个神经元的缓冲区需要被设置成一个环形的queue,但是设置成queue却比较难以管理,而且不是很擅长使用指针操作,因此,我把神经元的RingBuffer设置成了vector,但是应该如何给他设置大小呢?我们分析一下:
设S为当前时间片开始的时间。在此时间片期间到达的所有脉冲必须在来自于上一个时间片,从S-min_delay开始。因此,最早峰值交付时间为
min T_d = S-min_delay + min_delay = S。
最晚的交付时间为
max T_d = S-1 + max_delay = S + (max_delay - 1)
因此0<=S-T_d<=max_del-1。使得环形缓冲器需要max_delay元素
从我们之间的描述来看,脉冲的模拟一直是按照时间走的,所有的神经元的ringbuffer在同一时刻都执行的时刻的输入电流。那代表我们能够建立从现在起的偏移的时间步长到环形缓冲ringbuffer的映射关系。那应该如何建立,我们定义为moduli,其大小如前面分析的应该为max_delay+min_delay,接下来就是分析如何建立这种映射关系。