Class: Stick::Vector

Inherits:
Object
  • Object
show all
Includes:
Enumerable, ExceptionForMatrix
Defined in:
lib/stick/matrix/core.rb,
lib/stick/matrix.rb

Overview

The Vector class represents a mathematical vector, which is useful in its own right, and also constitutes a row or column of a Matrix.

Method Catalogue

To create a Vector:

  • Vector.[](*array)

  • Vector.elements(array, copy = true)

To access elements:

  • [](i)

To enumerate the elements:

  • #each2(v)

  • #collect2(v)

Vector arithmetic:

  • *(x) "is matrix or number"

  • +(v)

  • -(v)

Vector functions:

  • #inner_product(v)

  • #collect

  • #map

  • #map2(v)

  • #r

  • #size

Conversion to other data types:

  • #covector

  • #to_a

  • #coerce(other)

String representations:

  • #to_s

  • #inspect

Defined Under Namespace

Modules: Norm

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(method, array, copy) ⇒ Vector

For internal use.



1127
1128
1129
# File 'lib/stick/matrix/core.rb', line 1127

def initialize(method, array, copy)
  self.send(method, array, copy)
end

Class Method Details

.[](*array) ⇒ Object

Creates a Vector from a list of elements.

Vector[7, 4, ...]


1112
1113
1114
# File 'lib/stick/matrix/core.rb', line 1112

def Vector.[](*array)
  new(:init_elements, array, copy = false)
end

.concat(*args) ⇒ Object

Returns a concatenated Vector



65
66
67
68
69
# File 'lib/stick/matrix.rb', line 65

def concat(*args)
  v = []
  args.each{|x| v += x.to_a}
  Vector[*v]
end

.elements(array, copy = true) ⇒ Object

Creates a vector from an Array. The optional second argument specifies whether the array itself or a copy is used internally.



1120
1121
1122
# File 'lib/stick/matrix/core.rb', line 1120

def Vector.elements(array, copy = true)
  new(:init_elements, array, copy)
end

.gram_schmidt(*vectors) ⇒ Object

