yinspire 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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,77 @@
|
|
1
|
+
#include "neuron_srm_01.h"
|
2
|
+
#include "simulator.h"
|
3
|
+
#include <math.h>
|
4
|
+
|
5
|
+
// formerly known as KernelbasedLIF
|
6
|
+
|
7
|
+
|
8
|
+
Neuron_SRM_01::Neuron_SRM_01()
|
9
|
+
{
|
10
|
+
this->tau_m = 0.0;
|
11
|
+
this->tau_ref = 0.0;
|
12
|
+
this->ref_weight = 0.0;
|
13
|
+
this->mem_pot = 0.0;
|
14
|
+
this->const_threshold = 0.0;
|
15
|
+
}
|
16
|
+
|
17
|
+
void
|
18
|
+
Neuron_SRM_01::dump(jsonHash *into)
|
19
|
+
{
|
20
|
+
}
|
21
|
+
|
22
|
+
void
|
23
|
+
Neuron_SRM_01::load(jsonHash *data)
|
24
|
+
{
|
25
|
+
super::load(data);
|
26
|
+
|
27
|
+
this->tau_m = data->get_number("tau_m", 0.0);
|
28
|
+
this->tau_ref = data->get_number("tau_ref", 0.0);
|
29
|
+
this->ref_weight = data->get_number("ref_weight", 0.0);
|
30
|
+
this->mem_pot = data->get_number("mem_pot", 0.0);
|
31
|
+
this->const_threshold = data->get_number("const_threshold", 0.0);
|
32
|
+
}
|
33
|
+
|
34
|
+
void
|
35
|
+
Neuron_SRM_01::stimulate(simtime at, real weight, NeuralEntity *source)
|
36
|
+
{
|
37
|
+
if (at >= this->last_fire_time + this->abs_refr_duration)
|
38
|
+
{
|
39
|
+
++this->simulator->stat_event_counter;
|
40
|
+
super::stimulate(at, weight, source);
|
41
|
+
}
|
42
|
+
}
|
43
|
+
|
44
|
+
void
|
45
|
+
Neuron_SRM_01::process(simtime at)
|
46
|
+
{
|
47
|
+
real weight = stimuli_sum(at);
|
48
|
+
const real delta = at - this->last_fire_time - this->abs_refr_duration;
|
49
|
+
|
50
|
+
if (delta < 0.0) return;
|
51
|
+
|
52
|
+
/*
|
53
|
+
* Calculate new membrane potential
|
54
|
+
*/
|
55
|
+
|
56
|
+
this->mem_pot = weight + this->mem_pot * real_exp( -(at - this->last_spike_time)/this->tau_m );
|
57
|
+
this->last_spike_time = at;
|
58
|
+
|
59
|
+
/*
|
60
|
+
* Calculate dynamic threshold
|
61
|
+
*/
|
62
|
+
const real dynamic_threshold = this->ref_weight * real_exp(-delta/this->tau_ref);
|
63
|
+
|
64
|
+
if (this->mem_pot >= this->const_threshold + dynamic_threshold)
|
65
|
+
{
|
66
|
+
fire(at);
|
67
|
+
}
|
68
|
+
}
|
69
|
+
|
70
|
+
void
|
71
|
+
Neuron_SRM_01::fire(simtime at)
|
72
|
+
{
|
73
|
+
this->simulator->stat_record_fire_event(at, this);
|
74
|
+
this->mem_pot = 0.0;
|
75
|
+
this->last_fire_time = at;
|
76
|
+
fire_synapses(at);
|
77
|
+
}
|
@@ -0,0 +1,36 @@
|
|
1
|
+
#ifndef __YINSPIRE__NEURON_SRM_01__
|
2
|
+
#define __YINSPIRE__NEURON_SRM_01__
|
3
|
+
|
4
|
+
#include "neuron.h"
|
5
|
+
|
6
|
+
class Neuron_SRM_01 : public Neuron
|
7
|
+
{
|
8
|
+
typedef Neuron super;
|
9
|
+
|
10
|
+
protected:
|
11
|
+
|
12
|
+
real tau_m;
|
13
|
+
real tau_ref;
|
14
|
+
real ref_weight;
|
15
|
+
real mem_pot;
|
16
|
+
real const_threshold;
|
17
|
+
|
18
|
+
public:
|
19
|
+
|
20
|
+
Neuron_SRM_01();
|
21
|
+
|
22
|
+
public:
|
23
|
+
|
24
|
+
virtual void dump(jsonHash *into);
|
25
|
+
virtual void load(jsonHash *data);
|
26
|
+
|
27
|
+
virtual void stimulate(simtime at, real weight, NeuralEntity *source);
|
28
|
+
virtual void process(simtime at);
|
29
|
+
|
30
|
+
protected:
|
31
|
+
|
32
|
+
void fire(simtime at);
|
33
|
+
|
34
|
+
};
|
35
|
+
|
36
|
+
#endif
|
@@ -0,0 +1,151 @@
|
|
1
|
+
#include <math.h>
|
2
|
+
#include <string>
|
3
|
+
#include "simulator.h"
|
4
|
+
#include "json/json_parser.h"
|
5
|
+
|
6
|
+
Simulator::Simulator()
|
7
|
+
{
|
8
|
+
this->schedule_current_time = 0.0;
|
9
|
+
this->schedule_step = INFINITY;
|
10
|
+
this->schedule_next_step = this->schedule_current_time + this->schedule_step;
|
11
|
+
this->schedule_stepping_list_root = NULL;
|
12
|
+
this->stimuli_tolerance = 0.0;
|
13
|
+
this->stat_event_counter = 0;
|
14
|
+
this->stat_fire_counter = 0;
|
15
|
+
}
|
16
|
+
|
17
|
+
void
|
18
|
+
Simulator::entity_register_type(const char *type, entity_factory_t factory)
|
19
|
+
{
|
20
|
+
this->types[type] = factory;
|
21
|
+
}
|
22
|
+
|
23
|
+
NeuralEntity*
|
24
|
+
Simulator::entity_allocate(const char* type)
|
25
|
+
{
|
26
|
+
entity_factory_t factory = this->types[type];
|
27
|
+
return factory();
|
28
|
+
}
|
29
|
+
|
30
|
+
void
|
31
|
+
Simulator::load(const char *filename)
|
32
|
+
{
|
33
|
+
jsonHash *data = jsonParser::parse_file_mmap(filename)->asHash();
|
34
|
+
|
35
|
+
std::string format = data->get("format")->asString()->value;
|
36
|
+
|
37
|
+
if (format != "yinspire.c")
|
38
|
+
{
|
39
|
+
throw "unrecognized data format";
|
40
|
+
}
|
41
|
+
|
42
|
+
jsonHash *templates = data->get("templates")->asHash();
|
43
|
+
jsonArray *entities = data->get("entities")->asArray();
|
44
|
+
jsonArray *connections = data->get("connections")->asArray();
|
45
|
+
jsonHash *events = data->get("events")->asHash();
|
46
|
+
|
47
|
+
/*
|
48
|
+
* construct entities
|
49
|
+
*/
|
50
|
+
jsonArrayIterator_EACH(entities, e)
|
51
|
+
{
|
52
|
+
jsonArray *entity_spec = e->asArray();
|
53
|
+
jsonString *id = entity_spec->get(0)->asString();
|
54
|
+
jsonString *template_name = entity_spec->get(1)->asString();
|
55
|
+
|
56
|
+
jsonArray *t = templates->get(template_name)->asArray();
|
57
|
+
|
58
|
+
jsonString *type = t->get(0)->asString();
|
59
|
+
jsonHash *hash = t->get(1)->asHash();
|
60
|
+
|
61
|
+
NeuralEntity *entity = entity_allocate(type->value.c_str());
|
62
|
+
|
63
|
+
entity->set_id(strdup(id->asString()->value.c_str()));
|
64
|
+
entity->set_simulator(this);
|
65
|
+
this->entities[entity->get_id()] = entity;
|
66
|
+
|
67
|
+
entity->load(hash);
|
68
|
+
}
|
69
|
+
|
70
|
+
/*
|
71
|
+
* connect entities
|
72
|
+
*/
|
73
|
+
jsonArrayIterator_EACH(connections, conn)
|
74
|
+
{
|
75
|
+
NeuralEntity *from = NULL;
|
76
|
+
jsonArrayIterator_EACH(conn->asArray(), i)
|
77
|
+
{
|
78
|
+
std::string &id = i->asString()->value;
|
79
|
+
NeuralEntity *e = this->entities[id.c_str()];
|
80
|
+
if (from == NULL) from = e;
|
81
|
+
else from->connect(e);
|
82
|
+
}
|
83
|
+
}
|
84
|
+
|
85
|
+
/*
|
86
|
+
* events
|
87
|
+
*/
|
88
|
+
jsonHashIterator_EACH(events, key, val)
|
89
|
+
{
|
90
|
+
NeuralEntity *entity = this->entities[key->value.c_str()];
|
91
|
+
jsonArrayIterator_EACH(val->asArray(), e)
|
92
|
+
{
|
93
|
+
entity->stimulate(e->asNumber()->value, INFINITY, NULL);
|
94
|
+
}
|
95
|
+
}
|
96
|
+
|
97
|
+
data->ref_decr();
|
98
|
+
}
|
99
|
+
|
100
|
+
void
|
101
|
+
Simulator::run(simtime stop_at)
|
102
|
+
{
|
103
|
+
while (true)
|
104
|
+
{
|
105
|
+
simtime next_stop = MIN(stop_at, this->schedule_next_step);
|
106
|
+
|
107
|
+
/*
|
108
|
+
* Calculate all events from the priority queue until the next time
|
109
|
+
* step is reached.
|
110
|
+
*/
|
111
|
+
while (!this->schedule_pq.empty())
|
112
|
+
{
|
113
|
+
NeuralEntity *top = this->schedule_pq.top();
|
114
|
+
if (top->get_schedule_at() >= next_stop)
|
115
|
+
break;
|
116
|
+
this->schedule_current_time = top->get_schedule_at();
|
117
|
+
this->schedule_pq.pop();
|
118
|
+
top->process(top->get_schedule_at());
|
119
|
+
}
|
120
|
+
|
121
|
+
if (this->schedule_current_time >= stop_at)
|
122
|
+
break;
|
123
|
+
|
124
|
+
if (this->schedule_stepping_list_root == NULL && this->schedule_pq.empty())
|
125
|
+
break;
|
126
|
+
|
127
|
+
/*
|
128
|
+
* Calculate the entities that require stepped processing.
|
129
|
+
*/
|
130
|
+
this->schedule_current_time = this->schedule_next_step;
|
131
|
+
|
132
|
+
if (this->schedule_stepping_list_root != NULL)
|
133
|
+
{
|
134
|
+
// FIXME: collect all entities in an array. then process them.
|
135
|
+
}
|
136
|
+
|
137
|
+
this->schedule_next_step += this->schedule_step;
|
138
|
+
}
|
139
|
+
}
|
140
|
+
|
141
|
+
void
|
142
|
+
Simulator::schedule_update(NeuralEntity *entity)
|
143
|
+
{
|
144
|
+
this->schedule_pq.update(entity);
|
145
|
+
}
|
146
|
+
|
147
|
+
void
|
148
|
+
Simulator::stat_record_fire_event(simtime at, NeuralEntity *source)
|
149
|
+
{
|
150
|
+
++this->stat_fire_counter;
|
151
|
+
}
|
@@ -0,0 +1,116 @@
|
|
1
|
+
#ifndef __YINSPIRE__SIMULATOR__
|
2
|
+
#define __YINSPIRE__SIMULATOR__
|
3
|
+
|
4
|
+
#include "types.h"
|
5
|
+
#include "neural_entity.h"
|
6
|
+
#include "memory_allocator.h"
|
7
|
+
#include "algo/indexed_binary_heap.h"
|
8
|
+
#include <string.h>
|
9
|
+
#include <map>
|
10
|
+
|
11
|
+
struct ltstr
|
12
|
+
{
|
13
|
+
inline bool operator()(const char *s1, const char *s2) const
|
14
|
+
{
|
15
|
+
return strcmp(s1, s2) < 0;
|
16
|
+
}
|
17
|
+
};
|
18
|
+
|
19
|
+
class Simulator
|
20
|
+
{
|
21
|
+
friend class NeuralEntity;
|
22
|
+
|
23
|
+
protected:
|
24
|
+
|
25
|
+
/*
|
26
|
+
* The current time.
|
27
|
+
*/
|
28
|
+
simtime schedule_current_time;
|
29
|
+
|
30
|
+
/*
|
31
|
+
* The time step used for stepped scheduling.
|
32
|
+
*/
|
33
|
+
simtime schedule_step;
|
34
|
+
|
35
|
+
/*
|
36
|
+
* The time of the next step.
|
37
|
+
*/
|
38
|
+
simtime schedule_next_step;
|
39
|
+
|
40
|
+
/*
|
41
|
+
* The tolerance (time difference) up to which local stimuli are
|
42
|
+
* accumulated.
|
43
|
+
*/
|
44
|
+
simtime stimuli_tolerance;
|
45
|
+
|
46
|
+
/*
|
47
|
+
* Priority queue used to schedule the entities.
|
48
|
+
*/
|
49
|
+
IndexedBinaryHeap<NeuralEntity *, MemoryAllocator<NeuralEntity*>, NeuralEntity> schedule_pq;
|
50
|
+
|
51
|
+
/*
|
52
|
+
* If stepped scheduling is used, this points to the
|
53
|
+
* first entity in the stepped schedule list.
|
54
|
+
*/
|
55
|
+
NeuralEntity *schedule_stepping_list_root;
|
56
|
+
|
57
|
+
/*
|
58
|
+
* An id -> NeuralEntity mapping
|
59
|
+
*
|
60
|
+
* Contains all entities known by the simulator.
|
61
|
+
*/
|
62
|
+
std::map<const char *, NeuralEntity *, ltstr> entities;
|
63
|
+
|
64
|
+
/*
|
65
|
+
* An entity type name -> "factory function for this type" mapping.
|
66
|
+
*/
|
67
|
+
typedef NeuralEntity* (*entity_factory_t)();
|
68
|
+
std::map<const char *, entity_factory_t, ltstr> types;
|
69
|
+
|
70
|
+
public:
|
71
|
+
|
72
|
+
/*
|
73
|
+
* Constructor
|
74
|
+
*/
|
75
|
+
Simulator();
|
76
|
+
|
77
|
+
/*
|
78
|
+
* Load the neural net from +filename+.
|
79
|
+
*/
|
80
|
+
void load(const char *filename);
|
81
|
+
|
82
|
+
/*
|
83
|
+
* Start the simulation.
|
84
|
+
*/
|
85
|
+
void run(simtime stop_at);
|
86
|
+
|
87
|
+
/*
|
88
|
+
* Register an entity type and the corresponding +factory+ function.
|
89
|
+
*/
|
90
|
+
void entity_register_type(const char *type, entity_factory_t factory);
|
91
|
+
|
92
|
+
/*
|
93
|
+
* Allocate an entity of the specified +type+.
|
94
|
+
*/
|
95
|
+
NeuralEntity *entity_allocate(const char *type);
|
96
|
+
|
97
|
+
/*
|
98
|
+
* If an entity has changed it's scheduling time,
|
99
|
+
* it has to call this method to reflect the change within the
|
100
|
+
* priority queue.
|
101
|
+
*/
|
102
|
+
void schedule_update(NeuralEntity *entity);
|
103
|
+
|
104
|
+
/*
|
105
|
+
* Notify that a fire event has happened
|
106
|
+
*/
|
107
|
+
void stat_record_fire_event(simtime at, NeuralEntity *source);
|
108
|
+
|
109
|
+
public:
|
110
|
+
|
111
|
+
uint stat_fire_counter;
|
112
|
+
uint stat_event_counter;
|
113
|
+
|
114
|
+
};
|
115
|
+
|
116
|
+
#endif
|
@@ -0,0 +1,117 @@
|
|
1
|
+
#include "synapse.h"
|
2
|
+
#include "neuron.h"
|
3
|
+
#include <assert.h>
|
4
|
+
|
5
|
+
Synapse::Synapse()
|
6
|
+
{
|
7
|
+
this->weight = 0.0;
|
8
|
+
this->delay = 0.0;
|
9
|
+
this->pre_neuron = NULL;
|
10
|
+
this->post_neuron = NULL;
|
11
|
+
this->next_pre_synapse = NULL;
|
12
|
+
this->next_post_synapse = NULL;
|
13
|
+
}
|
14
|
+
|
15
|
+
void
|
16
|
+
Synapse::dump(jsonHash *into)
|
17
|
+
{
|
18
|
+
}
|
19
|
+
|
20
|
+
void
|
21
|
+
Synapse::load(jsonHash *data)
|
22
|
+
{
|
23
|
+
super::load(data);
|
24
|
+
|
25
|
+
this->weight = data->get_number("weight", 0.0);
|
26
|
+
this->delay = data->get_number("delay", 0.0);
|
27
|
+
}
|
28
|
+
|
29
|
+
|
30
|
+
void
|
31
|
+
Synapse::stimulate(simtime at, real weight, NeuralEntity *source)
|
32
|
+
{
|
33
|
+
/*
|
34
|
+
* Only propagate the stimulation if it doesn't originate from the
|
35
|
+
* post Neuron. Stimuli from a post Neuron are handled by a specific
|
36
|
+
* Synapse class (e.g. Hebb).
|
37
|
+
*
|
38
|
+
* We ignore the weight parameter that is passed by the Neuron.
|
39
|
+
*/
|
40
|
+
if (source != this->post_neuron)
|
41
|
+
{
|
42
|
+
this->post_neuron->stimulate(at + this->delay, this->weight, this);
|
43
|
+
}
|
44
|
+
}
|
45
|
+
|
46
|
+
|
47
|
+
/*
|
48
|
+
* Adding a pre synapse. Target must be a Neuron.
|
49
|
+
*
|
50
|
+
* O(1)
|
51
|
+
*/
|
52
|
+
void
|
53
|
+
Synapse::connect(NeuralEntity *target)
|
54
|
+
{
|
55
|
+
Neuron *neuron = dynamic_cast<Neuron*>(target);
|
56
|
+
|
57
|
+
if (this->post_neuron != NULL || this->next_pre_synapse != NULL)
|
58
|
+
throw "Synapse already connected";
|
59
|
+
|
60
|
+
this->next_pre_synapse = neuron->first_pre_synapse;
|
61
|
+
neuron->first_pre_synapse = this;
|
62
|
+
this->post_neuron = neuron;
|
63
|
+
}
|
64
|
+
|
65
|
+
/*
|
66
|
+
* O(n)
|
67
|
+
*/
|
68
|
+
void
|
69
|
+
Synapse::disconnect(NeuralEntity *target)
|
70
|
+
{
|
71
|
+
Neuron *neuron = dynamic_cast<Neuron*>(target);
|
72
|
+
|
73
|
+
if (this->post_neuron != neuron)
|
74
|
+
throw "Synapse not connected to this Neuron";
|
75
|
+
|
76
|
+
/*
|
77
|
+
* Find the synapse in the linked list that precedes +this+.
|
78
|
+
*/
|
79
|
+
Synapse *prev = NULL;
|
80
|
+
Synapse *curr = neuron->first_pre_synapse;
|
81
|
+
|
82
|
+
while (true)
|
83
|
+
{
|
84
|
+
if (curr == NULL) break;
|
85
|
+
if (curr == this) break;
|
86
|
+
prev = curr;
|
87
|
+
curr = curr->next_pre_synapse;
|
88
|
+
}
|
89
|
+
|
90
|
+
if (curr != this)
|
91
|
+
throw "Synapse not in pre synapse list";
|
92
|
+
|
93
|
+
/*
|
94
|
+
* Remove ourself (this) from linked list
|
95
|
+
*/
|
96
|
+
if (prev == NULL)
|
97
|
+
{
|
98
|
+
/*
|
99
|
+
* we are the last synapse in the pre synapse list.
|
100
|
+
*/
|
101
|
+
assert(neuron->first_pre_synapse == this);
|
102
|
+
neuron->first_pre_synapse = NULL;
|
103
|
+
}
|
104
|
+
else
|
105
|
+
{
|
106
|
+
prev->next_pre_synapse = this->next_pre_synapse;
|
107
|
+
}
|
108
|
+
|
109
|
+
this->post_neuron = NULL;
|
110
|
+
this->next_pre_synapse = NULL;
|
111
|
+
}
|
112
|
+
|
113
|
+
void
|
114
|
+
Synapse::each_connection(void (*yield)(NeuralEntity *self, NeuralEntity *conn))
|
115
|
+
{
|
116
|
+
yield(this, this->post_neuron);
|
117
|
+
}
|