Skip to content

Commit

Permalink
Merge pull request #161 from nikox94/FibonacciHeap
Browse files Browse the repository at this point in the history
Implement Fibonacci heap
  • Loading branch information
dustinhiatt-wf authored Mar 2, 2017
2 parents 6e483a4 + 283a4be commit dd1dc71
Show file tree
Hide file tree
Showing 13 changed files with 1,157 additions and 5 deletions.
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ and ensure goroutines quit so objects can be GC'd. Threadsafety is achieved
using only CAS operations making this queue quite fast. Benchmarks can be found
in that package.

#### Fibonacci Heap

A standard Fibonacci heap providing the usual operations. Can be useful in executing Dijkstra or Prim's algorithms in the theoretically minimal time. Also useful as a general-purpose priority queue. The special thing about Fibonacci heaps versus other heap variants is the cheap decrease-key operation. This heap has a constant complexity for find minimum, insert and merge of two heaps, an amortized constant complexity for decrease key and O(log(n)) complexity for a deletion or dequeue minimum. In practice the constant factors are large, so Fibonacci heaps could be slower than Pairing heaps, depending on usage. Benchmarks - in the project subfolder. The heap has not been designed for thread-safety.

#### Range Tree

Useful to determine if n-dimensional points fall within an n-dimensional range.
Expand Down Expand Up @@ -147,7 +151,7 @@ method which in turn calls into runtime.assertI2T. We need generics.

#### Immutable B Tree
A btree based on two principals, immutablability and concurrency.
Somewhat slow for single value lookups and puts, it is very fast for bulk operations.
Somewhat slow for single value lookups and puts, it is very fast for bulk operations.
A persister can be injected to make this index persistent.

#### Ctrie
Expand Down
1 change: 1 addition & 0 deletions datastructures.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
_ "github.com/Workiva/go-datastructures/bitarray"
_ "github.com/Workiva/go-datastructures/btree/palm"
_ "github.com/Workiva/go-datastructures/btree/plus"
_ "github.com/Workiva/go-datastructures/fibheap"
_ "github.com/Workiva/go-datastructures/futures"
_ "github.com/Workiva/go-datastructures/hashmap/fastinteger"
_ "github.com/Workiva/go-datastructures/numerics/optimization"
Expand Down
16 changes: 12 additions & 4 deletions documentation.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

The goal of the go-datastructures library is to port implementations of some common datastructures to Go or to improve on some existing datastructures. These datastructures are designed to be re-used for anyone that needs them throughout the community. (and hopefully improved upon).

Given the commonality and popularity of these datastructures in other languages, it is hoped that by open sourcing this library we an leverage a great deal of institutional knowledge to improve upon the Go-specific implementations.
Given the commonality and popularity of these datastructures in other languages, it is hoped that by open sourcing this library we leverage a great deal of institutional knowledge to improve upon the Go-specific implementations.

# Datastructures

Expand All @@ -16,7 +16,7 @@ The actual implementation is a top-down red-black binary search tree.

### Future

Implement a bottom-up version as well.
Implement a bottom-up version as well.

## Bit Array

Expand Down Expand Up @@ -46,7 +46,7 @@ When I get time, I'd like to implement a lockless ring buffer for further perfor

## Range Tree

The range tree is a way to store n-dimensional points of data in a manner that it permits logarithmic queries. These points are usually representing as points on a Cartesian graph represented by integers.
The range tree is a way to store n-dimensional points of data in a manner that permits logarithmic-complexity queries. These points are usually represented as points on a Cartesian graph represented by integers.

There are two implementations of a range tree in this package, one that is mutable and one that is immutable. The mutable version can be faster, but involves lock contention if the consumer needs to ensure threadsafety. The immutable version is a copy-on-write range tree that is optimized by only copying portions of the rangetree on write and is best written to in batches. Operations on the immutable version are slower, but it is safe to read and write from this version at the same time from different threads.

Expand All @@ -56,6 +56,14 @@ Although rangetrees are often represented as BBSTs as described above, the n-dim

Unite both implementations of the rangetree under the same interface. The implementations (especially the immutable one) could use some futher performance optimizations.

## Fibonacci Heap

The usual Fibonacci Heap with a floating-point priority key. Does a good job as a priority queue, especially for large n. Should be useful in writing an optimal solution for Dijkstra's and Prim's algorithms. (because of it's efficient decrease-key)

### Future

I'd like to add a value interface{} pointer that will be able to hold any user data attached to each node in the heap. Another thing would be writing a fast implementation of Dijkstra and Prim using this structure. And a third would be analysing thread-safety and coming up with a thread-safe variant.

## Set

Not much to say here. This is an unordered set back by a Go map. This particular version is threadsafe which does hinder performance a bit, although reads can happen simultaneously.
Expand All @@ -76,4 +84,4 @@ This package just wraps some common interfaces with a lock to make them threadsa

There is a PR into the datastructures repo that contains some pieces required for implementing a B+ tree. With a B+ tree and bitmap, the pieces are in place to write a native Go database. Going forward, I'd like to take these pieces, expand upon them, and implement a fast database in Go.

As always, any optimizations or bug fixes in any of this code would be greatly appreciated and encouraged :). These datastructures can and are the foundations of many programs and algorithms, even if they are abstracted away in different libraries which makes working with them a lot of fun and very informative.
As always, any optimizations or bug fixes in any of this code would be greatly appreciated and encouraged :). These datastructures can and are the foundations of many programs and algorithms, even if they are abstracted away in different libraries which makes working with them a lot of fun and very informative.
31 changes: 31 additions & 0 deletions fibheap/Test Generator/EnqDecrKey.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
l = [-2901939070.965906, 4539462982.372177, -6222008480.049856,
-1400427921.5968666, 9866088144.060883,
-2943107648.529664, 8985474333.11443,
9204710651.257133, 5354113876.8447075,
8122228442.770859, -8121418938.303131,
538431208.3261185, 9913821013.519611,
-8722989752.449871, -3091279426.694975,
7229910558.195713, -2908838839.99403,
2835257231.305996, 3922059795.3656673,
-9298869735.322557]

