nth permutation of a vector in MATLAB - matlab

Suppose I have a vector of integers like this:
A = [1 2 3]
What I need is nth permutation of vector A. As we now a vector of n numbers has n! permutation, For example some permutation of A is:
[1 2 3]
[1 3 2]
[2 1 3]
[2 3 1]
...
Is there any built-in function for calculating nth permutation? if not, can anyone please offer me a efficient algorithm for calculate it? Any suggestion would be highly appreciated

I found my answer from #Divakar comment (special thanks to #Divakar)
What I need is:
% this my vector 1, 2, 3 , ..., N
A = 1 : N;
P = perms(A);
% nth permutation of A is nth row of P
nthPerm = P(n, :);

If A is just the trivial sequence 1:N, as #Divakar said, the command
perms(1:N)
produces the permutations you need.
If A is an array whose content is generic and whose length is N, perms can be used to obtain the indices allowing the permutations, i.e.
A_permutations = A(perms(1:N))
Example:
given
A =
3 7 9
A(perms(1:3))
9 7 3
9 3 7
7 9 3
7 3 9
3 7 9
3 9 7

perms(v) works for the n! case,
http://www.mathworks.de/matlabcentral/fileexchange/11462-npermutek/content/npermutek.m
works for the n^n or n^k case.

If you like doing stuff in less lines of code, you can also do:
A=1:N;
nthPerm=getfield(perms(A),{n,A})
Note that this is only valid if A=1,2,3,...,N. For different values of A, you would have to change this into:
A=1:N;
nthPerm=getfield(perms(A),{n,1:length(A)})

Related

Calculate the first N terms of a geometric sequence in Matlab [duplicate]

This question already has answers here:
Common way to generate finite geometric series in MATLAB
(2 answers)
Closed 7 years ago.
How to calculate the first N terms of the geometric sequence Un = 2^n in Matlab?
Are there any Matlab functions that I'm not aware of to facilitate this? or do I have to pick a math book to understand this and implement it in a for loop or something?
Any links to similar Matlab code would be appreciated, or if you could explain it for me that would be appreciated!
First, you set the N terms for your sequence, i.e.:
N = 10 %//set first 10
Now you want to make a vector from 1 to N, i.e.:
n= [1:N]
Un = 2.^n %//Note the dot is very important! I almost forgot
%//ans = [2,4,8,16...1024]
This would make function a vector of 1 by N where each element is the corresponding answer to your function.
for your second question (in comment)
you want to do something like:
Bflip = B' %//This flips the matrix B so that what use to be column is now rows
So Bflip would be the result you want, I tested with your example:
A = [2 2 2;4 4 4; 6 6 6];
B = [0 0 0; 1 1 1; 2 2 2];
Bflit = [ 0 1 2
0 1 2
0 1 2]
This will generate a 3 dimension matrix. To call on each of the 4 sets of results, just do something like result1 = permutation(:,:,1)

How to do rank-1 factorization in MATLAB?

