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

Create a horizontically stretched upper triangular matrix

我想创建一个与上三角矩阵非常相似的 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

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

一种vectorized方法-

nrows = 4;
ncols = 12;

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

取决于您的 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]))

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

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

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

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

第一个底线 - 小矩阵:

新的 repelem 做得很好,而且 reshape(repmat(permute... 也没有让人失望。 bsxfun 方法在成为大型矩阵的领导者之前,对于一些中型矩阵来说有点落后:

第二个底线——大矩阵:

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