创建一个水平拉伸的上三角矩阵

时间:2015-04-28 20:26:07

标签: matlab matrix vectorization memory-efficient

我想创建一个与上三角矩阵非常相似的4x12矩阵,它看起来像这样:

1 1 1 1 1 1 1 1 1 1 1 1  
0 0 0 1 1 1 1 1 1 1 1 1
0 0 0 0 0 0 1 1 1 1 1 1
0 0 0 0 0 0 0 0 0 1 1 1

所以我的问题是。创建它的最有效方法是什么?没有循环,没有cellfun。感谢。

4 个答案:

答案 0 :(得分:2)

一种vectorized方法 -

nrows = 4;
ncols = 12;

row_idx = repmat(1:nrows,ncols/nrows,1)
out = bsxfun(@le,[1:nrows]',row_idx(:).')

答案 1 :(得分:2)

创建一个上三角矩阵,置换第二维和第三维,沿第二维重复,然后重塑成所需的形状:

m = 4;
n = 12;
result = reshape(repmat(permute(triu(ones(m,m)), [1 3 2]), [1 n/m 1]), [m n]);

答案 2 :(得分:2)

使用新引入的repelem Matlab R2015a及更高版本方法:

n = 4;
m = 3;
out = repelem(triu(ones(n)),1,m);
out =

     1     1     1     1     1     1     1     1     1     1     1     1
     0     0     0     1     1     1     1     1     1     1     1     1
     0     0     0     0     0     0     1     1     1     1     1     1
     0     0     0     0     0     0     0     0     0     1     1     1

它似乎比bsxfun方法更快,但我无法相信这一点;)

基准

不幸的是我无法考虑 andrew的解决方案因为它不完整而且我没有完全理解。

function [t] = bench()

   n = 4;
   m = 12;
   t = zeros(3,15);
   for ii = 1:15
        fcns = {
            @() thewaywewalk(ii*n,ii*m);
            @() Divakar(ii*n,ii*m);
            @() LuisMendo(ii*n,ii*m);
        };
        % timeit
        for jj = 1:100;
            t(:,ii) = t(:,ii) + cellfun(@timeit, fcns);
        end
   end

   plot(1:15,t(1,:)); hold on;
   plot(1:15,t(2,:)); hold on;
   plot(1:15,t(3,:)); hold on;
   xlabel('Matrix size: n = x*4, m = x*12')
   ylabel('timing')
   legend({'thewaywewalk','Divakar','Luis Mendo'},'location','northwest')

end
function Z = thewaywewalk(n,m) 
    Z = repelem(triu(ones(n)),1,m/n);
end
function Z = Divakar(n,m)  
    row_idx = repmat(1:n,m/n,1);
    Z = bsxfun(@le,[1:n]',row_idx(:).');
end
function Z = LuisMendo(n,m)
    Z = reshape(repmat(permute(triu(ones(n,n)), [1 3 2]), [1 m/n 1]), [n m]);
end

enter image description here

第一个底线 - 小矩阵:

新的repelem表现非常出色,reshape(repmat(permute...也没有让人失望。在成为大型矩阵的领导者之前,bsxfun方法对某些中型矩阵来说有点落后:

第二个底线 - 大矩阵:

正如Divakar预测的那样,bsxfun对于较大的矩阵来说是最快的,实际上正如预期的那样bsxfun总是最快的!有趣的是,其他两个完美对齐,可以猜测它们内部几乎一样。

enter image description here

答案 3 :(得分:0)

取决于您的matlab版本

m = 4;
n = 12;

dec2bin(bitshift(num,-1*[0:n/m:n-1])) %this prints out a string

这些应该是逻辑阵列(我没有其中任何一个,所以我不能测试它)

decimalToBinaryVector(bitshift(num,-1*[0:n/m:n-1]))

de2bi(bitshift(num,-1*[0:n/m:n-1]))