Class: Matrix

Inherits:
Object show all
Defined in:
lib/y_support/abstract_algebra.rb,
lib/y_support/stdlib_ext/matrix/misc.rb

Overview

As a matter of fact, current version of the Matrix class (by Marc-Andre Lafortune) does not work with physical magnitudes. It is a feature of the physical magnitudes, that they do not allow themselves summed with plain numbers or incompatible magnitudes. But current version of Matrix class, upon matrix multiplication, performs needless addition of the matrix elements to literal numeric 0.

The obvious solution is to patch Matrix class so that the needless addition to literal 0 is no longer performed.

More systematically, abstract algebra is to be added to Ruby, and Matrix is to require that its elements comply with monoid, group, ring, field, depending on the operation one wants to do with such matrices.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#zeroObject



179
180
181
# File 'lib/y_support/abstract_algebra.rb', line 179

def zero
  if empty? then @zero else self[0, 0] * 0 end
end

Class Method Details

.build(row_size, column_size = row_size) ⇒ Object

Creates a matrix of size row_size x column_size. It fills the values by calling the given block, passing the current row and column. Returns an enumerator if no block is given.

m = Matrix.build(2, 4) {|row, col| col - row }
  => Matrix[[0, 1, 2, 3], [-1, 0, 1, 2]]
m = Matrix.build(3) { rand }
  => a 3x3 matrix with random elements

Raises:

  • (ArgumentError)


114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/y_support/stdlib_ext/matrix/misc.rb', line 114

def Matrix.build(row_size, column_size = row_size)
  row_size = CoercionHelper.coerce_to_int(row_size)
  column_size = CoercionHelper.coerce_to_int(column_size)
  raise ArgumentError if row_size < 0 || column_size < 0
  return to_enum :build, row_size, column_size unless block_given?
  rows = Array.new(row_size) do |i|
    Array.new(column_size) do |j|
      yield i, j
    end
  end
  new rows, column_size
end

.correspondence_matrix(array1, array2) ⇒ Object

Given two arrays, creates correspondence matrix, with no. of cols equal to the 1st array, and no. of rows to the 2nd. This matrix can be used eg. for conversion between column vectors corresponding to the 1st and 2nd array:

Matrix.correspondence_matrix( array1, array2 ) * col_vector_1 #=> col_vector_2



39
40
41
42
43
# File 'lib/y_support/stdlib_ext/matrix/misc.rb', line 39

def self.correspondence_matrix( array1, array2 )
  return Matrix.empty 0, array1.size if array2.empty?
  return Matrix.empty array2.size, 0 if array1.empty?
  self[ *array2.map { |e2| array1.map { |e1| e1 == e2 ? 1 : 0 } } ] # FIXME: Ordinary zero
end

.cv(*aa, &b) ⇒ Object

Shorter aliases for #row_vector, #column_vector



57
# File 'lib/y_support/stdlib_ext/matrix/misc.rb', line 57

def self.cv *aa, &b; column_vector *aa, &b end

.empty(row_size = 0, column_size = 0) ⇒ Object

Creates a empty matrix of row_size x column_size. At least one of row_size or column_size must be 0.

m = Matrix.empty(2, 0)
m == Matrix[ [], [] ]
  => true
n = Matrix.empty(0, 3)
n == Matrix.columns([ [], [], [] ])
  => true
m * n
  => Matrix[[0, 0, 0], [0, 0, 0]]


96
97
98
99
100
101
# File 'lib/y_support/stdlib_ext/matrix/misc.rb', line 96

def Matrix.empty(row_size = 0, column_size = 0)
  Matrix.Raise ArgumentError, "One size must be 0" if column_size != 0 && row_size != 0
  Matrix.Raise ArgumentError, "Negative size" if column_size < 0 || row_size < 0

  new([[]]*row_size, column_size)
end

.rv(*aa, &b) ⇒ Object



58
# File 'lib/y_support/stdlib_ext/matrix/misc.rb', line 58

def self.rv *aa, &b; row_vector *aa, &b end

.wildcard_zero(r_count, c_count = r_count) ⇒ Object

Creates a matrix of prescribed dimensions filled with wildcard zeros.



