Skip to content

Commit e7eda8e

Browse files
committed
Added struct members which were missing from the flann parameters listed
in the manual. Added a way of initializing FFI::Structs from a hash, converted defaults into a hash. Defaults now seem to work.
1 parent 923e82d commit e7eda8e

File tree

3 files changed

+60
-21
lines changed

3 files changed

+60
-21
lines changed

src/ruby/lib/flann.rb

Lines changed: 55 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -15,30 +15,52 @@ module Flann
1515
LogLevel = enum(:none, :fatal, :error, :warn, :info)
1616
DistanceType = enum(:euclidean, :manhattan, :minkowski, :hist_intersect, :hellinger, :chi_square, :kullback_leibler)
1717

18-
DEFAULT_PARAMETERS = [:kdtree,
19-
32, 0.0,
20-
0, -1, 0,
21-
4, 4,
22-
32, 11, :random, 0.2,
23-
0.9, 0.01, 0, 0.1,
24-
:none, 0
25-
]
26-
2718
# For NMatrix compatibility
2819
typedef :float, :float32
2920
typedef :double, :float64
3021
typedef :pointer, :index_params_ptr
3122
typedef :pointer, :index_ptr
3223

24+
25+
class InitializableStruct < FFI::Struct
26+
def initialize pointer=nil, *layout, &block
27+
if pointer.respond_to?(:each_pair)
28+
options = pointer
29+
pointer = nil
30+
else
31+
options
32+
end
33+
34+
super(pointer, *layout, &block)
35+
36+
if defined?(self.class::DEFAULTS)
37+
options = self.class::DEFAULTS.merge(options)
38+
end
39+
40+
options.each_pair do |key, value|
41+
self[key] = value
42+
end unless options.nil?
43+
end
44+
end
45+
46+
3347
# A nearest neighbor search index for a given dataset.
34-
class Parameters < FFI::Struct
48+
class Parameters < InitializableStruct
3549
layout :algorithm, Flann::Algorithm, # The algorithm to use (linear, kdtree, kmeans, composite, kdtree_single, saved, autotuned)
3650
:checks, :int, # How many leaves (features) to use (for kdtree)
37-
:cluster_boundary_index, :float, # aka cb_tree, used when searching the kmeans tree
51+
:eps, :float, # eps parameter for eps-knn search
52+
:sorted, :int, # indicates if results returned by radius search should be sorted or not
53+
:max_neighbors, :int, # limits the maximum number of neighbors returned
54+
:cores, :int, # number of parallel cores to use for searching
55+
3856
:trees, :int, # Number of randomized trees to use (for kdtree)
57+
:leaf_max_size, :int, # ?
58+
3959
:branching, :int, # Branching factor (for kmeans tree)
4060
:iterations, :int, # Max iterations to perform in one kmeans clustering (kmeans tree)
4161
:centers_init, Flann::CentersInit, # Algorithm used (random, gonzales, kmeanspp)
62+
:cluster_boundary_index, :float, # Cluster boundary index. Used when searching the kmeans tree
63+
4264
:target_precision, :float, # Precision desired (used for auto-tuning, -1 otherwise)
4365
:build_weight, :float, # Build tree time weighting factor
4466
:memory_weight, :float, # Index memory weighting factor
@@ -47,8 +69,17 @@ class Parameters < FFI::Struct
4769
:table_number, :uint, # The number of hash tables to use
4870
:key_size, :uint, # The length of the key to use in the hash tables
4971
:multi_probe_level, :uint, # Number of levels to use in multi-probe LSH, 0 for standard LSH
72+
5073
:log_level, Flann::LogLevel, # Determines the verbosity of each flann function
5174
:random_seed, :long # Random seed to use
75+
76+
DEFAULT = {algorithm: :kdtree,
77+
checks: 32, eps: 0.0,
78+
sorted: 0, max_neighbors: -1, cores: 0,
79+
trees: 4, leaf_max_size: 4,
80+
log_level: :none, random_seed: 0}
81+
82+
5283
end
5384

5485
class << self
@@ -72,7 +103,7 @@ def allocate_results_space result_size #:nodoc:
72103

73104
# Don't know if these will be a hash, a static struct, or a pointer to a struct. Return the pointer and the struct.
74105
def handle_parameters parameters #:nodoc:
75-
parameters ||= DEFAULT_PARAMETERS unless block_given?
106+
parameters ||= Parameters::DEFAULT unless block_given?
76107

77108
if parameters.is_a?(FFI::MemoryPointer) # User supplies us with the necessary parameters already in the correct form.
78109
c_parameters_ptr = parameters
@@ -100,8 +131,8 @@ def handle_parameters parameters #:nodoc:
100131

