Spec-Zone.ru › Ruby 2.7

класс Matrix

Родитель:
Объект
Включенные модули:
Enumerable, ExceptionForMatrix

Класс Matrix представляет собой математическую матрицу. Он предоставляет методы для создания матриц, выполнения арифметических и алгебраических операций над ними, а также определения их математических свойств, таких как след, ранг, обратная матрица, определитель или собственные значения.

Константы

SELECTORS
VERSION

Атрибуты

column_count[R]

Возвращает количество столбцов.

column_size[R]

Возвращает количество столбцов.

rows[R]

создание экземпляров

Методы публичного класса

I(n)
Псевдоним для: identity
[](*rows) Показать исходный код
# File lib/matrix.rb, line 78
def Matrix.[](*rows)
  rows(rows, false)
end

Создает матрицу, где каждый аргумент является строкой.

Matrix[ [25, 93], [-1, 66] ]
   =>  25 93
       -1 66
build(row_count, column_count = row_count) { |i, j| ... } Показать исходный код
# File lib/matrix.rb, line 123
def Matrix.build(row_count, column_count = row_count)
  row_count = CoercionHelper.coerce_to_int(row_count)
  column_count = CoercionHelper.coerce_to_int(column_count)
  raise ArgumentError if row_count < 0 || column_count < 0
  return to_enum :build, row_count, column_count unless block_given?
  rows = Array.new(row_count) do |i|
    Array.new(column_count) do |j|
      yield i, j
    end
  end
  new rows, column_count
end

Создает матрицу размером row_count x column_count. Она заполняет значения, вызывая заданный блок, передавая текущую строку и столбец. Возвращает перечислитель, если блок не задан.

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
column_vector(column) Показать исходный код
# File lib/matrix.rb, line 209
def Matrix.column_vector(column)
  column = convert_to_array(column)
  new [column].transpose, 1
end

Создает матрицу с одним столбцом, где значения этого столбца заданы в column.

Matrix.column_vector([4,5,6])
  => 4
     5
     6
columns(columns) Показать исходный код
# File lib/matrix.rb, line 108
def Matrix.columns(columns)
  rows(columns, false).transpose
end

Создает матрицу, используя columns в качестве массива столбцов.

Matrix.columns([[25, 93], [-1, 66]])
   =>  25 -1
       93 66
combine(*matrices) { |map{|m| m}| ... } Показать исходный код
# File lib/matrix.rb, line 286
def Matrix.combine(*matrices)
  return to_enum(__method__, *matrices) unless block_given?

  return Matrix.empty if matrices.empty?
  matrices.map!(&CoercionHelper.method(:coerce_to_matrix))
  x = matrices.first
  matrices.each do |m|
    raise ErrDimensionMismatch unless x.row_count == m.row_count && x.column_count == m.column_count
  end

  rows = Array.new(x.row_count) do |i|
    Array.new(x.column_count) do |j|
      yield matrices.map{|m| m[i,j]}
    end
  end
  new rows, x.column_count
end

Создает матрицу, объединяя матрицы по элементам, используя заданный блок

x = Matrix[[6, 6], [4, 4]]
y = Matrix[[1, 2], [3, 4]]
Matrix.combine(x, y) {|a, b| a - b} # => Matrix[[5, 4], [1, 0]]
diagonal(*values) Показать исходный код
# File lib/matrix.rb, line 143
def Matrix.diagonal(*values)
  size = values.size
  return Matrix.empty if size == 0
  rows = Array.new(size) {|j|
    row = Array.new(size, 0)
    row[j] = values[j]
    row
  }
  new rows
end

Создает матрицу, где диагональные элементы состоят из values.

Matrix.diagonal(9, 5, -3)
  =>  9  0  0
      0  5  0
      0  0 -3
empty(row_count = 0, column_count = 0) Показать исходный код
# File lib/matrix.rb, line 227
def Matrix.empty(row_count = 0, column_count = 0)
  raise ArgumentError, "One size must be 0" if column_count != 0 && row_count != 0
  raise ArgumentError, "Negative size" if column_count < 0 || row_count < 0

  new([[]]*row_count, column_count)
end

Создает пустую матрицу размером row_count x column_count. По крайней мере, один из row_count или column_count должен быть равен 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]]
hstack(x, *matrices) Показать исходный код
# File lib/matrix.rb, line 262
def Matrix.hstack(x, *matrices)
  x = CoercionHelper.coerce_to_matrix(x)
  result = x.send(:rows).map(&:dup)
  total_column_count = x.column_count
  matrices.each do |m|
    m = CoercionHelper.coerce_to_matrix(m)
    if m.row_count != x.row_count
      raise ErrDimensionMismatch, "The given matrices must have #{x.row_count} rows, but one has #{m.row_count}"
    end
    result.each_with_index do |row, i|
      row.concat m.send(:rows)[i]
    end
    total_column_count += m.column_count
  end
  new result, total_column_count
end

Создает матрицу, объединяя матрицы по горизонтали

x = Matrix[[1, 2], [3, 4]]
y = Matrix[[5, 6], [7, 8]]
Matrix.hstack(x, y) # => Matrix[[1, 2, 5, 6], [3, 4, 7, 8]]
identity(n) Показать исходный код
# File lib/matrix.rb, line 171
def Matrix.identity(n)
  scalar(n, 1)
end

Создаёт n на n единичную матрицу.

Matrix.identity(2)
  => 1 0
     0 1
Также алиасы: unit, I
new(rows, column_count = rows[0].size) Показать исходный код
# File lib/matrix.rb, line 311
def initialize(rows, column_count = rows[0].size)
  # No checking is done at this point. rows must be an Array of Arrays.
  # column_count must be the size of the first row, if there is one,
  # otherwise it *must* be specified and can be any integer >= 0
  @rows = rows
  @column_count = column_count
end

Matrix.new является приватным; используйте Matrix.rows, columns, [], и т.д. для создания.

row_vector(row) Показать исходный код
# File lib/matrix.rb, line 196
def Matrix.row_vector(row)
  row = convert_to_array(row)
  new [row]
end

Создаёт матрицу с одной строкой, где значения этой строки заданы в row.

Matrix.row_vector([4,5,6])
  => 4 5 6
