class Neighbor::Vector
Public Class Methods
cast(value, dimensions:, normalize:, column_info:)
click to toggle source
# File lib/neighbor/vector.rb, line 11 def self.cast(value, dimensions:, normalize:, column_info:) value = value.to_a.map(&:to_f) dimensions ||= column_info[:dimensions] raise Error, "Expected #{dimensions} dimensions, not #{value.size}" if dimensions && value.size != dimensions raise Error, "Values must be finite" unless value.all?(&:finite?) if normalize norm = Math.sqrt(value.sum { |v| v * v }) # store zero vector as all zeros # since NaN makes the distance always 0 # could also throw error # safe to update in-place since earlier map dups value.map! { |v| v / norm } if norm > 0 end value end
column_info(model, attribute_name)
click to toggle source
# File lib/neighbor/vector.rb, line 33 def self.column_info(model, attribute_name) attribute_name = attribute_name.to_s column = model.columns.detect { |c| c.name == attribute_name } { type: column.try(:type), dimensions: column.try(:limit) } end
new(dimensions:, normalize:, model:, attribute_name:)
click to toggle source
Calls superclass method
# File lib/neighbor/vector.rb, line 3 def initialize(dimensions:, normalize:, model:, attribute_name:) super() @dimensions = dimensions @normalize = normalize @model = model @attribute_name = attribute_name end
Public Instance Methods
cast(value)
click to toggle source
# File lib/neighbor/vector.rb, line 47 def cast(value) self.class.cast(value, dimensions: @dimensions, normalize: @normalize, column_info: column_info) unless value.nil? end
column_info()
click to toggle source
need to be careful to avoid loading column info before needed
# File lib/neighbor/vector.rb, line 43 def column_info @column_info ||= self.class.column_info(@model, @attribute_name) end
deserialize(value)
click to toggle source
# File lib/neighbor/vector.rb, line 61 def deserialize(value) value[1..-1].split(",").map(&:to_f) unless value.nil? end
serialize(value)
click to toggle source
# File lib/neighbor/vector.rb, line 51 def serialize(value) unless value.nil? if column_info[:type] == :vector "[#{cast(value).join(", ")}]" else "(#{cast(value).join(", ")})" end end end