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,38 @@
1
+ require 'Yinspire/Core/Neuron'
2
+ require 'Yinspire/Core/StimuliMixin'
3
+
4
+ class Neuron_Base < Neuron
5
+
6
+ include StimuliMixin
7
+
8
+ #
9
+ # Duration of the absolute refraction period.
10
+ #
11
+ property :abs_refr_duration, 'simtime', :marshal => true
12
+
13
+ #
14
+ # Last spike time
15
+ #
16
+ property :last_spike_time, 'simtime', :init => -Infinity, :marshal => true
17
+
18
+ #
19
+ # Last fire time
20
+ #
21
+ property :last_fire_time, 'simtime', :init => -Infinity, :marshal => true
22
+
23
+ #
24
+ # Whether this neuron is a hebb neuron or not. A hebb neuron also
25
+ # stimulates it's pre synapses upon firing.
26
+ #
27
+ property :hebb, 'bool', :init => false, :marshal => true
28
+
29
+ method :stimulate_synapses, {:at => 'simtime'}, {:weight => 'real'}, %{
30
+ if (@hebb) stimulate_pre_synapses(at, weight);
31
+ stimulate_post_synapses(at, weight);
32
+ }
33
+
34
+ method :stimulate, {:at => 'simtime'},{:weight => 'real'},{:source => NeuralEntity}, %{
35
+ stimuli_add(at, weight);
36
+ }
37
+
38
+ end
@@ -0,0 +1,12 @@
1
+ require 'Yinspire/Models/Neuron_InputOutput'
2
+
3
+ #
4
+ # Input Neuron. Simply forwards stimuli.
5
+ #
6
+ class Neuron_Input < Neuron_InputOutput
7
+
8
+ method :fire, {:at => 'simtime'},{:weight => 'real'}, %{
9
+ stimulate_synapses(at, weight);
10
+ }
11
+
12
+ end
@@ -0,0 +1,39 @@
1
+ require 'Yinspire/Models/Neuron_Base'
2
+
3
+ #
4
+ # Common base class for input and output neurons. They behave almost
5
+ # the same except for what action is performed once a neuron fires.
6
+ #
7
+ class Neuron_InputOutput < Neuron_Base
8
+
9
+ virtual :fire
10
+ method :fire, {:at => 'simtime'},{:weight => 'real'}, nil
11
+
12
+ #
13
+ # Process each stimuli separately, i.e. it does NOT
14
+ # add stimuli with the same timestamp together.
15
+ #
16
+ method :process, {:at => 'simtime'}, %{
17
+ simtime _at;
18
+ real _weight;
19
+
20
+ while (!@stimuli_pq.empty() && @stimuli_pq.top().at <= at)
21
+ {
22
+ _at = @stimuli_pq.top().at;
23
+ _weight = @stimuli_pq.top().weight;
24
+ @stimuli_pq.pop();
25
+ @simulator->record_fire(_at, _weight, this);
26
+ fire(_at, _weight);
27
+ }
28
+
29
+ /*
30
+ * NOTE: we don't have to remove the entity from the schedule if the
31
+ * pq is empty.
32
+ */
33
+ if (!@stimuli_pq.empty())
34
+ {
35
+ schedule(@stimuli_pq.top().at);
36
+ }
37
+ }
38
+
39
+ end
@@ -0,0 +1,15 @@
1
+ require 'Yinspire/Models/Neuron_InputOutput'
2
+
3
+ #
4
+ # Output Neuron. Used to record fire events.
5
+ #
6
+ class Neuron_Output < Neuron_InputOutput
7
+
8
+ stub_method :fire, {:at => 'simtime'},{:weight => 'real'}
9
+
10
+ #
11
+ # Overwrite
12
+ #
13
+ def fire(at, weight) end
14
+
15
+ end
@@ -0,0 +1,50 @@
1
+ require 'Yinspire/Models/Neuron_Base'
2
+
3
+ #
4
+ # Formerly known as KernelbasedLIF
5
+ #
6
+ class Neuron_SRM01 < Neuron_Base
7
+
8
+ property :tau_m, 'real', :marshal => true
9
+ property :tau_ref, 'real', :marshal => true
10
+ property :ref_weight, 'real', :marshal => true
11
+ property :mem_pot, 'real', :marshal => true
12
+ property :const_threshold, 'real', :marshal => true
13
+
14
+ method :stimulate, {:at => 'simtime'},{:weight => 'real'},{:source => NeuralEntity}, %{
15
+ if (at >= @last_fire_time + @abs_refr_duration)
16
+ {
17
+ @simulator->event_counter++;
18
+ super::stimulate(at, weight, source);
19
+ }
20
+ }
21
+
22
+ method :process, {:at => 'simtime'}, %{
23
+ real weight = stimuli_sum(at);
24
+ const real delta = at - @last_fire_time - @abs_refr_duration;
25
+
26
+ if (delta < 0.0) return;
27
+
28
+ /*
29
+ * Calculate new membrane potential
30
+ */
31
+
32
+ @mem_pot = weight + @mem_pot * real_exp( -(at - @last_spike_time)/@tau_m );
33
+ @last_spike_time = at;
34
+
35
+ /*
36
+ * Calculate dynamic threshold
37
+ */
38
+ const real dynamic_threshold = @ref_weight * real_exp(-delta/@tau_ref);
39
+
40
+ if (@mem_pot >= @const_threshold + dynamic_threshold)
41
+ {
42
+ /* Fire */
43
+ @mem_pot = 0.0;
44
+ @last_fire_time = at;
45
+ @simulator->record_fire(at, Infinity, this);
46
+ stimulate_synapses(at, Infinity);
47
+ }
48
+ }
49
+
50
+ end
@@ -0,0 +1,64 @@
1
+ require 'Yinspire/Models/Neuron_Base'
2
+
3
+ #
4
+ # Formerly known as SpecialEKernel
5
+ #
6
+ class Neuron_SRM02 < Neuron_Base
7
+
8
+ property :tau_m, 'real', :marshal => true
9
+ property :tau_ref, 'real', :marshal => true
10
+ property :reset, 'real', :marshal => true
11
+ property :u_reset, 'real', :marshal => true
12
+ property :mem_pot, 'real', :marshal => true
13
+ property :const_threshold, 'real', :marshal => true
14
+
15
+ method :stimulate, {:at => 'simtime'},{:weight => 'real'},{:source => NeuralEntity}, %{
16
+ @simulator->event_counter++;
17
+ super::stimulate(at, weight, source);
18
+ }
19
+
20
+ method :process, {:at => 'simtime'}, %{
21
+ real weight = stimuli_sum(at);
22
+
23
+ /*
24
+ * Calculate new membrane potential
25
+ */
26
+
27
+ @mem_pot = weight + @mem_pot * real_exp( -(at - @last_spike_time)/@tau_m );
28
+ @last_spike_time = at;
29
+
30
+ if (at < @last_fire_time + @abs_refr_duration)
31
+ return;
32
+
33
+ /*
34
+ * Calculate dynamic reset
35
+ */
36
+ const real delta = at - @last_fire_time - @abs_refr_duration;
37
+ const real dynamic_reset = @reset * real_exp(-delta/@tau_ref);
38
+
39
+ if (@mem_pot >= @const_threshold + dynamic_reset)
40
+ {
41
+ /* Fire */
42
+
43
+ if (@abs_refr_duration > 0.0)
44
+ {
45
+ schedule(at + @abs_refr_duration);
46
+ }
47
+
48
+ if (isinf(@mem_pot))
49
+ {
50
+ @mem_pot = 0.0;
51
+ @reset = @u_reset;
52
+ }
53
+ else
54
+ {
55
+ @reset = dynamic_reset + @u_reset;
56
+ }
57
+ @last_fire_time = at;
58
+
59
+ @simulator->record_fire(at, Infinity, this);
60
+ stimulate_synapses(at, Infinity);
61
+ }
62
+ }
63
+
64
+ end
@@ -0,0 +1,67 @@
1
+ class Synapse_Hebb < Synapse
2
+
3
+ property :last_post_neuron_fire_time, 'simtime', :init => -Infinity, :marshal => true
4
+ property :current_post_neuron_fire_time, 'simtime', :init => -Infinity, :marshal => true
5
+ property :learning_rate, 'real', :init => 0.01, :marshal => true
6
+ property :decrease_rate, 'real', :init => 0.00005, :marshal => true
7
+ property :pre_synaptic_spikes, 'Array<simtime>'
8
+
9
+ #
10
+ # Default arguments for learning_window method
11
+ #
12
+ DEFAULT_LW_ARGS = "1, 1, 10, 8"
13
+
14
+ method :stimulate, {:at => 'simtime'},{:weight => 'real'},{:source => NeuralEntity}, %{
15
+ if (source != @post_neuron)
16
+ {
17
+ @pre_synaptic_spikes.push(at);
18
+
19
+ if (@last_post_neuron_fire_time > 0.0)
20
+ {
21
+ real delta_time = @last_post_neuron_fire_time - at;
22
+ real delta_weight = @learning_rate * learning_window(delta_time, #{DEFAULT_LW_ARGS});
23
+
24
+ if (@pre_synaptic_spikes.size() > 1)
25
+ {
26
+ delta_time = @pre_synaptic_spikes[@pre_synaptic_spikes.size() - 2] - at;
27
+ }
28
+
29
+ delta_weight += @decrease_rate * delta_time;
30
+ @weight += (1.0 - real_fabs(@weight)) * delta_weight;
31
+ }
32
+
33
+ @post_neuron->stimulate(at+@delay, @weight, this);
34
+ }
35
+ else
36
+ {
37
+ @last_post_neuron_fire_time = @current_post_neuron_fire_time;
38
+ @current_post_neuron_fire_time = at;
39
+
40
+ real delta_weight = 0.0;
41
+
42
+ for (int i=0; i < @pre_synaptic_spikes.size(); i++)
43
+ {
44
+ delta_weight += @learning_rate * learning_window(at - @pre_synaptic_spikes[i], #{DEFAULT_LW_ARGS});
45
+ }
46
+
47
+ @weight += (1.0 - real_fabs(@weight)) * delta_weight;
48
+ @pre_synaptic_spikes.clear();
49
+ }
50
+ }
51
+
52
+ static_method :learning_window,
53
+ {:delta_x => 'real'},
54
+ {:pos_ramp => 'real'},{:neg_ramp => 'real'},
55
+ {:pos_decay => 'real'},{:neg_decay => 'real'},
56
+ {:returns => 'real'}, %{
57
+ if (delta_x >= 0)
58
+ {
59
+ return (pos_ramp * delta_x * real_exp(-delta_x/pos_decay));
60
+ }
61
+ else
62
+ {
63
+ return (neg_ramp * delta_x * real_exp(delta_x/neg_decay));
64
+ }
65
+ }
66
+
67
+ end
@@ -0,0 +1,22 @@
1
+ CC=g++
2
+ #PROFILE=-O0 -pg -g
3
+ CFLAGS=-DNDEBUG -O3 -Winline -Wall -DWITHOUT_MMAP -I${PWD}/src
4
+
5
+ DEPS=src/algo/binary_heap.h src/algo/indexed_binary_heap.h src/memory_allocator.h \
6
+ src/neuron.h src/neuron_srm_01.h src/simulator.h \
7
+ src/synapse.h src/types.h \
8
+ src/neural_entity.cc src/neuron.cc src/neuron_srm_01.cc \
9
+ src/simulator.cc src/synapse.cc \
10
+ src/main.cc \
11
+ src/json/json.h src/json/json_parser.h src/json/json.cc src/json/json_parser.cc \
12
+ Makefile
13
+
14
+ inspire: ${DEPS}
15
+ ${CC} ${CFLAGS} `find src -name '*.cc'` -o inspire ${LDFLAGS}
16
+
17
+ src/json/json_parser.cc: src/json/json_parser.rl
18
+ ragel src/json/json_parser.rl | rlgen-cd -o src/json/json_parser.cc
19
+
20
+ clean:
21
+ rm -f inspire
22
+
@@ -0,0 +1,2 @@
1
+ Compile with -DWITHOUT_MMAP on Windows or any other platform that does
2
+ not support mmap(2).
@@ -0,0 +1,277 @@
1
+ /*
2
+ * An implicit Binary Heap.
3
+ *
4
+ * Copyright (c) 2007, 2008 by Michael Neumann (mneumann@ntecs.de)
5
+ *
6
+ * NOTE: We start counting from 1 in the elements array!
7
+ *
8
+ * Template parameters:
9
+ *
10
+ * E: Element type
11
+ * Alloc: Allocator
12
+ * Acc: Accessor struct. Defines ordering relation (less).
13
+ * MIN_CAPA: minimum number of elements
14
+ *
15
+ * Example:
16
+ *
17
+ * struct Acc
18
+ * {
19
+ * static inline bool less(const int& a, const int& b)
20
+ * {
21
+ * return a < b;
22
+ * }
23
+ * };
24
+ *
25
+ * BinaryHeap<int, MemoryAllocator, Acc> heap;
26
+ * heap.push(4);
27
+ * heap.pop();
28
+ * ...
29
+ *
30
+ */
31
+
32
+ #ifndef __YINSPIRE__BINARY_HEAP__
33
+ #define __YINSPIRE__BINARY_HEAP__
34
+
35
+ #include <assert.h>
36
+
37
+ /*
38
+ * This is used to be able to keep track of
39
+ * an elements index in the IndexedBinaryHeap subclass.
40
+ * Unused in this class.
41
+ */
42
+ template <typename E>
43
+ struct BinaryHeapDummyIndexer
44
+ {
45
+ static inline void index_changed(E& e, unsigned int i)
46
+ {
47
+ /* DUMMY */
48
+ }
49
+ };
50
+
51
+ template <typename E, class Alloc, class Acc=E, class Idx=BinaryHeapDummyIndexer<E>, unsigned int MIN_CAPA=1024>
52
+ class BinaryHeap
53
+ {
54
+ typedef unsigned int I; // index type
55
+
56
+ public:
57
+
58
+ BinaryHeap()
59
+ {
60
+ this->capacity = 0;
61
+ this->size_ = 0;
62
+ this->elements = NULL; // we do lazy allocation!
63
+ }
64
+
65
+ ~BinaryHeap()
66
+ {
67
+ if (this->elements != NULL)
68
+ {
69
+ Alloc::free(this->elements+1);
70
+ }
71
+ this->elements = NULL;
72
+ }
73
+
74
+ inline E&
75
+ top() const
76
+ {
77
+ assert(this->size > 0);
78
+ return this->elements[1];
79
+ }
80
+
81
+ void
82
+ pop()
83
+ {
84
+ remove(1);
85
+ }
86
+
87
+ inline void
88
+ remove(I i)
89
+ {
90
+ assert(i <= this->size_);
91
+
92
+ //
93
+ // Element i is removed from the heap and as such becomes
94
+ // a "bubble" (free element). Move the bubble until
95
+ // the bubble becomes a leaf element.
96
+ //
97
+ Idx::index_changed(this->elements[i], 0); // detach from heap
98
+ I bubble = move_bubble_down(i);
99
+
100
+ //
101
+ // Now take the last element and insert it at the position of
102
+ // the bubble. In case the bubble is already the last element we
103
+ // are done.
104
+ //
105
+ if (bubble != this->size_)
106
+ {
107
+ insert_and_bubble_up(bubble, this->elements[this->size_]);
108
+ }
109
+ --this->size_;
110
+ }
111
+
112
+ void
113
+ push(const E& element)
114
+ {
115
+ if (this->size_ >= this->capacity) resize(2*this->capacity);
116
+ insert_and_bubble_up(++this->size_, element);
117
+ }
118
+
119
+ inline I
120
+ size() const
121
+ {
122
+ return this->size_;
123
+ }
124
+
125
+ inline bool
126
+ empty() const
127
+ {
128
+ return (this->size_ == 0);
129
+ }
130
+
131
+ /*
132
+ * A return value of +false+ means that the element wasn't accumulated with
133
+ * another element and as such has to be inserted into the heap.
134
+ */
135
+ bool
136
+ accumulate(const E& element, bool (*accum)(E&,const E&,void*), void *data)
137
+ {
138
+ I i;
139
+
140
+ //
141
+ // Find the position of the first element that is less than +element+.
142
+ //
143
+ for (i = this->size_; i != 0 && Acc::less(element, this->elements[i]); i /= 2);
144
+
145
+ assert(i == 0 || Acc::less(this->elements[i], element));
146
+
147
+ if (i == 0 || !accum(this->elements[i], element, data))
148
+ {
149
+ return false;
150
+ }
151
+ return true;
152
+ }
153
+
154
+ /*
155
+ * Iterate over all elements (non-destructive)
156
+ */
157
+ void
158
+ each(void (*yield)(const E&, void*), void *data)
159
+ {
160
+ for (I i=1; i <= this->size_; i++)
161
+ {
162
+ yield(this->elements[i], data);
163
+ }
164
+ }
165
+
166
+ protected:
167
+
168
+ /*
169
+ * Insert +element+ into the heap beginning from
170
+ * +i+ and searching upwards to the root for the
171
+ * right position (heap ordered) to insert.
172
+ *
173
+ * Element at index +i+ MUST be empty, i.e. unused!
174
+ */
175
+ inline void
176
+ insert_and_bubble_up(I i, const E& element)
177
+ {
178
+ for (;i >= 2 && Acc::less(element, this->elements[i/2]); i /= 2)
179
+ {
180
+ store_element(i, this->elements[i/2]);
181
+ }
182
+
183
+ // finally store it into the determined hole
184
+ store_element(i, element);
185
+ }
186
+
187
+ /*
188
+ * Move the bubble (empty element) at +i+ down in direction
189
+ * to the leaves. When the bubble reaches a leaf, stop and
190
+ * return the index of the leaf element which is now empty.
191
+ */
192
+ inline I
193
+ move_bubble_down(I i)
194
+ {
195
+ const I sz = this->size_;
196
+ I right_child = i * 2 + 1;
197
+
198
+ while (right_child <= sz)
199
+ {
200
+ if (Acc::less(this->elements[right_child-1], this->elements[right_child]))
201
+ {
202
+ --right_child; // minimum child is left child
203
+ }
204
+
205
+ store_element(i, this->elements[right_child]);
206
+ i = right_child;
207
+ right_child = i * 2 + 1;
208
+ }
209
+
210
+ //
211
+ // Edge case (comparison with the last element)
212
+ //
213
+ if (right_child-1 == sz)
214
+ {
215
+ store_element(i, this->elements[right_child-1]);
216
+ i = right_child-1;
217
+ }
218
+
219
+ return i;
220
+ }
221
+
222
+ /*
223
+ * The 0'th element is never used (accessed), so
224
+ * we allocate only "capacity" elements (instead of capacity+1)
225
+ * and move the pointer one element before the begin of the
226
+ * allocated memory.
227
+ */
228
+ void
229
+ resize(I new_capacity)
230
+ {
231
+ E *new_elements;
232
+
233
+ if (new_capacity < MIN_CAPA) this->capacity = MIN_CAPA;
234
+ else this->capacity = new_capacity;
235
+
236
+ //
237
+ // We do lazy allocation!
238
+ //
239
+ if (this->elements != NULL)
240
+ {
241
+ new_elements = Alloc::realloc_n(this->elements+1, this->capacity);
242
+ }
243
+ else
244
+ {
245
+ new_elements = Alloc::alloc_n(this->capacity);
246
+ }
247
+
248
+ assert(new_elements != NULL);
249
+ assert(this->capacity >= this->size);
250
+
251
+ //
252
+ // move pointer so that we "introduce" a zero'th
253
+ // element.
254
+ //
255
+ this->elements = new_elements-1;
256
+ }
257
+
258
+ /*
259
+ * FIXME: cannot overwrite method in a subclass
260
+ * The only purpose of this method is that we overwrite it in the
261
+ * subclass IndexedBinaryHeap to keep track of an elements index.
262
+ */
263
+ inline void
264
+ store_element(I i, const E& element)
265
+ {
266
+ this->elements[i] = element;
267
+ Idx::index_changed(this->elements[i], i);
268
+ }
269
+
270
+ protected:
271
+
272
+ I size_;
273
+ E *elements;
274
+ I capacity;
275
+ };
276
+
277
+ #endif