Ruby 2.4

Matrix

Matrix类

Parent:ObjectIncluded modules:Enumerable

Matrix类表示一个数学矩阵。它提供了创建矩阵的方法,以算术和代数方式对它们进行操作,并确定它们的数学属性(迹,秩,反,行列式)。

方法目录

创建一个矩阵:

  • Matrix

  • ::[]

  • ::rows(rows, copy = true)

  • ::columns

  • ::build(row_count, #column_count, &block)

  • ::diagonal

  • ::scalar(n, value)

  • ::identity

  • ::unit

  • Matrix.I(n)

  • ::zero

  • ::row_vector

  • ::column_vector

  • ::empty(row_count, #column_count)

  • ::hstack

  • ::vstack

To access Matrix elements/columns/rows/submatrices/properties:

  • [](i, j)

  • row_count (row_size)

  • column_count (column_size)

  • row(i)

  • column(j)

  • collect

  • map

  • each

  • each_with_index

  • find_index

  • minor(*param)

  • first_minor(row, column)

  • cofactor(row, column)

  • adjugate

  • laplace_expansion(row_or_column: num)

  • cofactor_expansion(row_or_column: num)

矩阵的属性:

  • diagonal?

  • empty?

  • hermitian?

  • lower_triangular?

  • normal?

  • orthogonal?

  • permutation?

  • real?

  • regular?

  • singular?

  • square?

  • symmetric?

  • unitary?

  • upper_triangular?

  • zero?Matrix arithmetic:

  • #*(m)

  • #+(m)

  • #-(m)

  • #/(m)

  • inverse

  • inv

  • #**

  • #+@

  • #-@

矩阵功能:

  • determinant

  • det

  • hstack(*matrices)

  • rank

  • round

  • trace

  • tr

  • transpose

  • t

  • vstack(*matrices)

矩阵分解:

  • eigen

  • eigensystem

  • lup

  • lup_decomposition

复杂的算术:

  • conj

  • conjugate

  • imag

  • imaginary

  • real

  • rect

  • rectangularConversion to other data types:

  • coerce(other)

  • row_vectors

  • column_vectors

  • to_aString representations:

  • to_s

  • inspects

  • :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

# File lib/matrix.rb, line 462 def each(which = :all) # :yield: e return to_enum :each, which unless block_given? last = column_count - 1 case which when :all block = Proc.new @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

each_with_index(which = :all) { |e, row, column| ... } Show source

与每个元素相同,除了元素之外,还包括行索引和列索引

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

# File lib/matrix.rb, line 523 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

eigen()

别名r: eigensystem

eigensystem() Show source

返回矩阵的Eigensystem; 见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

# File lib/matrix.rb, line 1369 def eigensystem EigenvalueDecomposition.new(self) end

别名: eigen

element(i, j)

别名: []

elements_to_f() Show source

# File lib/matrix.rb, line 1490 def elements_to_f warn "#{caller(1)[0]}: warning: Matrix#elements_to_f is deprecated, use map(&:to_f)" map(&:to_f) end

elements_to_i() Show source

# File lib/matrix.rb, line 1495 def elements_to_i warn "#{caller(1)[0]}: warning: Matrix#elements_to_i is deprecated, use map(&:to_i)" map(&:to_i) end

elements_to_r() Show source

# File lib/matrix.rb, line 1500 def elements_to_r warn "#{caller(1)[0]}: warning: Matrix#elements_to_r is deprecated, use map(&:to_r)" map(&:to_r) end

empty?() Show source

如果这是一个空的矩阵,即,如果行数或列数是0返回true,。

# File lib/matrix.rb, line 755 def empty? column_count == 0 || row_count == 0 end

eql?(other) Show source

# File lib/matrix.rb, line 920 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) Show source

返回通过删除指定的行和列而获得的子矩阵。

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

# File lib/matrix.rb, line 658 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

hash() Show source

返回矩阵的散列码。

# File lib/matrix.rb, line 938 def hash @rows.hash end

hermitian?() Show source

如果这是一个厄密矩阵,则返回true。如果矩阵不是正方形,则会引发错误。

# File lib/matrix.rb, line 763 def hermitian? Matrix.Raise ErrDimensionMismatch unless square? each_with_index(:upper).all? do |e, row, col| e == rows[col][row].conj end end

hstack(*matrices) Show source

返回一个新的矩阵,通过水平叠加给定矩阵的接收器

x = Matrix[[1, 2], [3, 4]] y = Matrix[[5, 6], [7, 8]] x.hstack(y) # => Matrix[[1, 2, 5, 6], [3, 4, 7, 8]]

# File lib/matrix.rb, line 1260 def hstack(*matrices) self.class.hstack(self, *matrices) end

imag()

别名: imaginary

imaginary() Show source

返回矩阵的虚部。

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

# File lib/matrix.rb, line 1416 def imaginary collect(&:imaginary) end

别名: imag

index(value, selector = :all) → row, column()

index(selector = :all){ block } → row, column

index(selector = :all) → an_enumerator

index方法专用于将索引作为行,列返回。它还接受可选的选择器参数,请参阅每个参数以获取详细信息。

Matrix[ [1,2], [3,4] ].index(&:even?) # => [0, 1] Matrix[ [1,1], [1,1] ].index(1, :strict_lower) # => [1, 0]

# File lib/matrix.rb, line 586 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

别名: find_index

inspect() Show source

覆盖对象#检查

# File lib/matrix.rb, line 1525 def inspect if empty? "#{self.class}.empty(#{row_count}, #{column_count})" else "#{self.class}#{@rows.inspect}" end end

inv()

别名: inverse

inverse() Show source

返回矩阵的逆。

Matrix[[-1, -1], [0, -1]].inverse => -1 1 0 -1

# File lib/matrix.rb, line 1059 def inverse Matrix.Raise ErrDimensionMismatch unless square? self.class.I(row_count).send(:inverse_from, self) end

别名: inv

laplace_expansion(row: nil, column: nil) Show source

沿给定的行或列返回拉普拉斯扩展。

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]

# File lib/matrix.rb, line 717 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 Matrix.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

别名: cofactor_expansion

lower_triangular?() Show source

如果这是一个下三角矩阵,则返回true

# File lib/matrix.rb, line 773 def lower_triangular? each(:strict_upper).all?(&:zero?) end

lup() Show source

返回矩阵的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)]

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