rows(rows, copy = true) Показать исходный код
# File lib/matrix.rb, line 90
def Matrix.rows(rows, copy = true)
  rows = convert_to_array(rows, copy)
  rows.map! do |row|
    convert_to_array(row, copy)
  end
  size = (rows[0] || []).size
  rows.each do |row|
    raise ErrDimensionMismatch, "row size differs (#{row.size} should be #{size})" unless row.size == size
  end
  new rows, size
end

Создаёт матрицу, где rows является массивом массивов, каждый из которых является строкой матрицы. Если необязательный аргумент copy равен false, используйте заданные массивы как внутреннюю структуру матрицы без копирования.

Matrix.rows([[25, 93], [-1, 66]])
   =>  25 93
       -1 66
scalar(n, value) Показать исходный код
# File lib/matrix.rb, line 161
def Matrix.scalar(n, value)
  diagonal(*Array.new(n, value))
end

Создаёт n на n диагональную матрицу, где каждый диагональный элемент равен value.

Matrix.scalar(2, 5)
  => 5 0
     0 5
unit(n)
Псевдоним для: identity
vstack(x, *matrices) Показать исходный код
# File lib/matrix.rb, line 241
def Matrix.vstack(x, *matrices)
  x = CoercionHelper.coerce_to_matrix(x)
  result = x.send(:rows).map(&:dup)
  matrices.each do |m|
    m = CoercionHelper.coerce_to_matrix(m)
    if m.column_count != x.column_count
      raise ErrDimensionMismatch, "The given matrices must have #{x.column_count} columns, but one has #{m.column_count}"
    end
    result.concat(m.send(:rows))
  end
  new result, x.column_count
end

Создаёт матрицу, объединяя матрицы по вертикали

x = Matrix[[1, 2], [3, 4]]
y = Matrix[[5, 6], [7, 8]]
Matrix.vstack(x, y) # => Matrix[[1, 2], [3, 4], [5, 6], [7, 8]]
zero(row_count, column_count = row_count) Показать исходный код
# File lib/matrix.rb, line 185
def Matrix.zero(row_count, column_count = row_count)
  rows = Array.new(row_count){Array.new(column_count, 0)}
  new rows, column_count
end

Создаёт нулевую матрицу.

Matrix.zero(2)
  => 0 0
     0 0

Методы публичного экземпляра

*(m) Показать исходный код
# File lib/matrix.rb, line 1045
def *(m) # m is matrix or vector or number
  case(m)
  when Numeric
    rows = @rows.collect {|row|
      row.collect {|e| e * m }
    }
    return new_matrix rows, column_count
  when Vector
    m = self.class.column_vector(m)
    r = self * m
    return r.column(0)
  when Matrix
    raise ErrDimensionMismatch if column_count != m.row_count

    rows = Array.new(row_count) {|i|
      Array.new(m.column_count) {|j|
        (0 ... column_count).inject(0) do |vij, k|
          vij + self[i, k] * m[k, j]
        end
      }
    }
    return new_matrix rows, m.column_count
  else
    return apply_through_coercion(m, __method__)
  end
end

Умножение на Matrix.

Matrix[[2,4], [6,8]] * Matrix.identity(2)
  => 2 4
     6 8
**(other) Показать исходный код
# File lib/matrix.rb, line 1222
def **(other)
  case other
  when Integer
    x = self
    if other <= 0
      x = self.inverse
      return self.class.identity(self.column_count) if other == 0
      other = -other
    end
    z = nil
    loop do
      z = z ? z * x : x if other[0] == 1
      return z if (other >>= 1).zero?
      x *= x
    end
  when Numeric
    v, d, v_inv = eigensystem
    v * self.class.diagonal(*d.each(:diagonal).map{|e| e ** other}) * v_inv
  else
    raise ErrOperationNotDefined, ["**", self.class, other.class]
  end
end

Возведение в степень Matrix. Эквивалентно умножению матрицы на себя N раз. Для нецелых показателей степени будет использовано диагонализация матрицы.

Matrix[[7,6], [3,9]] ** 2
  => 67 96
     48 99
+(m) Показать исходный код
# File lib/matrix.rb, line 1078
def +(m)
  case m
  when Numeric
    raise ErrOperationNotDefined, ["+", self.class, m.class]
  when Vector
    m = self.class.column_vector(m)
  when Matrix
  else
    return apply_through_coercion(m, __method__)
  end

  raise ErrDimensionMismatch unless row_count == m.row_count && column_count == m.column_count

  rows = Array.new(row_count) {|i|
    Array.new(column_count) {|j|
      self[i, j] + m[i, j]
    }
  }
  new_matrix rows, column_count
end

Сложение Matrix.

Matrix.scalar(2,5) + Matrix[[1,0], [-4,7]]
  =>  6  0
     -4 12
+@() Показать исходный код
# File lib/matrix.rb, line 1245
def +@
  self
end
-(m) Показать исходный код
# File lib/matrix.rb, line 1105
def -(m)
  case m
  when Numeric
    raise ErrOperationNotDefined, ["-", self.class, m.class]
  when Vector
    m = self.class.column_vector(m)
  when Matrix
  else
    return apply_through_coercion(m, __method__)
  end

  raise ErrDimensionMismatch unless row_count == m.row_count && column_count == m.column_count

  rows = Array.new(row_count) {|i|
    Array.new(column_count) {|j|
      self[i, j] - m[i, j]
    }
  }
  new_matrix rows, column_count
end

Вычитание Matrix.

Matrix[[1,5], [4,2]] - Matrix[[9,3], [-4,1]]
  => -8  2
      8  1
-@() Показать исходный код
# File lib/matrix.rb, line 1249
def -@
  collect {|e| -e }
end
/(other) Показать исходный код
# File lib/matrix.rb, line 1132
def /(other)
  case other
  when Numeric
    rows = @rows.collect {|row|
      row.collect {|e| e / other }
    }
    return new_matrix rows, column_count
  when Matrix
    return self * other.inverse
  else
    return apply_through_coercion(other, __method__)
  end
end

Деление (умножение на обратную матрицу) Matrix.

Matrix[[7,6], [3,9]] / Matrix[[2,9], [3,1]]
  => -7  1
     -3 -6
==(other) Показать исходный код
# File lib/matrix.rb, line 1008
def ==(other)
  return false unless Matrix === other &&
                      column_count == other.column_count # necessary for empty matrices
  rows == other.rows
