matlab - 如何创建一个对称矩阵,其中每行/列都是已知向量的子集

标签 matlab matrix diagonal symmetry

<分区>

我有一个 7*1 向量 a = (1:7).'。我想从向量 a 中形成一个大小为 4*4 的矩阵 A,这样 a 的元素形成矩阵 的反对角线code>A如下:

A = [1 2 3 4;
     2 3 4 5;
     3 4 5 6;
     4 5 6 7]

我希望这适用于一般的 a,而不仅仅是当元素是连续整数时。

感谢任何帮助。

最佳答案

设置索引

meshgrid 的两个输出相加可以给出索引:

[x, y] = meshgrid(1:4, 0:3);
x + y;
% ans = [1     2     3     4
%        2     3     4     5
%        3     4     5     6
%        4     5     6     7];

如果a就像在您的示例中一样,您可以停在那里。或者,使用它来索引一般向量 a .为了进行比较,我将使用与 rahnema1 为他们的方法所做的相同的示例输入:

a = [4 6 2 7 3 5 1];
[x, y] = meshgrid(1:4, 0:3);
A = a(x + y);    
% A = [4     6     2     7
%      6     2     7     3
%      2     7     3     5
%      7     3     5     1] 

许多方法可以创建索引而不是使用 meshgrid ,请参阅下面的基准测试函数以获取一些示例!


基准测试和七种不同的方法。

以下是运行不同方法的一些时间安排,包括使用 cumsum 的方法, repmat , hankel和一个简单的 for环形。该基准测试是在 Matlab 2015b 中完成的,因此利用了 Matlab 优化等,而 rahnema1 答案中的 Octave 基准测试可能无法做到。我也用 timeittic 更强大的功能/toc因为它会进行多次试验等。

function benchie()
    n = 10000;    % (large) square matrix size
    a = 1:2*n-1;  % array of correct size, could be anything this long
    f1 = @() m1(a,n);  disp(['bsxfun:   ', num2str(timeit(f1))]);
    f2 = @() m2(a,n);  disp(['cumsum:   ', num2str(timeit(f2))]);
    f3 = @() m3(a,n);  disp(['meshgrid: ', num2str(timeit(f3))]);
    f4 = @() m4(a,n);  disp(['repmat:   ', num2str(timeit(f4))]);
    f5 = @() m5(a,n);  disp(['for loop: ', num2str(timeit(f5))]);
    f6 = @() m6(a,n);  disp(['hankel1:  ', num2str(timeit(f6))]); 
    f7 = @() m7(a,n);  disp(['hankel2:  ', num2str(timeit(f7))]); 
end
% Use bsxfun to do broadcasting of addition
function m1(a,n); A = a(bsxfun(@plus, (1:n), (0:n-1).')); end
% Use cumsum to do cumulative vertical addition to create indices
function m2(a,n); A = a(cumsum([(1:n); ones(n-1,n)])); end
% Add the two meshgrid outputs to get indices
function m3(a,n); [x, y] = meshgrid(1:n, 0:n-1); A = a(x + y); end
% Use repmat twice to replicate the meshgrid results, for equivalent one liner
function m4(a,n); A = a(repmat((1:n)',1,n) + repmat(0:n-1,n,1)); end
% Use a simple for loop. Initialise A and assign values to each row in turn
function m5(a,n); A = zeros(n); for ii = 1:n; A(:,ii) = a(ii:ii+n-1); end; end
% Create a Hankel matrix (constant along anti-diagonals) for indexing
function m6(a,n); A = a(hankel(1:n,n:2*n-1)); end
% Create a Hankel matrix directly from elements
function m7(a,n); A = hankel(a(1:n),a(n:2*n-1)); end

输出:

bsxfun:   1.4397 sec
cumsum:   2.0563 sec
meshgrid: 2.0169 sec
repmat:   1.8598 sec
for loop: 0.4953 sec % MUCH quicker!
hankel1:  2.6154 sec
hankel2:  1.4235 sec

所以你最好使用 rahnema1 的建议 bsxfun或直接生成 hankel matrix 如果你想要一个衬里,这是一个很棒的 StackOverflow 答案,它解释了一些 bsxfun的优势:In Matlab, when is it optimal to use bsxfun?

但是,for 循环的速度要快两倍多!优化可以是最快的。

关于matlab - 如何创建一个对称矩阵,其中每行/列都是已知向量的子集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44715150/

相关文章:

matlab - 为什么 MATLAB 会删除我的 classdef 中的断点?

python-3.x - 通过堆叠对角 K 矩阵来创建一个新的大矩阵

python - 在 scipy 中删除/设置稀疏矩阵的非零对角线元素

r - "could not find function H"从 R 中的 txt 文件加载的变量

r - 矩阵乘法与 Rcpp - 分配输出时的不同值

android - 用三角形绘制android xml形状对角线

matlab - 如何在元胞数组matlab中找到一行的子项?

c - mex:计算权;但是,我得到了错误的输出

matlab - 确定每个四分音符的脉冲

c - 矩阵生成器 - C 中的段错误