def rng(self) -> tuple: """Gathers all random variables. Returns: declared_rng, initialize_rng, rng_method """ declared_rng = """ // Random variables""" initialize_rng = """ // Random Variables""" rng_tpl = Template(""" $init for(unsigned int i = 0; i < this->size; i++) { $draw } """) rng_init = "" rng_update = "" for name, var in self.parser.random_variables.items(): if isinstance(var, parser.RandomDistributions.Uniform): dist = "uniform_real_distribution< double >" # If the arguments are fixed throughout the simulation, no need to redraw fixed = isinstance(var.min, (float, int)) and isinstance( var.max, (float, int)) arg1 = parser.code_generation(var.min, self.correspondences) arg2 = parser.code_generation(var.max, self.correspondences) if isinstance(var, parser.RandomDistributions.Normal): dist = "normal_distribution< double >" # If the arguments are fixed throughout the simulation, no need to redraw fixed = isinstance(var.mu, (float, int)) and isinstance( var.sigma, (float, int)) arg1 = parser.code_generation(var.mu, self.correspondences) arg2 = parser.code_generation(var.sigma, self.correspondences) declared_rng += Template(""" std::vector<double> $name; std::$dist dist$name; """).substitute(name=name, dist=dist) initialize_rng += Template(""" this->$name = std::vector<double>(size, 0.0); this->dist$name = std::$dist($arg1, $arg2); """).substitute(name=name, dist=dist, arg1=arg1, arg2=arg2) if not fixed: rng_init += Template(""" this->dist$name = std::$dist($arg1, $arg2); """).substitute(name=name, dist=dist, arg1=arg1, arg2=arg2) rng_update += Template(""" this->$name[i] = this->dist$name(this->net->rng); """).substitute(name=name, dist=dist) rng_method = rng_tpl.substitute(init=rng_init, draw=rng_update) return declared_rng, initialize_rng, rng_method
def reset(self) -> str: """Processes the Neuron.reset() field. Returns: the content of the `reset()` C++ method. """ tpl_reset = Template(""" for(unsigned int idx = 0; idx< this->spikes.size(); idx++){ int i = this->spikes[idx]; $reset } """) # Equation template tpl_eq = Template(""" // $hr $lhs $op $rhs; """) # Iterate over all blocks of equations code = "" for block in self.parser.reset_equations: for eq in block.equations: code += tpl_eq.substitute( lhs="this->" + eq['name'] if eq['name'] in self.parser.shared else "this->" + eq['name'] + "[i]", op=eq['op'], rhs=parser.code_generation(eq['rhs'], self.correspondences), hr=eq['human-readable']) return tpl_reset.substitute(reset=code)
def update(self) -> str: """Processes the Neuron.update() field. Returns: the content of the `update()` C++ method. """ # Block template tlp_block = Template(""" for(unsigned int i = 0; i< this->size; i++){ $update } """) # Equation template tpl_eq = Template(""" // $hr $lhs $op $rhs; """) # Iterate over all blocks of equations code = "" for block in self.parser.update_equations: for eq in block.equations: # Temporary variables if eq['type'] == 'tmp': code += tpl_eq.substitute(lhs="double " + eq['name'], op=eq['op'], rhs=parser.code_generation( eq['rhs'], self.correspondences), hr=eq['human-readable']) else: code += tpl_eq.substitute( lhs="this->" + eq['name'] if eq['name'] in self.parser.shared else "this->" + eq['name'] + "[i]", op=eq['op'], rhs=parser.code_generation(eq['rhs'], self.correspondences), hr=eq['human-readable']) return tlp_block.substitute(update=code)
def spike(self) -> str: """Processes the Neuron.spike() field. Returns: the content of the `spike()` C++ method. """ tpl_spike = Template(""" this->spikes.clear(); for(unsigned int i = 0; i< this->size; i++){ if ($condition){ this->spikes.push_back(i); } } """) cond = parser.code_generation( self.parser.spike_condition.equation['eq'], self.correspondences) return tpl_spike.substitute(condition=cond)