// poly_spnet.cpp // This source code was downloaded from the authors website: https://www.izhikevich.org/publications/spnet.htm // Modifications are marked with --GT, ++GT // #include // --GT #include // ++GT #include #include #include #include #include using namespace std; // ++GT #define rand01 (0.9999999*double(rand())/RAND_MAX) #define getrandom(max1) (((rand())%(max1))) // random integer between 0 and max-1 //There are two implementations of polychronous group search algorithm here. // The old one is event-trigered (very fast). // The new one is activity-trigered (slow, but more precise). // By default, the new definition is used. Uncomment the line below to use the old one. //#define old_definition_of_polychronous //M=100; % the number of synapses per neuron const int M = 100; //D=10; % maximal axonal conduction delay const int D=20; //% excitatory neurons inhibitory neurons total number //Ne=800; Ni=200; N=Ne+Ni; const int Ne =800; const int Ni =200; const int N = Ne+Ni; double C_max=10; #if( ODE_SOLVER_REFINEMENT ) // ++GT (precise threshold detection) int spike[N]; // spike count in simulation step #endif const int W=3; // initial width of polychronous groups int min_group_path = 7; // minimal length of a group int min_group_time = 40; // minimal duration of a group (ms) double a[N], d[N]; // int post[N][M]; // double s[N][M], sd[N][M]; // short delays[N][D][M]; // short delays_length[N][D]; // int N_pre[N], I_pre[N][3*M], D_pre[N][3*M]; // double *s_pre[N][3*M], *sd_pre[N][3*M]; double LTP[N][1001+D], LTD[N]; // double v[N], u[N]; // int N_firings; const int N_firings_max=100000; int firings[N_firings_max][2]; void initialize() { int i,j,k,jj,dd, exists, r; // a=[0.02*ones(Ne,1); 0.1*ones(Ni,1)]; for (i=0;i0); % Indeces of pre excitatory neurons // aux{i} = N*(D-1-ceil(ceil(pre{i}/N)/(M/D))) + 1+mod(pre{i}-1,N); for (i=0;i C_rel) { I_my_pre[N_my_pre]=I_pre[nnum][i]; D_my_pre[N_my_pre]=D_pre[nnum][i]; N_my_pre++; } if (N_my_pre C_rel) & (d>=D_my_pre[npre[i]])) | (p >=Ne)) { timing = t_fired[i]+d+1; J_postspikes[timing][N_postspikes[timing]]=group[i]; // presynaptic D_postspikes[timing][N_postspikes[timing]]=d; // delay L_postspikes[timing][N_postspikes[timing]]=1; // layer I_postspikes[timing][N_postspikes[timing]++]=p;// index of post target } } } N_inh_list=0; NL_max = 1; N_links = 0; N_fired=W; t_last = D+D+latency+1; for (t=0;t0) { N_postspikes[t]--; already = 0; if (I_postspikes[t][N_postspikes[t]] t-20)) already = 2; for (j=0;j=t)) already++; } else { for (j=0;j t-20)) already = 2; } if ((already<=0) & (N_fired < polylenmax)) { NL = 0; exc=0; first = -1; t_fire = t+4; for (tf=0;tf<=tf_final;tf++) for (j=0;j<=N_postspikes[t+tf]-0.5*tf;j++) if (I_postspikes[t+tf][j]==I_postspikes[t][N_postspikes[t]]) { if (first < 0) first = tf; last = tf; pre_list[exc]=J_postspikes[t+tf][j]; del_list[exc]=D_postspikes[t+tf][j]; exc++; t_fire = t+tf; if (NL =last) & (exc>=V-slacke)) | (((I_postspikes[t][N_postspikes[t]]=V)) | ((I_postspikes[t][N_postspikes[t]]>=Ne)&(first+2>=last)&(exc>=V-slacki)))) { i = N_fired++; group[i]= I_postspikes[t][N_postspikes[t]]; t_fired[i]= t_fire+latency; if (exc==2) t_fired[i]=t_fired[i]+latency; // longer latencies for weaker inputs for (j=0;j C_rel) { timing = t_fired[i]+d+1; J_postspikes[timing][N_postspikes[timing]]=group[i]; // presynaptic D_postspikes[timing][N_postspikes[timing]]=d; // delay L_postspikes[timing][N_postspikes[timing]]=NL+1; // layer I_postspikes[timing][N_postspikes[timing]++]=post[group[i]][delays[group[i]][d][j]];// index of post target } } else { for (d=0; d10) // needs cleaning { for (k=j;k NL_max) NL_max = NL; if (t_last < timing+1) { t_last = timing+1; if (t_last > polylenmax-D-latency-tf_final-1) t_last = polylenmax-D-latency-tf_final-1; } } } } if (t_last == polylenmax-D) for (d=t_last;d=min_group_path)) { discard = 0; for (i=0;i N_my_pre-i) if (++i > W) return; while (i>1) {npre[W-i+1]=npre[W-i]+1; i--;} } } #else // The new (default) algorithm to find polychronous groups const int latency = D; // maximum latency //-------------------------------------------------------------- void polychronous(int nnum) { int i,j, t, p, k; int npre[W]; int dd; int t_last, timing; int Dmax, L_max; int used[W], discard; double v[N],u[N],I[N]; #if( ODE_SOLVER_REFINEMENT ) // ++GT printf("\nFIND POLYCHRONOUS GROUPS: nnum = %d\n", nnum); for( int i = 0; i < N; ++i) spike[i] = 0; #endif N_my_pre = 0; for (i=0;i C_rel) { I_my_pre[N_my_pre]=I_pre[nnum][i]; D_my_pre[N_my_pre]=D_pre[nnum][i]; N_my_pre++; } if (N_my_pre C_rel) & (dd>=D_my_pre[npre[i]])) { timing = t_fired[i]+dd+1; J_postspikes[timing][N_postspikes[timing]]=group[i]; // presynaptic D_postspikes[timing][N_postspikes[timing]]=dd; // delay C_postspikes[timing][N_postspikes[timing]]=s[group[i]][delays[group[i]][dd][j]]; // syn weight I_postspikes[timing][N_postspikes[timing]++]=p; // index of post target } } } for (i=0;i= 30.0) { // precise threshold detection v[i] = -65.0; u[i] += d[i]; spike[i]++; } } I[i]=0; } #else for (i=0;i0) { if(spike[i]>1) printf("FIND POLYCHRONOUS GROUPS: more than one spike\n"); spike[i]=0; #else if (v[i]>=30) { v[i] = -65; u[i]+=d[i]; #endif if (N_fired < polylenmax) { t_fired[N_fired]= t; group[N_fired++]=i; for (dd=0; dd C_rel) | (i>=Ne)) { timing = t+dd+1; J_postspikes[timing][N_postspikes[timing]]=i; // presynaptic D_postspikes[timing][N_postspikes[timing]]=dd; // delay // L_postspikes[timing][N_postspikes[timing]]=NL+1; // layer C_postspikes[timing][N_postspikes[timing]]=s[i][delays[i][dd][j]]; // syn weight I_postspikes[timing][N_postspikes[timing]++]=post[i][delays[i][dd][j]];// index of post target } if (t_last < timing+1) { t_last = timing+1; if (t_last > polylenmax-D-1) t_last = polylenmax-D-1; } } } } if (N_fired>2*W) { N_links=0; L_max=0; for (i=W;it_fired[i]-latency) & (p>=0); p--) for (j=0;jlayer[i])) layer[i]=layer[k]+1; { links[N_links][0]=J_postspikes[p][j]; links[N_links][1]=I_postspikes[p][j]; links[N_links][2]=D_postspikes[p][j]; links[N_links++][3]=layer[i]; if (L_max < layer[i]) L_max = layer[i]; } } } discard = 0; for (i=0;i min_group_time) ) // (L_max >= min_group_path)) if ((discard == 0) & (L_max >= min_group_path)) { for (i=0;i N_my_pre-i) if (++i > W) return; while (i>1) {npre[W-i+1]=npre[W-i]+1; i--;} } } #endif //-------------------------------------------------------------- void all_polychronous() { int i; N_polychronous=0; fpoly = fopen("..//polyall.dat","w"); for (i=0;i= Ne); x=s[ri][rj]; y=sd[ri][rj]; s[i][j]=s[ri][rj]; sd[i][j]=sd[ri][rj]; s[ri][rj]=x; sd[ri][rj]=y; } } // -------------------------------------------------------------------------- // void main() // --GT int main() // ++GT { int i,j,k; int sec, t; double I[N]; FILE *fs, *fx, *fd; #if( ODE_SOLVER_REFINEMENT ) // ++GT for( int i = 0; i < N; ++i ) { spike[i] = 0; } #endif srand(0); initialize(); // for sec=1:60*60*5 // for (sec=0; sec<60*60*5; sec++) // --GT for (sec=0; sec<60*60*1; sec++) // ++GT (set to 1 hour: determine the number of polychronous groups with // the refined ODE solver ) { // for t=1:1000 % simulation of 1 sec for (t=0;t<1000;t++) { for (i=0;i0) { if(spike[i] > 1 ) printf("more than 1 spike in interval\n"); spike[i] = 0; LTP[i][t+D] = 0.1; LTD[i] = 0.12; for (j = 0; j=30); % indices of fired neurons if (v[i]>=30) { // v(fired)=-65; v[i] = -65; // u(fired)=u(fired)+d(fired); u[i]+=d[i]; // LTP(fired,t+D)=0.1; LTP[i][t+D]= 0.1; // LTD(fired)=0.12; LTD[i]=0.12; // for k=1:length(fired) // sd(pre{fired(k)}) = sd(pre{fired(k)})+LTP(N*t+aux{fired(k)}); // end; for (j=0;j= 30.0 ) { v[i] = -65.0; u[i] += d[i]; spike[i]++; } } #else v[i]+=0.5*((0.04*v[i]+5)*v[i]+140-u[i]+I[i]); v[i]+=0.5*((0.04*v[i]+5)*v[i]+140-u[i]+I[i]); // u = u + a.*(0.2*v-u); u[i]+=a[i]*(0.2*v[i]-u[i]); #endif // LTP(:,t+D+1)=0.95*LTP(:,t+D); % tau = 20 ms LTP[i][t+D+1]=0.95*LTP[i][t+D]; // LTD=0.95*LTD; % tau = 20 ms LTD[i]*=0.95; } // end; } // frate(end+1)=sum(firings(:,2)<=Ne)/Ne; double frate=0; for (i=1;i=0) && (firings[i][1] 6.3))/Ne; double str=0; for (i=0;i 0.9*C_max) && (post[i][j] Ne)/Ni] double ifrate=0; for (i=1;i=0) && (firings[i][1] >=Ne)) ifrate++; ifrate = ifrate/Ni; cout << "sec=" << sec << ", exc. frate=" << frate << ", exc->exc str=" << str << ", inh. frate=" << ifrate << ".\n"; fx = fopen("..//dat.dat","a"); fprintf(fx, "%d %2.2f %2.2f %2.2f\n", sec, frate, str, ifrate); fclose(fx); // plot(firings(:,1),firings(:,2),'.'); // axis([0 1000 0 N]); drawnow; #if(0) // --GT fs = fopen("..//spikest.dat","w"); for (i=1;i=0) fprintf(fs, "%d %d\n", sec*000+firings[i][0], firings[i][1]); fclose(fs); remove("..//spikes.dat"); rename( "..//spikest.dat", "..//spikes.dat" ); #endif #if(1) // ++GT (record spike times in same format as in the refactored version) FILE* pFile = fopen( "origImpl_firings.dat","a+" ); // skip negative times int idx = 0; while( firings[idx][0] < 0 ) { idx++; } for( ; idx < N_firings; ++idx ) { fprintf( pFile, "%06d %03d %03d\n", sec, firings[idx][0], firings[idx][1]); } fclose(pFile); #endif // LTP(:,1:D+1)=LTP(:,1001:1001+D); for (i=0;iC_max) s[i][j]=C_max; if (s[i][j]<0) s[i][j]=0; } // if mod(sec,10)==0, // save all; // end; if ( (sec%100==0) & (sec > 0)) { save_all("..//all.dat"); fs = fopen("..//s.dat", "w"); for (i=0; i