3

I have 2 variables... the number of inputs N and the length of the history M. These two variables determine the size of the matrix V which is n x m, i.e., n rows, m columns.

I have difficulties to come up with a algorithm which enables me to generate a certain amount of permutations (or sequences, how you see fit).

I would be really glad if someone could help me with a algorithm, if possible in Matlab, but a pseudo-algorithm would also be very nice.

I give you 3 examples:

  1. If the number of inputs is N = 1 and the length of the history is M = 2, I have (M+1)^N different combinations, in this case 3. The permutations are:

(In case you are not familiar with matlab matrix notation, , seperates columns, ; seperates rows.)

V(1) = [1,0,0] 
V(2) = [0,1,0]
V(3) = [0,0,1]
  1. If the number of inputs is N = 2 and the length of the history is M = 2, I have (M+1)^N different combinations, in this case 9.

The permutations are:

V(1) = [1,0,0; 1,0,0]
V(2) = [1,0,0; 0,1,0]
V(3) = [1,0,0; 0,0,1]
V(4) = [0,1,0; 1,0,0]
V(5) = [0,1,0; 0,1,0]
V(6) = [0,1,0; 0,0,1]
V(7) = [0,0,1; 1,0,0]
V(8) = [0,0,1; 0,1,0]
V(9) = [0,0,1; 0,0,1]
  1. If the number of inputs is N = 3 and the length of the history is M = 3, I have (M+1)^N different combinations, in this case 64.

The permutations are:

V(1)  = [1,0,0,0; 1,0,0,0; 1,0,0,0] 
V(2)  = [1,0,0,0; 1,0,0,0; 0,1,0,0]
V(3)  = [1,0,0,0; 1,0,0,0; 0,0,1,0]
V(4)  = [1,0,0,0; 1,0,0,0; 0,0,0,1]
V(5)  = [1,0,0,0; 0,1,0,0; 1,0,0,0]
        ...
V(8)  = [1,0,0,0; 0,1,0,0; 0,0,0,1]
V(9)  = [1,0,0,0; 0,0,1,0; 1,0,0,0]
        ...
V(16) = [1,0,0,0; 0,0,0,1; 0,0,0,1]
V(17) = [0,1,0,0; 1,0,0,0; 1,0,0,0]
        ...
V(64) = [0,0,0,1; 0,0,0,1; 0,0,0,1]

Edit: I just found a way to generate really large matrices W in which each row represents V(i)

For the first case:

W = eye(3)

Herein eye(k) creates an identity matrix of size k x k

For the second case:

W = [kron(eye(3),    ones(3,1)), ...
     kron(ones(3,1),    eye(3))]

Herein kron is the kronecker product, and ones(k,l) creates a matrix with ones of size k x l

For the third case:

W = [kron(kron(eye(4),    ones(4,1)), ones(4,1)), ...
     kron(kron(ones(4,1),    eye(4)), ones(4,1)), ...
     kron(kron(ones(4,1), ones(4,1)),    eye(4))]

Now we have created the matrices W in which each row represents V(i) in vector form, V(i) is not yet a matrix.

Observe two things:

  1. When the input N is increased an extra column is added with an extra kronecker product and the identity matrix moves along the vector.
  2. When the length of the history M is increased the identity matrices vectors are increased, e.g., eye(4) -> eye(5), ones(4,1) -> ones(5,1).
WG-
  • 1,046
  • 2
  • 14
  • 27
  • Algorithm or do you just need a function that produces the results? And is the order that the `V` vector are returned in important (i.e., `[1 0 0]` before `[0 1 0]` or vice versa). – horchler Oct 27 '14 at 21:13

3 Answers3

3

I guess this satisfies all your requirements. Even the order seems correct to me:

M=3;N=3;
mat1=eye(M+1);
vectors=mat2cell(repmat(1:M+1,N,1),ones(N,1),[M+1]);

Super-efficient cartesian product, taken from here:

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
n = numel(vectors); %// number of vectors
combs = cell(1,n); %// pre-define to generate comma-separated list
[combs{end:-1:1}] = ndgrid(vectors{end:-1:1}); %// the reverse order in these two
%// comma-separated lists is needed to produce the rows of the result matrix in
%// lexicographical order
combs = cat(n+1, combs{:}); %// concat the n n-dim arrays along dimension n+1
combs = reshape(combs,[],n); %// reshape to obtain desired matrix
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%    

V=cell(size(combs,1),1);
for i=1:size(combs,1)
    for j=1:size(combs,2)
        V{i,1}=[V{i,1};mat1(combs(i,j),:)];
    end
end

Outputs:

M=2,N=2;

V=

[1,0,0;1,0,0]
[1,0,0;0,1,0]
[1,0,0;0,0,1]
[0,1,0;1,0,0]
[0,1,0;0,1,0]
[0,1,0;0,0,1]
[0,0,1;1,0,0]
[0,0,1;0,1,0]
[0,0,1;0,0,1]

M=3;N=3;  %order verified for the indices given in the question