end

Возвращает true, если и только если две матрицы содержат одинаковые элементы.

[](i, j) Показать исходный код
# File lib/matrix.rb, line 326
def [](i, j)
  @rows.fetch(i){return nil}[j]
end

Возвращает элемент (i, j) матрицы. То есть: строка i, столбец j.

Также алиасирован как: element, component
matrix[range, range] = matrix/element Показать исходный код
matrix[range, integer] = vector/column_matrix/element
matrix[integer, range] = vector/row_matrix/element
matrix[integer, integer] = element
# File lib/matrix.rb, line 340
def []=(i, j, v)
  raise FrozenError, "can't modify frozen Matrix" if frozen?
  rows = check_range(i, :row) or row = check_int(i, :row)
  columns = check_range(j, :column) or column = check_int(j, :column)
  if rows && columns
    set_row_and_col_range(rows, columns, v)
  elsif rows
    set_row_range(rows, column, v)
  elsif columns
    set_col_range(row, columns, v)
  else
    set_value(row, column, v)
  end
end

Установка элемента или элементов Set матрицы.

Также алиасирован как: set_element, set_component
abs() Показать исходный код
# File lib/matrix.rb, line 1256
def abs
  collect(&:abs)
end

Возвращает модуль элементов по отдельности

adjugate() Показать исходный код
# File lib/matrix.rb, line 781
def adjugate
  raise ErrDimensionMismatch unless square?
  Matrix.build(row_count, column_count) do |row, column|
    cofactor(column, row)
  end
end

Возвращает присоединенную матрицу.

Matrix[ [7,6],[3,9] ].adjugate
  => 9 -6
     -3 7
antisymmetric?() Показать исходный код
# File lib/matrix.rb, line 960
def antisymmetric?
  raise ErrDimensionMismatch unless square?
  each_with_index(:upper) do |e, row, col|
    return false unless e == -rows[col][row]
  end
  true
end

Возвращает true, если это кососимметрическая матрица. Возвращает ошибку, если матрица не квадратная.

Также алиасирован как: skew_symmetric?
coerce(other) Показать исходный код
# File lib/matrix.rb, line 1565
def coerce(other)
  case other
  when Numeric
    return Scalar.new(other), self
  else
    raise TypeError, "#{self.class} can't be coerced into #{other.class}"
  end
end

Метод coerce обеспечивает поддержку приведения типов в Ruby. Этот механизм приведения типов используется Ruby для обработки операций с числами разных типов: он призван найти совместимый общий тип между двумя операндами оператора. См. также Numeric#coerce.

cofactor(row, column) Показать исходный код
# File lib/matrix.rb, line 766
def cofactor(row, column)
  raise RuntimeError, "cofactor of empty matrix is not defined" if empty?
  raise ErrDimensionMismatch unless square?

  det_of_minor = first_minor(row, column).determinant
  det_of_minor * (-1) ** (row + column)
end

Возвращает (строка, столбец) алгебраическое дополнение, полученное умножением первого минора на (-1)**(строка + столбец).

Matrix.diagonal(9, 5, -3, 4).cofactor(1, 1)
  => -108
cofactor_expansion(row: nil, column: nil)
Псевдоним для: laplace_expansion
collect(which = :all) { |e| ... } Показать исходный код
# File lib/matrix.rb, line 497
def collect(which = :all, &block) # :yield: e
  return to_enum(:collect, which) unless block_given?
  dup.collect!(which, &block)
end

Возвращает матрицу, являющуюся результатом итерации заданного блока по всем элементам матрицы. Элементы можно ограничить, передав аргумент:

  • :all (по умолчанию): возвращает все элементы

  • :diagonal: возвращает только элементы на диагонали

  • :off_diagonal: возвращает все элементы, кроме диагональных

  • :lower: возвращает только элементы на или ниже диагонали

  • :strict_lower: возвращает только элементы ниже диагонали

  • :strict_upper: возвращает только элементы выше диагонали

  • :upper: возвращает только элементы на или выше диагонали

  • Matrix[ [1,2], [3,4] ].collect { |e| e**2 }

    => 1  4
       9 16
Также алиасирован как: map
collect!(which = :all) { |e| ... } Показать исходный код
# File lib/matrix.rb, line 515
def collect!(which = :all)
  return to_enum(:collect!, which) unless block_given?
  raise FrozenError, "can't modify frozen Matrix" if frozen?
  each_with_index(which){ |e, row_index, col_index| @rows[row_index][col_index] = yield e }
end

Вызывает заданный блок для каждого элемента матрицы, заменяя элемент значением, возвращаемым блоком. Элементы можно ограничить, передав аргумент:

  • :all (по умолчанию): возвращает все элементы

  • :diagonal: возвращает только элементы на диагонали

  • :off_diagonal: возвращает все элементы, кроме диагональных

  • :lower: возвращает только элементы на или ниже диагонали

  • :strict_lower: возвращает только элементы ниже диагонали

  • :strict_upper: возвращает только элементы выше диагонали

  • :upper: возвращает только элементы на или выше диагонали

Также алиасирован как: map!
column(j) { |e| ... } Показать исходный код
# File lib/matrix.rb, line 466
def column(j) # :yield: e
  if block_given?
    return self if j >= column_count || j < -column_count
    row_count.times do |i|
      yield @rows[i][j]
    end
    self
  else
    return nil if j >= column_count || j < -column_count
    col = Array.new(row_count) {|i|
      @rows[i][j]
    }
    Vector.elements(col, false)
  end
end

Возвращает вектор-столбец с номером j матрицы в виде Vector (начиная с 0, как в массиве). Если задан блок, элементы этого вектора будут итерироваться.

column_vectors() Показать исходный код
# File lib/matrix.rb, line 1586
def column_vectors
  Array.new(column_count) {|i|
    column(i)
  }
end

Возвращает массив векторов-столбцов матрицы. См. Vector.

combine(*matrices, &block) Показать исходный код
# File lib/matrix.rb, line 304
def combine(*matrices, &block)
  Matrix.combine(self, *matrices, &block)
end
component(i, j)
Псевдоним для: []
conj()
Псевдоним для: conjugate
conjugate() Показать исходный код
# File lib/matrix.rb, line 1511
def conjugate
  collect(&:conjugate)
