Class: NamedVector

Inherits:
Object
  • Object
show all
Defined in:
lib/named_vector.rb

Overview

Vectors with named dimensions. Infinite dimensional objects with simple vector calculus operations defined.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(*dims) ⇒ NamedVector

creates a new named vector

Parameters:

  • dims (Hash<String,Fixnum>, Hash<Symbol,Fixnum>, Array<String>, Array<Symbol>)

    the dimensions to initialize the vectors with, either as a hash of assignments or simply the names of the dimensions.



12
13
14
15
16
# File 'lib/named_vector.rb', line 12

def initialize(*dims)
	@vector = Hash.new
	@keys   = Set.new
	import_dimensions(dims)
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(mid, *args) ⇒ Object (private)

:nodoc:



111
112
113
114
115
116
117
118
119
120
121
122
123
124
# File 'lib/named_vector.rb', line 111

def method_missing(mid, *args) # :nodoc:
	mname = mid.id2name
	len = args.length
	if mname.chomp!('=')
		if len != 1
			raise ArgumentError, "wrong number of arguments (#{len} for 1)", caller(1)
		end
		modify_dimension(mname, args[0])
	elsif len == 0
		@vector.fetch(mname,0.0)
	else
		raise NoMethodError, "undefined method `#{mid}' for #{self}", caller(1)
	end
end

Instance Attribute Details

#keysObject (readonly) Also known as: dimensions

Returns the value of attribute keys.



7
8
9
# File 'lib/named_vector.rb', line 7

def keys
  @keys
end

Class Method Details

.add_dimension_iterator(obj) ⇒ Object

adds a dimension iterator (iterate through the keys) to a Hash or NamedVector

Parameters:

  • obj (Hash, NamedVector)

    the object to add the method to.



59
60
61
62
63
64
65
# File 'lib/named_vector.rb', line 59

def self.add_dimension_iterator(obj)
	obj.define_singleton_method(:each_dimension) do |&block|
		self.keys.each do |key|
			block.call(key)
		end
	end
end

.dot_product(a, b) ⇒ Object

Perform a dot product with another vector

Parameters:

  • a (Hash, NamedVector)

    the vector or scalar to multiply this vector with.

  • b (Hash, NamedVector)

    the vector or scalar to multiply this vector with.



76
77
78
79
80
81
82
83
84
# File 'lib/named_vector.rb', line 76

def self.dot_product(a, b)
	sum    = 0.0
	if a.keys.length < b.keys.length
		a.each_dimension {|i| sum+=a[i]*b[i]}
	else
		b.each_dimension {|i| sum+=b[i]*a[i]}
	end
	sum
end

.from_mongo(doc) ⇒ Object

Mongo retrieval

Parameters:

  • doc (BSON::OrderedHash)

    the mongo document to retrieve the vector from.



162
163
164
165
166
167
168
# File 'lib/named_vector.rb', line 162

def self.from_mongo(doc)
	hash = {}
	doc["keys"].each_with_index do |k, index|
		hash[k] = doc["dimensions"][index]
	end
	self.new hash
end

Instance Method Details

#*(value) ⇒ Object

Perform a dot product with another vector

Parameters:

  • value (Hash, Fixnum, Float, NamedVector)

    the vector or scalar to multiply this vector with. Scalar multiplication is destructive.



43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/named_vector.rb', line 43

def *(value)
	case value
	when Fixnum, Float  #scalar multiplication product
		each_dimension {|i| @vector[i] = self[i]*value}
	when NamedVector #dot product
		NamedVector.dot_product(self, value)
	when Hash #dot product
		NamedVector.add_dimension_iterator(value)
		NamedVector.dot_product(self,value)
	else
		raise TypeError, "#{value.class} cannot be coerced to NamedVector."
	end
end

#[](key) ⇒ Object

fetches the value at the dimension specified

Parameters:

  • key (Symbol, String)

    the dimension requested



95
96
97
# File 'lib/named_vector.rb', line 95

def [](key)
	@vector.fetch(key.to_s,0.0)
end

#[]=(key, value) ⇒ Object

assigns a value at the dimension specified

Parameters:

  • key (Symbol, String)

    the dimension requested

  • value (Fixnum, Float)

    the assignment for this dimension



107
108
109
# File 'lib/named_vector.rb', line 107

def []=(key,value)
	modify_dimension(key,value)
end

#dot_product(value) ⇒ Object

Perform a dot product with another vector

Parameters:

  • value (Hash, NamedVector)

    the vector to multiply this vector with.



69
70
71
# File 'lib/named_vector.rb', line 69

def dot_product(value)
	NamedVector.dot_product(self, value)
end

#each_dimensionObject

iterates through each dimension of a vector



87
88
89
90
91
# File 'lib/named_vector.rb', line 87

def each_dimension
	@keys.each do |key|
		yield(key)
	end
end

#import_dimensions(dims) ⇒ Object

imports the dimension information in Array form

Parameters:

  • dims  (Array<Array>, Array<String>, Array<Symbol>, Array<Hash>, Array<Fixnum>, Array<Array>)

    values to initialize



20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/named_vector.rb', line 20

def import_dimensions(dims)
	if dims && dims.first
		case dims.first
		when Array
			array = dims.first
			if array.first.class == String
				@keys = Set.new(array.map {|i| i.to_s})
				array.each {|d| self[d]+=1}
			end
		when Hash
			hash = dims.first
			hash.keys.each {|d| modify_dimension(d, hash[d])}
		when String, Symbol, Fixnum
			@keys = Set.new(dims.map {|i| i.to_s})
			dims.each {|d| new_dimension(d)}
		end
	else
		@keys = []
	end
end

#normObject

the Euclidean norm of a vector



145
146
147
# File 'lib/named_vector.rb', line 145

def norm
	Math.sqrt(squared_norm)
end

#normalizeObject

normalizes the vector destructively.



150
151
152
153
# File 'lib/named_vector.rb', line 150

def normalize
	current_norm = norm
	if current_norm > 0 then self*(1.0/current_norm) end
end

#squared_normObject

the squared Euclidean norm of a vector



138
139
140
141
142
# File 'lib/named_vector.rb', line 138

def squared_norm
	norm    = 0.0
	each_dimension {|i| norm+=self[i]**2}
	norm
end

#to_mongoObject

Mongo conversion



156
157
158
# File 'lib/named_vector.rb', line 156

def to_mongo
	{"keys"=> @keys, "dimensions"=> @keys.map {|i| self[i]}}
end