将上三角矩阵乘以1D阵列算法

时间:2016-01-15 04:03:54

标签: c++ arrays matrix matrix-multiplication

我在c ++中进行上三角矩阵乘法。这些矩阵存储在一维阵列中而不是普通的二维阵列中。该值从行到行存储在数组中,并忽略底部的0。我做了很多数学,试图找出一个模式,但我仍然想不出算法。假设我有2个矩阵,每个矩阵都是正方形,并且这两个值都存储在1D数组A和B中。我想将结果存储在数组C中。我认为最难的部分是添加不同数量的在for循环运行时更改元素。

任何人都可以给我一些灵感?

2 个答案:

答案 0 :(得分:2)

假设整个矩阵的大小为N x N

在第一行row = 0中,有N个元素 在第二行row = 1中,有N - 1个元素。

...

在第k行row = k,有N - k个元素。

这是一个ASCII图:

|<-               N                    ->|

+--+--+--+       ---            +--+--+--+
|  |  |  |                      |  |  |  |  row = 0, N elements
+--+--+--+       ---            +--+--+--+
   |  |  |                      |  |  |  |  row = 1, N-1 elements
   +--+--+       ---            +--+--+--+
      |  |                      |  |  |  |  row = 2, N-2 elements
      +--+       ---            +--+--+--+


                 ---            +--+--+--+
                                |  |  |  |  row = k, N-k elements
                 ---            +--+--+--+


                                +--+--+--+
                                |  |  |  |  row = N-3, 3 elements
                                +--+--+--+
                                   |  |  |  row = N-2, 2 elements
                                   +--+--+
                                      |  |  row = N-1, 1 element
                                      +--+

1D数组中存储此类矩阵所需的元素数量为:

1 + 2 + ... + N = N*(N+1)/2

要访问矩阵的元素,我们需要将行索引和列索引映射到1D数组中的索引。

要获取第一行的j列(行索引= 0,列索引= j),

index = j

要获取第二行的j列(行索引= 1,列索引= j),

index = N + (j-1)

要获取第三行的j列(行索引= 2,列索引= j),

index = N + (N-1) + (j-2)

...

要获取j行的i列(行索引= i,列索引= j),

index = N + (N-1) + ... + (N-(i-1)) + (j-i)
      = N + N     +  .. + N
          - ( 1   +        + (i-1) )  + j-i
      = N * i - (i-1)*i/2 + (j-i)

通过以上信息,您可以编写以下功能:

  1. 为上三角矩阵分配适量的内存
  2. 设置行索引(i)和列索引(j)的矩阵值。
  3. 获取给定行索引(i)和列索引(j)的矩阵的值。
  4. 这应该足以能够将上三角矩阵与另一个上三角矩阵以及规则矩阵相乘。

答案 1 :(得分:0)

我接近这个方法的方法是从索引形式的矩阵乘法定义开始

(A B){i,j} = sum_k A{i,k} B{k, j}

现在你需要一种方法来将索引映射到i和j之间的一维数组中。

int toArrayIndex(tuple<int,int> ij); // return -1 if not in array
tuple<int,int> toMatrixIndex(int arrayIndex);

然后你的功能看起来就像

for(int arrayIndex=0; i<maxArrayIndex; ++arrayIndex ) {
  tuple<int,int> ij = toArrayIndex(arrayIndex);
  for(int k=0; k<matrixSize; ++k) {
    tuple<int,int> ik = make_tuple( std::get<0>(ij), k );
    tuple<int,int> kj = make_tuple( k, std::get<1>(ij) );
    int ik_index = toMatrixIndex(ik);
    int kj_index =  toMatrixIndex(kj);
    if(ik_index < 0 || kj_index < 0) continue;
    ab[arrayIndex] += a[ik_index] * b[kj_index];
  }
}

这不是最佳的,因为内部k循环的大小可以减小。