CCF-CSP202109-3脉冲神经网络

题目要求实现一个脉冲神经网络的模拟器,主要由三部分:神经元,脉冲源,突触 构成,其中,神经元和脉冲源都由突触连接,可以是 脉冲源-->神经元,也可以是 神经元-->神经元,因此可以把它看成是一个有向图,脉冲源只有出度,神经元可以既有出度,又有入度,而突触就是把每个点相连的边。

对脉冲源分析:

每个脉冲源都有一个参数 r ,只有在 r > myrand()时脉冲源才会释放一次脉冲到神经元。

对神经元分析:

每个神经元有两个关键参数 u 和 v,只有在某时刻该神经元的 v >= 30 时该神经元才会释放一次脉冲, 释放脉冲后 v 变成 c , u 变成 u+d。

对突触分析:

每个突触都有两个参数 w 和 d,w 表示脉冲强度,d表示传输延迟,也就是说无论是神经元还是脉冲源发射了脉冲,其脉冲值都只与相连的突触有关。

分析完毕见代码:

#include <iostream>
#include <cstring>

using namespace std;
static unsigned long _next = 1;

const double INF = 1e8;

//RAND_MAX assumed to be 32767
int myrand(void) {
    _next = _next * 1103515245 + 12345;
    return((unsigned)(_next/65536) % 32768);
}
const int N = 2010;
int n,S,P,T;
double dt;
int h[N],e[N*2],D[N*2],ne[N*2],idx;
double w[N],v[N],u[N],a[N],b[N],c[N],d[N];
int r[N],cnt[N];
double I[1024][N/2];

void Add(int a,int b,double c,int d)
{
    e[idx] = b;
    w[idx] = c;
    D[idx] = d;
    ne[idx] = h[a];
    h[a] = idx++;
}//采用邻接表存储,在存储连接关系时也要额外存储突触的两个性质

int main()
{
    memset(h,-1,sizeof h);
    scanf("%d%d%d%d",&n,&S,&P,&T);
    scanf("%lf",&dt);
    for(int i = 0;i < n;)
    {
        int rn;
        scanf("%d",&rn);
        double vv,uu,aa,bb,cc,dd;
        scanf("%lf%lf%lf%lf%lf%lf",&vv,&uu,&aa,&bb,&cc,&dd);
        for(int j = 0;j < rn;j++,i++)
        {
            v[i] = vv;u[i] = uu;a[i] = aa;b[i] = bb;c[i] = cc;d[i] = dd;
        }
    }//读入神经元相关数据
    for(int i = n;i < n+P;i++)
    {
        scanf("%d",&r[i]);
    }//读入脉冲源相关数据
    int mod = 0;//mod的目的是找到最大的时间跨度,存储空间不够,只能开成循环数组了
    for(int i = 0;i < S;i++)
    {
        int a0,b0,d0;
        double c0;
        scanf("%d%d%lf%d",&a0,&b0,&c0,&d0);
        mod = max(mod,d0+1);
        Add(a0,b0,c0,d0);//对有向图进行初始化
    }
    for(int i = 0;i < T;i++)
    {
        int t = i % mod;
        for(int j = n;j < n+P;j++)
        {
            if(r[j] > myrand())
            {
                for(int k = h[j]; k != -1;k = ne[k])
                {
                    int x = e[k];
                    I[(t+D[k])%mod][x] += w[k];
                }
            }//发射脉冲
        }
        for(int j = 0;j < n;j++)
        {
            double vv = v[j],uu = u[j];
            v[j] = vv+dt*(0.04*vv*vv+5*vv+140-uu)+I[t][j];
            u[j] = uu+dt*a[j]*(b[j]*vv-uu);
            if(v[j] >= 30)
            {
                for(int k = h[j]; k != -1;k = ne[k])
                {
                    int x = e[k];
                    I[(t+D[k])%mod][x] += w[k];
                }
                cnt[j]++;
                v[j] = c[j];
                u[j] = u[j]+d[j];
            }
        }
        memset(I[t],0,sizeof I[t]);
    }
    double minv = INF,maxv = -INF;
    int minc = INF,maxc = -INF;
    for(int i = 0;i < n;i++)
    {
        minv = min(minv,v[i]);
        maxv = max(maxv,v[i]);
        minc = min(minc,cnt[i]);
        maxc = max(maxc,cnt[i]);
    }
    printf("%.3f %.3f\n",minv,maxv);
    printf("%d %d",minc,maxc);
    return 0;

}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值