Performance 稀疏矩阵乘法的特例

Performance 稀疏矩阵乘法的特例,performance,algorithm,matrix,sparse-matrix,matrix-multiplication,Performance,Algorithm,Matrix,Sparse Matrix,Matrix Multiplication,我试图想出一个快速算法来找到运算结果,在哪里 L-是具有实数的对称矩阵 A-是稀疏的nxm矩阵,m

我试图想出一个快速算法来找到运算结果,在哪里

  • L-是具有实数的对称矩阵
  • A-是稀疏的
    nxm
    矩阵,
    m
    。每行只有一个非零元素,它等于1。它还保证每个列最多有两个非零元素
我提出了一个算法,但我觉得应该有比这个更快的算法

让我们将一个表的每一列表示为一对具有非零元素的行号。如果列只有一个非零元素,则其行号将列出两次。例如,对于以下矩阵

这种代表性将是非常重要的

第0列:[0,2];第1栏:[1,3];第2栏:[4,4]

或者我们可以将其列为单个数组:
a=[0,2,1,3,4,4]现在,可以计算为:

for (i = 0; i < A.length; i += 2):
  if A[i] != A[i + 1]:
     # sum of two column vectors, i/2-th column of L'
     L'[i/2] = L[A[i]] + L[A[i + 1]] 
  else:
     L'[i/2] = L[A[i]]
用于(i=0;i
为了计算,我们再做一次:

for (i = 0; i < A.length; i += 2):
  if A[i] != A[i + 1]:
    # sum of two row vectors, i/2-th row of L''
    L''[i/2] = L'[A[i]] + L'[A[i + 1]]
  else:
    L''[i/2] = L'[A[i]]
用于(i=0;i

该方法的时间复杂度为O(mn+mn),空间复杂度为O(nn)。我想知道是否有可能在空间和/或性能方面将其提高到O(mm)?

第二个循环最多组合2m行L',因此,如果m远小于n,则将有几行L',从未使用过

避免计算和存储这些未使用项的一种方法是将第一个循环更改为一个函数,并仅在需要时计算L'的各个元素

def L'(row,col):
  i=col*2
  if A[i] != A[i + 1]:
    # sum of two column vectors, i/2-th column of L'
    return L[row][A[i]] + L[row][A[i + 1]] 
  else:
    return L[row][A[i]]

for (i = 0; i < A.length; i += 2):
  if A[i] != A[i + 1]:
    for (k=0;k<m;k++):
      L''[i/2][k] = L'(A[i],k) + L'(A[i + 1],k)
  else:
    for (k=0;k<m;k++):
      L''[i/2][k] = L'(A[i],k)
def L'(行,列):
i=col*2
如果A[i]!=A[i+1]:
#两列向量之和,L'的第i/2列
返回L[行][A[i]]+L[行][A[i+1]]
其他:
返回L[行][A[i]]
对于(i=0;i对于(k=0;k第二个循环组合了最多2m行的L',因此,如果m远小于n,则有几行L',从未使用过

避免计算和存储这些未使用项的一种方法是将第一个循环更改为一个函数,并仅在需要时计算L'的各个元素

def L'(row,col):
  i=col*2
  if A[i] != A[i + 1]:
    # sum of two column vectors, i/2-th column of L'
    return L[row][A[i]] + L[row][A[i + 1]] 
  else:
    return L[row][A[i]]

for (i = 0; i < A.length; i += 2):
  if A[i] != A[i + 1]:
    for (k=0;k<m;k++):
      L''[i/2][k] = L'(A[i],k) + L'(A[i + 1],k)
  else:
    for (k=0;k<m;k++):
      L''[i/2][k] = L'(A[i],k)
def L'(行,列):
i=col*2
如果A[i]!=A[i+1]:
#两列向量之和,L'的第i/2列
返回L[行][A[i]]+L[行][A[i+1]]
其他:
返回L[行][A[i]]
对于(i=0;i对于(k=0;k而言,
转置(A)*L
操作如下:

对于A的每一列,我们可以看到:

column 1 has `1` in row 1 and 3
column 2 has `1` in row 2 and 4
column 3 has `1` in row 5
输出矩阵
B=转置(A)*L
有三行,它们等于:

Row(B, 1) = Row(A, 1) + Row(A, 3)
Row(B, 2) = Row(A, 2) + Row(A, 4)
Row(B, 3) = Row(A, 5)
如果我们乘以
C=B*A

Column(C, 1) = Column(B, 1) + Column(B, 3)
Column(C, 2) = Column(B, 2) + Column(B, 4)
Column(C, 3) = Column(B, 5)

如果您以算法的方式完成此操作,您应该可以实现与Peter de Rivaz所建议的非常类似的操作。

操作
转置(a)*L
的工作原理如下:

对于A的每一列,我们可以看到:

column 1 has `1` in row 1 and 3
column 2 has `1` in row 2 and 4
column 3 has `1` in row 5
输出矩阵
B=转置(A)*L
有三行,它们等于:

Row(B, 1) = Row(A, 1) + Row(A, 3)
Row(B, 2) = Row(A, 2) + Row(A, 4)
Row(B, 3) = Row(A, 5)
如果我们乘以
C=B*A

Column(C, 1) = Column(B, 1) + Column(B, 3)
Column(C, 2) = Column(B, 2) + Column(B, 4)
Column(C, 3) = Column(B, 5)

如果你用一种算法的方式来完成这一过程,你应该会得到与彼得·德里瓦兹(Peter de Rivaz)所建议的非常相似的结果。

你的算法的时间复杂度是O(n^2),而不是O(m*n)。L的行和列的长度是n,a数组的长度是2n

如果a[k]是a的k行具有1的列,则可以写入:

A[k,i] = δ(a[k],i)
乘积p=A^T*L*A是:

P[i,j] = Σ(k,l) A^T[i,k]*L[k,l]*A[l,j]
       = Σ(k,l) A[k,i]*L[k,l]*A[l,j]
       = Σ(k,l) δ(a[k],i)*L[k,l]*δ(a[l],j)
如果我们把它转过来,看看L的元素发生了什么,我们会看到L[k,L]被添加到p[a[k],a[L]],很容易用O(n^2)时间复杂度得到O(m^2)空间复杂度


因为[k]是为所有k=0..n-1定义的,所以我们知道L的每个元素都必须出现在乘积中的某个地方。因为L中有O(n^2)个不同的元素,所以不能比O(n^2)的时间复杂度更好。

算法的时间复杂度是O(n^2),而不是O(m*n).L的行和列的长度为n,A数组的长度为2n

如果a[k]是a的k行具有1的列,则可以写入:

A[k,i] = δ(a[k],i)
乘积p=A^T*L*A是:

P[i,j] = Σ(k,l) A^T[i,k]*L[k,l]*A[l,j]
       = Σ(k,l) A[k,i]*L[k,l]*A[l,j]
       = Σ(k,l) δ(a[k],i)*L[k,l]*δ(a[l],j)
如果我们把它转过来,看看L的元素发生了什么,我们会看到L[k,L]被添加到p[a[k],a[L]],很容易用O(n^2)时间复杂度得到O(m^2)空间复杂度

因为[k]是为所有k=0..n-1定义的,所以我们知道L的每个元素都必须出现在乘积中的某个地方。因为L中有O(n^2)个不同的元素,所以时间复杂度不能超过O(n^2)