Module: Flann

Extended by:
FFI::Library
Defined in:
lib/flann/version.rb,
lib/flann.rb,
lib/flann/index.rb

Overview

Copyright 2014 John O. Woods ([email protected]), West Virginia

University's Applied Space Exploration Lab, and West Virginia Robotic
Technology Center. All rights reserved.

THE BSD LICENSE

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.

  2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE AUTHOR “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Defined Under Namespace

Modules: VERSION Classes: Index, InitializableStruct, Parameters

Constant Summary collapse

Algorithm =

Declare enumerators

enum(:algorithm, [:linear, :kdtree, :kmeans, :composite, :kdtree_single, :hierarchical, :lsh, :kdtree_cuda, :saved, 254, :autotuned, 255])
CentersInit =
enum(:centers_init, [:random, :gonzales, :kmeanspp])
LogLevel =
enum(:log_level, [:none, :fatal, :error, :warn, :info, :debug])
DistanceType =

Note that Hamming and beyond are not supported in the C API. We include them here just in case of future improvements.

enum(:distance_type, [:undefined, :euclidean, :l2, :manhattan, :l1, :minkowski, :max, :hist_intersect, :hellinger, :chi_square, :kullback_leibler, :hamming, :hamming_lut, :hamming_popcnt, :l2_simple])
DTYPE_TO_C =
{:float32 => :float, :float64 => :double, :int32 => :int, :byte => :byte, :int8 => :byte}

Class Method Summary collapse

Class Method Details

.allocate_results_space(result_size, c_type) ⇒ Object

Allocates index space and distance space for storing results from various searches. For a k-nearest neighbors search, for example, you want trows (the number of rows in the testset) times k (the number of nearest neighbors being searched for).

Note that c_type will produce float for everything except double, which produces double.



141
142
143
# File 'lib/flann.rb', line 141

def allocate_results_space result_size, c_type #:nodoc:
  [FFI::MemoryPointer.new(:int, result_size), FFI::MemoryPointer.new(c_type == :double ? :double : :float, result_size)]
end

.cluster(dataset, clusters, parameters = {}) ⇒ Object Also known as: compute_cluster_centers

Perform hierarchical clustering of a set of points.

Arguments:

  • dataset: NMatrix of points

  • parameters:



224
225
226
227
228
229
230
231
232
233
234
235
236
# File 'lib/flann.rb', line 224

def cluster dataset, clusters, parameters = {}
  parameters = Parameters.new(Flann::Parameters::DEFAULT.merge(parameters))
  c_method = "flann_compute_cluster_centers_#{Flann::dtype_to_c(dataset.dtype)}".to_sym

  result = dataset.clone_structure
  parameters_ptr, parameters = handle_parameters(parameters)

  #err_code =
  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)
  #raise("unknown error in cluster") if err_code < 0

  result
end

.dtype_to_c(d) ⇒ Object

:nodoc:

Raises:

  • (NMatrix::DataTypeError)


130
131
132
133
# File 'lib/flann.rb', line 130

def dtype_to_c d #:nodoc:
  return DTYPE_TO_C[d] if DTYPE_TO_C.has_key?(d)
  raise(NMatrix::DataTypeError, "FLANN does not support this dtype")
end

.get_distance_orderObject Also known as: distance_order



212
213
214
# File 'lib/flann.rb', line 212

def get_distance_order
  Flann.flann_get_distance_order
end

.get_distance_typeObject Also known as: distance_type



209
210
211
# File 'lib/flann.rb', line 209

def get_distance_type
  Flann.flann_get_distance_type
end

.get_distance_type_and_orderObject

Get the distance type and order



206
207
208
# File 'lib/flann.rb', line 206

def get_distance_type_and_order
  [Flann.flann_get_distance_type, Flann.flann_get_distance_order]
end

.handle_parameters(parameters) {|c_parameters| ... } ⇒ Object

Don’t know if these will be a hash, a static struct, or a pointer to a struct. Return the pointer and the struct.

Yields:

  • (c_parameters)


147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
# File 'lib/flann.rb', line 147

def handle_parameters parameters #:nodoc:
  parameters ||= Parameters::DEFAULT unless block_given?

  if parameters.is_a?(FFI::MemoryPointer) # User supplies us with the necessary parameters already in the correct form.
    c_parameters_ptr = parameters
    c_parameters = Flann::Parameters.new(c_parameters_ptr)
  elsif parameters.is_a?(Flann::Parameters)
    c_parameters = parameters
    c_parameters_ptr = parameters.pointer
  else
    # Set the old fasioned way
    c_parameters_ptr = FFI::MemoryPointer.new(Flann::Parameters.size)
    c_parameters = Flann::Parameters.new(c_parameters_ptr)
    if parameters.is_a?(Hash)
      parameters.each_pair do |key, value|
        c_parameters[key] = value
      end
    end
  end

  # There may also be a block.
  yield c_parameters if block_given?

  [c_parameters_ptr, c_parameters]
end

.nearest_neighbors(dataset, testset, k, parameters = {}) ⇒ Object Also known as: nn

Find the k nearest neighbors.

If no index parameters are given, FLANN_Parameters::DEFAULT are used. A block is accepted as well.



177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
# File 'lib/flann.rb', line 177

def nearest_neighbors dataset, testset, k, parameters = {}
  parameters = Parameters.new(Flann::Parameters::DEFAULT.merge(parameters))
  # Get a pointer and a struct regardless of how the arguments are supplied.
  parameters_ptr, parameters = handle_parameters(parameters)
  result_size = testset.shape[0] * k

  c_type = Flann::dtype_to_c(dataset.dtype)
  c_method = "flann_find_nearest_neighbors_#{c_type}".to_sym
  indices_int_ptr, distances_t_ptr = allocate_results_space(result_size, c_type)

  # dataset, rows, cols, testset, trows, indices, dists, nn, flann_params
  Flann.send c_method,   FFI::Pointer.new_from_nmatrix(dataset), dataset.shape[0], dataset.shape[1],
                         FFI::Pointer.new_from_nmatrix(testset), testset.shape[0],
                         indices_int_ptr, distances_t_ptr, k, parameters_ptr

  # Return results: two arrays, one of indices and one of distances.
  [indices_int_ptr.read_array_of_int(result_size),
   c_type == :double ? distances_t_ptr.read_array_of_double(result_size) : distances_t_ptr.read_array_of_float(result_size)]
end

.set_distance_type!(distance_function) ⇒ Object Also known as: set_distance_type_and_order!

Set the distance function to use when computing distances between data points.



199
200
201
202
# File 'lib/flann.rb', line 199

def set_distance_type! distance_function
  Flann.send(:flann_set_distance_type, distance_function, get_distance_order)
  self
end