end

Возвращает сопряжённую матрицу.

Matrix[[Complex(1,2), Complex(0,1), 0], [1, 2, 3]]
  => 1+2i   i  0
        1   2  3
Matrix[[Complex(1,2), Complex(0,1), 0], [1, 2, 3]].conjugate
  => 1-2i  -i  0
        1   2  3
Также псевдоним для: conj
det()
Псевдоним для: determinant
det_e()
Псевдоним для: determinant_e
determinant() Показать исходный код
# File lib/matrix.rb, line 1274
def determinant
  raise ErrDimensionMismatch unless square?
  m = @rows
  case row_count
    # Up to 4x4, give result using Laplacian expansion by minors.
    # This will typically be faster, as well as giving good results
    # in case of Floats
  when 0
    +1
  when 1
    + m[0][0]
  when 2
    + m[0][0] * m[1][1] - m[0][1] * m[1][0]
  when 3
    m0, m1, m2 = m
    + m0[0] * m1[1] * m2[2] - m0[0] * m1[2] * m2[1] \
    - m0[1] * m1[0] * m2[2] + m0[1] * m1[2] * m2[0] \
    + m0[2] * m1[0] * m2[1] - m0[2] * m1[1] * m2[0]
  when 4
    m0, m1, m2, m3 = m
    + m0[0] * m1[1] * m2[2] * m3[3] - m0[0] * m1[1] * m2[3] * m3[2] \
    - m0[0] * m1[2] * m2[1] * m3[3] + m0[0] * m1[2] * m2[3] * m3[1] \
    + m0[0] * m1[3] * m2[1] * m3[2] - m0[0] * m1[3] * m2[2] * m3[1] \
    - m0[1] * m1[0] * m2[2] * m3[3] + m0[1] * m1[0] * m2[3] * m3[2] \
    + m0[1] * m1[2] * m2[0] * m3[3] - m0[1] * m1[2] * m2[3] * m3[0] \
    - m0[1] * m1[3] * m2[0] * m3[2] + m0[1] * m1[3] * m2[2] * m3[0] \
    + m0[2] * m1[0] * m2[1] * m3[3] - m0[2] * m1[0] * m2[3] * m3[1] \
    - m0[2] * m1[1] * m2[0] * m3[3] + m0[2] * m1[1] * m2[3] * m3[0] \
    + m0[2] * m1[3] * m2[0] * m3[1] - m0[2] * m1[3] * m2[1] * m3[0] \
    - m0[3] * m1[0] * m2[1] * m3[2] + m0[3] * m1[0] * m2[2] * m3[1] \
    + m0[3] * m1[1] * m2[0] * m3[2] - m0[3] * m1[1] * m2[2] * m3[0] \
    - m0[3] * m1[2] * m2[0] * m3[1] + m0[3] * m1[2] * m2[1] * m3[0]
  else
    # For bigger matrices, use an efficient and general algorithm.
    # Currently, we use the Gauss-Bareiss algorithm
    determinant_bareiss
  end
end

Возвращает определитель матрицы.

Будьте внимательны, использование значений типа Float может привести к неточным результатам из-за недостаточной точности. Рассмотрите использование точных типов, таких как Rational или BigDecimal.

Matrix[[7,6], [3,9]].determinant
  => 45
Также псевдоним для: det
determinant_e() Показать исходный код
# File lib/matrix.rb, line 1355
def determinant_e
  warn "Matrix#determinant_e is deprecated; use #determinant", uplevel: 1
  determinant
end

устаревшее; используйте Matrix#determinant

Также псевдоним для: det_e
diagonal?() Показать исходный код
# File lib/matrix.rb, line 827
def diagonal?
  raise ErrDimensionMismatch unless square?
  each(:off_diagonal).all?(&:zero?)
end

Возвращает true, если это диагональная матрица. Вызывает ошибку, если матрица не квадратная.

each(which = :all) { |e| ... } Показать исходный код
# File lib/matrix.rb, line 544
def each(which = :all, &block) # :yield: e
  return to_enum :each, which unless block_given?
  last = column_count - 1
  case which
  when :all
    @rows.each do |row|
      row.each(&block)
    end
  when :diagonal
    @rows.each_with_index do |row, row_index|
      yield row.fetch(row_index){return self}
    end
  when :off_diagonal
    @rows.each_with_index do |row, row_index|
      column_count.times do |col_index|
        yield row[col_index] unless row_index == col_index
      end
    end
  when :lower
    @rows.each_with_index do |row, row_index|
      0.upto([row_index, last].min) do |col_index|
        yield row[col_index]
      end
    end
  when :strict_lower
    @rows.each_with_index do |row, row_index|
      [row_index, column_count].min.times do |col_index|
        yield row[col_index]
      end
    end
  when :strict_upper
    @rows.each_with_index do |row, row_index|
      (row_index+1).upto(last) do |col_index|
        yield row[col_index]
      end
    end
  when :upper
    @rows.each_with_index do |row, row_index|
      row_index.upto(last) do |col_index|
        yield row[col_index]
      end
    end
  else
    raise ArgumentError, "expected #{which.inspect} to be one of :all, :diagonal, :off_diagonal, :lower, :strict_lower, :strict_upper or :upper"
  end
  self
end

Возвращает все элементы матрицы, начиная с первого ряда, или возвращает перечислитель Enumerator, если блок не задан. Элементы могут быть ограничены, передав аргумент:

  • :all (по умолчанию): возвращает все элементы

  • :diagonal: возвращает только элементы на диагонали

  • :off_diagonal: возвращает все элементы, кроме элементов на диагонали

  • :lower: возвращает только элементы на или ниже диагонали

  • :strict_lower: возвращает только элементы ниже диагонали

  • :strict_upper: возвращает только элементы выше диагонали

  • :upper: возвращает только элементы на или выше диагонали

    Matrix[ [1,2], [3,4] ].each { |e| puts e }

    # => prints the numbers 1 to 4
    

    Matrix[ [1,2], [3,4] ].each(:strict_lower).to_a # => [3]