229
230
231
# File 'lib/y_support/abstract_algebra.rb', line 229

def Matrix.wildcard_zero r_count, c_count=r_count
  build r_count, c_count do |r, c| WILDCARD_ZERO end
end

Instance Method Details

#*(arg) ⇒ Object

Matrix multiplication.



185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
# File 'lib/y_support/abstract_algebra.rb', line 185

def * arg # arg is matrix or vector or number
  case arg
  when Numeric
    rows = @rows.map { |row| row.map { |e| e * arg } }
    return new_matrix rows, column_size
  when Vector
    arg = Matrix.column_vector arg
    result = self * arg
    return result.column 0
  when Matrix
    Matrix.Raise ErrDimensionMismatch if column_size != arg.row_size
    if empty? then # if empty?, then reduce uses WILDCARD_ZERO
      rows = Array.new row_size do |i|
        Array.new arg.column_size do |j|
          ( 0...column_size ).reduce WILDCARD_ZERO do |sum, c|
            sum + arg[c, j] * self[i, c]
          end
        end
      end
    else             # if non-empty, reduce proceeds without WILDCARD_ZERO
      rows = Array.new row_size do |i|
        Array.new arg.column_size do |j|
          ( 0...column_size ).map { |c| arg[c, j] * self[i, c] }.reduce :+
        end
      end
    end
    return new_matrix( rows, arg.column_size )
  when SY::Magnitude # newly added - multiplication by a magnitude
    # I am not happy with this explicit switch on SY::Magnitude type here.
    # Perhaps coerce should handle this?
    rows = Array.new row_size do |i|
      Array.new column_size do |j|
        self[i, j] * arg
      end
    end
    return self.class[ *rows ]
  else
    compat_1, compat_2 = arg.coerce self
    return compat_1 * compat_2
  end
end

#column_to_a(n = 0) ⇒ Object

Converts a column into array. If argument is given, it chooses column number, otherwise column 0 is assumed.



48
# File 'lib/y_support/stdlib_ext/matrix/misc.rb', line 48

def column_to_a n=0; ( col = column( n ) ) ? col.to_a : nil end

#join_bottom(other) ⇒ Object

join_bottom method

Raises:

  • (ArgumentError)


62
63
64
65
66
67
68
# File 'lib/y_support/stdlib_ext/matrix/misc.rb', line 62

def join_bottom other;
  raise ArgumentError, "Column size mismatch" unless
    column_size == other.column_size
  return other.map { |e| e } if row_size == 0
  return Matrix.empty row_size + other.row_size, 0 if column_size == 0
  self.class[ *( row_vectors + other.row_vectors ) ]
end

#join_right(other) ⇒ Object

join_right methods

Raises:

  • (ArgumentError)


72
73
74
75
# File 'lib/y_support/stdlib_ext/matrix/misc.rb', line 72

def join_right other;
  raise ArgumentError, "Row size mismatch" unless row_size == other.row_size
  ( t.join_bottom( other.t ) ).t
end

#pretty_inspectObject

Pretty inspect



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# File 'lib/y_support/stdlib_ext/matrix/misc.rb', line 7

def pretty_inspect
  return inspect if row_size == 0 or column_size == 0
  aa = send(:rows).each.with_object [] do |row, memo|
    memo << row.map{ |o|
      os = o.to_s
      case o
      when Numeric then os[0] == '-' ? os : ' ' + os
      else o.to_s end
    }
  end
  width = aa.map{ |row| row.map( &:size ).max }.max + 1
  aa.each_with_object "" do |row, memo|
    row.each{ |e| memo << e << ' ' * ( width - e.size ) }
    memo << "\n"
  end
end

#pretty_printObject Also known as: pp

Pretty print



25
26
27
28
# File 'lib/y_support/stdlib_ext/matrix/misc.rb', line 25

def pretty_print
  print pretty_inspect
  return nil
end

#row_to_a(n = 0) ⇒ Object

Converts a row into array. If argument is given, it chooses row number, otherwise row 0 is assumed.



53
# File 'lib/y_support/stdlib_ext/matrix/misc.rb', line 53

def row_to_a n=0; ( r = row( n ) ) ? r.to_a : nil end