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,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