在Ax=b
类型问题中使用了一个大矩阵。 A 是对称的。是否有任何算法让我们只保存矩阵的一半并在其上执行x=A\b
之类的操作?
答案 0 :(得分:6)
你只能节省一半的内存,但你可以通过创建矩阵的平面版本来保存,然后取消它。请注意,所需的额外时间可能不会使保存变得有价值:
% pretend this is symettric...
A = rand(10, 10);
% store it as a flat list
flatA = [];
for k = 1:size(A,1)
flatA = [flatA; A([1:k],k)];
end
save('flatA.mat', 'flatA');
% undo
N = (-1 + (1+4*2*length(flatA))^0.5)/2;
newA = NaN(N,N);
cur = 1;
for k = 1:N
len = k;
newA(1:len, k) = flatA(cur:cur+len-1);
cur = cur + len;
end
% real A cannot have NaNs or this trick fails
newA(isnan(newA)) = newA(isnan(newA'))';
答案 1 :(得分:3)
这是一个想法,但我还没有测试过。如果你的对称矩阵是正定的,那么对称矩阵A的Cholesky分解,给你A = U * U'。如果使用MATLAB的内置稀疏矩阵将U存储为稀疏矩阵,则可以获得所需的一切,并且使用了大约一半的内存。由于它使用MATLAB的稀疏矩阵类型,您可以使用标准MATLAB函数对其进行操作,只要您记住A = U * U'
例如,要计算A * x = b,请使用x = U'\ U \ b。与其他提出的解决方案不同,MATLAB实际上永远不会在内部使用完整矩阵,甚至会使用加速求解器,这将利用您只用三角形求解的事实。成本是解决单个系统的问题,实际上你已经运行了两次反斜杠运算符(参见上文)。但是,这是你从未实例化完整矩阵所付出的代价。
答案 2 :(得分:1)
如果提取上三角形部分并转换为稀疏矩阵,则应节省内存。这种技术相当快。
% Create a symmetric matrix
A = rand(1000);
A = A + A';
% Extract the upper triangular part
B = sparse(triu(A)) % This is the important line, the rest is just checking.
% Undo
BB = full(B);
C = BB + BB' - diag(diag(BB));
% Check correct
assert(all(A(:) == C(:)));
% Save matrices
save('A.mat', 'A');
save('B.mat', 'B');
% Get file sizes
infoA = dir('A.mat'); infoA.bytes
infoB = dir('B.mat'); infoB.bytes
编辑澄清木片的事情
上述解决方案演示了一种以较少文件空间保存矩阵的方法。矩阵B
也比原始矩阵A
占用更少的内存。如果你想在B
上做线性代数运算,那就非常有效。比较
b = rand(1000);
fullTriUA = triu(A);
sparseTriUA = sparse(fullTriUA); %same as B above
fullResult = fullTriUA\b;
sparseResult = sparseTriUA\b;
assert(all(fullResult(:) == sparseResult(:)))