首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在MATLAB中将零对角添加到矩阵中

在MATLAB中将零对角添加到矩阵中
EN

Stack Overflow用户
提问于 2017-12-08 11:26:17
回答 3查看 1.9K关注 0票数 8

假设我在MATLAB中有一个维数A的矩阵Nx(N-1)

代码语言:javascript
运行
复制
N=5;
A=[1  2  3  4;
   5  6  7  8;
   9  10 11 12;
   13 14 15 16;
   17 18 19 20 ];

我想将A转换为NxN矩阵B,只需添加一个零对角线,即,

代码语言:javascript
运行
复制
B=[ 0  1   2   3   4;
    5  0   6   7   8;
    9  10  0   11  12;
    13 14  15  0   16;
    17 18  19  20  0];

这个代码实现了我想要的结果:

代码语言:javascript
运行
复制
B_temp = zeros(N,N); 
B_temp(1,:) = [0 A(1,:)];
B_temp(N,:) = [A(N,:) 0];
for j=2:N-1
    B_temp(j,:)= [A(j,1:j-1) 0 A(j,j:end)];
end
B = B_temp; 

你能提出一种有效的方法把它矢量化吗?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2017-12-08 11:50:52

您可以使用矩阵的上三角部分和下三角部分(triutril)来完成此操作。

这是一个1行的解决方案:

代码语言:javascript
运行
复制
B = [tril(A,-1) zeros(N, 1)] + [zeros(N,1) triu(A)];

编辑:基准测试

这是循环方法、Sardar's answer中的两个方法和我上面的方法的比较。

基准代码,使用timeit来计时,并直接解除代码的问答:

代码语言:javascript
运行
复制
function benchie()
    N = 1e4; A = rand(N,N-1); % Initialise large matrix
    % Set up anonymous functions for input to timeit
    s1 = @() sardar1(A,N); s2 = @() sardar2(A,N); 
    w =  @() wolfie(A,N); u = @() user3285148(A,N);
    % timings
    timeit(s1), timeit(s2), timeit(w), timeit(u)
end
function sardar1(A, N) % using eye as an indexing matrix
    B=double(~eye(N)); B(find(B))=A.'; B=B.';
end
function sardar2(A,N) % similar to sardar1, but avoiding slow operations
    B=1-eye(N); B(logical(B))=A.'; B=B.';
end
function wolfie(A,N) % using triangular parts of the matrix
    B = [tril(A,-1) zeros(N, 1)] + [zeros(N,1) triu(A)];
end
function user3285148(A, N) % original looping method
    B = zeros(N,N); B(1,:) = [0 A(1,:)]; B(N,:) = [A(N,:) 0];
    for j=2:N-1; B(j,:)= [A(j,1:j-1) 0 A(j,j:end)]; end
end

结果:

  • Sardar方法1: 2.83秒
  • Sardar方法2: 1.82秒
  • 我的方法: 1.45秒
  • 循环方法:3.80秒(!)

结论:

  • 你想要矢量化这一点是有根据的,循环比其他方法慢得多。
  • 避免大型矩阵的数据转换和find是很重要的,在Sardar方法之间节省了35%的处理时间。
  • 通过避免所有索引在一起,您可以节省20%的处理时间。
票数 13
EN

Stack Overflow用户

发布于 2017-12-08 11:37:30

生成对角线为零,非对角线为零的矩阵.用A的转置替换非对角线元素(因为MATLAB是列的主要部分)。再转一次,得到正确的顺序。

代码语言:javascript
运行
复制
B = double(~eye(N));  %Converting to double since we want to replace with double entries
B(find(B)) = A.';     %Replacing the entries
B = B.';              %Transposing again to get the matrix in the correct order

编辑:

作为https://stackoverflow.com/questions/47713435/add-a-zero-diagonal-to-a-matrix-in-matlab#comment82387253_47713640https://stackoverflow.com/users/3978545/wolfie的相同算法,您可以去掉对double的转换和使用find

代码语言:javascript
运行
复制
B = 1-eye(N);
B(logical(B)) = A.'; 
B = B.';
票数 5
EN

Stack Overflow用户

发布于 2018-09-21 09:31:22

如果要在矩阵的对角线上插入任何向量,可以使用普通索引。下面的片段给出了所需对角线的索引,给定方阵n的大小(矩阵是n by n),以及对角线k的数目,其中k=0对应于主对角线,k的正数对应于上对角,k的负数对应于下对角线。ixd最终给出了2D索引。

代码语言:javascript
运行
复制
function [idx] = diagidx(n,k)
% n size of square matrix
% k number of diagonal
if k==0 % identity
    idx = [(1:n).' (1:n).']; % [row col]
elseif k>0 % Upper diagonal
    idx = [(1:n-k).' (1+k:n).'];
elseif k<0 % lower diagonal
    idx = [(1+abs(k):n).' (1:n-abs(k)).'];
end
end

用法:

代码语言:javascript
运行
复制
n=10;
k=3;
A = rand(n);
idx = diagidx(n,k);

A(idx) = 1:(n-k);

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/47713435

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档