MATLAB: create a large matrix by repeating elements of a vector, with increasing stride for each column

大城市里の小女人 提交于 2019-12-06 05:25:28

Use allcomb tool from MATLAB file-exchange to generate the possible combinations of the indices [1 2 3 4] and then use them to index into x -

v = repmat({1:numel(x)},1,m);
A = x(fliplr(allcomb(v{:})));

Also, it seems instead of using fliplr, you can use - allcomb(v{:},'matlab') instead.

For the edited part of the question, you can use a modified version of it -

V = prod(x(allcomb(v{:})),2)

Benchmarking

Please note that these are for runnable solutions posted here.

Benchmarking Code

%// Parameters and input x
n = 10; m = 6;num_runs = 20; x =  randi(9,n,1);

disp('-------- With allcomb')
tic
for runs = 1:num_runs
    v = repmat({1:numel(x)},1,m);
    A = x(fliplr(allcomb(v{:})));
end
toc,    clear v A

disp('-------- With bsxfun')
tic
for runs = 1:num_runs
    A = x(floor(mod(bsxfun(@rdivide, (0:n^m-1).', n.^[0:m-1] ), n)+1)); %//'
end
toc,    clear A

disp('-------- With ttable')
tic
for runs = 1:num_runs
    I = ttable(n*ones(1,m));
    A = x(I);
end
toc,    clear I A

disp('-------- With arrayfun')
tic
for runs = 1:num_runs
    A = cell2mat(arrayfun(@(i)...
        (repmat(reshape(repmat(x',n^(i-1),1),[],1),n^(m-i),1)),1:m,'uni',0));
end
toc

Results

-------- With allcomb
Elapsed time is 6.544981 seconds.
-------- With bsxfun
Elapsed time is 11.547062 seconds.
-------- With ttable
Elapsed time is 15.729932 seconds.
-------- With arrayfun
Elapsed time is 4.319048 seconds.

One-liner based only on built-in functions (namely, mod and the very powerful bsxfun):

result = x(floor(mod(bsxfun(@rdivide, (0:n^m-1).', n.^[0:m-1] ), n)+1));

Try this: (all are bulit-in functions)

A = cell2mat(arrayfun(@(i)(repmat(reshape(repmat(x',n^(i-1),1),[],1),n^(m-i),1)),1:m,'UniformOutput',0))

Explanation:

n = 2;
m = 4;
x = (1:n)';
A = [];
for i = 1:m
%// temp1 is (n^(i-1)) x n matrix with each row equal to x' 
    temp1 = repmat(x',n^(i-1),1); 
%// temp2 is (n^(i-1))*n x 1 column vector with corresponding elements of temp1
    temp2 = reshape(temp1,[],1);
%// temp3 is a (n^(m-i))*(n^(i-1))*n x 1, i.e n^m x 1 column vector with elements of temp2 repeated n^(m-i) times
    temp3 = repmat(temp2,n^(m-i),1);
%// A is appending temp3 into its ith column
    A = cat(2,A,temp3);
end

For The EDIT part:

You can do what you said i.e do prod(B,2) where B is a matrix calculated using above code

Dan

I think the generalized truth table function from the file exchange will help you

try (not tested):

I = ttable(n*ones(1,m));
x(I);

Okay, there are tricky one-liner solutions for this. There is, however, a file on matlab file exchanging providing the solution that you are looking at if the order doesn't matter. See here combn. It basically makes use of the same tricks as the one-liner presented by other answers. If the order matters, you might have to do some sorting aftwerwards or adjust the source code directly.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!