sPyNNaker neural_modelling  7.4.2
connection_generator_fixed_post.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 
32  uint32_t with_replacement;
34  uint32_t n_post;
35 };
36 
42 struct fixed_post {
45 };
46 
54  // Allocate memory for the parameters
55  struct fixed_post *obj = spin1_malloc(sizeof(struct fixed_post));
56 
57  // Copy the parameters in
58  struct fixed_post_params *params_sdram = *region;
59  obj->params = *params_sdram;
60  *region = &params_sdram[1];
61 
62  log_debug("Fixed Number Post Connector, allow self connections = %u, "
63  "with replacement = %u, n_post = %u",
66  return obj;
67 }
68 
73 static void connection_generator_fixed_post_free(void *generator) {
74  sark_free(generator);
75 }
76 
84 static uint32_t post_random_in_range(rng_t *rng, uint32_t range) {
85  uint32_t u01 = rng_generator(rng) & 0x00007fff;
86  return (u01 * range) >> 15;
87 }
88 
89 static bool fixed_post_write(uint32_t pre, uint32_t post, accum weight_scale,
90  accum timestep_per_delay, param_generator_t weight_generator,
91  param_generator_t delay_generator, matrix_generator_t matrix_generator) {
92  accum weight = param_generator_generate(weight_generator);
93  uint16_t delay = rescale_delay(
94  param_generator_generate(delay_generator), timestep_per_delay);
96  matrix_generator, pre, post, weight, delay, weight_scale);
97 }
98 
119  void *generator, uint32_t pre_lo, uint32_t pre_hi,
120  uint32_t post_lo, uint32_t post_hi, UNUSED uint32_t post_index,
121  uint32_t post_slice_start, uint32_t post_slice_count,
122  unsigned long accum weight_scale, accum timestep_per_delay,
123  param_generator_t weight_generator, param_generator_t delay_generator,
124  matrix_generator_t matrix_generator) {
125 
126  // Get the actual ranges to generate within
127  uint32_t post_slice_end = post_slice_start + post_slice_count;
128 
129  struct fixed_post *obj = generator;
130  // Get how many values can be sampled from
131  uint32_t n_values = post_hi - post_lo + 1;
132  // Get the number of connections on each row
133  uint32_t n_conns = obj->params.n_post;
134 
135  // We have to generate everything for each row, then just take our share,
136  // so we use the population_rng here to ensure all cores do the same thing
137  for (uint32_t pre = pre_lo; pre <= pre_hi; pre++) {
138  if (obj->params.with_replacement) {
139  // If with replacement just repeated pick
140  for (uint32_t j = 0; j < n_conns; j++) {
141  uint32_t post;
142  do {
143  post = post_random_in_range(population_rng, n_values) + post_lo;
144  } while (!obj->params.allow_self_connections && post == pre);
145  // We can only use post neurons in range here
146  if (post >= post_slice_start && post < post_slice_end) {
147  post -= post_slice_start;
148  if (!fixed_post_write(pre, post, weight_scale, timestep_per_delay,
149  weight_generator, delay_generator, matrix_generator)) {
150  log_error("Matrix not sized correctly!");
151  return false;
152  }
153  }
154  }
155  } else {
156  // Without replacement uses reservoir sampling to save space
157  uint16_t values[n_conns];
158  uint32_t replace_start = n_conns;
159  for (uint32_t j = 0; j < n_conns; j++) {
160  if (j == pre && !obj->params.allow_self_connections) {
161  values[j] = n_conns;
162  replace_start = n_conns + 1;
163  } else {
164  values[j] = j + post_lo;
165  }
166  }
167  for (uint32_t j = replace_start; j < n_values; j++) {
168  // r = random(0, j) (inclusive); swap j into array if r
169  // is in range
170  if (j != pre || obj->params.allow_self_connections) {
171  uint32_t r = post_random_in_range(population_rng, j + 1);
172  if (r < n_conns) {
173  values[r] = j + post_lo;
174  }
175  }
176  }
177  for (uint32_t j = 0; j < n_conns; j++) {
178  if (values[j] >= post_slice_start && values[j] < post_slice_end) {
179  uint32_t post = values[j] - post_slice_start;
180  if (!fixed_post_write(pre, post, weight_scale, timestep_per_delay,
181  weight_generator, delay_generator, matrix_generator)) {
182  log_error("Matrix not sized correctly!");
183  return false;
184  }
185  }
186  }
187  }
188  }
189  return true;
190 }
static uint32_t post_random_in_range(rng_t *rng, uint32_t range)
Generates a uniformly-distributed random number.
static bool connection_generator_fixed_post_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-post connection generator.
struct fixed_post_params params
Parameters read from SDRAM.
uint32_t allow_self_connections
Do we allow self connections?
static void * connection_generator_fixed_post_initialise(void **region)
Initialise the fixed-post connection generator.
uint32_t with_replacement
Do we allow any neuron to be multiply connected by this connector?
static void connection_generator_fixed_post_free(void *generator)
Free the fixed-post connection generator.
uint32_t n_post
Number of connections per pre-neuron in total.
The state of this connection generator.
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 * population_rng
An RNG that starts in the same place on every core of the Population.
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.