我有一个稀疏matricies myBasis
,...,B_1
的单元格数组B_n
。
我想用Matlab评估矩阵Q(i,j) = trace (B^T_i * B_j)
。
因此,我写了以下代码:
for i=1:n
for j=1:n
B=myBasis{i};
C=myBasis{j};
Q(i,j)=trace(B'*C);
end
end
当n=1226
和B_i
有50行和50列时,已经过了68秒。
有没有机会加快速度?通常我在c ++文件中从我的matlab代码中排除for循环 - 但我没有经验如何在C ++中处理稀疏单元数组。
答案 0 :(得分:4)
Q
所述,它是对称的,因此您只需要明确计算一半条目。trace( B.'*C )
相当于B(:).'*C(:)
:trace(B.'*C)
= sum_i [B.'*C]_ii
= sum_i sum_j B_ij * C_ij
B(:).'*C(:)
在明确计算trace( B.'*C )
时,您实际上预先计算所有 k-by-k条目B.'*C
,但稍后才使用对角线。 AFAIK,Matlab没有优化其计算以节省计算所有条目。 这是一种方式
for ii = 1:n
B = myBasis{ii};
for jj = ii:n
C = myBasis{jj};
t = full( B(:).'*C(:) ); % equivalent to trace(B'*C)!
Q(ii,jj) = t;
Q(jj,ii) = t;
end
end
PS,
最好not to use i
and j
as variable names in Matlab。
PPS,
您应该注意到Matlab中的'
运算符不矩阵转置,但是hermitian conjugate,对于实际的转置,您需要使用.'
。在大多数情况下,不涉及复数,两个运算符之间没有区别,但是一旦引入复杂数据,两个运算符之间的混淆会使调试变得非常混乱......
答案 1 :(得分:1)
好吧,有几点想法
1)基本内容:'* B =(B'* A)'和跟踪(A)=跟踪(A')。好吧,只有这个技巧会使你的计算减少近50%。你的Q(i,j)矩阵是对称的,你只需要计算n(n + 1)/ 2项(而不是n²)
2)要计算迹线,您不需要计算B'* C的每个项,只需计算对角线。不过,我不知道在Matlab中创建一个脚本是否比在计算B'* C(MatLab与矩阵运算相当快)时更快。
但我肯定会实施(1)