V(1)  = [1,0,0,0; 1,0,0,0; 1,0,0,0] 
V(2)  = [1,0,0,0; 1,0,0,0; 0,1,0,0]
V(3)  = [1,0,0,0; 1,0,0,0; 0,0,1,0]
V(4)  = [1,0,0,0; 1,0,0,0; 0,0,0,1]
V(5)  = [1,0,0,0; 0,1,0,0; 1,0,0,0]
        ...
V(8)  = [1,0,0,0; 0,1,0,0; 0,0,0,1]
V(9)  = [1,0,0,0; 0,0,1,0; 1,0,0,0]
        ...
V(16) = [1,0,0,0; 0,0,0,1; 0,0,0,1]
V(17) = [0,1,0,0; 1,0,0,0; 1,0,0,0]
        ...
V(64) = [0,0,0,1; 0,0,0,1; 0,0,0,1]
Community
  • 1
  • 1
Autonomous
  • 8,935
  • 1
  • 38
  • 77
  • Thank you really much for you answer! I do not know how you came up with this that fast! But thank you very much :D – WG- Oct 27 '14 at 21:39
  • Key observation was that it was enough to create all permutations of vector of length N which has only two values -> 0 and 1. So that can be achieved by an identity matrix. Then it was easy too see that if you just keep one of the row constant and vary other row such that you get all permutation (given by permutation matrix), then you get the answer. – Autonomous Oct 27 '14 at 21:40
  • Yes okay, I also observed that, but translating that to correct Matlab code was a difficult problem for me :P – WG- Oct 27 '14 at 21:49
  • 1
    @ParagS.Chandakkar Thanks for the reference :-) And clever way to "decode" the numbers into zeros and a one – Luis Mendo Oct 27 '14 at 21:50
  • @ParagS.Chandakkar, one small question, why do you use `V{i,1}` instead of `V{i}`? Is this faster or somehow? – WG- Oct 27 '14 at 23:09
  • two reasons: 1. MATLAB stores data in column-major order i.e. first column elements are stored together, then second etc. Read [this](http://stackoverflow.com/questions/21413164/is-matlab-row-specific-or-column-specific). I think this makes accessing the data faster. Even visualization too. Do this experiment: make a `1x100000000` vector, try to open it in workspace, then create a `100000000x1` vector. I am sure the column vector can be opened faster. 2. It is easier for scrolling and visualizing. I don't have a horizontal scroll. Also, I can quickly resize a column if number is too big! – Autonomous Oct 27 '14 at 23:25
2

You can generate these by considering the input in base M+1.

Each digit in this base specifies which part of your matrix should be set to 1 in each row.

function V=makeperm(i,N,M)
i = i - 1;
V = zeros(N,M+1);
P = M+1;
% Generate digits in base P
for row = N:-1:1
    col=mod(i,P)+1;
    i=floor(i/P);
    V(row,col)=1;
end

This function will produce the i^th permutation for inputs of N,M.

e.g.

makeperm(17,3,3)
ans =

0   1   0   0
1   0   0   0
1   0   0   0
Peter de Rivaz
  • 33,126
  • 4
  • 46
  • 75
2

This code uses allcomb tool from MATLAB file-exchange to generate the decimal numbers corresponding to each row of V. The code for allcomb can be obtained from here.

The working code to solve the stated problem would be -

power_vals = power(2,M:-1:0);
pattern1 = repmat({power_vals},1,N);
dec_nums = allcomb(pattern1{:});

bin_nums = fliplr(de2bi(num2str(dec_nums,'%1d').'-'0')); %//'
Vout = permute(reshape(bin_nums,N,size(bin_nums,1)/N,[]),[1 3 2]);

Thus, the nth 3D slice of Vout would represent V(n).

Sample run -

With M = 2 and N = 2, you would have -

>> Vout
Vout(:,:,1) =
     1     0     0
     1     0     0
Vout(:,:,2) =
     1     0     0
     0     1     0
Vout(:,:,3) =
     1     0     0
     0     0     1
Vout(:,:,4) =
     0     1     0
     1     0     0
Vout(:,:,5) =
     0     1     0
     0     1     0
Vout(:,:,6) =
     0     1     0
     0     0     1
Vout(:,:,7) =
     0     0     1
     1     0     0
Vout(:,:,8) =
     0     0     1
     0     1     0
Vout(:,:,9) =
     0     0     1
     0     0     1
Divakar
  • 218,885
  • 19
  • 262
  • 358
  • @ParagS.Chandakkar Thanks! That's use here is to cut into 3D slices. – Divakar Oct 27 '14 at 21:45
  • @LuisMendo Well I delved into `dec2bin` for a while without success, so switched boats as `de2bi` works easily with numeric arrrays. – Divakar Oct 27 '14 at 22:10
  • @Divakar It should be noted that de2bi is in the Communcations System Toolbox, which is not part of the default MATLAB distribution. – MrAzzaman Oct 27 '14 at 22:30
  • @MrAzzaman That's right! I think I will edit the solution with that info, if I need to make any revision into it. Appreciate your interest in the solutions posted here :) – Divakar Oct 27 '14 at 22:31
  • @LuisMendo Oh I think, I am first calculating the numerals with `some_string - '0'` that I am feeding into `de2bi`. So it's sort of like `de2bi( '5' - '0')`. Hope this makes sense. – Divakar Oct 28 '14 at 04:32