对称带矩阵向量乘法

Symmetric band matrix vector multiplication

提问人:2Napasa 提问时间:8/5/2022 最后编辑:2Napasa 更新时间:8/7/2022 访问量:198

问:

尝试将对称带矩阵乘以向量,即简单乘法

A*x = b

其中 A 是对称带矩阵,存储格式如下。因此,它的下半部分不会保存到存储中。

cols是包含非零波段索引的向量,例如 是主对角线,是位于主对角线 +1 位移处的上轨带,cols(1,1)=1cols(1,2)=2

第二行是条带的长度,这个值是常数,我最初存储它是为了得到矩阵大小。cols

代码的第一部分

  1. 读取文件,将表格转换为二维数组

  2. 生成随机向量来测试结果x

  3. 将对称能带形式转换为正则矩阵,目的与上述相同

所以这个想法是采用时间向量并做元素明智的乘积。 比如说,将矩阵主对角线的每个元素与相应的向量元素相乘,然后递增 rhs 向量。xb

对于移位的波段,我对向量进行切片并增加相应的xb

我设法将上面的三角形乘以向量,差值为零xmax(abs(triu(asps)*x-b))

但是当我尝试对下矩阵部分进行乘法时,max(abs(asps*x-b)) 给出了一些错误。

可能是什么问题?也许索引是错误的?

错误应该在上乘法之后或当我将数组切成时包含的行的某个地方b(i+width)xxTimesLower

Band Matrix 文件

clc; clear; close all;
adnsT = readtable('C:\Users\user\Documents\denseCTAC.txt','ReadVariableNames', false);
cols = [1 2 3 9 10 11 19;...
    81 80 79 73 72 71 63];
adns = table2array(adnsT);
n = 81;
for i = 1:7
   len = cols(2,i);
   colShift = cols(1,i)-1;
   for j = 1:len
       asps(j,j+colShift)=adns(j,i);
   end
end
asps = asps' + asps - eye(n).*diag(asps);
% spy(asps);

x = rand(n);
x = x(:,1);
b = x*0;

for j = 1:7
    width = cols(1,j)-1;
    for i = 1:n-width
        if width == 0
            b(i) = b(i)+adns(i,1)*x(i);
        else
            xTimesUpper = x(1+width:n);
            xTimesLower = x(1:n-width);
            
            %%%% multiplying upper part
            b(i) = b(i) + adns(i,j)*xTimesUpper(i); % OK if compared to triuA*x-b
            
            %%%% multiplying lower part
            % b(i+width) = b(i+width) + adns(i,j)*xTimesLower(i); % shift issue?
        end
    end
end
max((asps)*x-b)
fprintf("Error=%d\n",max(abs(asps*x-b)));
MATLAB 矩阵 舍入 精密 线性代数

评论


答:

1赞 2Napasa 8/7/2022 #1

看起来代码正在工作 刚刚在整数矩阵上测试,差值为零,

由于浮点加法的非关联性,double 类型的结果相差 10^-14 到 10^-15

在整数代码大小写下方

clc; clear; close all;
adnsT = readtable('denseCTAC.txt','ReadVariableNames', false);
cols = [1 2 3 9 10 11 19;...
    81 80 79 73 72 71 63];
adns = floor(table2array(adnsT)*100);
n = 81;
for i = 1:7
   len = cols(2,i);
   colShift = cols(1,i)-1;
   for j = 1:len
       asps(j,j+colShift)=adns(j,i);
   end
end
asps = asps' + asps - eye(n).*diag(asps);
% spy(asps);

x = randi(10,n);
x = x(:,1);
b = x*0;
% x = x';

for j = 1:7
    width = cols(1,j)-1;
    for i = 1:n-width
        if width == 0
            b(i) = b(i)+adns(i,1)*x(i);
        else
            xTimesUpper = x(1+width:n);
            xTimesLower = x(1:n-width);
            
            %%%% multiplying upper part
            b(i) = b(i) + adns(i,j) * xTimesUpper(i); % OK if compared to triuA*x-b
            b(i+width) = b(i+width) + adns(i,j)*xTimesLower(i);
            %%%% multiplying lower part
%             b(i+width) = b(i+width) + adns(i,j)*xTimesLower(i); % shift issue?
        end
    end
end
% max(triu(asps)*x-b)
max(abs(asps*x-b))

% fprintf("Error=%d\n",max(abs(asps*x-b)));