sPyNNaker neural_modelling  development
connection_generator_fixed_pre.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017 The University of Manchester
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * https://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
24 #include <log.h>
25 #include <synapse_expander/rng.h>
26 #include <stdbool.h>
27 
30  uint32_t allow_self_connections;
31  uint32_t with_replacement;
32  uint32_t n_pre;
33 };
34 
38 struct fixed_pre {
39  struct fixed_pre_params params;
40 };
41 
49 static uint32_t pre_random_in_range(rng_t *rng, uint32_t range) {
50  uint32_t u01 = rng_generator(rng) & 0x00007fff;
51  return (u01 * range) >> 15;
52 }
53 
61  // Allocate memory for the parameters
62  struct fixed_pre *obj = spin1_malloc(sizeof(struct fixed_pre));
63 
64  // Copy the parameters in
65  struct fixed_pre_params *params_sdram = *region;
66  obj->params = *params_sdram;
67  *region = &params_sdram[1];
68 
69  log_debug("Fixed Number Pre Connector parameters: "
70  "allow self connections = %u, "
71  "with replacement = %u, n_pre = %u",
72  obj->params.allow_self_connections,
73  obj->params.with_replacement, obj->params.n_pre);
74 
75  return obj;
76 }
77 
82 void connection_generator_fixed_pre_free(void *generator) {
83  sark_free(generator);
84 }
85 
106  void *generator, uint32_t pre_lo, uint32_t pre_hi,
107  uint32_t post_lo, uint32_t post_hi, UNUSED uint32_t post_index,
108  uint32_t post_slice_start, uint32_t post_slice_count,
109  unsigned long accum weight_scale, accum timestep_per_delay,
110  param_generator_t weight_generator, param_generator_t delay_generator,
111  matrix_generator_t matrix_generator) {
112  // Get the actual ranges to generate within
113  uint32_t post_start = max(post_slice_start, post_lo);
114  uint32_t post_end = min(post_slice_start + post_slice_count - 1, post_hi);
115 
116  struct fixed_pre *obj = generator;
117  // Get how many values can be sampled from
118  uint32_t n_values = pre_hi - pre_lo + 1;
119  // Get the number of connections in each column
120  uint32_t n_conns = obj->params.n_pre;
121 
122  // We have to generate everything for each column, then just take our share,
123  // so we use the population_rng here to ensure all cores do the same thing
124  for (uint32_t post = post_start; post <= post_end; post++) {
125  uint32_t local_post = post - post_slice_start;
126  if (obj->params.with_replacement) {
127  // If with replacement just repeated pick
128  for (uint32_t j = 0; j < n_conns; j++) {
129  accum weight = param_generator_generate(weight_generator);
130  uint16_t delay = rescale_delay(
131  param_generator_generate(delay_generator), timestep_per_delay);
132  uint32_t pre;
133  bool written = false;
134  uint32_t n_retries = 0;
135  do {
136  pre = pre_random_in_range(core_rng, n_values) + pre_lo;
137  if (obj->params.allow_self_connections || pre != post) {
139  matrix_generator, pre, local_post, weight, delay,
140  weight_scale);
141  n_retries++;
142  }
143  } while (!written && n_retries < 10);
144  if (!written) {
145  log_error("Couldn't find a row to write to!");
146  return false;
147  }
148  }
149  } else {
150  // Without replacement uses reservoir sampling to save space
151  uint16_t values[n_conns];
152  uint32_t replace_start = n_conns;
153  for (uint32_t j = 0; j < n_conns; j++) {
154  if (j == post && !obj->params.allow_self_connections) {
155  values[j] = n_conns;
156  replace_start = n_conns + 1;
157  } else {
158  values[j] = j + pre_lo;
159  }
160  }
161  for (uint32_t j = replace_start; j < n_values; j++) {
162  // r = random(0, j) (inclusive); swap j into array if r
163  // is in range
164  if (j != post || obj->params.allow_self_connections) {
165  uint32_t r = pre_random_in_range(core_rng, j + 1);
166  if (r < n_conns) {
167  values[r] = j + pre_lo;
168  }
169  }
170  }
171  for (uint32_t j = 0; j < n_conns; j++) {
172  accum weight = param_generator_generate(weight_generator);
173  uint16_t delay = rescale_delay(
174  param_generator_generate(delay_generator), timestep_per_delay);
175  // Not a lot we can do here!
177  local_post, weight, delay, weight_scale)) {
178  log_warning("Could not write to matrix!");
179  }
180  }
181  }
182  }
183  return true;
184 }
static void * connection_generator_fixed_pre_initialise(void **region)
Initialise the fixed-pre connection generator.
bool connection_generator_fixed_pre_generate(void *generator, uint32_t pre_lo, uint32_t pre_hi, uint32_t post_lo, uint32_t post_hi, uint32_t post_index, uint32_t post_slice_start, uint32_t post_slice_count, unsigned long accum weight_scale, accum timestep_per_delay, param_generator_t weight_generator, param_generator_t delay_generator, matrix_generator_t matrix_generator)
Generate connections with the fixed-pre connection generator.
static uint32_t pre_random_in_range(rng_t *rng, uint32_t range)
Generates a uniformly-distributed random number.
void connection_generator_fixed_pre_free(void *generator)
Free the fixed-pre connection generator.
The data to be passed around.
The parameters that can be copied from SDRAM.
static uint16_t rescale_delay(accum delay, accum timestep_per_delay)
Rescales a delay to account for timesteps and type-converts it.
bool matrix_generator_write_synapse(matrix_generator_t generator, uint32_t pre_index, uint16_t post_index, accum weight, uint16_t delay, unsigned long accum weight_scale)
Write a synapse with a matrix generator.
The data for a matrix generator.
rng_t * core_rng
An RNG that is local to the current core.
accum param_generator_generate(param_generator_t generator)
Generate value with a parameter generator.
uint32_t rng_generator(rng_t *rng)
Generate a uniformly-distributed random number.
Definition: rng.c:26
Random number generator interface.
The Random number generator parameters.
Definition: rng.h:30
region
spike source array region IDs in human readable form
static uint32_t rng(void)
Random number generation for the Poisson sources. This is a local version for speed of operation.
static stdp_params params
Configuration parameters.