Neural modeling of an internal clock (Yamazaki and Tanaka 2008)

 Download zip file 
Help downloading and running models
Accession:115966
"We studied a simple random recurrent inhibitory network. Despite its simplicity, the dynamics was so rich that activity patterns of neurons evolved with time without recurrence due to random recurrent connections among neurons. The sequence of activity patterns was generated by the trigger of an external signal, and the generation was stable against noise.... Therefore, a time passage from the trigger of an external signal could be represented by the sequence of activity patterns, suggesting that this model could work as an internal clock. ..."
Reference:
1 . Yamazaki T, Tanaka S (2005) Neural modeling of an internal clock. Neural Comput 17:1032-58 [PubMed]
Citations  Citation Browser
Model Information (Click on a link to find other models with that property)
Model Type: Realistic Network;
Brain Region(s)/Organism: Cerebellum;
Cell Type(s):
Channel(s):
Gap Junctions:
Receptor(s):
Gene(s):
Transmitter(s):
Simulation Environment: C or C++ program;
Model Concept(s): Temporal Pattern Generation; Spatio-temporal Activity Patterns; Rate-coding model neurons;
Implementer(s):
//
// Simulation program
//

#include<stdio.h>
#include<stdlib.h>
#include<math.h>

// Parameters (p.1034)
#define N 1000			// # of neurons
#define T 1000			// # of time steps
#define Pr 0.1			// connection probability
#define tau 100.0		// temporal integration constant
#define kappa 5.0		// strength of recurrent inhibition
#define I 1.0			// strength of input signals

#define wid(i,j) ((j)+N*(i))
#define zid(t,i) ((i)+N*(t))

extern void init_genrand(unsigned long);
extern double genrand_real2(void);

// This function takes a seed for the random number generator and
// returns the random matrix w_{ij} (Eq.(2.1) in p.1033).
// The matrix is the size of N*N, and the i th row represents the list
// of indices for presynaptic neurons of neuron i.  The connection
// probability is Pr.
// Each row terminates with -1 so that the program can know
// the end of the list.
int *random_matrix_index(const unsigned long seed)
{
  int i, j, n;
  int *w;

  init_genrand(seed);

  w = (int *)malloc(N*N*sizeof(int));
  for(i = 0; i < N; i++){
    n = 0;
    for(j = 0; j < N; j++){
      if (genrand_real2() < Pr){
	w[wid(i,n)] = j;
	n++;
      }
    }
    w[wid(i,n)] = -1;
  }
  return w;
}

// This function returns the T*N vector of neural activity z(t,i) (p. 1033).
// The vector is accessed as a T*N matrix through the function zid(t,i).
double *activity_pattern(void)
{
  int t, i;
  double *z;

  z = (double *)malloc(T*N*sizeof(double));
  for(t = 0; t < T; t++){
    for(i = 0; i < N; i++){
      z[zid(t,i)] = 0;
    }
  }
  return z;
}

// This function takes the neural activity z(t,i) and the value of the
// inter-stimulus interval (ISI) for eyeblink conditioning, and
// generate 3 files: activity.dat, raster.dat, and readout.dat.
void output(const double *z, const int isi)
{
  FILE *file;
  int t, i;
  char buf[1024];
  double r, w[N];

  // "activity.dat" contains neural activity z(t,i), which is used
  // to calculate the similarity index (Eq. (2.2))
  file = fopen("activity.dat", "w");
  for(t = 0; t < T; t++){
    for(i = 0; i < N; i++){
      fprintf(file, "%f\n", z[zid(t,i)]);
    }
  }
  fclose(file);

  // "raster.dat" represents the indices of active neurons (z(t,i)>0).
  // This is a list of pairs of firing time t and neuron index i.
  sprintf(buf, "raster.dat");
  file = fopen(buf, "w");
  for(t = 0; t < T; t++){
    for(i = 0; i < N; i++){
      if (z[zid(t,i)] > 0){
	fprintf(file, "%d %d\n", t, i);
      }
    }
  }
  fclose(file);

  // "readout.dat" represents Net input(t) in p. 1048.
  sprintf(buf, "readout.dat");
  file = fopen(buf, "w");
  // Synaptic weight for neuron i is set at 0 if the neuron is active
  // at the specified ISI; otherwise the weight is 1.
  for(i = 0; i < N; i++){
    if (z[zid(isi,i)] > 0){
      w[i] = 0;
    }else{
      w[i] = 1;
    }
  }
  // Plot the net input
  for(t = 0; t < T; t++){
    r = 0;
    for(i = 0; i < N; i++){
      r += w[i]*z[zid(t,i)];
    }
    fprintf(file, "%d %f\n", t, r);
  }
  fclose(file);
}

// This function takes the random matrix w and the empty array of
// the neural activity z, and fill the array z.
void run(const int *w, double *z)
{
  int t, i, n;
  double u[N], q[N];
  double r;

  const double decay = exp(-1.0/tau);
  const double coef = 2.0*kappa/N;

  for(i = 0; i < N; i++){
    q[i] = 0;
  }

  // Iterative calculation of Eq. (2.1)
  for(t = 1; t < T; t++){
    for(i = 0; i < N; i++){
      q[i] = z[zid(t-1,i)] + decay*q[i];
    }
    for(i = 0; i < N; i++){
      r = 0;
      // the list of presynaptic neurons is terminated with -1.
      for(n = 0; w[wid(i,n)] >= 0; n++){
	r += coef*q[w[wid(i,n)]];
      }	
      u[i] = I - r;
    }
    for(i = 0; i < N; i++){
      z[zid(t,i)] = (u[i] > 0) ? u[i] : 0;
    }
  }
}

int main(int argc, char *argv[])
{
  double *z;
  int *w, isi;

  if (argc < 3){
    fprintf(stderr, "usage: %s <seed> <isi>\n", argv[0]);
    exit(1);
  }

  w = random_matrix_index(atol(argv[1]));
  z = activity_pattern();
  isi = atol(argv[2]);

  run(w, z);
  output(z, isi);

  free(w);
  free(z);

  return 0;
}