如何从ruby中的矩阵中提取子矩阵

时间:2014-04-20 17:52:44

标签: ruby matrix

从ruby中的矩阵中提取子矩阵的惯用方法是什么。

我有一个矩阵,这是Matrix

的对象
[131, 673, 234, 103, 18]
[201, 96, 342, 965, 150]
[630, 803, 746, 422, 111] 
[537, 699, 497, 121, 956] 
[805, 732, 524, 37, 331]

我正在寻找带有签名的方法 matrix.submatrix(1,1)这应该返回

[96, 342, 965, 150]
[803, 746, 422, 111] 
[699, 497, 121, 956] 
[732, 524, 37, 331]

matrix.submatrix(2,2)会返回

[746, 422, 111] 
[497, 121, 956] 
[524, 37, 331]

我浏览了rubydoc,但无法找到能给我想要的任何方法。我将如何在ruby中执行此操作?

对于2D数组,我想出了

def submatrix(matrix)
  submatrix = matrix.collect{|row| row.slice(1..-1)}
  # Pop off the first row
  submatrix[1..-1]
end

我想知道我是否应该重新发明轮子,或者我可以使用Matrix类的东西。

3 个答案:

答案 0 :(得分:8)

看看Matrix#minor

a = [[131, 673, 234, 103, 18], 
     [201, 96, 342, 965, 150], 
     [630, 803, 746, 422, 111], 
     [537, 699, 497, 121, 956], 
     [805, 732, 524, 37, 331]]

m = Matrix[*a]

m1 = m.minor(1..4, 1..4)
=> Matrix[[96, 342, 965, 150],  [803, 746, 422, 111], 
          [699, 497, 121, 956], [732, 524, 37, 331]]

m2 = m1.minor(1..3, 1..3)
=> Matrix[[746, 422, 111], [497, 121, 956], [524, 37, 331]]

你也可以这样做:

m1 = m.minor(1..-1, 1..-1)
m2 = m1.minor(1..-1, 1..-1)

或者:

class Matrix
  def submatrix(x, y)
    self.minor(x..-1, y..-1)
  end
end

m.submatrix(2, 2)
=> Matrix[[746, 422, 111], [497, 121, 956], [524, 37, 331]]

答案 1 :(得分:1)

以下是两种方法,一种使用Matrix对象,另一种只是操作数组。

操纵Matrix对象

<强>代码

require 'matrix'

def doit(matrix,i,j)
   selection_matrix(matrix.row_count,i) * matrix *
      selection_matrix(matrix.row_size,j)
end

def selection_matrix(n,m)
  Matrix.diagonal(*(0...n).map { |i| (i<m) ? 0 : 1 })
end

使用doit(matrix,i,j).to_a返回Array个对象。

<强>实施例

a = [[131, 673, 234, 103,  18], 
     [201, 96,  342, 965, 150], 
     [630, 803, 746, 422, 111], 
     [537, 699, 497, 121, 956], 
     [805, 732, 524,  37, 331]]

matrix = Matrix[*a]
doit(matrix,2,2)
  #=> Matrix[[0, 0,   0,   0,   0],
  #          [0, 0,   0,   0,   0],
  #          [0, 0, 746, 422, 111],
  #          [0, 0, 497, 121, 956],
  #          [0, 0, 524,  37, 331]]

doit(matrix,1,1)
  #=> Matrix[[0,   0,   0,   0,   0],
  #          [0,  96, 342, 965, 150],
  #          [0, 803, 746, 422, 111], 
  #          [0, 699, 497, 121, 956],
  #          [0, 732, 524,  37, 331]]

<强>解释

selection_matrix(n,m)返回一个对角线矩阵,其对角元素为1和0,其中的对齐矩阵的相应行或列。矩阵通过对角矩阵预乘(后乘),其对数矩阵等于矩阵的行(列)数。

selection_matrix(5,2)
  #=> Matrix[[0, 0, 0, 0, 0],
  #          [0, 0, 0, 0, 0],
  #          [0, 0, 1, 0, 0],
  #          [0, 0, 0, 1, 0],
  #          [0, 0, 0, 0, 1]]

a = selection_matrix(5,2) * matrix
  #=> Matrix[[  0,   0,   0,   0,   0],
  #          [  0,   0,   0,   0,   0],
  #          [630, 803, 746, 422, 111],
  #          [537, 699, 497, 121, 956],
  #          [805, 732, 524,  37, 331]]

b = a * selection_matrix(5,2)
  #=> Matrix[[0, 0,   0,   0,   0],
  #          [0, 0,   0,   0,   0],
  #          [0, 0, 746, 422, 111],
  #          [0, 0, 497, 121, 956],
  #          [0, 0, 524,  37, 331]]

b.to_a
  #=>       [[0, 0,   0,   0,   0],
  #          [0, 0,   0,   0,   0],
  #          [0, 0, 746, 422, 111],
  #          [0, 0, 497, 121, 956],
  #          [0, 0, 524,  37, 331]]

操纵Array对象

如果不创建Matrix对象,您可以这样做:

<强>代码

def doit(a,i,j)
  a[i..-1].transpose[j..-1].transpose
end

<强>实施例

a = [[131, 673, 234, 103,  18], 
     [201,  96, 342, 965, 150], 
     [630, 803, 746, 422, 111], 
     [537, 699, 497, 121, 956], 
     [805, 732, 524,  37, 331]]

doit(a,1,1)
  #=> [[ 96, 342, 965, 150],
  #    [803, 746, 422, 111],
  #    [699, 497, 121, 956],
  #    [732, 524,  37, 331]]

doit(a,2,2)
  #=> [[746, 422, 111],
  #    [497, 121, 956],
  #    [524,  37, 331]]

答案 2 :(得分:1)

如果您使用的是Ruby 2.2.0或更高版本,则可以使用Matrix#first_minor删除指定的行和列。我不确定它的效率如何,但这里有一些代码可以解决你的问题:

require 'matrix'

def my_submatrix(matrix, n)
  matrix = matrix.first_minor(0, 0) while matrix.row_count > n
  matrix
end

m = Matrix[[131, 673, 234, 103, 18],
           [201, 96, 342, 965, 150],
           [630, 803, 746, 422, 111],
           [537, 699, 497, 121, 956],
           [805, 732, 524, 37, 331]]

p my_submatrix(m, 3)
# => Matrix[[746, 422, 111], [497, 121, 956], [524, 37, 331]]