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.
Files changed (78) hide show
  1. data/README +24 -0
  2. data/bench/pq/Makefile +5 -0
  3. data/bench/pq/bench.cc +321 -0
  4. data/bench/pq/bench.rb +125 -0
  5. data/bench/pq/bench_binaryheap.h +46 -0
  6. data/bench/pq/bench_calendarqueue.h +58 -0
  7. data/bench/pq/bench_pairingheap.h +61 -0
  8. data/bench/pq/bench_stlpq.h +46 -0
  9. data/bench/pq/benchmark.h +225 -0
  10. data/bench/pq/distribution.h +93 -0
  11. data/bench/pq/make.rb +24 -0
  12. data/bin/yinspire +186 -0
  13. data/examples/nets/gereon2005.c.json +93723 -0
  14. data/examples/nets/gereon2005.yin +232650 -0
  15. data/examples/nets/skorpion.graphml +396 -0
  16. data/examples/nets/spiketrains_angle_180.txt +8 -0
  17. data/lib/Algorithms/Array.h +52 -0
  18. data/lib/Algorithms/BinaryHeap.h +265 -0
  19. data/lib/Algorithms/CalendarQueue.h +257 -0
  20. data/lib/Algorithms/IndexedBinaryHeap.h +90 -0
  21. data/lib/Algorithms/PairingHeap.h +169 -0
  22. data/lib/Allocators/ChunkedFreelistAllocator.h +96 -0
  23. data/lib/Allocators/MemoryAllocator.h +45 -0
  24. data/lib/Allocators/RubyMemoryAllocator.h +37 -0
  25. data/lib/Yinspire.rb +69 -0
  26. data/lib/Yinspire/All.rb +10 -0
  27. data/lib/Yinspire/Core/NeuralEntity.rb +133 -0
  28. data/lib/Yinspire/Core/Neuron.rb +162 -0
  29. data/lib/Yinspire/Core/Scheduling/NeuralEntity.rb +123 -0
  30. data/lib/Yinspire/Core/Scheduling/Simulator.rb +94 -0
  31. data/lib/Yinspire/Core/Simulator.rb +36 -0
  32. data/lib/Yinspire/Core/StimuliMixin.rb +103 -0
  33. data/lib/Yinspire/Core/Stimulus.rb +25 -0
  34. data/lib/Yinspire/Core/Synapse.rb +64 -0
  35. data/lib/Yinspire/Dumpers/Dumper.rb +19 -0
  36. data/lib/Yinspire/Dumpers/Dumper_Dot.rb +28 -0
  37. data/lib/Yinspire/Loaders/GraphML.rb +84 -0
  38. data/lib/Yinspire/Loaders/Loader.rb +31 -0
  39. data/lib/Yinspire/Loaders/Loader_GraphML.rb +97 -0
  40. data/lib/Yinspire/Loaders/Loader_JSON.rb +181 -0
  41. data/lib/Yinspire/Loaders/Loader_Spike.rb +42 -0
  42. data/lib/Yinspire/Loaders/Loader_Yin.rb +62 -0
  43. data/lib/Yinspire/Loaders/YinScanner.rb +247 -0
  44. data/lib/Yinspire/Models/Neuron_Base.rb +38 -0
  45. data/lib/Yinspire/Models/Neuron_Input.rb +12 -0
  46. data/lib/Yinspire/Models/Neuron_InputOutput.rb +39 -0
  47. data/lib/Yinspire/Models/Neuron_Output.rb +15 -0
  48. data/lib/Yinspire/Models/Neuron_SRM01.rb +50 -0
  49. data/lib/Yinspire/Models/Neuron_SRM02.rb +64 -0
  50. data/lib/Yinspire/Models/Synapse_Hebb.rb +67 -0
  51. data/pure_cpp/Makefile +22 -0
  52. data/pure_cpp/README +2 -0
  53. data/pure_cpp/src/algo/binary_heap.h +277 -0
  54. data/pure_cpp/src/algo/indexed_binary_heap.h +90 -0
  55. data/pure_cpp/src/json/json.cc +542 -0
  56. data/pure_cpp/src/json/json.h +182 -0
  57. data/pure_cpp/src/json/json_parser.cc +685 -0
  58. data/pure_cpp/src/json/json_parser.h +15 -0
  59. data/pure_cpp/src/json/json_parser.rl +213 -0
  60. data/pure_cpp/src/main.cc +49 -0
  61. data/pure_cpp/src/memory_allocator.h +45 -0
  62. data/pure_cpp/src/neural_entity.cc +208 -0
  63. data/pure_cpp/src/neural_entity.h +243 -0
  64. data/pure_cpp/src/neuron.cc +136 -0
  65. data/pure_cpp/src/neuron.h +70 -0
  66. data/pure_cpp/src/neuron_srm_01.cc +77 -0
  67. data/pure_cpp/src/neuron_srm_01.h +36 -0
  68. data/pure_cpp/src/simulator.cc +151 -0
  69. data/pure_cpp/src/simulator.h +116 -0
  70. data/pure_cpp/src/synapse.cc +117 -0
  71. data/pure_cpp/src/synapse.h +60 -0
  72. data/pure_cpp/src/types.h +18 -0
  73. data/run.rb +68 -0
  74. data/tools/conv_jsonc_to_yin.rb +165 -0
  75. data/tools/converter.rb +93 -0
  76. data/tools/json_writer.rb +122 -0
  77. data/yinspire.gemspec +20 -0
  78. 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
+ }