别名: lup_decomposition

lup_decomposition()

别名: lup

map()

别名: collect

minor(*param) Show source

返回矩阵的一部分。参数是:

  • start_row, nrows, start_col, ncols; OR

  • row_range, col_range

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

像数组#[]一样,负索引从行或列的末尾向后计数(-1是最后一个元素)。如果起始行或列分别大于#row_count或#column_count,则返回nil。

# File lib/matrix.rb, line 617 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

normal?() Show source

如果这是一个常规矩阵,则返回true。如果矩阵不是正方形,则会引发错误。

# File lib/matrix.rb, line 781 def normal? Matrix.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

orthogonal?() Show source

如果这是一个正交矩阵,则返回true,如果矩阵不是平方,则引发一个错误。

# File lib/matrix.rb, line 799 def orthogonal? Matrix.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

permutation?() Show source

如果这是置换矩阵,则返回true,如果矩阵不是平方,则返回错误。

# File lib/matrix.rb, line 817 def permutation? Matrix.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

rank() Show source

返回矩阵的等级。请注意,使用Float值会因为精度不够而产生错误的结果。考虑使用类似Rational或BigDecimal的确切类型。

Matrix[[7,6], [3,9]].rank => 2

# File lib/matrix.rb, line 1273 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

rank_e() Show source

deprecated; use #rank

# File lib/matrix.rb, line 1304 def rank_e warn "#{caller(1)[0]}: warning: Matrix#rank_e is deprecated; use #rank" rank end

real() Show source

返回矩阵的实部。

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

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

real?() Show source

如果矩阵的所有条目都是实数,则返回true

# File lib/matrix.rb, line 838 def real? all?(&:real?) end

rect() Show source

返回包含与矩阵的实部和虚部对应的矩阵的数组

