sPyNNaker neural_modelling 7.3.1
Loading...
Searching...
No Matches
connection_generator_fixed_total.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
22#include <log.h>
25
28 // Whether to connect to self or not
29 uint32_t allow_self_connections;
30 // Whether to repeat connections or not
31 uint32_t with_replacement;
32 // The number of synapses to generate in total over all cores
33 uint32_t n_synapses_total;
34};
35
43
44 // This is how many connections there are to make per core
45 uint16_t *n_connections_per_core;
46};
47
48/*static inline uint32_t _pick(rng_t *rng, uint32_t K, uint32_t not_K) {
49 return (uint32_t) (ulrbits(rng_generator(rng)) * (K + not_K));
50}*/
51
60/*static uint32_t binomial(uint32_t n, uint32_t N, uint32_t K, rng_t *rng) {
61 uint32_t count = 0;
62 uint32_t not_K = N - K;
63 for (uint32_t i = 0; i < n; i++) {
64 if (_pick(rng, K, not_K) < K) {
65 count++;
66 }
67 }
68 return count;
69}*/
70
79/*static uint32_t hypergeom(uint32_t n, uint32_t N, uint32_t K, rng_t *rng) {
80 uint32_t count = 0;
81 uint32_t K_remaining = K;
82 uint32_t not_K_remaining = N - K;
83 for (uint32_t i = 0; i < n; i++) {
84 if (_pick(rng, K_remaining, not_K_remaining) < K_remaining) {
85 count++;
86 K_remaining--;
87 } else {
88 not_K_remaining--;
89 }
90 }
91 return count;
92} */
93
101 // Allocate memory for the parameters
102 struct fixed_total *obj = spin1_malloc(sizeof(struct fixed_total));
103
104 // Copy the parameters in
105 struct fixed_total_params *params_sdram = *region;
106 obj->params = *params_sdram;
107 *region = &params_sdram[1];
108
109 log_debug("Fixed Total Number Connector, allow self connections = %u, "
110 "with replacement = %u, n_synapses_total = %u",
111 obj->params.allow_self_connections,
112 obj->params.with_replacement, obj->params.n_synapses_total);
113
114 // Go through every core and use the population-level RNG to generate
115 // the number of synapses on every core with a binomial.
116 /*obj->n_connections_per_core = spin1_malloc(obj->params.n_cores * sizeof(uint16_t));
117 uint32_t n_to_go = obj->params.n_synapses_total;
118 uint32_t synapses_to_go = obj->params.max_synapses_total;
119 for (uint32_t i = 0; i < obj->params.n_cores; i++) {
120 if (i + 1 == obj->params.n_cores) {
121 // Last core gets the treat
122 obj->n_connections_per_core[i] = n_to_go;
123 } else {
124 // Do a binomial for this core
125 uint32_t n_conns = binomial(n_to_go, synapses_to_go,
126 obj->params.max_synapses_per_core, population_rng);
127 obj->n_connections_per_core[i] = n_conns;
128 n_to_go -= n_conns;
129 synapses_to_go -= obj->params.max_synapses_per_core;
130 }
131 } */
132
133 return obj;
134}
135
140static void connection_generator_fixed_total_free(void *generator) {
141 sark_free(generator);
142}
143
144static uint32_t random_in_range(rng_t *rng, uint32_t range) {
145 unsigned long fract u01 = ulrbits(rng_generator(rng));
146 return muliulr(range, u01);
147}
148
149static void fixed_total_next(uint32_t *pre, uint32_t *post, uint32_t pre_lo, uint32_t pre_hi) {
150 *pre += 1;
151 if (*pre > pre_hi) {
152 *pre = pre_lo;
153 *post += 1;
154 }
155}
156
157
178 void *generator, uint32_t pre_lo, uint32_t pre_hi,
179 uint32_t post_lo, uint32_t post_hi, UNUSED uint32_t post_index,
180 uint32_t post_slice_start, uint32_t post_slice_count,
181 unsigned long accum weight_scale, accum timestep_per_delay,
182 param_generator_t weight_generator, param_generator_t delay_generator,
183 matrix_generator_t matrix_generator) {
184 struct fixed_total *obj = generator;
185
186 uint32_t n_pre = pre_hi - pre_lo + 1;
187 uint32_t n_post = post_hi - post_lo + 1;
188 uint32_t post_slice_end = post_slice_start + post_slice_count;
189 uint32_t n_conns = obj->params.n_synapses_total;
190
191 // Generate the connections for all cores then filter for this one
192 if (obj->params.with_replacement) {
193 for (uint32_t i = 0; i < n_conns; i++) {
194 uint32_t post = random_in_range(population_rng, n_post) + post_lo;
195 if (post >= post_slice_start && post < post_slice_end) {
196 uint32_t local_post = post - post_slice_start;
197 accum weight = param_generator_generate(weight_generator);
198 uint16_t delay = rescale_delay(
199 param_generator_generate(delay_generator), timestep_per_delay);
200
201 uint32_t pre;
202 bool written = false;
203 uint32_t n_retries = 0;
204 do {
205 pre = random_in_range(core_rng, n_pre) + pre_lo;
206 if (obj->params.allow_self_connections || pre != post) {
208 pre, local_post, weight, delay, weight_scale);
209 n_retries++;
210 }
211 } while (!written && n_retries < 10);
212 if (!written) {
213 log_error("Couldn't find a row to write to!");
214 return false;
215 }
216 }
217 }
218 } else {
219 uint32_t pre = pre_lo;
220 uint32_t post = post_lo;
221 uint32_t i = 0;
222 struct {
223 uint32_t pre;
224 uint32_t post;
225 } conns[n_conns];
226 for (i = 0; i < n_conns; i++) {
227 conns[i].pre = pre;
228 conns[i].post = post;
229 fixed_total_next(&pre, &post, pre_lo, pre_hi);
230 if (!obj->params.allow_self_connections && (pre == post)) {
231 fixed_total_next(&pre, &post, pre_lo, pre_hi);
232 }
233 }
234 while (pre <= pre_hi && post <= post_hi) {
235 uint32_t r = random_in_range(population_rng, i + 1);
236 if (r < n_conns) {
237 conns[r].pre = pre;
238 conns[r].post = post;
239 }
240 fixed_total_next(&pre, &post, pre_lo, pre_hi);
241 if (!obj->params.allow_self_connections && (pre == post)) {
242 fixed_total_next(&pre, &post, pre_lo, pre_hi);
243 }
244 i++;
245 }
246 for (uint32_t i = 0; i < n_conns; i++) {
247 uint32_t local_post = conns[i].post;
248 if (local_post >= post_slice_start && local_post < post_slice_end) {
249 local_post -= post_slice_start;
250 uint32_t local_pre = conns[i].pre;
251 accum weight = param_generator_generate(weight_generator);
252 uint16_t delay = rescale_delay(
253 param_generator_generate(delay_generator), timestep_per_delay);
254 if (!matrix_generator_write_synapse(matrix_generator, local_pre, local_post,
255 weight, delay, weight_scale)) {
256 // Not a lot we can do here...
257 log_error("Couldn't write matrix!");
258 return false;
259 }
260 }
261 }
262 }
263 return true;
264}
static void connection_generator_fixed_total_free(void *generator)
Free the fixed-total connection generator.
static void * connection_generator_fixed_total_initialise(void **region)
Draw from a binomial distribution i.e. with replacement.
static bool connection_generator_fixed_total_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-total connection generator.
The data to be passed around.
The parameters that can be copied from SDRAM.
void log_error(const char *message,...)
void log_debug(const char *message,...)
General types associated with generators.
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.
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
void sark_free(void *ptr)
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.