vptree 0.1.0 → 0.1.1
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.
- checksums.yaml +4 -4
- data/lib/vptree.rb +44 -41
- data/lib/vptree/version.rb +1 -1
- data/vptree.gemspec +5 -5
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ab1cad55c67c31419c094b75e69ff8c644975588
|
4
|
+
data.tar.gz: 767372d59512610d1afc4735af743c8e9a6abae0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dde8685d96b68f50349e574bbebaec071c18f6860db08daf04843be5196646db7fb349d7979e4d3ae1d10c09a97611966ef21e15ec5687f77060c9ed59d3f820
|
7
|
+
data.tar.gz: 1a3316078b12f532b3e1cc9debff1cabf85b73c9d620190126de64579ee4e27d8f060461cb3d545a348e13e9183bbedbaf336b4e5663ab57b35d3bfad1ce9075
|
data/lib/vptree.rb
CHANGED
@@ -1,9 +1,11 @@
|
|
1
|
-
require
|
2
|
-
require 'distance_measures'
|
1
|
+
require 'vptree/version'
|
2
|
+
#require 'distance_measures'
|
3
|
+
#require 'measurable'
|
3
4
|
require 'algorithms'
|
4
5
|
|
5
6
|
module Vptree
|
6
|
-
|
7
|
+
# Implementation of queue with fixed size.
|
8
|
+
# Will store elements with low priority
|
7
9
|
class FixedLengthQueue < Containers::PriorityQueue
|
8
10
|
def initialize(limit = 4) # 4 for example
|
9
11
|
super()
|
@@ -25,18 +27,31 @@ module Vptree
|
|
25
27
|
end
|
26
28
|
end
|
27
29
|
|
28
|
-
def dump
|
29
|
-
size.times.map{ @heap.pop }
|
30
|
+
def dump
|
31
|
+
size.times.map { @heap.pop }
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# Mixin for calculating distance in VPNode and VPTree
|
36
|
+
# compatable with Distance-measure gem
|
37
|
+
module CalcDistance
|
38
|
+
def calc_dist(obj1, obj2)
|
39
|
+
return @is_block ? obj1.distance(obj2, &@distance_measure) : obj1.distance(obj2, @distance_measure)
|
40
|
+
rescue
|
41
|
+
# old fasion distance gem, for arrays only
|
42
|
+
return @is_block ? @distance_measure.call(obj1, obj2) : obj1.send(@distance_measure, obj2)
|
30
43
|
end
|
31
44
|
end
|
32
45
|
|
46
|
+
# Implementation of node of VP-tree
|
33
47
|
class VPNode
|
34
|
-
attr_accessor :is_block, :distance_measure, :data
|
48
|
+
attr_accessor :is_block, :distance_measure, :data
|
49
|
+
attr_accessor :vp_point, :left_node, :right_node, :mu
|
35
50
|
|
36
|
-
def initialize(data, options={}, &block)
|
51
|
+
def initialize(data, options = {}, &block)
|
37
52
|
@data = data
|
38
|
-
@is_block =
|
39
|
-
@distance_measure = block || options[:distance_measure]
|
53
|
+
@is_block = block_given?
|
54
|
+
@distance_measure = block || options[:distance_measure] || :euclidean_distance
|
40
55
|
@left_node = nil
|
41
56
|
@right_node = nil
|
42
57
|
@mu = 0
|
@@ -47,31 +62,26 @@ module Vptree
|
|
47
62
|
@distance_measure = other_node.distance_measure
|
48
63
|
end
|
49
64
|
|
50
|
-
|
51
|
-
begin
|
52
|
-
return @is_block ? obj1.calc_distance(obj2, &@distance_measure) : obj1.calc_distance(obj2, @distance_measure)
|
53
|
-
rescue
|
54
|
-
return @is_block ? @distance_measure.call(obj1, obj2) : obj1.send(@distance_measure, obj2) # old fasion distance gem, for arrays only
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
def separate()
|
65
|
+
include CalcDistance
|
59
66
|
|
67
|
+
def separate
|
60
68
|
if @data.size <= 2
|
61
69
|
@vp_point = @data.first
|
62
70
|
@right_node = nil
|
63
71
|
if @data.size == 2
|
64
|
-
@mu = calc_dist(@data[0]
|
72
|
+
@mu = calc_dist(@data[0], @data[1]) / 2
|
65
73
|
@left_node = VPNode.new([@data[1]])
|
66
74
|
end
|
67
75
|
else
|
68
76
|
@vp_point = @data.sample
|
69
77
|
# all sorted nodes
|
70
|
-
next_node_data = @data.sort_by{ |a| calc_dist(a, @vp_point) }[1..-1]
|
78
|
+
next_node_data = @data.sort_by { |a| calc_dist(a, @vp_point) }[1..-1]
|
71
79
|
len = next_node_data.size
|
72
|
-
r_points = next_node_data[0..(len/2 - 1)]
|
73
|
-
l_points = next_node_data[(len/2)..-1]
|
74
|
-
@mu =
|
80
|
+
r_points = next_node_data[0..(len / 2 - 1)]
|
81
|
+
l_points = next_node_data[(len / 2)..-1]
|
82
|
+
@mu = calc_dist(r_points.last, @vp_point)
|
83
|
+
@mu += calc_dist(l_points.first, @vp_point)
|
84
|
+
@mu /= 2.0
|
75
85
|
@right_node = VPNode.new(r_points)
|
76
86
|
@left_node = VPNode.new(l_points)
|
77
87
|
end
|
@@ -82,30 +92,22 @@ module Vptree
|
|
82
92
|
@left_node.separate if @left_node
|
83
93
|
@data = nil
|
84
94
|
end
|
85
|
-
|
86
95
|
end
|
87
96
|
|
97
|
+
# Implementation of VP-tree
|
88
98
|
class VPTree
|
89
|
-
|
90
99
|
attr_accessor :root
|
91
100
|
|
92
|
-
def initialize(data, options={}, &block)
|
101
|
+
def initialize(data, options = {}, &block)
|
93
102
|
@data = data
|
94
|
-
@is_block =
|
95
|
-
@distance_measure = block || options[:distance_measure]
|
103
|
+
@is_block = block_given?
|
104
|
+
@distance_measure = block || options[:distance_measure] || :euclidean_distance
|
96
105
|
@root = VPNode.new(data, options, &block)
|
97
106
|
end
|
98
107
|
|
99
|
-
|
100
|
-
begin
|
101
|
-
return @is_block ? obj1.calc_distance(obj2, &@distance_measure) : obj1.calc_distance(obj2, @distance_measure)
|
102
|
-
rescue
|
103
|
-
return @is_block ? @distance_measure.call(obj1, obj2) : obj1.send(@distance_measure, obj2) # old fasion distance gem, for arrays only
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
108
|
+
include CalcDistance
|
107
109
|
|
108
|
-
def build_tree
|
110
|
+
def build_tree
|
109
111
|
@root.separate
|
110
112
|
end
|
111
113
|
|
@@ -118,13 +120,13 @@ module Vptree
|
|
118
120
|
# sorted from closest to farthest neighbor
|
119
121
|
neighbors = FixedLengthQueue.new(k)
|
120
122
|
|
121
|
-
while nodes_to_visit.size
|
122
|
-
node = nodes_to_visit.pop
|
123
|
+
while nodes_to_visit.size > 0
|
124
|
+
node = nodes_to_visit.pop
|
123
125
|
d = calc_dist(obj, node.vp_point)
|
124
126
|
if d < tau
|
125
127
|
# store node.vp_point as a neighbor if it's closer than any other point
|
126
128
|
# seen so far
|
127
|
-
neighbors.push(node.vp_point, d)
|
129
|
+
neighbors.push([d, node.vp_point], d)
|
128
130
|
# shrink tau
|
129
131
|
tau = neighbors.max_priority
|
130
132
|
end
|
@@ -141,7 +143,8 @@ module Vptree
|
|
141
143
|
end
|
142
144
|
end
|
143
145
|
|
144
|
-
return neighbors.dump
|
146
|
+
return neighbors.dump.reverse
|
145
147
|
end
|
148
|
+
|
146
149
|
end
|
147
150
|
end
|
data/lib/vptree/version.rb
CHANGED
data/vptree.gemspec
CHANGED
@@ -16,11 +16,11 @@ Gem::Specification.new do |spec|
|
|
16
16
|
|
17
17
|
# Prevent pushing this gem to RubyGems.org by setting 'allowed_push_host', or
|
18
18
|
# delete this section to allow pushing this gem to any host.
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
19
|
+
if spec.respond_to?(:metadata)
|
20
|
+
# spec.metadata['allowed_push_host'] = "TODO: Set to 'http://mygemserver.com'"
|
21
|
+
else
|
22
|
+
raise "RubyGems 2.0 or newer is required to protect against public gem pushes."
|
23
|
+
end
|
24
24
|
|
25
25
|
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
26
26
|
spec.bindir = "exe"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: vptree
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- generall
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-02-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|