101132
# Find the k nearest neighbors.
102133
#
103-
# If no index parameters are given, FLANN_DEFAULT_PARAMETERS are used. A block is accepted as well.
104-
def nearest_neighbors dataset, testset, k, parameters: DEFAULT_PARAMETERS
134+
# If no index parameters are given, FLANN_Parameters::DEFAULT are used. A block is accepted as well.
135+
def nearest_neighbors dataset, testset, k, parameters: Parameters.new(Parameters::DEFAULT)
105136
# Get a pointer and a struct regardless of how the arguments are supplied.
106137
parameters_ptr, parameters = handle_parameters(parameters)
107138
result_size = testset.shape[0] * k
@@ -123,12 +154,19 @@ def set_distance_type! distance_function, order = 0
123154
end
124155

125156
# Perform hierarchical clustering of a set of points.
126-
def cluster dataset, clusters, parameters: DEFAULT_PARAMETERS
157+
#
158+
# Arguments:
159+
# * dataset: NMatrix of points
160+
# * parameters:
161+
def cluster dataset, clusters, parameters: Parameters.new(Parameters::DEFAULT)
127162
c_method = "flann_compute_cluster_centers_#{Flann::dtype_to_c(dataset.dtype)}".to_sym
128163

129164
result = dataset.clone_structure
130165
parameters_ptr, parameters = handle_parameters(parameters)
166+
167+
#err_code =
131168
Flann.send(c_method, FFI::Pointer.new_from_nmatrix(dataset), dataset.shape[0], dataset.shape[1], clusters, FFI::Pointer.new_from_nmatrix(result), parameters_ptr)
169+
#raise("unknown error in cluster") if err_code < 0
132170

133171
result
134172
end
@@ -138,8 +176,8 @@ def cluster dataset, clusters, parameters: DEFAULT_PARAMETERS
138176

139177
protected
140178

141-
# byte: unsigned char*dataset, int rows, int cols, float* speedup, FLANNParameters* flann_params
142-
# only thing that changes is the pointer type for the first arg.
179+
# byte: unsigned char*dataset, int rows, int cols, float* speedup, FLANNParameters* flann_params
180+
# only thing that changes is the pointer type for the first arg.
143181
attach_function :flann_build_index_byte, [:pointer, :int, :int, :pointer, :index_params_ptr], :index_ptr
144182
attach_function :flann_build_index_int, [:pointer, :int, :int, :pointer, :index_params_ptr], :index_ptr
145183
attach_function :flann_build_index_float, [:pointer, :int, :int, :pointer, :index_params_ptr], :index_ptr

src/ruby/lib/flann/index.rb

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ class Index
1616
#
1717
# * https://github.com/mariusmuja/flann/tree/master/src/cpp/flann/algorithms
1818
#
19-
def initialize dataset: nil, dtype: :float64, parameters: Flann::DEFAULT_PARAMETERS
19+
def initialize dataset: nil, dtype: :float64, parameters: Flann::Parameters::DEFAULT
2020
@dataset = dataset
2121
@dtype = (!dataset.nil? && dataset.is_a?(NMatrix)) ? dataset.dtype : dtype
2222
@index_ptr = nil
@@ -40,7 +40,7 @@ def build!
4040
end
4141

4242
# Get the nearest neighbors based on this index. Forces a build of the index if one hasn't been done yet.
43-
def nearest_neighbors testset, k, parameters: DEFAULT_PARAMETERS
43+
def nearest_neighbors testset, k, parameters: Parameters.new(Parameters::DEFAULT)
4444
self.build! if index_ptr.nil?
4545

4646
parameters_ptr, parameters = Flann::handle_parameters(parameters)
@@ -58,7 +58,7 @@ def nearest_neighbors testset, k, parameters: DEFAULT_PARAMETERS
5858
end
5959

6060
# Perform a radius search on a single query point
61-
def radius_search query, radius, max_k: dataset.shape[1], parameters: DEFAULT_PARAMETERS
61+
def radius_search query, radius, max_k: dataset.shape[1], parameters: Parameters.new(Parameters::DEFAULT)
6262
self.build! if index_ptr.nil?
6363
parameters_ptr, parameters = Flann::handle_parameters(parameters)
6464
indices_int_ptr, distances_float_ptr = Flann::allocate_results_space(max_k)
@@ -89,7 +89,7 @@ def load! filename
8989
end
9090

9191
# Free an index
92-
def free! parameters = DEFAULT_PARAMETERS
92+
def free! parameters = Parameters.new(Parameters::DEFAULT)
9393
c_method = "flann_free_index_#{Flann::dtype_to_c(dtype)}".to_sym
9494
parameters_ptr, parameters = Flann::handle_parameters(parameters)
9595
Flann.send(c_method, index_ptr, parameters_ptr)

src/ruby/spec/flann_spec.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
require File.dirname(__FILE__) + "/spec_helper.rb"
22

33
describe Flann do
4+
45
it "::VERSION::STRING matches #define FLANN_VERSION_ in config.h" do
56
found = false
67
File.open(File.dirname(__FILE__) + "/../../cpp/flann/config.h", "r") do |f|

0 commit comments

Comments
 (0)