MATLAB: Step through iterations of a vector - matlab

all.
I have a 15 element array = [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15];.
I was wondering if there was a command such that it would step through iterations of the array without repeating itself. In other words, since there is a chance that randperm() will create the same matrix twice, I want to step through each permutation only once and perform a calculation.
I concede that there are factorial(15) permutations, but for my purposes, these two vectors (and similar) are identical and don't need to be counted twice:
[1 2 3 4 5 6 7 8 9 10 11 12 13 14 15]
[15 14 13 12 11 10 9 8 7 6 5 4 3 2 1]
Thus, is there any way to step through this?
Thanks.

I think what you are looking for is perms. randperm returns a single random permutation, you want all the permutations.
So use
my_permuations = perms([1:15]);
If forward-backward is the same as backward-foward then you can use the top half of the list only...
my_permutation_to_use = my_permutations(1:length(my_permutations)/2, :);

You may compare all permutations, but this would require to store all past permutations. Instead a local decision is better. I recommend this simple rule:
A permutation is valid, if the first element is smaller than the last element.
A permutation is redundant, if the first element is larger than the last element.
For small sizes, this could simply be done with this code:
%generate all permutations
x=perms(1:10)
%select only the valid lines, remove all redundant lines
x(x(:,1)<x(:,end),:)
Remains the problem, that generating x for 1:15 breaks all memory limits and would require about 100h.

Related

Generate a matrix containing all possible numbers

I am trying to achieve multiple matrices that will cover the full set of numbers. For example say I want to generate 5 matrices of length 10 that cover all the numbers from 1-20.
So matrix one will contain half the numbers say
m1 = [1 2 3 4 5 6 7 8 9 10];
while matrix two contains
m2 = [11 12 13 14 15 16 17 18 19 20];
Although this satisfies my condition with only two matrices not 5, I preferably need to generate all matrices randomly. Other than randomly generating the matrices and checking all values are generated is there a more efficient way to do this?
You can do it like that:
>> l=[1:20,randi(20,1,30)];
>> vec=l(randperm(length(l)));
>> v=reshape(vec,5,10);
The first line generates an array of 50 numbers from 1 to 20. It guarantees that each such number appears at least once. The second line randomizes the order of the numbers. The third line reshapes the vector into an array of arrays (that is, a 2D matrix, where each row is one of the arrays).

reshape four dimensional matrix

I have some problems using reshape. I want to reshape a 4-dimensional matrix, and the fourth dimension has to become a column.
so if I have:
A(:,:,1,1) =
1 4
2 5
A(:,:,2,1) =
2 5
3 6
A(:,:,1,2) =
10 14
12 15
A(:,:,2,2) =
12 15
13 16
My reshape should be:
Columns 1 through 5
1 4 2 5 2
10 14 12 15 12
Columns 6 through 8
5 3 6
15 13 16
This should work:
reshape(permute(A,[1 4 2 3]),[2 8])
To understand this, you can go step by step. First do the following:
reshape(A,[2 8])
ans =
1 2 2 3 10 12 12 13
4 5 5 6 14 15 15 16
You observe that the columns of the reshaped matrix are taken by sliding across the second dimension in the original matrix. After second dimension is over, you slide over to third dimension and the re-iterate over second dimension (here first dimension is rows, second is column, so on...).
What you want to do is, iterate over 4th dimension (as if its a second dimension). You also want (4,14) after (1,10). You can see that corresponding elements vary across second dimension (but reshape is going to slide over third dimension, no matter what. So swap 2nd and 3rd dimensions).
Finally, you get, reshape(permute(A,[1 4 2 3]),[2 8]).
I have always had a hard time explaining permute to somebody. I hope I didn't confuse you more.
You're going to have to do a permutation first to put the dimensions in the appropriate order. Try this:
reshape(permute(A,[4,2,1,3]),[2,8])
or break it up into two separate permutations, one to switch dimensions 1 and 2 in the original array, then reshape to 8x2, then take the transpose:
reshape(permute(A,[2,1,3,4]),[8,2])'

How Matlab extract a subset of a bigger matrix by specifying the indices?

I have a matrix A
A =
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
16 17 18 19 20
i have another matrix to specify the indices
index =
1 2
3 4
Now, i have got third matrix C from A
C = A(index)
C =
1 6
11 16
Problem: I am unable to understand how come i have received such a matrixC. I mean, what is logi behind it?
The logic behind it is linear indexing: When you provide a single index, Matlab moves along columns first, then along rows, then along further dimensions (according to their order).
So in your case (4 x 5 matrix) the entries of A are being accessed in the following order (each number here represents order, not the value of the entry):
1 5 9 13 17
2 6 10 14 18
3 7 11 15 19
4 8 12 16 20
Once you get used to it, you'll see linear indexing is a very powerful tool.
As an example: to obtain the maximum value in A you could just use max(A(1:20)). This could be further simplified to max(A(1:end)) or max(A(:)). Note that "A(:)" is a common Matlab idiom, used to turn any array into a column vector; which is sometimes called linearizing the array.
See also ind2sub and sub2ind, which are used to convert from linear index to standard indices and vice versa.

Accessing indexes as first columns of matrix in Matlab

I have data that is output from a computational chemistry program (Gaussian09) which contains sets of Force Constant data. The data is arranged with indexes as the first 2-4 columns (quadratic, cubic and quartic FC's are calculated). As an example the cubic FC's look something like this, and MatLab has read them in successfully so I have the correct matrix:
cube=[
1 1 1 5 5 5
1 1 2 6 6 6
.
.
4 1 1 8 8 8
4 2 1 9 9 9
4 3 1 7 7 7 ]
I need a way to access the last 3 columns when feeding in the indices of the first 3 columns. Something along the lines of
>>index=find([cube(:,1)==4 && cube(:,2)==3 && cube(:,3)==1]);
Which would give me the row number of the data that is index [ 4 3 1 ] and allow me to read out the values [7 7 7] which I need within loops to calculate anharmonic frequencies.
Is there a way to do this without a bunch of loops?
Thanks in advance,
Ben
You have already found one way to solve this, by using & in your expression (allowing you to make non-scalar comparisons).
Another way is to use ismember:
index = find(ismember(cube(:,1:3),[4 3 1]));
Note that in many cases, you may not even need the call to find: the binary vector returned by the comparisons or ismember can directly be used to index into another array.

How can I flatten every n rows in matrix using Matlab?

I can easily flatten an entire matrix into one row using reshape(M,1,[]). However, this time I want to flatten every n rows into one row. Thus, if we start with 100 rows and n=10, we will end up with 10 rows.
e.g.
1 2 3
4 5 6
7 8 9
10 11 12
with n=2 changes into
1 2 3 4 5 6
7 8 9 10 11 12
Is there a simple way to do this?
Suppose your original matrix is m, then:
reshape(m',[6 2])'
produces the required output. I'll leave it to you to generalise to other cases; comment or post again if that causes you problems.
This should work.
reshape(M',l/n,n)'
Where n is what you've defined and l is the total elements in M.
EDIT: Made it one-liner