ngt 0.2.3 → 0.2.4
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/CHANGELOG.md +6 -0
- data/README.md +35 -2
- data/lib/ngt/ffi.rb +4 -5
- data/lib/ngt/index.rb +31 -23
- data/lib/ngt/optimizer.rb +8 -2
- data/lib/ngt/version.rb +1 -1
- data/vendor/libngt.dylib +0 -0
- data/vendor/libngt.so +0 -0
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d00cfd25aa3d93228994f1f490c27e5c7bd0566013c6d4af9c9ec22157cd5bf0
|
4
|
+
data.tar.gz: a33f524d222fc6b9c7733039217349e9897926b19854faff58f088a80bb55b58
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1e1431ab3453ce24ab8d3886fc4ce201cc48ec239eb8eb083bb72d9880d8bf554e2e45ce7252e207d7e7da7f10323023364ff1b33ca95ab6bd6795fdbf79e5c0
|
7
|
+
data.tar.gz: 3a932a1da2b75baac08ac477f9e92d1d6f203237f3b94e6962c749d906eb7c63a4a5f0162395f39db21734338ba147a10acb4210cb37d5397d024aef00f32795
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
## 0.2.4 (2020-03-09)
|
2
|
+
|
3
|
+
- Updated NGT to 1.9.1
|
4
|
+
- Added support for passing an index to optimizers
|
5
|
+
- Added `dimensions`, `distance_type`, `edge_size_for_creation`, `edge_size_for_search`, and `object_type` methods
|
6
|
+
|
1
7
|
## 0.2.3 (2020-03-08)
|
2
8
|
|
3
9
|
- Added `load` method
|
data/README.md
CHANGED
@@ -12,7 +12,7 @@ Add this line to your application’s Gemfile:
|
|
12
12
|
gem 'ngt'
|
13
13
|
```
|
14
14
|
|
15
|
-
NGT is not available for Windows
|
15
|
+
NGT is not available for Windows
|
16
16
|
|
17
17
|
## Getting Started
|
18
18
|
|
@@ -84,7 +84,8 @@ Optimize the index
|
|
84
84
|
|
85
85
|
```ruby
|
86
86
|
optimizer = Ngt::Optimizer.new(outgoing: 10, incoming: 120)
|
87
|
-
optimizer.
|
87
|
+
optimizer.adjust_search_coefficients(index)
|
88
|
+
optimizer.execute(index, new_path)
|
88
89
|
```
|
89
90
|
|
90
91
|
## Full Example
|
@@ -108,6 +109,38 @@ result.each do |res|
|
|
108
109
|
end
|
109
110
|
```
|
110
111
|
|
112
|
+
## Index Options
|
113
|
+
|
114
|
+
Defaults shown below
|
115
|
+
|
116
|
+
```ruby
|
117
|
+
Ngt::Index.new(dimensions,
|
118
|
+
edge_size_for_creation: 10,
|
119
|
+
edge_size_for_search: 40,
|
120
|
+
object_type: :float, # :float, :integer
|
121
|
+
distance_type: :l2, # :l1, :l2, :hamming, :angle, :cosine, or :jaccard
|
122
|
+
path: nil
|
123
|
+
)
|
124
|
+
```
|
125
|
+
|
126
|
+
## Optimizer Options
|
127
|
+
|
128
|
+
Defaults shown below
|
129
|
+
|
130
|
+
```ruby
|
131
|
+
Ngt::Optimizer.new(
|
132
|
+
outgoing: 10,
|
133
|
+
incoming: 120,
|
134
|
+
queries: 100,
|
135
|
+
low_accuracy_from: 0.3,
|
136
|
+
low_accuracy_to: 0.5,
|
137
|
+
high_accuracy_from: 0.8,
|
138
|
+
high_accuracy_to: 0.9,
|
139
|
+
gt_epsilon: 0.1,
|
140
|
+
merge: 0.2
|
141
|
+
)
|
142
|
+
```
|
143
|
+
|
111
144
|
## Data
|
112
145
|
|
113
146
|
Data can be an array of arrays
|
data/lib/ngt/ffi.rb
CHANGED
@@ -2,11 +2,7 @@ module Ngt
|
|
2
2
|
module FFI
|
3
3
|
extend ::FFI::Library
|
4
4
|
|
5
|
-
|
6
|
-
ffi_lib Ngt.ffi_lib
|
7
|
-
rescue LoadError => e
|
8
|
-
raise e
|
9
|
-
end
|
5
|
+
ffi_lib Ngt.ffi_lib
|
10
6
|
|
11
7
|
# https://github.com/yahoojapan/NGT/blob/master/lib/NGT/Capi.h
|
12
8
|
# keep same order
|
@@ -52,6 +48,9 @@ module Ngt
|
|
52
48
|
attach_function :ngt_get_object_as_integer, %i[pointer int pointer], :pointer
|
53
49
|
attach_function :ngt_destroy_property, %i[pointer], :void
|
54
50
|
attach_function :ngt_close_index, %i[pointer], :void
|
51
|
+
attach_function :ngt_get_property_edge_size_for_creation, %i[pointer pointer], :int16
|
52
|
+
attach_function :ngt_get_property_edge_size_for_search, %i[pointer pointer], :int16
|
53
|
+
attach_function :ngt_get_property_distance_type, %i[pointer pointer], :int32
|
55
54
|
attach_function :ngt_create_error_object, %i[], :pointer
|
56
55
|
attach_function :ngt_get_error_string, %i[pointer], :string
|
57
56
|
attach_function :ngt_destroy_error_object, %i[pointer], :void
|
data/lib/ngt/index.rb
CHANGED
@@ -2,6 +2,10 @@ module Ngt
|
|
2
2
|
class Index
|
3
3
|
include Utils
|
4
4
|
|
5
|
+
DISTANCE_TYPES = [:l1, :l2, :hamming, :angle, :cosine, :normalized_angle, :normalized_cosine, :jaccard]
|
6
|
+
|
7
|
+
attr_reader :dimensions, :distance_type, :edge_size_for_creation, :edge_size_for_search, :object_type, :path
|
8
|
+
|
5
9
|
def initialize(path)
|
6
10
|
@path = path
|
7
11
|
@error = FFI.ngt_create_error_object
|
@@ -10,10 +14,14 @@ module Ngt
|
|
10
14
|
property = ffi(:ngt_create_property)
|
11
15
|
ffi(:ngt_get_property, @index, property)
|
12
16
|
|
13
|
-
@
|
17
|
+
@dimensions = ffi(:ngt_get_property_dimension, property)
|
18
|
+
@distance_type = DISTANCE_TYPES[ffi(:ngt_get_property_distance_type, property)]
|
19
|
+
@edge_size_for_creation = ffi(:ngt_get_property_edge_size_for_creation, property)
|
20
|
+
@edge_size_for_search = ffi(:ngt_get_property_edge_size_for_search, property)
|
14
21
|
|
15
22
|
object_type = ffi(:ngt_get_property_object_type, property)
|
16
23
|
@float = FFI.ngt_is_property_object_type_float(object_type)
|
24
|
+
@object_type = @float ? :float : :integer
|
17
25
|
|
18
26
|
@object_space = ffi(:ngt_get_object_space, @index)
|
19
27
|
|
@@ -21,7 +29,7 @@ module Ngt
|
|
21
29
|
end
|
22
30
|
|
23
31
|
def insert(object)
|
24
|
-
ffi(:ngt_insert_index, @index, c_object(object.to_a), @
|
32
|
+
ffi(:ngt_insert_index, @index, c_object(object.to_a), @dimensions)
|
25
33
|
end
|
26
34
|
|
27
35
|
def batch_insert(objects, num_threads: 8)
|
@@ -53,10 +61,10 @@ module Ngt
|
|
53
61
|
def object(id)
|
54
62
|
if float?
|
55
63
|
res = ffi(:ngt_get_object_as_float, @object_space, id)
|
56
|
-
res.read_array_of_float(@
|
64
|
+
res.read_array_of_float(@dimensions)
|
57
65
|
else
|
58
66
|
res = ffi(:ngt_get_object_as_integer, @object_space, id)
|
59
|
-
res.read_array_of_uint8(@
|
67
|
+
res.read_array_of_uint8(@dimensions)
|
60
68
|
end
|
61
69
|
end
|
62
70
|
|
@@ -67,7 +75,7 @@ module Ngt
|
|
67
75
|
def search(query, size: 20, epsilon: 0.1, radius: nil)
|
68
76
|
radius ||= -1.0
|
69
77
|
results = ffi(:ngt_create_empty_results)
|
70
|
-
ffi(:ngt_search_index, @index, c_object(query.to_a), @
|
78
|
+
ffi(:ngt_search_index, @index, c_object(query.to_a), @dimensions, size, epsilon, radius, results)
|
71
79
|
result_size = ffi(:ngt_get_result_size, results)
|
72
80
|
ret = []
|
73
81
|
result_size.times do |i|
|
@@ -90,47 +98,47 @@ module Ngt
|
|
90
98
|
FFI.ngt_close_index(@index)
|
91
99
|
end
|
92
100
|
|
93
|
-
def self.new(
|
94
|
-
edge_size_for_search: 40, object_type:
|
101
|
+
def self.new(dimensions, path: nil, edge_size_for_creation: 10,
|
102
|
+
edge_size_for_search: 40, object_type: :float, distance_type: :l2)
|
95
103
|
|
96
104
|
# called from load
|
97
|
-
return super(path) if path &&
|
105
|
+
return super(path) if path && dimensions.nil?
|
98
106
|
|
99
107
|
# TODO remove in 0.3.0
|
100
|
-
create =
|
108
|
+
create = dimensions.is_a?(Integer) || path
|
101
109
|
unless create
|
102
110
|
warn "[ngt] Passing a path to new is deprecated - use load instead"
|
103
|
-
return super(
|
111
|
+
return super(dimensions)
|
104
112
|
end
|
105
113
|
|
106
114
|
path ||= Dir.mktmpdir
|
107
115
|
error = FFI.ngt_create_error_object
|
108
116
|
property = ffi(:ngt_create_property, error)
|
109
|
-
ffi(:ngt_set_property_dimension, property,
|
117
|
+
ffi(:ngt_set_property_dimension, property, dimensions, error)
|
110
118
|
ffi(:ngt_set_property_edge_size_for_creation, property, edge_size_for_creation, error)
|
111
119
|
ffi(:ngt_set_property_edge_size_for_search, property, edge_size_for_search, error)
|
112
120
|
|
113
|
-
case object_type.to_s
|
114
|
-
when "
|
121
|
+
case object_type.to_s.downcase
|
122
|
+
when "float"
|
115
123
|
ffi(:ngt_set_property_object_type_float, property, error)
|
116
|
-
when "
|
124
|
+
when "integer"
|
117
125
|
ffi(:ngt_set_property_object_type_integer, property, error)
|
118
126
|
else
|
119
127
|
raise ArgumentError, "Unknown object type: #{object_type}"
|
120
128
|
end
|
121
129
|
|
122
|
-
case distance_type.to_s
|
123
|
-
when "
|
130
|
+
case distance_type.to_s.downcase
|
131
|
+
when "l1"
|
124
132
|
ffi(:ngt_set_property_distance_type_l1, property, error)
|
125
|
-
when "
|
133
|
+
when "l2"
|
126
134
|
ffi(:ngt_set_property_distance_type_l2, property, error)
|
127
|
-
when "
|
135
|
+
when "angle"
|
128
136
|
ffi(:ngt_set_property_distance_type_angle, property, error)
|
129
|
-
when "
|
137
|
+
when "hamming"
|
130
138
|
ffi(:ngt_set_property_distance_type_hamming, property, error)
|
131
|
-
when "
|
139
|
+
when "jaccard"
|
132
140
|
ffi(:ngt_set_property_distance_type_jaccard, property, error)
|
133
|
-
when "
|
141
|
+
when "cosine"
|
134
142
|
ffi(:ngt_set_property_distance_type_cosine, property, error)
|
135
143
|
else
|
136
144
|
raise ArgumentError, "Unknown distance type: #{distance_type}"
|
@@ -151,9 +159,9 @@ module Ngt
|
|
151
159
|
new(nil, path: path)
|
152
160
|
end
|
153
161
|
|
154
|
-
def self.create(path,
|
162
|
+
def self.create(path, dimensions, **options)
|
155
163
|
warn "[ngt] create is deprecated - use new instead"
|
156
|
-
new(
|
164
|
+
new(dimensions, path: path, **options)
|
157
165
|
end
|
158
166
|
|
159
167
|
# private
|
data/lib/ngt/optimizer.rb
CHANGED
@@ -15,11 +15,11 @@ module Ngt
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def execute(in_index_path, out_index_path)
|
18
|
-
ffi(:ngt_optimizer_execute, @optimizer, in_index_path, out_index_path)
|
18
|
+
ffi(:ngt_optimizer_execute, @optimizer, path(in_index_path), out_index_path)
|
19
19
|
end
|
20
20
|
|
21
21
|
def adjust_search_coefficients(index_path)
|
22
|
-
ffi(:ngt_optimizer_adjust_search_coefficients, @optimizer, index_path)
|
22
|
+
ffi(:ngt_optimizer_adjust_search_coefficients, @optimizer, path(index_path))
|
23
23
|
end
|
24
24
|
|
25
25
|
def self.finalize(optimizer, error)
|
@@ -29,5 +29,11 @@ module Ngt
|
|
29
29
|
FFI.ngt_destroy_error_object(error)
|
30
30
|
end
|
31
31
|
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def path(obj)
|
36
|
+
obj.is_a?(Ngt::Index) ? obj.path : obj
|
37
|
+
end
|
32
38
|
end
|
33
39
|
end
|
data/lib/ngt/version.rb
CHANGED
data/vendor/libngt.dylib
CHANGED
Binary file
|
data/vendor/libngt.so
CHANGED
Binary file
|