each_with_index(which = :all) { |e, row, column| ... } Показать исходный код
# File lib/matrix.rb, line 604
def each_with_index(which = :all) # :yield: e, row, column
  return to_enum :each_with_index, which unless block_given?
  last = column_count - 1
  case which
  when :all
    @rows.each_with_index do |row, row_index|
      row.each_with_index do |e, col_index|
        yield e, row_index, col_index
      end
    end
  when :diagonal
    @rows.each_with_index do |row, row_index|
      yield row.fetch(row_index){return self}, row_index, row_index
    end
  when :off_diagonal
    @rows.each_with_index do |row, row_index|
      column_count.times do |col_index|
        yield row[col_index], row_index, col_index unless row_index == col_index
      end
    end
  when :lower
    @rows.each_with_index do |row, row_index|
      0.upto([row_index, last].min) do |col_index|
        yield row[col_index], row_index, col_index
      end
    end
  when :strict_lower
    @rows.each_with_index do |row, row_index|
      [row_index, column_count].min.times do |col_index|
        yield row[col_index], row_index, col_index
      end
    end
  when :strict_upper
    @rows.each_with_index do |row, row_index|
      (row_index+1).upto(last) do |col_index|
        yield row[col_index], row_index, col_index
      end
    end
  when :upper
    @rows.each_with_index do |row, row_index|
      row_index.upto(last) do |col_index|
        yield row[col_index], row_index, col_index
      end
    end
  else
    raise ArgumentError, "expected #{which.inspect} to be one of :all, :diagonal, :off_diagonal, :lower, :strict_lower, :strict_upper or :upper"
  end
  self
end

Аналогично each, но с индексами строки и столбца, а также элементом

Matrix[ [1,2], [3,4] ].each_with_index do |e, row, col|
  puts "#{e} at #{row}, #{col}"
end
  # => Prints:
  #    1 at 0, 0
  #    2 at 0, 1
  #    3 at 1, 0
  #    4 at 1, 1
eigen()
Псевдоним для: eigensystem
eigensystem() Показать исходный код
# File lib/matrix.rb, line 1478
def eigensystem
  EigenvalueDecomposition.new(self)
end

Возвращает собственную систему матрицы; см. EigenvalueDecomposition.

m = Matrix[[1, 2], [3, 4]]
v, d, v_inv = m.eigensystem
d.diagonal? # => true
v.inv == v_inv # => true
(v * d * v_inv).round(5) == m # => true
Также псевдоним для: eigen
element(i, j)
Псевдоним для: []
elements_to_f() Показать исходный код
# File lib/matrix.rb, line 1609
def elements_to_f
  warn "Matrix#elements_to_f is deprecated, use map(&:to_f)", uplevel: 1
  map(&:to_f)
end

Устаревшее.

Используйте map(&:to_f)

elements_to_i() Показать исходный код
# File lib/matrix.rb, line 1617
def elements_to_i
  warn "Matrix#elements_to_i is deprecated, use map(&:to_i)", uplevel: 1
  map(&:to_i)
end

Устаревшее.

Используйте map(&:to_i)

elements_to_r() Показать исходный код
# File lib/matrix.rb, line 1625
def elements_to_r
  warn "Matrix#elements_to_r is deprecated, use map(&:to_r)", uplevel: 1
  map(&:to_r)
end

Устаревшее.

Используйте map(&:to_r)

empty?() Показать исходный код
# File lib/matrix.rb, line 836
def empty?
  column_count == 0 || row_count == 0
end

Возвращает true, если это пустая матрица, т.е. если число строк или столбцов равно 0.

entrywise_product(m)
Псевдоним для: hadamard_product
eql?(other) Показать исходный код
# File lib/matrix.rb, line 1014
def eql?(other)
  return false unless Matrix === other &&
                      column_count == other.column_count # necessary for empty matrices
  rows.eql? other.rows
end
find_index(*args)
Псевдоним для: index
first_minor(row, column) Показать исходный код
# File lib/matrix.rb, line 739
def first_minor(row, column)
  raise RuntimeError, "first_minor of empty matrix is not defined" if empty?

  unless 0 <= row && row < row_count
    raise ArgumentError, "invalid row (#{row.inspect} for 0..#{row_count - 1})"
  end

  unless 0 <= column && column < column_count
    raise ArgumentError, "invalid column (#{column.inspect} for 0..#{column_count - 1})"
  end

  arrays = to_a
  arrays.delete_at(row)
  arrays.each do |array|
    array.delete_at(column)
  end

  new_matrix arrays, column_count - 1
end

Возвращает подматрицу, полученную путём удаления указанной строки и столбца.

Matrix.diagonal(9, 5, -3, 4).first_minor(1, 2)
  => 9 0 0
     0 0 0
     0 0 4
freeze() Показать исходный код
# File lib/matrix.rb, line 523
def freeze
  @rows.freeze
  super
end
Вызывает метод предка Object#freeze
hadamard_product(m) Показать исходный код
# File lib/matrix.rb, line 1152
def hadamard_product(m)
  combine(m){|a, b| a * b}
end

Произведение Адамара

Matrix[[1,2], [3,4]].hadamard_product(Matrix[[1,2], [3,2]])
  => 1  4
     9  8
Также псевдоним для: entrywise_product
hash() Показать исходный код
# File lib/matrix.rb, line 1031
def hash
  @rows.hash
end

Возвращает хэш-код для матрицы.

hermitian?() Показать исходный код
# File lib/matrix.rb, line 844
def hermitian?
  raise ErrDimensionMismatch unless square?
  each_with_index(:upper).all? do |e, row, col|
    e == rows[col][row].conj
  end
end

Возвращает true, если это эрмитова матрица. Вызывает ошибку, если матрица не квадратная.

hstack(*matrices) Показать исходный код
# File lib/matrix.rb, line 1369
def hstack(*matrices)
  self.class.hstack(self, *matrices)
end

Возвращает новую матрицу, полученную путём горизонтального объединения текущей матрицы с заданными матрицами.

x = Matrix[[1, 2], [3, 4]]
y = Matrix[[5, 6], [7, 8]]
x.hstack(y) # => Matrix[[1, 2, 5, 6], [3, 4, 7, 8]]
END_OF_DOCUMENT_MARKER
imag()
Alias for: imaginary
imaginary() Show source
# File lib/matrix.rb, line 1525
def imaginary
  collect(&:imaginary)
end

Возвращает мнимую часть матрицы.

Matrix[[Complex(1,2), Complex(0,1), 0], [1, 2, 3]]
  => 1+2i  i  0
        1  2  3
