块对角化J-by-2矩阵的行

时间:2015-11-24 16:27:04

标签: matlab

给定J - by-2矩阵,例如

{{1}}

我想阻止对角线化。也就是说,我想:

{{1}}

执行此操作的一个命令是:

{{1}}

如果{{1}}很大,这将是缓慢而乏味的。是否有内置的Matlab函数可以做到这一点?

4 个答案:

答案 0 :(得分:5)

以下是使用linear indexingJ x 2数组案例的 hacky 解决方案 -

%// Get number of rows
N = size(A,1);                   

%// Get linear indices of the first column elements positions in output array
idx = 1:2*N+1:(N-1)*(2*N+1)+1;   

%// Setup output array
out = zeros(N,N*2);

%// Put first and second column elements into idx and idx+N positions
out([idx(:) idx(:)+N]) = A

只有一个函数调用(忽略size,因为它必须是最小的)zeros的开销,甚至可以使用this undocumented zeros initialization trick删除 -

out(N,N*2) = 0; %// Instead of out = zeros(N,N*2);

示例运行 -

A =
     1     2
     3     4
     5     6
     7     8
out =
     1     2     0     0     0     0     0     0
     0     0     3     4     0     0     0     0
     0     0     0     0     5     6     0     0
     0     0     0     0     0     0     7     8

这是迄今为止发布的解决方案的基准测试。

基准代码

%//Set up some random data
J = 7000;   A = rand(J,2);
%// Warm up tic/toc
for k = 1:100000
    tic(); elapsed = toc();
end   
disp('---------------------------------- With @mikkola solution')
tic
temp = mat2cell(A, ones(J,1), 2);
B = blkdiag(temp{:});
toc, clear B temp
disp('---------------------------------- With @Jeff Irwin solution')
tic
m = size(A, 1);
n = size(A, 2);
B = zeros(m, m * n);
for k = 1: n
    B(:, k: n: m * n) = diag(A(:, k));
end
toc, clear B k m n
disp('---------------------------------- With Hacky1 solution')
tic
N = size(A,1);                   
idx = 1:2*N+1:(N-1)*(2*N+1)+1;   
out = zeros(N,N*2);
out([idx(:) idx(:)+N]) = A;
toc, clear out idx N
disp('---------------------------------- With Hacky2 solution')
tic
N = size(A,1);                   
idx = 1:2*N+1:(N-1)*(2*N+1)+1;
out(N,N*2) = 0;
out([idx(:) idx(:)+N]) = A;
toc, clear out idx N

<强>运行时

---------------------------------- With @mikkola solution
Elapsed time is 0.546584 seconds.
---------------------------------- With @Jeff Irwin solution
Elapsed time is 1.330666 seconds.
---------------------------------- With Hacky1 solution
Elapsed time is 0.455735 seconds.
---------------------------------- With Hacky2 solution
Elapsed time is 0.364227 seconds.

答案 1 :(得分:4)

这里使用mat2cell重塑为J-by-1单元格数组,其中每个元素包含一行A。然后使用{:}运算符将内容作为逗号分隔的变量列表推送到blkdiag

%//Set up some random data
J = 100;
A = rand(J,2);
%// Solution for arbitrary J-by-2 A
temp = mat2cell(A, ones(J,1), 2);
B = blkdiag(temp{:})

很好的解决方案!我在这里有一些计时结果,但重复他们运行@Divakar的基准测试代码。我的结果如下。

---------------------------------- With @mikkola solution
Elapsed time is 0.100674 seconds.
---------------------------------- With @Jeff Irwin solution
Elapsed time is 0.283275 seconds.
---------------------------------- With @Divakar Hacky1 solution
Elapsed time is 0.079194 seconds.
---------------------------------- With @Divakar Hacky2 solution
Elapsed time is 0.051629 seconds.

答案 2 :(得分:3)

这是另一个解决方案。不确定它的效率如何,但适用于任何大小的矩阵A

A = [1 2; 3 4; 5 6]
m = size(A, 1)
n = size(A, 2)

B = zeros(m, m * n)
for k = 1: n
    B(:, k: n: m * n) = diag(A(:, k))
end

答案 3 :(得分:0)

我找到了一种方法,使用sparse在内存和时钟时间上击败其他解决方案:

N = size(A,1);
ind_1 = [1:N].';
ind_2 = [1:2:2*N-1].';
A_1   = sparse(ind_1,ind_2,A(:,1),N,2*N);
ind_2 = [2:2:2*N].';
A_2   = sparse(ind_1,ind_2,A(:,2),N,2*N);
out       = A_1 + A_2;

下面使用与@Divakar相同的基准代码报告结果:

---------------------------------- With @mikkola solution
Elapsed time is 0.065136 seconds.
---------------------------------- With @Jeff Irwin solution
Elapsed time is 0.500264 seconds.
---------------------------------- With Hacky1 solution
Elapsed time is 0.200303 seconds.
---------------------------------- With Hacky2 solution
Elapsed time is 0.011991 seconds.
---------------------------------- With @Matt T solution
Elapsed time is 0.000712 seconds.