I have a matrix M of dimensions 6x6 and it has rank 1. How can I factorize it into two matrices of dimensions 6x1 (say A) and 1x6 (say B) so that M=A*B.
take the largest eigen vector and multiply it by the largest eigenvalue :
A=[1 2 3 4]'*[1 2 3 4]
A =
1 2 3 4
2 4 6 8
3 6 9 12
4 8 12 16
[v,e] = eigs(A,1);
sqrt(e)*v
ans =
-1.0000
-2.0000
-3.0000
-4.0000
of course, the result is good only up to a sign change.
EDIT:
if you assume that the two vectors can be different:
A=[1 2 3 4]'*[5 6 7 8]
[uu,ss,vv]=svd(A);
u=uu(:,1)*ss(1,1)
v=vv(:,1)
assert(norm(u*v'-A)<1E-10)
Now the solution is even less unique. You are determining 2*n values based on only n. This is one solution among many.
For example, look at this other even simpler solution (which will assume your matrix is perfectly rank 1) :
aa=A(:,:)./repmat(A(1,:),[size(A,1),1]);
bb=A(:,:)./repmat(A(:,1),[1,size(A,2)]);
u=aa(:,1);
v=bb(1,:)'*A(1);
assert(norm(u*v'-A)<1E-10)
it produces a totally different result, but that still factorizes the matrix. If you want non-negative factorizations only to slightly reduce the space of possible results, I'd suggest you ask a new question!
If it has rank 1, then all columns/rows are multiples of the first column/row (or indeed of any non-zero column/row). i.e.:
m = M(:,1);
M = [ a*m, b*m, c*m, d*m, e*m, f*m ];
Hopefully you can take it from there.

How does "/" really work on two row vectors?

I have the following basic observation:
[1 2 3 4]/[2 4 6 8] % output: 0.5
[1 2 3 4]/[2 3 4 5] % output: 0.7407
([1 2 3 4]*[2 4 6 8] % error of course)
It does not look for me as A*inv(B) kind of operation (nor like mrdivide on timeseries which would work like [1 2 3 4]./[2 4 6 8] if Im not mistaken).
Now, my question is, what operation does "/" define on two row vectors with the same length?
UPDATE:
#user1884905 gave the idea that a/b on two row vectors might minimise norm(b*x - a). So far it seemed to work on some numeric tests. If it is true, can you give some official reference behind this please?
Yes, it seems I was right. From MathWorks mrdivide
"If A is a rectangular m-by-n matrix with m ~= n, and B is a row vector with n elements or a matrix with n columns, then x = B/A returns a least-squares solution of the system of equations x*A = B."

Extract fixed amounts of data from array based on a list of indices

I have the array
a=1:20
and a series of indices which indicate where I want to start pulling data out:
i=[4,12]
For each index i, I want that index and the next four (well, x, really) elements in a column or row. I'll avoid getting to close to the end of the array, so that special case can be disregarded.
If I was hard-coding this, I could use:
a([4:8;12:16])
and this would achieve my result.
But i may have many different values.
Any thoughts on how I can transform a list of indices into a matrix of ranges, or other ways to solve this problem?
EDIT
I am using Matlab 2007; it would be preferable if the solution relied solely on Matlab's internals and toolboxes. bsxfun is not present until 2007a.
Let i be your indicesx and x the number of elements you want in addition to the elements in i, then you can use
i = [4 6 8];
x = 4;
bsxfun(#plus, 0:x, i(:))
to get a matrix of indices:
ans =
4 5 6 7 8
6 7 8 9 10
8 9 10 11 12
If you do not have access to bsxfun you can use repmat instead:
i = [4 6 8];
x = 4;
repmat(i(:), 1, x+1) + repmat(0:x, length(i), 1)
Here is a solution without bsxfun but with repmat inspired by the previous answer.
i = [4 6 8];
x = 4;
p = repmat(1:x,length(i),1);
q = repmat(i',1,x);
p+q

How to efficiently access/change one item in each row of a matrix

I have a matrix A with size (nr,nc), a vector of column indices B (so B has size (nr,1) and every element in B is an integer between 1 and nc), and I want to do something to every element in A that is of the form A(i,B(i)) for i between 1 and nr, efficiency being the key concern.
For concreteness, say C is a vector of size (nr,1), the goal is to do
for i=1:nr
A(i,B(i))=A(i,B(i))+C(i)
end
more efficiently. The context is usually that nr>>nc (because when nr is large vectorization is efficient for many operations). I have gotten a factor 3 speedup by using an indicator function approach:
for k=1:nc
A(:,k)=A(:,k)+(k==B).*C
end
Are there other ways (more efficient hopefully) to do this?
I guess this is similar to many questions on double-indexing, but it's concretely one I run into all the time.
Use linear indexing:
idx = sub2ind(size(A), 1:nr, B');
A(idx) = A(idx) + C';
or (edited version with one less transpose)
idx = sub2ind(size(A), (1:nr)', B);
A(idx) = A(idx) + C;
One way would be to use linear indexing of the matrix. You will need a vector v holding the offsets of the first element in each line, then index using A(v + B). For example:
>A=[1 2 3; 4 5 6; 7 8 9]
A =
1 2 3
4 5 6
7 8 9
>B = [1 2 3] % we want the 1st element of row 1, 2nd of row 2, 3rd of row 3
>ii = [0 3 6] + B
>a(ii)
1 5 9
Note: As groovingandi had shown, it is also possible (and more readable) to use sub2ind to generate the ii linear indices vector. The idea is essentially the same.