Matrix[[Complex(1,2), Complex(0,1), 0], [1, 2, 3]].imaginary
  =>   2i  i  0
        0  0  0
Также является псевдонимом для: imag
index(value, selector = :all) → [row, column] Show source
index(selector = :all){ block } → [row, column]
index(selector = :all) → an_enumerator
# File lib/matrix.rb, line 667
def index(*args)
  raise ArgumentError, "wrong number of arguments(#{args.size} for 0-2)" if args.size > 2
  which = (args.size == 2 || SELECTORS.include?(args.last)) ? args.pop : :all
  return to_enum :find_index, which, *args unless block_given? || args.size == 1
  if args.size == 1
    value = args.first
    each_with_index(which) do |e, row_index, col_index|
      return row_index, col_index if e == value
    end
  else
    each_with_index(which) do |e, row_index, col_index|
      return row_index, col_index if yield e
    end
  end
  nil
end

Метод index специализирован для возврата индекса как [row, column]. Он также принимает необязательный selector аргумент, см. each для получения подробной информации.

Matrix[ [1,2], [3,4] ].index(&:even?) # => [0, 1]
Matrix[ [1,1], [1,1] ].index(1, :strict_lower) # => [1, 0]
Также является псевдонимом для: find_index
inspect() Show source
# File lib/matrix.rb, line 1650
def inspect
  if empty?
    "#{self.class}.empty(#{row_count}, #{column_count})"
  else
    "#{self.class}#{@rows.inspect}"
  end
end

Переопределяет Object#inspect

inv()
Alias for: inverse
inverse() Show source
# File lib/matrix.rb, line 1163
def inverse
  raise ErrDimensionMismatch unless square?
  self.class.I(row_count).send(:inverse_from, self)
end

Возвращает обратную матрицу.

Matrix[[-1, -1], [0, -1]].inverse
  => -1  1
      0 -1
Также является псевдонимом для: inv
laplace_expansion(row: nil, column: nil) Show source
# File lib/matrix.rb, line 798
def laplace_expansion(row: nil, column: nil)
  num = row || column

  if !num || (row && column)
    raise ArgumentError, "exactly one the row or column arguments must be specified"
  end

  raise ErrDimensionMismatch unless square?
  raise RuntimeError, "laplace_expansion of empty matrix is not defined" if empty?

  unless 0 <= num && num < row_count
    raise ArgumentError, "invalid num (#{num.inspect} for 0..#{row_count - 1})"
  end

  send(row ? :row : :column, num).map.with_index { |e, k|
    e * cofactor(*(row ? [num, k] : [k,num]))
  }.inject(:+)
end

Возвращает разложение Лапласа по заданной строке или столбцу.

Matrix[[7,6], [3,9]].laplace_expansion(column: 1)
 => 45

Matrix[[Vector[1, 0], Vector[0, 1]], [2, 3]].laplace_expansion(row: 0)
 => Vector[3, -2]
Также является псевдонимом для: cofactor_expansion
lower_triangular?() Show source
# File lib/matrix.rb, line 854
def lower_triangular?
  each(:strict_upper).all?(&:zero?)
end

Возвращает true если это нижняя треугольная матрица.

lup() Show source
# File lib/matrix.rb, line 1493
def lup
  LUPDecomposition.new(self)
end

Возвращает LUP-разложение матрицы; см. LUPDecomposition.

a = Matrix[[1, 2], [3, 4]]
l, u, p = a.lup
l.lower_triangular? # => true
u.upper_triangular? # => true
p.permutation?      # => true
l * u == p * a      # => true
a.lup.solve([2, 5]) # => Vector[(1/1), (1/2)]
Также является псевдонимом для: lup_decomposition
lup_decomposition()
Alias for: lup
map(which = :all)
Alias for: collect
map!(which = :all)
Alias for: collect!
minor(*param) Show source
# File lib/matrix.rb, line 698
def minor(*param)
  case param.size
  when 2
    row_range, col_range = param
    from_row = row_range.first
    from_row += row_count if from_row < 0
    to_row = row_range.end
    to_row += row_count if to_row < 0
    to_row += 1 unless row_range.exclude_end?
    size_row = to_row - from_row

    from_col = col_range.first
    from_col += column_count if from_col < 0
    to_col = col_range.end
    to_col += column_count if to_col < 0
    to_col += 1 unless col_range.exclude_end?
    size_col = to_col - from_col
  when 4
    from_row, size_row, from_col, size_col = param
    return nil if size_row < 0 || size_col < 0
    from_row += row_count if from_row < 0
    from_col += column_count if from_col < 0
  else
    raise ArgumentError, param.inspect
  end

  return nil if from_row > row_count || from_col > column_count || from_row < 0 || from_col < 0
  rows = @rows[from_row, size_row].collect{|row|
    row[from_col, size_col]
  }
  new_matrix rows, [column_count - from_col, size_col].min
end

Возвращает секцию матрицы. Параметрами являются:

  • start_row, nrows, start_col, ncols; ИЛИ

  • row_range, col_range

Matrix.diagonal(9, 5, -3).minor(0..1, 0..2)
  => 9 0 0
     0 5 0

Как Array#[], отрицательные индексы отсчитываются от конца строки или столбца (-1 - последний элемент). Возвращает nil, если начальная строка или столбец больше, чем row_count или column_count соответственно.

normal?() Show source
# File lib/matrix.rb, line 862
def normal?
  raise ErrDimensionMismatch unless square?
  rows.each_with_index do |row_i, i|
    rows.each_with_index do |row_j, j|
      s = 0
      rows.each_with_index do |row_k, k|
        s += row_i[k] * row_j[k].conj - row_k[i].conj * row_k[j]
      end
      return false unless s == 0
    end
  end
  true
end

Возвращает true если это нормальная матрица. Вызывает ошибку, если матрица не квадратная.

orthogonal?() Show source
# File lib/matrix.rb, line 880
def orthogonal?
  raise ErrDimensionMismatch unless square?
  rows.each_with_index do |row, i|
    column_count.times do |j|
      s = 0
      row_count.times do |k|
        s += row[k] * rows[k][j]
      end
      return false unless s == (i == j ? 1 : 0)
    end
  end
  true
end

Возвращает true если это ортогональная матрица. Вызывает ошибку, если матрица не квадратная.