m.rect == m.real, m.imag # ==> true for all matrices m

# File lib/matrix.rb, line 1440 def rect [real, imag] end

别名: rectangular

rectangular()

别名: rect

regular?() Show source

如果这是一个常规(即非奇异)矩阵,则返回true

# File lib/matrix.rb, line 845 def regular? not singular? end

round(ndigits=0) Show source

返回一个矩阵,其中的条目四舍五入到给定的精度(请参见Float#round)

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

row(i) { |e| ... } Show source

i将矩阵的行向量数作为向量返回(从数组开始,从0开始)。当给出一个块时,该向量的元素被迭代。

# File lib/matrix.rb, line 402 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

row_count() Show source

返回行数。

# File lib/matrix.rb, line 387 def row_count @rows.size end

另外别名为:row_size

row_size()

别名为:row_count

row_vectors() Show source

返回矩阵的行向量数组。请参阅矢量。

# File lib/matrix.rb, line 1468 def row_vectors Array.new(row_count) {|i| row(i) } end

singular?() Show source

如果这是一个奇异矩阵,则返回true

# File lib/matrix.rb, line 852 def singular? determinant == 0 end

square?() Show source

如果这是一个方形矩阵,则返回true

# File lib/matrix.rb, line 859 def square? column_count == row_count end

symmetric?() Show source

如果这是一个对称矩阵,则返回true。如果矩阵不是正方形,则会引发错误。

# File lib/matrix.rb, line 867 def symmetric? Matrix.Raise ErrDimensionMismatch unless square? each_with_index(:strict_upper) do |e, row, col| return false if e != rows[col][row] end true end

t()

别名: transpose

to_a() Show source

返回描述矩阵行的数组数组。

# File lib/matrix.rb, line 1486 def to_a @rows.collect(&:dup) end

to_s() Show source

Overrides Object#to_s

# File lib/matrix.rb, line 1512 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

tr()

别名r: trace

trace() Show source

返回矩阵的迹线(对角线元素的总和)。

Matrix[[7,6], [3,9]].trace => 16

# File lib/matrix.rb, line 1321 def trace Matrix.Raise ErrDimensionMismatch unless square? (0...column_count).inject(0) do |tr, i| tr + @rows[i][i] end end

别名: tr

transpose() Show source

返回矩阵的转置。

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

# File lib/matrix.rb, line 1339 def transpose return self.class.empty(column_count, 0) if row_count.zero? new_matrix @rows.transpose, row_count end

别名: t

unitary?() Show source

如果这是一个酉矩阵,则返回true,如果矩阵不是平方,则返回一个错误。

# File lib/matrix.rb, line 879 def unitary? Matrix.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

upper_triangular?() Show source

如果这是一个上三角矩阵,则返回true

# File lib/matrix.rb, line 896 def upper_triangular? each(:strict_lower).all?(&:zero?) end

vstack(*matrices) Show source

通过垂直堆叠给定矩阵的接收器返回一个新矩阵

x = Matrix[[1, 2], [3, 4]] y = Matrix[[5, 6], [7, 8]] x.vstack(y) # => Matrix[[1, 2], [3, 4], [5, 6], [7, 8]]

# File lib/matrix.rb, line 1353 def vstack(*matrices) self.class.vstack(self, *matrices) end

zero?() Show source

如果这是一个只有零元素的矩阵,则返回true

# File lib/matrix.rb, line 903 def zero? all?(&:zero?) end

私有实例方法

[]=(i, j, v) Show source

# File lib/matrix.rb, line 377 def []=(i, j, v) @rows[i][j] = v end

别名: set_element, set_component

determinant_bareiss() Show source

Private. Use #determinant

使用Bareiss'多步整数保持高斯消除法返回矩阵的行列式。它具有与标准高斯消元相同的计算成本阶数O(n ^ 3)。中间结果是免费的,且复杂度较低。整数矩阵的中间结果也是整数,较小的二元数(如果有的话),而浮点矩阵通常具有更好精度的中间结果。

# File lib/matrix.rb, line 1215 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

set_component(i, j, v)

别名: []=

set_element(i, j, v)

别名: []=