yinspire 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README +24 -0
- data/bench/pq/Makefile +5 -0
- data/bench/pq/bench.cc +321 -0
- data/bench/pq/bench.rb +125 -0
- data/bench/pq/bench_binaryheap.h +46 -0
- data/bench/pq/bench_calendarqueue.h +58 -0
- data/bench/pq/bench_pairingheap.h +61 -0
- data/bench/pq/bench_stlpq.h +46 -0
- data/bench/pq/benchmark.h +225 -0
- data/bench/pq/distribution.h +93 -0
- data/bench/pq/make.rb +24 -0
- data/bin/yinspire +186 -0
- data/examples/nets/gereon2005.c.json +93723 -0
- data/examples/nets/gereon2005.yin +232650 -0
- data/examples/nets/skorpion.graphml +396 -0
- data/examples/nets/spiketrains_angle_180.txt +8 -0
- data/lib/Algorithms/Array.h +52 -0
- data/lib/Algorithms/BinaryHeap.h +265 -0
- data/lib/Algorithms/CalendarQueue.h +257 -0
- data/lib/Algorithms/IndexedBinaryHeap.h +90 -0
- data/lib/Algorithms/PairingHeap.h +169 -0
- data/lib/Allocators/ChunkedFreelistAllocator.h +96 -0
- data/lib/Allocators/MemoryAllocator.h +45 -0
- data/lib/Allocators/RubyMemoryAllocator.h +37 -0
- data/lib/Yinspire.rb +69 -0
- data/lib/Yinspire/All.rb +10 -0
- data/lib/Yinspire/Core/NeuralEntity.rb +133 -0
- data/lib/Yinspire/Core/Neuron.rb +162 -0
- data/lib/Yinspire/Core/Scheduling/NeuralEntity.rb +123 -0
- data/lib/Yinspire/Core/Scheduling/Simulator.rb +94 -0
- data/lib/Yinspire/Core/Simulator.rb +36 -0
- data/lib/Yinspire/Core/StimuliMixin.rb +103 -0
- data/lib/Yinspire/Core/Stimulus.rb +25 -0
- data/lib/Yinspire/Core/Synapse.rb +64 -0
- data/lib/Yinspire/Dumpers/Dumper.rb +19 -0
- data/lib/Yinspire/Dumpers/Dumper_Dot.rb +28 -0
- data/lib/Yinspire/Loaders/GraphML.rb +84 -0
- data/lib/Yinspire/Loaders/Loader.rb +31 -0
- data/lib/Yinspire/Loaders/Loader_GraphML.rb +97 -0
- data/lib/Yinspire/Loaders/Loader_JSON.rb +181 -0
- data/lib/Yinspire/Loaders/Loader_Spike.rb +42 -0
- data/lib/Yinspire/Loaders/Loader_Yin.rb +62 -0
- data/lib/Yinspire/Loaders/YinScanner.rb +247 -0
- data/lib/Yinspire/Models/Neuron_Base.rb +38 -0
- data/lib/Yinspire/Models/Neuron_Input.rb +12 -0
- data/lib/Yinspire/Models/Neuron_InputOutput.rb +39 -0
- data/lib/Yinspire/Models/Neuron_Output.rb +15 -0
- data/lib/Yinspire/Models/Neuron_SRM01.rb +50 -0
- data/lib/Yinspire/Models/Neuron_SRM02.rb +64 -0
- data/lib/Yinspire/Models/Synapse_Hebb.rb +67 -0
- data/pure_cpp/Makefile +22 -0
- data/pure_cpp/README +2 -0
- data/pure_cpp/src/algo/binary_heap.h +277 -0
- data/pure_cpp/src/algo/indexed_binary_heap.h +90 -0
- data/pure_cpp/src/json/json.cc +542 -0
- data/pure_cpp/src/json/json.h +182 -0
- data/pure_cpp/src/json/json_parser.cc +685 -0
- data/pure_cpp/src/json/json_parser.h +15 -0
- data/pure_cpp/src/json/json_parser.rl +213 -0
- data/pure_cpp/src/main.cc +49 -0
- data/pure_cpp/src/memory_allocator.h +45 -0
- data/pure_cpp/src/neural_entity.cc +208 -0
- data/pure_cpp/src/neural_entity.h +243 -0
- data/pure_cpp/src/neuron.cc +136 -0
- data/pure_cpp/src/neuron.h +70 -0
- data/pure_cpp/src/neuron_srm_01.cc +77 -0
- data/pure_cpp/src/neuron_srm_01.h +36 -0
- data/pure_cpp/src/simulator.cc +151 -0
- data/pure_cpp/src/simulator.h +116 -0
- data/pure_cpp/src/synapse.cc +117 -0
- data/pure_cpp/src/synapse.h +60 -0
- data/pure_cpp/src/types.h +18 -0
- data/run.rb +68 -0
- data/tools/conv_jsonc_to_yin.rb +165 -0
- data/tools/converter.rb +93 -0
- data/tools/json_writer.rb +122 -0
- data/yinspire.gemspec +20 -0
- metadata +156 -0
@@ -0,0 +1,243 @@
|
|
1
|
+
#ifndef __YINSPIRE__NEURAL_ENTITY__
|
2
|
+
#define __YINSPIRE__NEURAL_ENTITY__
|
3
|
+
|
4
|
+
#include "types.h"
|
5
|
+
#include "memory_allocator.h"
|
6
|
+
#include "algo/binary_heap.h"
|
7
|
+
#include "json/json.h"
|
8
|
+
|
9
|
+
class Simulator; // forward declaration
|
10
|
+
|
11
|
+
/*
|
12
|
+
* The data structure used for storing a fire impluse or any other form
|
13
|
+
* of stimulation.
|
14
|
+
*/
|
15
|
+
struct Stimulus
|
16
|
+
{
|
17
|
+
simtime at;
|
18
|
+
real weight;
|
19
|
+
|
20
|
+
inline static bool
|
21
|
+
less(const Stimulus &a, const Stimulus &b)
|
22
|
+
{
|
23
|
+
return (a.at < b.at);
|
24
|
+
}
|
25
|
+
};
|
26
|
+
|
27
|
+
/*
|
28
|
+
* The NeuralEntity is the base class of all entities in a neural net,
|
29
|
+
* i.e. Neurons and Synapses.
|
30
|
+
*/
|
31
|
+
class NeuralEntity
|
32
|
+
{
|
33
|
+
protected:
|
34
|
+
|
35
|
+
/*
|
36
|
+
* Each NeuralEntity has a pointer to the Simulator.
|
37
|
+
* This is used for example to update it's scheduling
|
38
|
+
* or to report a fire event.
|
39
|
+
*
|
40
|
+
* It's assigned by the Simulator!
|
41
|
+
*/
|
42
|
+
Simulator *simulator;
|
43
|
+
|
44
|
+
/*
|
45
|
+
* Each NeuralEntity has an +id+ associated which uniquely
|
46
|
+
* identifies itself within a Simulator instance. This +id+ is
|
47
|
+
* assigned by the Simulator and should not be changed by the
|
48
|
+
* NeuralEntity itself.
|
49
|
+
*
|
50
|
+
* The reference is NOT owned by the NeuralEntity. It's the
|
51
|
+
* responsibility of the Simulator to allocate and free the memory!
|
52
|
+
*/
|
53
|
+
const char *id;
|
54
|
+
|
55
|
+
/*
|
56
|
+
* Index of this entity in the entity priority queue managed by the
|
57
|
+
* Simulator. If schedule_index is zero then the entity is currently
|
58
|
+
* not present in the priority queue and as such the entity is not
|
59
|
+
* scheduled for a specific time.
|
60
|
+
*/
|
61
|
+
uint schedule_index;
|
62
|
+
|
63
|
+
/*
|
64
|
+
* The timestamp of the earliest event in the local priority queue.
|
65
|
+
*/
|
66
|
+
simtime schedule_at;
|
67
|
+
|
68
|
+
/*
|
69
|
+
* If stepped scheduling is used, points to the previous/next
|
70
|
+
* entity in the schedule list.
|
71
|
+
*/
|
72
|
+
NeuralEntity *schedule_stepping_list_prev;
|
73
|
+
NeuralEntity *schedule_stepping_list_next;
|
74
|
+
|
75
|
+
/*
|
76
|
+
* To be able to modify the stepped scheduling list
|
77
|
+
* (schedule_stepping_list_prev/next) during stepped schedule
|
78
|
+
* processing, we build up an internal linked list that we use to
|
79
|
+
* traverse all entities that require stepped schedule processing.
|
80
|
+
*
|
81
|
+
* This is cheaper than using an externalized linked list, as we
|
82
|
+
* would have to allocate memory, which we overcome with this
|
83
|
+
* approach.
|
84
|
+
*
|
85
|
+
* This is only used by the simulator!
|
86
|
+
*/
|
87
|
+
NeuralEntity *schedule_stepping_list_internal_next;
|
88
|
+
|
89
|
+
/*
|
90
|
+
* Each NeuralEntity has it's own local stimuli priority queue.
|
91
|
+
* Neurons make use of this whereas Synapses currently not.
|
92
|
+
*
|
93
|
+
* It's a quite low overhead to have this in the NeuralEntity class,
|
94
|
+
* just around 12 additional bytes.
|
95
|
+
*/
|
96
|
+
BinaryHeap<Stimulus, MemoryAllocator<Stimulus> > stimuli_pq;
|
97
|
+
|
98
|
+
public:
|
99
|
+
|
100
|
+
/*
|
101
|
+
* Constructor
|
102
|
+
*/
|
103
|
+
NeuralEntity();
|
104
|
+
|
105
|
+
/*
|
106
|
+
* Destructor
|
107
|
+
*/
|
108
|
+
virtual ~NeuralEntity();
|
109
|
+
|
110
|
+
/*
|
111
|
+
* Load the internal state of a NeuralEntity
|
112
|
+
* from +data+.
|
113
|
+
*
|
114
|
+
* Note that loading does not neccessarily reset
|
115
|
+
* the internal state of the entity!
|
116
|
+
*/
|
117
|
+
virtual void load(jsonHash *data);
|
118
|
+
|
119
|
+
/*
|
120
|
+
* Dump the internal state of a NeuralEntity
|
121
|
+
* and return it. Internal state does not contain
|
122
|
+
* the network connection (they have to be dumped
|
123
|
+
* separatly by the simulator using +each_connection+.
|
124
|
+
*/
|
125
|
+
virtual void dump(jsonHash *into);
|
126
|
+
|
127
|
+
/*
|
128
|
+
* Connect +self+ with +target+.
|
129
|
+
*/
|
130
|
+
virtual void connect(NeuralEntity *target) = 0;
|
131
|
+
|
132
|
+
/*
|
133
|
+
* Disconnect +self+ from +target+.
|
134
|
+
*/
|
135
|
+
virtual void disconnect(NeuralEntity *target) = 0;
|
136
|
+
|
137
|
+
/*
|
138
|
+
* Disconnect from all connections. Uses +each_connection+ and
|
139
|
+
* +disconnect+.
|
140
|
+
*/
|
141
|
+
void disconnect_all();
|
142
|
+
|
143
|
+
/*
|
144
|
+
* Calls the iterator function for each outgoing connection.
|
145
|
+
*/
|
146
|
+
virtual void each_connection(
|
147
|
+
void (*yield)(NeuralEntity *self, NeuralEntity *conn)) = 0;
|
148
|
+
|
149
|
+
/*
|
150
|
+
* Stimulate an entity at a specific time with a specific weight.
|
151
|
+
*/
|
152
|
+
virtual void stimulate(simtime at, real weight, NeuralEntity *source) = 0;
|
153
|
+
|
154
|
+
/*
|
155
|
+
* This method is called when a NeuralEntity reached it's scheduling
|
156
|
+
* time.
|
157
|
+
*
|
158
|
+
* Overwrite it if you need this behaviour.
|
159
|
+
*/
|
160
|
+
virtual void
|
161
|
+
process(simtime at)
|
162
|
+
{
|
163
|
+
throw "Abstract method";
|
164
|
+
}
|
165
|
+
|
166
|
+
/*
|
167
|
+
* This method is called in each time-step, if a NeuralEntity
|
168
|
+
* uses stepped scheduling.
|
169
|
+
*
|
170
|
+
* Overwrite it if you need this behaviour.
|
171
|
+
*/
|
172
|
+
virtual void
|
173
|
+
process_stepped(simtime at, simtime step)
|
174
|
+
{
|
175
|
+
throw "Abstract method";
|
176
|
+
}
|
177
|
+
|
178
|
+
/*
|
179
|
+
* Attribute accessor functions
|
180
|
+
*/
|
181
|
+
void set_simulator(Simulator *simulator);
|
182
|
+
void set_id(const char *id);
|
183
|
+
Simulator *get_simulator() const;
|
184
|
+
const char *get_id() const;
|
185
|
+
inline simtime get_schedule_at() const { return this->schedule_at; }
|
186
|
+
|
187
|
+
protected:
|
188
|
+
|
189
|
+
/*
|
190
|
+
* Schedules the entity at a specific time.
|
191
|
+
*/
|
192
|
+
void schedule(simtime at);
|
193
|
+
|
194
|
+
/*
|
195
|
+
* Returns true if stepped scheduling is enabled.
|
196
|
+
*/
|
197
|
+
bool schedule_stepping_enabled();
|
198
|
+
|
199
|
+
/*
|
200
|
+
* Enable/Disable stepped scheduling.
|
201
|
+
*/
|
202
|
+
void schedule_enable_stepping();
|
203
|
+
void schedule_disable_stepping();
|
204
|
+
|
205
|
+
/*
|
206
|
+
* Add a Stimuli to the local pq.
|
207
|
+
*/
|
208
|
+
void stimuli_add(simtime at, real weight);
|
209
|
+
|
210
|
+
/*
|
211
|
+
* Sum all Stimuli until +until+.
|
212
|
+
*/
|
213
|
+
real stimuli_sum(simtime until);
|
214
|
+
|
215
|
+
/*
|
216
|
+
* Sum all Stimuli until +until+, but treat infinite values
|
217
|
+
* differently. Do not sum them, instead set +is_inf+ to true.
|
218
|
+
*/
|
219
|
+
real stimuli_sum_inf(simtime until, bool &is_inf);
|
220
|
+
|
221
|
+
public:
|
222
|
+
|
223
|
+
/*
|
224
|
+
* Accessor function for BinaryHeap
|
225
|
+
*/
|
226
|
+
inline static bool
|
227
|
+
less(const NeuralEntity *a, const NeuralEntity *b)
|
228
|
+
{
|
229
|
+
return (a->schedule_at < b->schedule_at);
|
230
|
+
}
|
231
|
+
|
232
|
+
/*
|
233
|
+
* Accessor function for BinaryHeap
|
234
|
+
*/
|
235
|
+
inline static uint &
|
236
|
+
index(NeuralEntity *self)
|
237
|
+
{
|
238
|
+
return self->schedule_index;
|
239
|
+
}
|
240
|
+
|
241
|
+
};
|
242
|
+
|
243
|
+
#endif
|
@@ -0,0 +1,136 @@
|
|
1
|
+
#include "neuron.h"
|
2
|
+
#include "synapse.h"
|
3
|
+
#include <math.h>
|
4
|
+
#include <assert.h>
|
5
|
+
#include "simulator.h" // ?
|
6
|
+
|
7
|
+
Neuron::Neuron()
|
8
|
+
{
|
9
|
+
this->first_pre_synapse = NULL;
|
10
|
+
this->first_post_synapse = NULL;
|
11
|
+
this->abs_refr_duration = 0.0;
|
12
|
+
this->last_spike_time = -INFINITY;
|
13
|
+
this->last_fire_time = -INFINITY;
|
14
|
+
this->hebb = false;
|
15
|
+
}
|
16
|
+
|
17
|
+
void
|
18
|
+
Neuron::dump(jsonHash *into)
|
19
|
+
{
|
20
|
+
}
|
21
|
+
|
22
|
+
void
|
23
|
+
Neuron::load(jsonHash *data)
|
24
|
+
{
|
25
|
+
super::load(data);
|
26
|
+
|
27
|
+
this->abs_refr_duration = data->get_number("abs_refr_duration", 0.0);
|
28
|
+
this->last_spike_time = data->get_number("last_spike_time", -INFINITY);
|
29
|
+
this->last_fire_time = data->get_number("last_fire_time", -INFINITY);
|
30
|
+
this->hebb = data->get_bool("hebb", false);
|
31
|
+
}
|
32
|
+
|
33
|
+
void
|
34
|
+
Neuron::each_connection(void (*yield)(NeuralEntity *self, NeuralEntity *conn))
|
35
|
+
{
|
36
|
+
for (Synapse *syn = this->first_post_synapse; syn != NULL;
|
37
|
+
syn = syn->next_post_synapse)
|
38
|
+
{
|
39
|
+
yield(this, syn);
|
40
|
+
}
|
41
|
+
}
|
42
|
+
|
43
|
+
void
|
44
|
+
Neuron::stimulate(simtime at, real weight, NeuralEntity *source)
|
45
|
+
{
|
46
|
+
stimuli_add(at, weight);
|
47
|
+
}
|
48
|
+
|
49
|
+
/*
|
50
|
+
* Adding a post synapse. Target must be a Synapse.
|
51
|
+
*
|
52
|
+
* O(1)
|
53
|
+
*/
|
54
|
+
void
|
55
|
+
Neuron::connect(NeuralEntity *target)
|
56
|
+
{
|
57
|
+
Synapse *syn = dynamic_cast<Synapse*>(target);
|
58
|
+
|
59
|
+
if (syn->pre_neuron != NULL || syn->next_post_synapse != NULL)
|
60
|
+
throw "Synapse already connected";
|
61
|
+
|
62
|
+
syn->next_post_synapse = this->first_post_synapse;
|
63
|
+
this->first_post_synapse = syn;
|
64
|
+
syn->pre_neuron = this;
|
65
|
+
}
|
66
|
+
|
67
|
+
/*
|
68
|
+
* O(n)
|
69
|
+
*/
|
70
|
+
void
|
71
|
+
Neuron::disconnect(NeuralEntity *target)
|
72
|
+
{
|
73
|
+
Synapse *syn = dynamic_cast<Synapse*>(target);
|
74
|
+
|
75
|
+
if (syn->pre_neuron != this)
|
76
|
+
throw "Synapse not connected to this Neuron";
|
77
|
+
|
78
|
+
/*
|
79
|
+
* Find the synapse in the linked list that precedes +syn+.
|
80
|
+
*/
|
81
|
+
Synapse *prev = NULL;
|
82
|
+
Synapse *curr = this->first_post_synapse;
|
83
|
+
|
84
|
+
while (true)
|
85
|
+
{
|
86
|
+
if (curr == NULL) break;
|
87
|
+
if (curr == syn) break;
|
88
|
+
prev = curr;
|
89
|
+
curr = curr->next_post_synapse;
|
90
|
+
}
|
91
|
+
|
92
|
+
if (curr != syn)
|
93
|
+
throw "Synapse not in post synapse list";
|
94
|
+
|
95
|
+
/*
|
96
|
+
* Remove syn from linked list
|
97
|
+
*/
|
98
|
+
if (prev == NULL)
|
99
|
+
{
|
100
|
+
/*
|
101
|
+
* syn is the last synapse in the post synapse list.
|
102
|
+
*/
|
103
|
+
assert(this->first_post_synapse == syn);
|
104
|
+
this->first_post_synapse = NULL;
|
105
|
+
}
|
106
|
+
else
|
107
|
+
{
|
108
|
+
prev->next_post_synapse = syn->next_post_synapse;
|
109
|
+
}
|
110
|
+
|
111
|
+
syn->pre_neuron = NULL;
|
112
|
+
syn->next_post_synapse = NULL;
|
113
|
+
}
|
114
|
+
|
115
|
+
/*
|
116
|
+
* NOTE: The stimulation weight is 0.0 below
|
117
|
+
* as the synapse will add it's weight to the
|
118
|
+
* preceding neurons.
|
119
|
+
*/
|
120
|
+
void
|
121
|
+
Neuron::fire_synapses(simtime at)
|
122
|
+
{
|
123
|
+
if (this->hebb)
|
124
|
+
{
|
125
|
+
for (Synapse *syn = this->first_pre_synapse; syn != NULL;
|
126
|
+
syn = syn->next_pre_synapse)
|
127
|
+
{
|
128
|
+
syn->stimulate(at, 0.0, this);
|
129
|
+
}
|
130
|
+
}
|
131
|
+
for (Synapse *syn = this->first_post_synapse; syn != NULL;
|
132
|
+
syn = syn->next_post_synapse)
|
133
|
+
{
|
134
|
+
syn->stimulate(at, 0.0, this);
|
135
|
+
}
|
136
|
+
}
|
@@ -0,0 +1,70 @@
|
|
1
|
+
#ifndef __YINSPIRE__NEURON__
|
2
|
+
#define __YINSPIRE__NEURON__
|
3
|
+
|
4
|
+
#include "neural_entity.h"
|
5
|
+
|
6
|
+
class Synapse; // forward declaration
|
7
|
+
|
8
|
+
/*
|
9
|
+
* The base class of all neurons.
|
10
|
+
*/
|
11
|
+
class Neuron : public NeuralEntity
|
12
|
+
{
|
13
|
+
friend class Synapse;
|
14
|
+
typedef NeuralEntity super;
|
15
|
+
|
16
|
+
protected:
|
17
|
+
|
18
|
+
/*
|
19
|
+
* Pointers to the first pre/post synapse
|
20
|
+
*/
|
21
|
+
Synapse *first_pre_synapse;
|
22
|
+
Synapse *first_post_synapse;
|
23
|
+
|
24
|
+
/*
|
25
|
+
* Duration of the absolute refraction period.
|
26
|
+
*/
|
27
|
+
simtime abs_refr_duration;
|
28
|
+
|
29
|
+
/*
|
30
|
+
* Last spike time
|
31
|
+
*/
|
32
|
+
simtime last_spike_time;
|
33
|
+
|
34
|
+
/*
|
35
|
+
* Last fire time
|
36
|
+
*/
|
37
|
+
simtime last_fire_time;
|
38
|
+
|
39
|
+
/*
|
40
|
+
* Whether this neuron is a hebb neuron or not.
|
41
|
+
* A hebb neuron also stimulates it's pre synapses
|
42
|
+
* upon firing.
|
43
|
+
*/
|
44
|
+
bool hebb;
|
45
|
+
|
46
|
+
protected:
|
47
|
+
|
48
|
+
/*
|
49
|
+
* Constructor
|
50
|
+
*/
|
51
|
+
Neuron();
|
52
|
+
|
53
|
+
public:
|
54
|
+
|
55
|
+
virtual void dump(jsonHash *into);
|
56
|
+
virtual void load(jsonHash *data);
|
57
|
+
|
58
|
+
virtual void stimulate(simtime at, real weight, NeuralEntity *source);
|
59
|
+
virtual void connect(NeuralEntity *target);
|
60
|
+
virtual void disconnect(NeuralEntity *target);
|
61
|
+
virtual void each_connection(
|
62
|
+
void (*yield)(NeuralEntity *self, NeuralEntity *conn));
|
63
|
+
|
64
|
+
protected:
|
65
|
+
|
66
|
+
void fire_synapses(simtime at);
|
67
|
+
|
68
|
+
};
|
69
|
+
|
70
|
+
#endif
|