permutation?() Show source
# File lib/matrix.rb, line 898
def permutation?
  raise ErrDimensionMismatch unless square?
  cols = Array.new(column_count)
  rows.each_with_index do |row, i|
    found = false
    row.each_with_index do |e, j|
      if e == 1
        return false if found || cols[j]
        found = cols[j] = true
      elsif e != 0
        return false
      end
    end
    return false unless found
  end
  true
end

Возвращает true если это матрица перестановок. Вызывает ошибку, если матрица не квадратная.

rank() Show source
# File lib/matrix.rb, line 1382
def rank
  # We currently use Bareiss' multistep integer-preserving gaussian elimination
  # (see comments on determinant)
  a = to_a
  last_column = column_count - 1
  last_row = row_count - 1
  pivot_row = 0
  previous_pivot = 1
  0.upto(last_column) do |k|
    switch_row = (pivot_row .. last_row).find {|row|
      a[row][k] != 0
    }
    if switch_row
      a[switch_row], a[pivot_row] = a[pivot_row], a[switch_row] unless pivot_row == switch_row
      pivot = a[pivot_row][k]
      (pivot_row+1).upto(last_row) do |i|
         ai = a[i]
         (k+1).upto(last_column) do |j|
           ai[j] =  (pivot * ai[j] - ai[k] * a[pivot_row][j]) / previous_pivot
         end
       end
      pivot_row += 1
      previous_pivot = pivot
    end
  end
  pivot_row
end

Возвращает ранг матрицы. Имейте в виду, что использование значений Float может давать ошибочные результаты из-за их недостаточной точности. Рассмотрите использование точных типов, таких как Rational или BigDecimal вместо этого.

Matrix[[7,6], [3,9]].rank
  => 2
rank_e() Show source
# File lib/matrix.rb, line 1413
def rank_e
  warn "Matrix#rank_e is deprecated; use #rank", uplevel: 1
  rank
end

устарело; используйте Matrix#rank

real() Show source
# File lib/matrix.rb, line 1539
def real
  collect(&:real)
end

Возвращает действительную часть матрицы.

Matrix[[Complex(1,2), Complex(0,1), 0], [1, 2, 3]]
  => 1+2i  i  0
        1  2  3
Matrix[[Complex(1,2), Complex(0,1), 0], [1, 2, 3]].real
  =>    1  0  0
        1  2  3
real?() Show source
# File lib/matrix.rb, line 919
def real?
  all?(&:real?)
end

Возвращает true если все элементы матрицы действительны.

rect() Show source
# File lib/matrix.rb, line 1549
def rect
  [real, imag]
end

Возвращает массив, содержащий матрицы, соответствующие действительной и мнимой частям матрицы

m.rect == [m.real, m.imag] # ==> true для всех матриц m

Также является псевдонимом для: rectangular
rectangular()
Alias for: rect
regular?() Show source
# File lib/matrix.rb, line 926
def regular?
  not singular?
end

Возвращает true если это регулярная (т.е. несингулярная) матрица.

round(ndigits=0) Show source
# File lib/matrix.rb, line 1421
def round(ndigits=0)
  map{|e| e.round(ndigits)}
end

