PriorityQueue 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.
- data/CHANGELOG +19 -0
- data/README +85 -0
- data/benchmark/dijkstra.rb +169 -0
- data/benchmark/result-CPriorityQueue.gp +8 -0
- data/benchmark/result-CPriorityQueue.png +0 -0
- data/benchmark/result-PoorPriorityQueue.gp +8 -0
- data/benchmark/result-PoorPriorityQueue.png +0 -0
- data/benchmark/result-PriorityQueue.gp +6 -0
- data/benchmark/result-RubyPriorityQueue.gp +8 -0
- data/benchmark/result-RubyPriorityQueue.png +0 -0
- data/benchmark/results.csv +37 -0
- data/benchmark/results.gp +10 -0
- data/benchmark/results.png +0 -0
- data/doc/result-PoorPriorityQueue.png +0 -0
- data/doc/result-PriorityQueue.png +0 -0
- data/doc/result-RubyPriorityQueue.png +0 -0
- data/doc/results.png +0 -0
- data/ext/priority_queue/extconf.rb +2 -0
- data/ext/priority_queue/priority_queue.c +874 -0
- data/lib/priority_queue.rb +14 -0
- data/lib/priority_queue/poor_priority_queue.rb +46 -0
- data/lib/priority_queue/ruby_priority_queue.rb +394 -0
- data/setup.rb +1551 -0
- data/test.rb +11 -0
- data/test/priority_queue_test.rb +358 -0
- metadata +78 -0
data/test.rb
ADDED
@@ -0,0 +1,358 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
# Priority Queue tests
|
4
|
+
|
5
|
+
$:.unshift '../ext/priority_queue/CPriorityQueue'
|
6
|
+
$:.unshift '../lib/'
|
7
|
+
|
8
|
+
require 'test/unit'
|
9
|
+
|
10
|
+
require 'priority_queue/ruby_priority_queue'
|
11
|
+
require 'priority_queue/poor_priority_queue'
|
12
|
+
begin
|
13
|
+
require 'priority_queue/CPriorityQueue'
|
14
|
+
rescue LoadError
|
15
|
+
require 'CPriorityQueue'
|
16
|
+
end
|
17
|
+
|
18
|
+
|
19
|
+
module PriorityQueueTest
|
20
|
+
# Check that the order is maintained
|
21
|
+
def teardown
|
22
|
+
last = @q.min_priority
|
23
|
+
while priority = @q.delete_min_return_priority
|
24
|
+
assert_operator(last, :<=, priority)
|
25
|
+
last = priority
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_length
|
30
|
+
20.times do | i |
|
31
|
+
assert_equal(i, @q.length)
|
32
|
+
@q[i] = i
|
33
|
+
end
|
34
|
+
10.times do | i |
|
35
|
+
assert_equal(20-i, @q.length)
|
36
|
+
@q.delete_min
|
37
|
+
end
|
38
|
+
10.times do | i |
|
39
|
+
assert_equal(10+i, @q.length)
|
40
|
+
@q[i] = i
|
41
|
+
end
|
42
|
+
@q.delete(5)
|
43
|
+
assert_equal(19, @q.length)
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_merge
|
47
|
+
@q1 = @q.class.new
|
48
|
+
@q2 = @q.class.new
|
49
|
+
|
50
|
+
20.times do | i |
|
51
|
+
@q1[i] = i
|
52
|
+
@q2[i+20] = i+20
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# Assure that delete min works
|
57
|
+
def test_delete_min
|
58
|
+
assert_equal(nil, @q.delete_min, "Empty queue should pop nil")
|
59
|
+
@q["n1"] = 0
|
60
|
+
assert_equal(["n1", 0], @q.delete_min)
|
61
|
+
@q["n1"] = 0
|
62
|
+
@q["n2"] = -1
|
63
|
+
assert_equal(["n2", -1], @q.delete_min)
|
64
|
+
end
|
65
|
+
|
66
|
+
def test_delete_min_return_key
|
67
|
+
assert_equal(nil, @q.delete_min_return_key, "Empty queue should pop nil")
|
68
|
+
@q["n1"] = 0
|
69
|
+
assert_equal("n1", @q.delete_min_return_key)
|
70
|
+
@q["n1"] = 0
|
71
|
+
@q["n2"] = -1
|
72
|
+
assert_equal("n2", @q.delete_min_return_key)
|
73
|
+
end
|
74
|
+
|
75
|
+
def test_delete_min_return_priority
|
76
|
+
assert_equal(nil, @q.delete_min_return_priority, "Empty queue should pop nil")
|
77
|
+
@q["n1"] = 0
|
78
|
+
assert_equal(0, @q.delete_min_return_priority)
|
79
|
+
@q["n1"] = 0
|
80
|
+
@q["n2"] = -1
|
81
|
+
assert_equal(-1, @q.delete_min_return_priority)
|
82
|
+
end
|
83
|
+
|
84
|
+
def test_has_key?
|
85
|
+
assert(!@q.has_key?(1))
|
86
|
+
@q[1] = 1
|
87
|
+
assert(@q.has_key?(1))
|
88
|
+
end
|
89
|
+
|
90
|
+
def test_empty?
|
91
|
+
assert_equal(true, @q.empty?, "Empty queue should return true on empty?")
|
92
|
+
@q["node1"] = 10
|
93
|
+
assert_equal(false, @q.empty?, "Filled queue should return false on empty?")
|
94
|
+
end
|
95
|
+
|
96
|
+
def test_push_pop
|
97
|
+
20.times do | i |
|
98
|
+
@q.push i, i
|
99
|
+
end
|
100
|
+
|
101
|
+
20.times do | i |
|
102
|
+
assert_equal([i, i], @q.delete_min)
|
103
|
+
end
|
104
|
+
|
105
|
+
assert_equal(nil, @q.delete_min)
|
106
|
+
end
|
107
|
+
|
108
|
+
def test_push_decrease_pop
|
109
|
+
50.times do | i |
|
110
|
+
@q.push i, i
|
111
|
+
end
|
112
|
+
|
113
|
+
10.times do | i |
|
114
|
+
assert_equal([i, i], @q.delete_min)
|
115
|
+
end
|
116
|
+
|
117
|
+
10.times do | i |
|
118
|
+
@q[i+10] = i
|
119
|
+
end
|
120
|
+
|
121
|
+
10.times do | i |
|
122
|
+
assert_equal([i+10, i], @q.delete_min)
|
123
|
+
end
|
124
|
+
|
125
|
+
30.times do | i |
|
126
|
+
assert_equal([i+20, i+20], @q.delete_min)
|
127
|
+
end
|
128
|
+
|
129
|
+
assert_equal(nil, @q.delete_min)
|
130
|
+
end
|
131
|
+
|
132
|
+
def test_min_key
|
133
|
+
assert_equal(nil, @q.min_key)
|
134
|
+
@q["node1"] = 0
|
135
|
+
assert_equal("node1", @q.min_key)
|
136
|
+
@q["node2"] = 1
|
137
|
+
assert_equal("node1", @q.min_key)
|
138
|
+
@q["node3"] = -1
|
139
|
+
assert_equal("node3", @q.min_key)
|
140
|
+
end
|
141
|
+
|
142
|
+
def test_min_priority
|
143
|
+
assert_equal(nil, @q.min_priority)
|
144
|
+
@q["node1"] = 0
|
145
|
+
assert_equal(0, @q.min_priority)
|
146
|
+
@q["node2"] = 1
|
147
|
+
assert_equal(0, @q.min_priority)
|
148
|
+
@q["node3"] = -1
|
149
|
+
assert_equal(-1, @q.min_priority)
|
150
|
+
end
|
151
|
+
|
152
|
+
def test_access
|
153
|
+
assert_equal(0, @q["node1"] = 0)
|
154
|
+
assert_equal(["node1", 0], @q.min)
|
155
|
+
assert_equal(1, @q["node2"] = 1)
|
156
|
+
assert_equal(1, @q["node2"])
|
157
|
+
assert_equal("node1", @q.min_key)
|
158
|
+
assert_equal(2, @q["node3"] = 2)
|
159
|
+
assert_equal(2, @q["node3"])
|
160
|
+
assert_equal("node1", @q.min_key)
|
161
|
+
assert_equal(-1, @q["node3"] = -1)
|
162
|
+
assert_equal(-1, @q["node3"])
|
163
|
+
assert_equal("node3", @q.min_key)
|
164
|
+
end
|
165
|
+
|
166
|
+
def test_min
|
167
|
+
assert_equal(nil, @q.min)
|
168
|
+
@q["node1"] = 10
|
169
|
+
assert_equal(["node1", 10], @q.min)
|
170
|
+
@q["node2"] = 5
|
171
|
+
assert_equal(["node2", 5], @q.min)
|
172
|
+
end
|
173
|
+
|
174
|
+
def test_decrease_priority
|
175
|
+
|
176
|
+
20.times do | i |
|
177
|
+
@q.push i, i / 20.0
|
178
|
+
end
|
179
|
+
|
180
|
+
assert_equal([0, 0], @q.delete_min)
|
181
|
+
|
182
|
+
@q[10] = -1
|
183
|
+
@q[11] = -0.5
|
184
|
+
|
185
|
+
[10, 11, (1..9).to_a, (12..19).to_a, nil].flatten.each do | shall |
|
186
|
+
key, priority = *@q.delete_min
|
187
|
+
assert_equal(shall, key)
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
def test_increase_priority
|
192
|
+
20.times do | i |
|
193
|
+
@q[i] = i
|
194
|
+
end
|
195
|
+
@q[10] = 5
|
196
|
+
assert_equal([0,0], @q.delete_min)
|
197
|
+
assert_equal(10, @q[10] = 10)
|
198
|
+
assert_equal(20, @q[11] = 20)
|
199
|
+
assert_equal([1,1], @q.delete_min)
|
200
|
+
end
|
201
|
+
|
202
|
+
def test_delete
|
203
|
+
@q[1] = 1
|
204
|
+
@q[2] = 2
|
205
|
+
@q[3] = 3
|
206
|
+
assert_equal(1, @q[1])
|
207
|
+
assert_equal([1,1], @q.min)
|
208
|
+
assert_equal([1,1], @q.delete(1))
|
209
|
+
assert_equal(nil, @q[1])
|
210
|
+
assert_equal([2,2], @q.min)
|
211
|
+
assert_equal(nil, @q.delete(1))
|
212
|
+
end
|
213
|
+
|
214
|
+
def test_example_1
|
215
|
+
assert_equal(0, @q["node1"] = 0)
|
216
|
+
assert_equal(1, @q["node2"] = 1)
|
217
|
+
assert_equal("node1", @q.min_key)
|
218
|
+
assert_equal(0, @q[@q.min_key])
|
219
|
+
assert_equal(0, @q.min_priority)
|
220
|
+
|
221
|
+
@q["node2"] = -1
|
222
|
+
assert_equal(["node2", -1], @q.delete_min)
|
223
|
+
assert_equal(nil, @q["node2"])
|
224
|
+
@q["node3"] = 1
|
225
|
+
|
226
|
+
assert_equal(["node3", 1], @q.delete("node3"))
|
227
|
+
assert_equal(nil, @q.delete("node2"))
|
228
|
+
end
|
229
|
+
|
230
|
+
def test_dup
|
231
|
+
('a'..'z').each do | n |
|
232
|
+
@q[n] = n[0]
|
233
|
+
end
|
234
|
+
qq = @q.dup
|
235
|
+
until @q.empty?
|
236
|
+
puts "--"
|
237
|
+
puts @q.inspect
|
238
|
+
puts qq.inspect
|
239
|
+
assert_equal(@q.delete_min, qq.delete_min)
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
def test_each
|
244
|
+
('a'..'z').each do | n |
|
245
|
+
@q[n] = n[0]
|
246
|
+
end
|
247
|
+
queue = ('a'..'z').inject([]) { | r, n | r << [n, n[0]] }
|
248
|
+
assert_equal(queue.sort, @q.to_a.sort)
|
249
|
+
end
|
250
|
+
|
251
|
+
extend self
|
252
|
+
end
|
253
|
+
|
254
|
+
class CPriorityQueueTest #< Test::Unit::TestCase
|
255
|
+
include PriorityQueueTest
|
256
|
+
|
257
|
+
def setup
|
258
|
+
@q = CPriorityQueue.new
|
259
|
+
end
|
260
|
+
|
261
|
+
def test_to_dot
|
262
|
+
5.times do | i |
|
263
|
+
@q.push "N#{i}", i
|
264
|
+
end
|
265
|
+
@q.delete_min
|
266
|
+
assert_equal(
|
267
|
+
['digraph fibonaccy_heap {',
|
268
|
+
' NODE [label="N1 (1)",shape=box];',
|
269
|
+
' NODE [label="N3 (3)",shape=box];',
|
270
|
+
' NODE [label="N4 (4)",shape=box];',
|
271
|
+
' NODE -> NODE;',
|
272
|
+
' NODE -> NODE;',
|
273
|
+
' NODE [label="N2 (2)",shape=box];',
|
274
|
+
' NODE -> NODE;',
|
275
|
+
'}',''].join("\n"), @q.to_dot.gsub(/NODE[0-9]*/, 'NODE'))
|
276
|
+
end
|
277
|
+
|
278
|
+
end
|
279
|
+
|
280
|
+
class PoorPriorityQueueTest #< Test::Unit::TestCase
|
281
|
+
include PriorityQueueTest
|
282
|
+
|
283
|
+
def setup
|
284
|
+
@q = PoorPriorityQueue.new
|
285
|
+
end
|
286
|
+
|
287
|
+
end
|
288
|
+
|
289
|
+
class RubyPriorityQueueTest < Test::Unit::TestCase
|
290
|
+
include PriorityQueueTest
|
291
|
+
|
292
|
+
def setup
|
293
|
+
@q = RubyPriorityQueue.new
|
294
|
+
end
|
295
|
+
|
296
|
+
def test_private_link_nodes
|
297
|
+
q = RubyPriorityQueue.new
|
298
|
+
q[0] = 0
|
299
|
+
q[1] = 1
|
300
|
+
tc = self
|
301
|
+
q.instance_eval do
|
302
|
+
n0 = @nodes[0]
|
303
|
+
n1 = @nodes[1]
|
304
|
+
n0.right = n0.left = n0
|
305
|
+
n1.right = n1.left = n1
|
306
|
+
tc.assert_equal(n0, link_nodes(n0, n1))
|
307
|
+
tc.assert_equal(n0.child, n1)
|
308
|
+
tc.assert_equal(n1.child, nil)
|
309
|
+
tc.assert_equal(n0.left, n0)
|
310
|
+
tc.assert_equal(n1.left, n1)
|
311
|
+
tc.assert_equal(n0.right, n0)
|
312
|
+
tc.assert_equal(n1.right, n1)
|
313
|
+
end
|
314
|
+
q = RubyPriorityQueue.new
|
315
|
+
q[0] = 0
|
316
|
+
q[1] = 1
|
317
|
+
q.instance_eval do
|
318
|
+
n0 = @nodes[0]
|
319
|
+
n1 = @nodes[1]
|
320
|
+
n0.right = n0.left = n0
|
321
|
+
n1.right = n1.left = n1
|
322
|
+
tc.assert_equal(n0, link_nodes(n1, n0))
|
323
|
+
tc.assert_equal(n0.child, n1)
|
324
|
+
tc.assert_equal(n1.child, nil)
|
325
|
+
tc.assert_equal(n0.left, n0)
|
326
|
+
tc.assert_equal(n1.left, n1)
|
327
|
+
tc.assert_equal(n0.right, n0)
|
328
|
+
tc.assert_equal(n1.right, n1)
|
329
|
+
end
|
330
|
+
end
|
331
|
+
|
332
|
+
|
333
|
+
def test_private_delete_first
|
334
|
+
q = RubyPriorityQueue.new
|
335
|
+
q[0] = 0
|
336
|
+
q[1] = 1
|
337
|
+
q[2] = 2
|
338
|
+
tc = self
|
339
|
+
q.instance_eval do
|
340
|
+
2.times do
|
341
|
+
r = @rootlist
|
342
|
+
tc.assert_equal(r, delete_first)
|
343
|
+
tc.assert_equal(r.right, r)
|
344
|
+
tc.assert_equal(r.left, r)
|
345
|
+
tc.assert_not_equal(r, @rootlist.left)
|
346
|
+
tc.assert_not_equal(r, @rootlist.right)
|
347
|
+
end
|
348
|
+
r = @rootlist
|
349
|
+
tc.assert_equal(r, delete_first)
|
350
|
+
tc.assert_equal(r.right, r)
|
351
|
+
tc.assert_equal(r.left, r)
|
352
|
+
tc.assert_equal(nil, @rootlist)
|
353
|
+
|
354
|
+
tc.assert_equal(nil, delete_first)
|
355
|
+
end
|
356
|
+
end
|
357
|
+
end
|
358
|
+
|
metadata
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
rubygems_version: 0.8.11
|
3
|
+
specification_version: 1
|
4
|
+
name: PriorityQueue
|
5
|
+
version: !ruby/object:Gem::Version
|
6
|
+
version: 0.1.0
|
7
|
+
date: 2005-10-26 00:00:00 +02:00
|
8
|
+
summary: This is a fibonacy heap priority queue implementation
|
9
|
+
require_paths:
|
10
|
+
- lib
|
11
|
+
- lib
|
12
|
+
- ext
|
13
|
+
email: priority_queue@brian-schroeder.de
|
14
|
+
homepage: http://ruby.brian-schroeder.de/priority_queue
|
15
|
+
rubyforge_project:
|
16
|
+
description: "This is a fibonacy heap priority queue implementation. That means insert:
|
17
|
+
O(1) decrease_priority: Amortized O(1) delete_min: Amortized O(log n)
|
18
|
+
This project is different from K. Kodamas PQueue in that it allows a decrease
|
19
|
+
key operation. That makes PriorityQueue usable for algorithms like dijkstras
|
20
|
+
shortest path algorithm, while PQueue is more suitable for Heapsort and the
|
21
|
+
like."
|
22
|
+
autorequire: priority_queue.rb
|
23
|
+
default_executable:
|
24
|
+
bindir: bin
|
25
|
+
has_rdoc: true
|
26
|
+
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
27
|
+
requirements:
|
28
|
+
-
|
29
|
+
- ">"
|
30
|
+
- !ruby/object:Gem::Version
|
31
|
+
version: 0.0.0
|
32
|
+
version:
|
33
|
+
platform: ruby
|
34
|
+
signing_key:
|
35
|
+
cert_chain:
|
36
|
+
authors:
|
37
|
+
- Brian Schroeder
|
38
|
+
files:
|
39
|
+
- README
|
40
|
+
- test.rb
|
41
|
+
- CHANGELOG
|
42
|
+
- setup.rb
|
43
|
+
- doc
|
44
|
+
- ext
|
45
|
+
- lib
|
46
|
+
- test
|
47
|
+
- benchmark
|
48
|
+
- doc/result-PriorityQueue.png
|
49
|
+
- doc/results.png
|
50
|
+
- doc/result-PoorPriorityQueue.png
|
51
|
+
- doc/result-RubyPriorityQueue.png
|
52
|
+
- ext/priority_queue
|
53
|
+
- ext/priority_queue/extconf.rb
|
54
|
+
- ext/priority_queue/priority_queue.c
|
55
|
+
- lib/priority_queue.rb
|
56
|
+
- lib/priority_queue
|
57
|
+
- lib/priority_queue/poor_priority_queue.rb
|
58
|
+
- lib/priority_queue/ruby_priority_queue.rb
|
59
|
+
- test/priority_queue_test.rb
|
60
|
+
- benchmark/result-PriorityQueue.gp
|
61
|
+
- benchmark/result-RubyPriorityQueue.gp
|
62
|
+
- benchmark/dijkstra.rb
|
63
|
+
- benchmark/result-PoorPriorityQueue.gp
|
64
|
+
- benchmark/result-CPriorityQueue.png
|
65
|
+
- benchmark/results.csv
|
66
|
+
- benchmark/results.png
|
67
|
+
- benchmark/result-PoorPriorityQueue.png
|
68
|
+
- benchmark/result-RubyPriorityQueue.png
|
69
|
+
- benchmark/results.gp
|
70
|
+
- benchmark/result-CPriorityQueue.gp
|
71
|
+
test_files: []
|
72
|
+
rdoc_options: []
|
73
|
+
extra_rdoc_files: []
|
74
|
+
executables: []
|
75
|
+
extensions:
|
76
|
+
- ext/priority_queue/extconf.rb
|
77
|
+
requirements: []
|
78
|
+
dependencies: []
|