print(l)

l = sorted(l)
print(l)
a1 = l[19]
a2 = -8722989752.449871
print(str(a1) + " -> " + str(a2))
l[19] = a2

b1 = l[18]
b2 = -9698869735.322557
print(str(b1) + " -> " + str(b2))
l[18] = b2

c1 = l[17]
c2 = -9804710651.257133
print(str(c1) + " -> " + str(c2))
l[17] = c2

print(sorted(l))
27 changes: 27 additions & 0 deletions fibheap/Test Generator/EnqDelete.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
l = [-2901939070.965906, 4539462982.372177, -6222008480.049856,
-1400427921.5968666, 9866088144.060883, -2943107648.529664, 8985474333.11443,
9204710651.257133, 5354113876.8447075, 8122228442.770859, -8121418938.303131,
538431208.3261185, 9913821013.519611, -8722989752.449871, -3091279426.694975,
7229910558.195713, -2908838839.99403, 2835257231.305996, 3922059795.3656673,
-9298869735.322557]

print(l)

l = sorted(l)
print(l)
a1 = l[19]
a2 = 0
print(str(a1) + " -> " + str(a2))
l[19] = a2

b1 = l[18]
b2 = 0
print(str(b1) + " -> " + str(b2))
l[18] = b2

c1 = l[17]
c2 = 0
print(str(c1) + " -> " + str(c2))
l[17] = c2

print(sorted(l))
11 changes: 11 additions & 0 deletions fibheap/Test Generator/EnqDeqMin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#!/usr/bin/python3

import random

l = []
for i in range(20):
l.append(random.uniform(-1E10, 1E10))

print(l)
l = sorted(l)
print(l)
41 changes: 41 additions & 0 deletions fibheap/Test Generator/Merge.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import random

l1 = []
l2 = []
for i in range(20):
l1.append(random.uniform(-1E10, 1E10))
l2.append(random.uniform(-1E10, 1E10))


print(l1)
print(l2)

l = []
l.extend(l1)
l.extend(l2)

print(sorted(l))

'''
[6015943293.071386, -3878285748.0708866, 8674121166.062424, -1528465047.6118088,
7584260716.494843, -373958476.80486107, -6367787695.054295, 6813992306.719868,
5986097626.907181, 9011134545.052086, 7123644338.268343, 2646164210.08445,
4407427446.995375, -888196668.2563229, 7973918726.985172, -6529216482.09644,
6079069259.51853, -8415952427.784341, -6859960084.757652, -502409126.89040375]
[9241165993.258648, -9423768405.578083, 3280085607.6687145, -5253703037.682413,
3858507441.2785892, 9896256282.896187, -9439606732.236805, 3082628799.5320206,
9453124863.59945, 9928066165.458393, 1135071669.4712334, 6380353457.986282,
8329064041.853199, 2382910730.445751, -8478491750.445316, 9607469190.690144,
5417691217.440792, -9698248424.421888, -3933774735.280322, -5984555343.381466]
[-9698248424.421888, -9439606732.236805, -9423768405.578083, -8478491750.445316,
-8415952427.784341, -6859960084.757652, -6529216482.09644, -6367787695.054295,
-5984555343.381466, -5253703037.682413, -3933774735.280322, -3878285748.0708866,
-1528465047.6118088, -888196668.2563229, -502409126.89040375,
-373958476.80486107, 1135071669.4712334, 2382910730.445751, 2646164210.08445,
3082628799.5320206, 3280085607.6687145, 3858507441.2785892, 4407427446.995375,
5417691217.440792, 5986097626.907181, 6015943293.071386, 6079069259.51853,
6380353457.986282, 6813992306.719868, 7123644338.268343, 7584260716.494843,
7973918726.985172, 8329064041.853199, 8674121166.062424, 9011134545.052086,
9241165993.258648, 9453124863.59945, 9607469190.690144, 9896256282.896187,
9928066165.458393]
'''
1 change: 1 addition & 0 deletions fibheap/Test Generator/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
These are some Python helper scripts to help generate sample test arrays.
8 changes: 8 additions & 0 deletions fibheap/benchmarks.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
BenchmarkFibHeap_Enqueue-4 10000000 280 ns/op 64 B/op 1 allocs/op
BenchmarkFibHeap_DequeueMin-4 100 16990302 ns/op 16007168 B/op 2 allocs/op
BenchmarkFibHeap_DecreaseKey-4 20000000 900 ns/op 122 B/op 3 allocs/op
BenchmarkFibHeap_Delete-4 100 19087592 ns/op 16007168 B/op 2 allocs/op
BenchmarkFibHeap_Merge-4 3000000 482 ns/op 128 B/op 2 allocs/op
PASS
coverage: 96.2% of statements
ok _/home/nikola/git/go-datastructures/fibheap 37.206s
Loading

0 comments on commit dd1dc71

Please sign in to comment.