Возвращает матрицу с элементами, округленными до заданной точности (см. Float#round)

row(i) { |e| ... } Показать исходный код
# File lib/matrix.rb, line 452
def row(i, &block) # :yield: e
  if block_given?
    @rows.fetch(i){return self}.each(&block)
    self
  else
    Vector.elements(@rows.fetch(i){return nil})
  end
end

Возвращает вектор-строку с номером i матрицы в виде Vector (индексация начинается с 0, как в массиве). Если задан блок, элементы этого вектора будут итерироваться.

row_count() Показать исходный код
# File lib/matrix.rb, line 437
def row_count
  @rows.size
end

Возвращает количество строк.

Также известно как: row_size
row_size()
Псевдоним для: row_count
row_vectors() Показать исходный код
# File lib/matrix.rb, line 1577
def row_vectors
  Array.new(row_count) {|i|
    row(i)
  }
end

Возвращает массив векторов-строк матрицы. Смотрите Vector.

singular?() Показать исходный код
# File lib/matrix.rb, line 933
def singular?
  determinant == 0
end

Возвращает true, если матрица вырожденная.

skew_symmetric?()
Псевдоним для: antisymmetric?
square?() Показать исходный код
# File lib/matrix.rb, line 940
def square?
  column_count == row_count
end

Возвращает true, если матрица квадратная.

symmetric?() Показать исходный код
# File lib/matrix.rb, line 948
def symmetric?
  raise ErrDimensionMismatch unless square?
  each_with_index(:strict_upper) do |e, row, col|
    return false if e != rows[col][row]
  end
  true
end

Возвращает true, если матрица симметричная. Возбуждает ошибку, если матрица не квадратная.

t()
Псевдоним для: transpose
to_a() Показать исходный код
# File lib/matrix.rb, line 1602
def to_a
  @rows.collect(&:dup)
end

Возвращает массив массивов, описывающих строки матрицы.

to_matrix() Показать исходный код
# File lib/matrix.rb, line 1595
def to_matrix
  self
end

Явное преобразование в Matrix. Возвращает self

to_s() Показать исходный код
# File lib/matrix.rb, line 1637
def to_s
  if empty?
    "#{self.class}.empty(#{row_count}, #{column_count})"
  else
    "#{self.class}[" + @rows.collect{|row|
      "[" + row.collect{|e| e.to_s}.join(", ") + "]"
    }.join(", ")+"]"
  end
end

Переопределяет Object#to_s

tr()
Псевдоним для: trace
trace() Показать исходный код
# File lib/matrix.rb, line 1430
def trace
  raise ErrDimensionMismatch unless square?
  (0...column_count).inject(0) do |tr, i|
    tr + @rows[i][i]
  end
end

Возвращает след (сумму диагональных элементов) матрицы.

Matrix[[7,6], [3,9]].trace
  => 16
Также известно как: tr
transpose() Показать исходный код
# File lib/matrix.rb, line 1448
def transpose
  return self.class.empty(column_count, 0) if row_count.zero?
  new_matrix @rows.transpose, row_count
end

Возвращает транспонированную матрицу.

Matrix[[1,2], [3,4], [5,6]]
  => 1 2
     3 4
     5 6
Matrix[[1,2], [3,4], [5,6]].transpose
  => 1 3 5
     2 4 6
Также известно как: t
unitary?() Показать исходный код
# File lib/matrix.rb, line 973
def unitary?
  raise ErrDimensionMismatch unless square?
  rows.each_with_index do |row, i|
    column_count.times do |j|
      s = 0
      row_count.times do |k|
        s += row[k].conj * rows[k][j]
      end
      return false unless s == (i == j ? 1 : 0)
    end
  end
  true
end

Возвращает true, если матрица унитарная. Возбуждает ошибку, если матрица не квадратная.

upper_triangular?() Показать исходный код
# File lib/matrix.rb, line 990
def upper_triangular?
  each(:strict_lower).all?(&:zero?)
end

Возвращает true, если матрица верхнетреугольная.

vstack(*matrices) Показать исходный код
# File lib/matrix.rb, line 1462
def vstack(*matrices)
  self.class.vstack(self, *matrices)
end

Возвращает новую матрицу, полученную путем вертикального объединения текущей матрицы с указанными матрицами.

x = Matrix[[1, 2], [3, 4]]
y = Matrix[[5, 6], [7, 8]]
x.vstack(y) # => Matrix[[1, 2], [3, 4], [5, 6], [7, 8]]
zero?() Показать исходный код
# File lib/matrix.rb, line 997
def zero?
  all?(&:zero?)
end

Возвращает true, если матрица состоит только из нулевых элементов.

Приватные методы экземпляра

check_int(val, direction) Показать исходный код
# File lib/matrix.rb, line 365
        def check_int(val, direction)
  count = direction == :row ? row_count : column_count
  CoercionHelper.check_int(val, count, direction)
end
check_range(val, direction) Показать исходный код
# File lib/matrix.rb, line 359
        def check_range(val, direction)
  return unless val.is_a?(Range)
  count = direction == :row ? row_count : column_count
  CoercionHelper.check_range(val, count, direction)
end

Возвращает диапазон или nil

determinant_bareiss() Показать исходный код
# File lib/matrix.rb, line 1325
        def determinant_bareiss
  size = row_count
  last = size - 1
  a = to_a
  no_pivot = Proc.new{ return 0 }
  sign = +1
  pivot = 1
  size.times do |k|
    previous_pivot = pivot
    if (pivot = a[k][k]) == 0
      switch = (k+1 ... size).find(no_pivot) {|row|
        a[row][k] != 0
      }
      a[switch], a[k] = a[k], a[switch]
      pivot = a[k][k]
      sign = -sign
    end
    (k+1).upto(last) do |i|
      ai = a[i]
      (k+1).upto(last) do |j|
        ai[j] =  (pivot * ai[j] - ai[k] * a[k][j]) / previous_pivot
      end
    end
  end
  sign * pivot
end

Приватный. Используйте Matrix#determinant

Возвращает определитель матрицы, используя многоступенчатую целочисленную элиминацию Гаусса Барейсса. Она имеет ту же вычислительную сложность порядка O(n^3), что и стандартная элиминация Гаусса. Промежуточные результаты свободные от дробей и имеют меньшую сложность. Матрица целых чисел будет иметь таким образом промежуточные результаты, которые также являются целыми числами, с меньшими большими числами (если таковые имеются), в то время как матрица Float обычно имеет промежуточные результаты с большей точностью.

initialize_copy(m) Показать исходный код
# File lib/matrix.rb, line 1023
        def initialize_copy(m)
  super
  @rows = @rows.map(&:dup) unless frozen?
end

Вызывается для dup и clone.

Вызывает метод суперкласса
set_col_range(row, col_range, value) Показать исходный код
# File lib/matrix.rb, line 421
        def set_col_range(row, col_range, value)
  value = if value.is_a?(Vector)
    value.to_a
  elsif value.is_a?(Matrix)
    raise ErrDimensionMismatch unless value.row_count == 1
    value.row(0).to_a
  else
    Array.new(col_range.size, value)
  end
  raise ErrDimensionMismatch unless col_range.size == value.size
  @rows[row][col_range] = value
end
set_column_vector(row_range, col, value) Показать исходный код
# File lib/matrix.rb, line 414
        def set_column_vector(row_range, col, value)
  value.each_with_index do |e, index|
    r = row_range.begin + index
    @rows[r][col] = e
  end
end
set_component(i, j, v)
Псевдоним для: []=
set_element(i, j, v)
Псевдоним для: []=
set_row_and_col_range(row_range, col_range, value) Показать исходный код
# File lib/matrix.rb, line 376
        def set_row_and_col_range(row_range, col_range, value)
  if value.is_a?(Matrix)
    if row_range.size != value.row_count || col_range.size != value.column_count
      raise ErrDimensionMismatch, [
        'Expected a Matrix of dimensions',
        "#{row_range.size}x#{col_range.size}",
        'got',
        "#{value.row_count}x#{value.column_count}",
      ].join(' ')
    end
    source = value.instance_variable_get :@rows
    row_range.each_with_index do |row, i|
      @rows[row][col_range] = source[i]
    end
  elsif value.is_a?(Vector)
    raise ErrDimensionMismatch, 'Expected a Matrix or a value, got a Vector'
  else
    value_to_set = Array.new(col_range.size, value)
    row_range.each do |i|
      @rows[i][col_range] = value_to_set
    end
  end
end
set_row_range(row_range, col, value) Показать исходный код
# File lib/matrix.rb, line 400
        def set_row_range(row_range, col, value)
  if value.is_a?(Vector)
    raise ErrDimensionMismatch unless row_range.size == value.size
    set_column_vector(row_range, col, value)
  elsif value.is_a?(Matrix)
    raise ErrDimensionMismatch unless value.column_count == 1
    value = value.column(0)
    raise ErrDimensionMismatch unless row_range.size == value.size
    set_column_vector(row_range, col, value)
  else
    @rows[row_range].each{|e| e[col] = value }
  end
end
set_value(row, col, value) Показать исходный код
# File lib/matrix.rb, line 370
        def set_value(row, col, value)
  raise ErrDimensionMismatch, "Expected a a value, got a #{value.class}" if value.respond_to?(:to_matrix)

  @rows[row][col] = value
end

Ruby Core © 1993–2017 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API