Stabilized Gram-Schmidt process (en.wikipedia.org/wiki/Gram-Schmidt_process#Algorithm)



201
202
203
204
205
206
207
208
209
210
# File 'lib/stick/matrix.rb', line 201

def Vector.gram_schmidt(*vectors)
  v = vectors.clone
  for j in 0...v.size
    for i in 0..j-1
      v[j] -= v[i] * v[j].inner_product(v[i])
    end
    v[j] /= v[j].norm
  end
  v
end

Instance Method Details

#*(x) ⇒ Object

Multiplies the vector by x, where x is a number or another vector.



1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
# File 'lib/stick/matrix/core.rb', line 1236

def *(x)
  case x
  when Numeric
    els = @elements.collect{|e| e * x}
    Vector.elements(els, false)
  when Matrix
    Matrix.column_vector(self) * x
  else
    s, x = x.coerce(self)
    s * x
  end
end

#+(v) ⇒ Object

Vector addition.



1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
# File 'lib/stick/matrix/core.rb', line 1252

def +(v)
  case v
  when Vector
    Vector.Raise ErrDimensionMismatch if size != v.size
    els = collect2(v) {
      |v1, v2|
      v1 + v2
    }
    Vector.elements(els, false)
  when Matrix
    Matrix.column_vector(self) + v
  else
    s, x = v.coerce(self)
    s + x
  end
end

#-(v) ⇒ Object

Vector subtraction.



1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
# File 'lib/stick/matrix/core.rb', line 1272

def -(v)
  case v
  when Vector
    Vector.Raise ErrDimensionMismatch if size != v.size
    els = collect2(v) {
      |v1, v2|
      v1 - v2
    }
    Vector.elements(els, false)
  when Matrix
    Matrix.column_vector(self) - v
  else
    s, x = v.coerce(self)
    s - x
  end
end

#/(c) ⇒ Object

Return the vector divided by a scalar



144
145
146
# File 'lib/stick/matrix.rb', line 144

def /(c)
  map {|e| e.quo(c)}
end

#==(other) ⇒ Object Also known as: eqn?

Returns true iff the two vectors have the same elements in the same order.



1201
1202
1203
1204
1205
# File 'lib/stick/matrix/core.rb', line 1201

def ==(other)
  return false unless Vector === other

  other.compare_by(@elements)
end

#[](i) ⇒ Object Also known as: element, component

Returns element number i (starting at zero) of the vector.



35
36
37
38
39
40
41
42
# File 'lib/stick/matrix.rb', line 35

def [](i)
  case i
  when Range
    Vector[*to_a.slice(i)]
  else
    index(i)
  end
end

#[]=(i, v) ⇒ Object Also known as: set_element, set_component

Sets a vector value/(range of values) with a new value/(values from a vector) v = Vector[1, 2, 3] v = 9 => Vector[1, 2, 9] v = Vector[9, 9, 9, 9, 9] => v: Vector[1, 9, 9]



50
51
52
53
54
55
56
57
58
59
# File 'lib/stick/matrix.rb', line 50

def []=(i, v)
  case i
  when Range
    (self.size..i.begin - 1).each{|e| self[e] = 0} # self.size must be in the first place because the size of self can be modified
    [v.size, i.entries.size].min.times {|e| self[e + i.begin] = v[e]}
    (v.size + i.begin .. i.end).each {|e| self[e] = 0}
  else
    @elements[i]=v
  end
end

#cloneObject

Return a copy of the vector.



1218
1219
1220
# File 'lib/stick/matrix/core.rb', line 1218

def clone
  Vector.elements(@elements)
end

#coerce(other) ⇒ Object

FIXME: describe Vector#coerce.



1376
1377
1378
1379
1380
1381
1382
1383
# File 'lib/stick/matrix/core.rb', line 1376

def coerce(other)
  case other
  when Numeric
    return Matrix::Scalar.new(other), self
  else
    raise TypeError, "#{self.class} can't be coerced into #{other.class}"
  end
end

#collectObject Also known as: map

Like Array#collect.



1311
1312
1313
1314
1315
1316
1317
# File 'lib/stick/matrix/core.rb', line 1311

def collect # :yield: e
  els = @elements.collect {
    |v|
    yield v
  }
  Vector.elements(els, false)
end

#collect!Object

Changes the elements of vector and returns a Vector



75
76
77
78
# File 'lib/stick/matrix.rb', line 75

def collect!
  els = @elements.collect! {|v| yield(v)}
  Vector.elements(els, false)
end

#collect2(v) ⇒ Object

Collects (as in Enumerable#collect) over the elements of this vector and v in conjunction.



1186
1187
1188
1189
1190
1191
1192
# File 'lib/stick/matrix/core.rb', line 1186

def collect2(v) # :yield: e1, e2
  Vector.Raise ErrDimensionMismatch if size != v.size
  (0 .. size - 1).collect do
    |i|
    yield @elements[i], v[i]
  end
end

#compare_by(elements) ⇒ Object

For internal use.



1211
1212
1213
# File 'lib/stick/matrix/core.rb', line 1211

def compare_by(elements)
  @elements == elements
end

#covectorObject

Creates a single-row matrix from this vector.



1350
1351
1352
# File 'lib/stick/matrix/core.rb', line 1350

def covector
  Matrix.row_vector(self)
end

#eachObject

Iterates the elements of a vector



83
84
85
86
# File 'lib/stick/matrix.rb', line 83

def each
  (0...size).each {|i| yield(self[i])}
  nil
end

#each2(v) ⇒ Object

Iterate over the elements of this vector and v in conjunction.



1174
1175
1176
1177
1178
1179
1180
# File 'lib/stick/matrix/core.rb', line 1174

def each2(v) # :yield: e1, e2
  Vector.Raise ErrDimensionMismatch if size != v.size
  0.upto(size - 1) do
    |i|
    yield @elements[i], v[i]
  end
end

#elements_to_fObject



1361
1362
1363
# File 'lib/stick/matrix/core.rb', line 1361

def elements_to_f
  collect{|e| e.to_f}
end

#elements_to_iObject



1365
1366
1367
# File 'lib/stick/matrix/core.rb', line 1365

def elements_to_i
  collect{|e| e.to_i}
end

#elements_to_rObject



1369
1370
1371
# File 'lib/stick/matrix/core.rb', line 1369

def elements_to_r
  collect{|e| e.to_r}
end

#hashObject

Return a hash-code for the vector.



1225
1226
1227
# File 'lib/stick/matrix/core.rb', line 1225

def hash
  @elements.hash
end

#houseObject

Computes the Householder vector (MC, Golub, p. 210, algorithm 5.1.1)



160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
# File 'lib/stick/matrix.rb', line 160

def house
  s = self[1..length-1]
  sigma = s.inner_product(s)
  v = clone; v[0] = 1
  if sigma == 0
    beta = 0
  else
    mu = Math.sqrt(self[0] ** 2 + sigma)
    if self[0] <= 0
      v[0] = self[0] - mu
    else
      v[0] = - sigma.quo(self[0] + mu)
    end
    v2 = v[0] ** 2
    beta = 2 * v2.quo(sigma + v2)
    v /= v[0]
  end
  return v, beta
end

#indexObject



27
# File 'lib/stick/matrix.rb', line 27

alias :index :[]

#init_elements(array, copy) ⇒ Object

For internal use.



1134
1135
1136
1137
1138
1139
1140
# File 'lib/stick/matrix/core.rb', line 1134

def init_elements(array, copy)
  if copy
    @elements = array.dup
  else
    @elements = array
  end
end

#inner_product(v) ⇒ Object

Returns the inner product of this vector with the other.

Vector[4,7].inner_product Vector[10,1]  => 47


1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
# File 'lib/stick/matrix/core.rb', line 1297

def inner_product(v)
  Vector.Raise ErrDimensionMismatch if size != v.size

  p = 0
  each2(v) {
    |v1, v2|
    p += v1 * v2
  }
  p
end

#inspectObject

Overrides Object#inspect



1399
1400
1401
# File 'lib/stick/matrix/core.rb', line 1399

def inspect
  str = "Vector"+@elements.inspect
end

#lengthObject



26
# File 'lib/stick/matrix.rb', line 26

alias :length :size

#map2(v) ⇒ Object

Like Vector#collect2, but returns a Vector instead of an Array.



1323
1324
1325
1326
1327
1328
1329
# File 'lib/stick/matrix/core.rb', line 1323

def map2(v) # :yield: e1, e2
  els = collect2(v) {
    |v1, v2|
    yield v1, v2
  }
  Vector.elements(els, false)
end

#maxObject

Returns the maximum element of a vector



91
92
93
# File 'lib/stick/matrix.rb', line 91

def max
  to_a.max
end

#minObject

Returns the minimum element of a vector



98
99
100
# File 'lib/stick/matrix.rb', line 98

def min
  to_a.min
end

#norm(p = 2) ⇒ Object

Returns the p-norm of a vector



105
106
107
# File 'lib/stick/matrix.rb', line 105

def norm(p = 2)
  Norm.sqnorm(self, p) ** (Float(1)/p)
end

#norm_infObject

Returns the infinite-norm



112
113
114
# File 'lib/stick/matrix.rb', line 112

def norm_inf
  [min.abs, max.abs].max
end

#normalizeObject

Return the vector normalized



193
194
195
# File 'lib/stick/matrix.rb', line 193

def normalize
  self / self.norm
end

#proj(v) ⇒ Object



184
185
186
187
188
# File 'lib/stick/matrix.rb', line 184

def proj(v)
  vp = v.inner_product(self)
  vp = Float vp if vp.is_a?(Integer)
  self * (vp / inner_product(self))
end

#rObject

Returns the modulus (Pythagorean distance) of the vector.

Vector[5,8,2].r => 9.643650761


1335
1336
1337
1338
1339
1340
1341
# File 'lib/stick/matrix/core.rb', line 1335

def r
  v = 0
  for e in @elements
    v += e*e
  end
  return Math.sqrt(v)
end

#sizeObject

Returns the number of elements in the vector.



1163
1164
1165
# File 'lib/stick/matrix/core.rb', line 1163

def size
  @elements.size
end

#slice(*args) ⇒ Object

Returns a slice of vector



119
120
121
# File 'lib/stick/matrix.rb', line 119

def slice(*args)
  Vector[*to_a.slice(*args)]
end

#slice=(args) ⇒ Object

Sets a slice of vector



132
133
134
135
136
137
138
139
# File 'lib/stick/matrix.rb', line 132

def slice=(args)
  case args[1]
  when Range
    slice_set(args[0], args[1].begin, args[1].last)
  else
    slice_set(args[0], args[1], args[2])
  end
end

#slice_set(v, b, e) ⇒ Object



123
124
125
126
127
# File 'lib/stick/matrix.rb', line 123

def slice_set(v, b, e)
  for i in b..e
    self[i] = v[i-b]
  end
end

#to_aObject

Returns the elements of the vector in an array.



1357
1358
1359
# File 'lib/stick/matrix/core.rb', line 1357

def to_a
  @elements.dup
end

#to_sObject

Overrides Object#to_s



1392
1393
1394
# File 'lib/stick/matrix/core.rb', line 1392

def to_s
  "Vector[" + @elements.join(", ") + "]"
end

#transposeObject Also known as: t

Return the matrix column coresponding to the vector transpose



151
152
153
# File 'lib/stick/matrix.rb', line 151

def transpose
  Matrix[self.to_a]
end