yinspire 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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,10 @@
1
+ require 'Yinspire/Models/Neuron_Input'
2
+ require 'Yinspire/Models/Neuron_Output'
3
+ require 'Yinspire/Models/Neuron_SRM01'
4
+ require 'Yinspire/Models/Neuron_SRM02'
5
+ require 'Yinspire/Models/Synapse_Hebb'
6
+ require 'Yinspire/Loaders/Loader_JSON'
7
+ require 'Yinspire/Loaders/Loader_GraphML'
8
+ require 'Yinspire/Loaders/Loader_Yin'
9
+ require 'Yinspire/Loaders/Loader_Spike'
10
+ require 'Yinspire/Dumpers/Dumper_Dot'
@@ -0,0 +1,133 @@
1
+ require 'Yinspire/Core/Simulator'
2
+ require 'Yinspire/Core/Scheduling/NeuralEntity'
3
+
4
+ #
5
+ # NeuralEntity is the base class of all entities in a neural net, i.e.
6
+ # Neurons and Synapses.
7
+ #
8
+ class NeuralEntity
9
+
10
+ #
11
+ # Entity type name to class mapping.
12
+ #
13
+ @@entity_type_map = Hash.new
14
+ def self.entity_type_map() @@entity_type_map end
15
+
16
+
17
+ #
18
+ # Entity class to type name mapping.
19
+ #
20
+ @@entity_type_map_reverse = Hash.new
21
+ def self.entity_type_map_reverse() @@entity_type_map_reverse end
22
+
23
+ def entity_type() @@entity_type_map_reverse[self.class] end
24
+
25
+ #
26
+ # Annotation cache for loading entities.
27
+ #
28
+ @@entity_ann_load_cache = Hash.new
29
+ def self.entity_ann_load_cache() @@entity_ann_load_cache end
30
+
31
+ #
32
+ # Annotation cache for dumping entities.
33
+ #
34
+ @@entity_ann_dump_cache = Hash.new
35
+ def self.entity_ann_dump_cache() @@entity_ann_dump_cache end
36
+
37
+ def self.new_from_name(name, *args, &block)
38
+ (@@entity_type_map[name] || raise(ArgumentError)).new(*args, &block)
39
+ end
40
+
41
+ def self.class_from_name(name)
42
+ (@@entity_type_map[name] || raise(ArgumentError))
43
+ end
44
+
45
+ def load(hash)
46
+ a = @@entity_ann_load_cache[self.class]
47
+ hash.each {|key, value|
48
+ if meth = a[key]
49
+ send(meth, value)
50
+ end
51
+ }
52
+ end
53
+
54
+ def dump
55
+ hash = Hash.new
56
+ @@entity_ann_dump_cache[self.class].each {|key|
57
+ hash[key] = send(key)
58
+ }
59
+ hash
60
+ end
61
+
62
+ def initialize(id=nil, simulator=nil, &block)
63
+ self.id = id
64
+ self.simulator = simulator
65
+ block.call(self) if block
66
+ end
67
+
68
+ #
69
+ # Each NeuralEntity has an +id+ associated which uniquely identifies
70
+ # itself within a Simulator instance. This +id+ is usually assigned by the
71
+ # Simulator (during loading or constructing a neural net) and SHOULD
72
+ # NOT be changed afterwards (because it's used as a key in a Hash).
73
+ #
74
+ property :id
75
+
76
+ #
77
+ # Each NeuralEntity has a reference back to the Simulator. This is
78
+ # used for example to update it's scheduling or to report a fire
79
+ # event.
80
+ #
81
+ # Like +id+, this is assigned by the Simulator.
82
+ #
83
+ property :simulator, Simulator
84
+
85
+ #
86
+ # Connect +self+ with +target+.
87
+ #
88
+ def connect(target) raise "abstract method" end
89
+
90
+ #
91
+ # Disconnect +self+ from all connections.
92
+ #
93
+ def disconnect(target) raise "abstract method" end
94
+
95
+ #
96
+ # Iterates over each connection. To be overwritten by subclasses!
97
+ #
98
+ def each_connection() raise "abstract method" end
99
+
100
+ #
101
+ # Disconnect +self+ from all connections.
102
+ #
103
+ def disconnect_all
104
+ each_connection {|conn| disconnect(conn) }
105
+ end
106
+
107
+ virtual :stimulate, :process, :process_stepped
108
+
109
+ #
110
+ # Stimulate an entity +at+ a specific time with a specific +weight+
111
+ # and from a specific +source+.
112
+ #
113
+ # Overwrite!
114
+ #
115
+ method :stimulate, {:at => 'simtime'},{:weight => 'real'},{:source => NeuralEntity}, nil
116
+
117
+ #
118
+ # This method is called when a NeuralEntity reaches it's scheduling
119
+ # time.
120
+ #
121
+ # Overwrite if you need this behaviour!
122
+ #
123
+ method :process, {:at => 'simtime'}, nil
124
+
125
+ #
126
+ # This method is called in each time-step, if and only if a
127
+ # NeuralEntity had enabled stepped scheduling.
128
+ #
129
+ # Overwrite if you need this behaviour!
130
+ #
131
+ method :process_stepped, {:at => 'simtime'},{:step => 'simtime'}, nil
132
+
133
+ end
@@ -0,0 +1,162 @@
1
+ require 'Yinspire/Core/NeuralEntity'
2
+ require 'Yinspire/Core/Synapse'
3
+
4
+ #
5
+ # Base class of all Neurons. Defines the structure that is special for a
6
+ # Neuron, i.e. that a Neuron has pre- and post-Synapses.
7
+ #
8
+ class Neuron < NeuralEntity
9
+
10
+ property :first_pre_synapse, Synapse
11
+ property :first_post_synapse, Synapse
12
+ property :last_pre_synapse, Synapse
13
+ property :last_post_synapse, Synapse
14
+
15
+ def add_pre_synapse(syn)
16
+ raise ArgumentError, "Synapse expected" unless syn.kind_of?(Synapse)
17
+ raise "Synapse already connected" if syn.post_neuron || syn.next_pre_synapse
18
+
19
+ if last = self.last_pre_synapse
20
+ assert(last.next_pre_synapse == nil) # missing method: neuron instead of synapse
21
+ last.next_pre_synapse = syn
22
+ self.last_pre_synapse = syn # advance tail pointer
23
+ else
24
+ assert(self.first_pre_synapse == nil)
25
+ self.first_pre_synapse = self.last_pre_synapse = syn
26
+ end
27
+
28
+ syn.post_neuron = self
29
+ end
30
+
31
+ def add_post_synapse(syn)
32
+ raise ArgumentError, "Synapse expected" unless syn.kind_of?(Synapse)
33
+ raise "Synapse already connected" if syn.pre_neuron || syn.next_post_synapse
34
+
35
+ if last = self.last_post_synapse
36
+ assert(last.next_post_synapse == nil)
37
+ last.next_post_synapse = syn
38
+ self.last_post_synapse = syn # advance tail pointer
39
+ else
40
+ assert(self.first_post_synapse == nil)
41
+ self.first_post_synapse = self.last_post_synapse = syn
42
+ end
43
+
44
+ syn.pre_neuron = self
45
+ end
46
+
47
+ def delete_pre_synapse(syn)
48
+ raise ArgumentError, "Synapse expected" unless syn.kind_of?(Synapse)
49
+ raise "Synapse not connected to this Neuron" if syn.post_neuron != self
50
+
51
+ prev = find_preceding_synapse(syn, first_pre_synapse(), :next_pre_syapse)
52
+
53
+ #
54
+ # Remove +target+ from linked list.
55
+ #
56
+ if prev
57
+ prev.next_pre_synapse = target.next_post_synapse
58
+ self.last_post_synapse = prev if self.last_post_synapse == target
59
+ else
60
+ #
61
+ # target is the only synapse in the post synapse list.
62
+ #
63
+ assert self.first_post_synapse == target
64
+ assert self.last_post_synapse == target
65
+ self.first_post_synapse = nil
66
+ self.last_post_synapse = nil
67
+ end
68
+
69
+ target.pre_neuron = nil
70
+ target.next_post_synapse = nil
71
+ end
72
+
73
+ def delete_post_synapse(syn)
74
+ # FIXME
75
+ raise "target must be Synapse" unless target.kind_of?(Synapse)
76
+ raise "Synapse not connected to this Neuron" if target.pre_neuron != self
77
+
78
+ #
79
+ # Find the synapse in the linked list that precedes +target+.
80
+ #
81
+ prev = nil
82
+ curr = self.first_post_synapse
83
+
84
+ while true
85
+ break if curr == target
86
+ break unless curr
87
+ prev = curr
88
+ curr = curr.next_post_synapse
89
+ end
90
+
91
+ raise "Synapse not in post synapse list" if curr != target
92
+
93
+ #
94
+ # Remove +target+ from linked list.
95
+ #
96
+ if prev
97
+ prev.next_post_synapse = target.next_post_synapse
98
+ self.last_post_synapse = prev if self.last_post_synapse == target
99
+ else
100
+ #
101
+ # target is the only synapse in the post synapse list.
102
+ #
103
+ assert self.first_post_synapse == target
104
+ assert self.last_post_synapse == target
105
+ self.first_post_synapse = nil
106
+ self.last_post_synapse = nil
107
+ end
108
+
109
+ target.pre_neuron = nil
110
+ target.next_post_synapse = nil
111
+ end
112
+
113
+ alias connect add_post_synapse
114
+ alias disconnect delete_post_synapse
115
+
116
+ #
117
+ # Iterates over each outgoing connection (post synapses).
118
+ #
119
+ def each_connection
120
+ syn = self.first_post_synapse
121
+ while syn
122
+ yield syn
123
+ syn = syn.next_post_synapse
124
+ end
125
+ end
126
+
127
+ protected
128
+
129
+ #
130
+ # Find the synapse in the linked list that precedes +syn+, starting
131
+ # at synapse +first+ and using the +next_method+ chain (e.g.
132
+ # :next_pre_synapse or :next_post_synapse).
133
+ #
134
+ def find_preceding_synapse(syn, first, next_method)
135
+ prev, curr = nil, first
136
+
137
+ while true
138
+ break if curr == syn
139
+ break unless curr
140
+ prev = curr
141
+ curr = curr.send(next_method)
142
+ end
143
+
144
+ raise "Synapse not in pre synapse list" if curr != syn
145
+ return prev
146
+ end
147
+
148
+ method :stimulate_pre_synapses, {:at => 'simtime'}, {:weight => 'real'}, %{
149
+ for (Synapse *syn = @first_pre_synapse; syn != NULL; syn = syn->next_pre_synapse)
150
+ {
151
+ syn->stimulate(at, weight, this);
152
+ }
153
+ }
154
+
155
+ method :stimulate_post_synapses, {:at => 'simtime'}, {:weight => 'real'}, %{
156
+ for (Synapse *syn = @first_post_synapse; syn != NULL; syn = syn->next_post_synapse)
157
+ {
158
+ syn->stimulate(at, weight, this);
159
+ }
160
+ }
161
+
162
+ end
@@ -0,0 +1,123 @@
1
+ #
2
+ # Extends class NeuralEntity for methods related to
3
+ # scheduling.
4
+ #
5
+ class NeuralEntity
6
+
7
+ #
8
+ # The index of this entity in the entity priority queue managed by the
9
+ # Simulator. If +schedule_index+ is zero then the entity is currently
10
+ # not present in the priority queue and as such the entity is not
11
+ # scheduled at a specific time.
12
+ #
13
+ property :schedule_index, 'uint'
14
+
15
+ #
16
+ # If the entity has events in the future, this is the timestamp of the
17
+ # next event.
18
+ #
19
+ property :schedule_at, 'simtime', :init => Infinity
20
+
21
+ #
22
+ # If stepped scheduling is used, these two properties reference the
23
+ # previous/next entity in the stepped-scheduling list.
24
+ #
25
+ property :schedule_stepping_list_prev, NeuralEntity
26
+ property :schedule_stepping_list_next, NeuralEntity
27
+
28
+ #
29
+ # To be able to modify the stepped scheduling list
30
+ # (schedule_stepping_list_prev/next) during stepped schedule
31
+ # processing, we build up an internal linked list that we use to
32
+ # traverse all entities that require stepped schedule processing.
33
+ #
34
+ # This is cheaper than using an externalized linked list, as we would
35
+ # have to allocate memory which we overcome with this approach.
36
+ #
37
+ # This is only used by the simulator!
38
+ #
39
+ property :schedule_stepping_list_internal_next, NeuralEntity
40
+
41
+ #
42
+ # Schedule the entity at a specific time. Only schedule if the new
43
+ # schedule time is before the current schedule time.
44
+ #
45
+ method :schedule, {:at => 'simtime'}, %{
46
+ // FIXME: make sure that @schedule_at is
47
+ // reset when entity is removed from pq!
48
+ if (at < @schedule_at)
49
+ {
50
+ @schedule_at = at;
51
+ @simulator->schedule_update(this);
52
+ }
53
+ }, :inline => true
54
+
55
+ #
56
+ # Returns +true+ if stepped scheduling is enabled, +false+ otherwise.
57
+ #
58
+ method :schedule_stepping_enabled, {:returns => 'bool'}, %{
59
+ return (@schedule_stepping_list_prev != NULL &&
60
+ @schedule_stepping_list_next != NULL);
61
+ }
62
+
63
+ #
64
+ # Enables stepped scheduling.
65
+ #
66
+ method :schedule_enable_stepping, {}, %{
67
+ if (!schedule_stepping_enabled())
68
+ {
69
+ NeuralEntity*& root = @simulator->schedule_stepping_list_root;
70
+ if (root != NULL)
71
+ {
72
+ @schedule_stepping_list_prev = root;
73
+ @schedule_stepping_list_next = root->schedule_stepping_list_next;
74
+ root->schedule_stepping_list_next = this;
75
+ @schedule_stepping_list_next->schedule_stepping_list_prev = this;
76
+ }
77
+ else
78
+ {
79
+ root = this;
80
+ @schedule_stepping_list_prev = this;
81
+ @schedule_stepping_list_next = this;
82
+ }
83
+ }
84
+ }
85
+
86
+ #
87
+ # Disables stepped scheduling.
88
+ #
89
+ method :schedule_disable_stepping, {}, %{
90
+ if (schedule_stepping_enabled())
91
+ {
92
+ if (@schedule_stepping_list_prev != @schedule_stepping_list_next)
93
+ {
94
+ @schedule_stepping_list_prev->schedule_stepping_list_next = @schedule_stepping_list_next;
95
+ @schedule_stepping_list_next->schedule_stepping_list_prev = @schedule_stepping_list_prev;
96
+ }
97
+ else
98
+ {
99
+ /*
100
+ * We are the last entity in the stepping list.
101
+ */
102
+ @simulator->schedule_stepping_list_root = NULL;
103
+ @schedule_stepping_list_prev = NULL;
104
+ @schedule_stepping_list_next = NULL;
105
+ }
106
+ }
107
+ }
108
+
109
+ #
110
+ # Accessor function for BinaryHeap
111
+ #
112
+ static_method :less, {:a => NeuralEntity},{:b => NeuralEntity},{:returns => 'bool'}, %{
113
+ return (a->schedule_at < b->schedule_at);
114
+ }, :inline => true
115
+
116
+ #
117
+ # Accessor function for BinaryHeap
118
+ #
119
+ static_method :index, {:a => NeuralEntity},{:returns => 'uint&'}, %{
120
+ return a->schedule_index;
121
+ }, :inline => true
122
+
123
+ end
@@ -0,0 +1,94 @@
1
+ require 'Yinspire/Core/NeuralEntity'
2
+
3
+ #
4
+ # Extends class Simulator for methods related to
5
+ # scheduling.
6
+ #
7
+ class Simulator
8
+
9
+ #
10
+ # The current simulation time.
11
+ #
12
+ property :schedule_current_time, 'simtime'
13
+
14
+ #
15
+ # The time step used for stepped scheduling.
16
+ #
17
+ property :schedule_step, 'simtime', :init => Infinity
18
+
19
+ #
20
+ # The time of the next step.
21
+ #
22
+ property :schedule_next_step, 'simtime', :init => Infinity
23
+
24
+ #
25
+ # Priority queue used to schedule the entities.
26
+ #
27
+ property :schedule_pq, 'IndexedBinaryHeap<NeuralEntity*, MemoryAllocator<NeuralEntity*>, NeuralEntity>',
28
+ :mark => 'mark_schedule_pq()'
29
+
30
+ method :mark_schedule_pq, {}, %{
31
+ @schedule_pq.each(Simulator::mark_schedule_pq_iter, NULL);
32
+ }
33
+
34
+ static_method :mark_schedule_pq_iter, {:s => 'NeuralEntity* const&'}, {:ptr => 'void*'}, %{
35
+ if (s) rb_gc_mark(s->__obj__);
36
+ }
37
+
38
+ #
39
+ # If stepped scheduling is used, this points to the first entiy in the
40
+ # stepped schedule list.
41
+ #
42
+ property :schedule_stepping_list_root, NeuralEntity
43
+
44
+ #
45
+ # Run the simulation.
46
+ #
47
+ method :schedule_run, {:stop_at => 'simtime'}, %{
48
+ while (true)
49
+ {
50
+ simtime next_stop = MIN(stop_at, @schedule_next_step);
51
+
52
+ /*
53
+ * Calculate all events from the priority queue until the next time
54
+ * step is reached.
55
+ */
56
+ while (!@schedule_pq.empty())
57
+ {
58
+ NeuralEntity *top = @schedule_pq.top();
59
+ if (top->schedule_at >= next_stop)
60
+ break;
61
+ @schedule_current_time = top->schedule_at;
62
+ @schedule_pq.pop();
63
+ top->process(top->schedule_at);
64
+ }
65
+
66
+ if (@schedule_current_time >= stop_at)
67
+ break;
68
+
69
+ if (@schedule_stepping_list_root == NULL && @schedule_pq.empty())
70
+ break;
71
+
72
+ /*
73
+ * Calculate the entities that require stepped processing.
74
+ */
75
+ @schedule_current_time = @schedule_next_step;
76
+
77
+ if (@schedule_stepping_list_root != NULL)
78
+ {
79
+ // FIXME: collect all entities in an array. then process them.
80
+ }
81
+
82
+ @schedule_next_step += @schedule_step;
83
+ }
84
+ }
85
+
86
+ #
87
+ # If an entity has changed it's scheduling time, it has to call this
88
+ # method to reflect the change within the priority queue.
89
+ #
90
+ method :schedule_update, {:entity => NeuralEntity}, %{
91
+ @schedule_pq.update(entity);
92
+ }, :inline => true
93
+
94
+ end