This question already has answers here:
Index Exceeds Dimensions/Nested For loop issues
(2 answers)
Closed 9 years ago.
I am using a nested for loop to do the following functions:
I am going column by column in a TranLog matrix (W X N size) and finding which row has a non zero value
Based upon the row location of this non-zero Value in TranLog, I am calling the vector associated with that row # in the matrix Order.
The for loop is as follows:
for jj=1:W;
for ii=1:N;
if TranLog(ii,jj)>0.5
test=Order(ii,:);
end
end
end
When I am running this the number of vectors output are smaller than it should be. For example: If Tranlog is 23X5 and Order is 23X6, if there are 23 non zeros spread throughout the TranLog matrix (there is one non-zero value per row in TranLog) I am only getting 13 ouput vectors from the Order matrix. I am not sure why this isn't running to completion, I don't receive an error but it doesnt ouput as many vectors as I am expecting.
Here's the problem. Your matrix has W rows and N columns, yet the W index, jj, is indexing columns rather than rows in line 3. The opposite is happening with ii, the index of N. Switch those around and you should be good to go!
for jj=1:W;
for ii=1:N;
if TranLog(jj,ii)>0.5
test=Order(ii,:);
end
end
end
Related
This question already has answers here:
Random order of rows Matlab
(4 answers)
Closed 7 years ago.
So, I have a matrix called matrix1 (dimensions = 1280x5, with each element being a number). I have another matrix, called matrix2, which has the same dimensions and contains all zeros). Here's what I want to do: randomly select one row from matrix1 WITHOUT REPLACEMENT and insert it into row one of matrix2. The next randomly selected row from matrix1 would go in row 2 of matrix 2, and so on until all 1280 rows of matrix1 have been moved to matrix 2. Notably, I want all of this to happen using a for loop with 1280 iterations. On each iteration, 1 row from matrix will be selected at random without replacement and put into matrix 2. Please let me know if you have any suggestions.
Thanks!
G
You can do that with the proper indexing for the rows:
idx = randperm(size(mat1,1)); %// Random row index
mat2 = mat1(idx, :);
I have a 5-by-200 matrix where the i:50:200, i=1:50 are related to each other, so for example the matrix columns 1,51,101,151 are related to each other, and columns 49,99,149,199 are also related to each other.
I want to use a for-loop to create another matrix that re-sorts the previous matrix based on this relationship.
My code is
values=zeros(5,200);
for j=1:50
for m=1:4:200
a=factor_mat(:,j:50:200)
values(:,m)=a
end
end
However, the code does not work.
Here's what's happening. Let's say we're on the first iteration of the outer loop, so j == 1. This effectively gives you:
j = 1;
for m=1:4:200
a=factor_mat(:,j:50:200)
values(:,m)=a;
end
So you're creating the same submatrix for a (j doesn't change) 50 times and storing it at different places in the values matrix. This isn't really what you want to do.
To create each 4-column submatrix once and store them in 50 different places, you need to use j to tell you which of the 50 you're currently processing:
for j=1:50
a=factor_mat(:,j:50:200);
m=j*4; %// This gives us the **end** of the current range
values(:,m-3:m)=a;
end
I've used a little trick here, because the indices of Matlab arrays start at 1 rather than 0. I've calculated the index of the last column we want to insert. For the first group, this is column 4. Since j == 1, j * 4 == 4. Then I subtract 3 to find the first column index.
That will fix the problem you have with your loops. But loops aren't very Matlab-ish. They used to be very slow; now they're adequate. But they're still not the cool way to do things.
To do this without loops, you can use reshape and permute:
a=reshape(factor_mat,[],50,4);
b=permute(a,[1,3,2]);
values=reshape(b,[],200);
I am working on 2D rectangular packing. In order to minimize the length of the infinite sheet (Width is constant) by changing the order in which parts are placed. For example, we could place 11 parts in 11! ways.
I could label those parts and save all possible permutations using perms function and run it one by one, but I need a large amount of memory even for 11 parts. I'd like to be able to do it for around 1000 parts.
Luckily, I don't need every possible sequence. I would like to index each permutation to a number. Test a random sequence and then use GA to converge the results to find the optimal sequence.
Therefore, I need a function which gives a specific permutation value when run for any number of times unlike randperm function.
For example, function(5,6) should always return say [1 4 3 2 5 6] for 6 parts. I don't need the sequences in a specific order, but the function should give the same sequence for same index. and also for some other index, the sequence should not be same as this one.
So far, I have used randperm function to generate random sequence for around 2000 iterations and finding a best sequence out of it by comparing length, but this works only for few number of parts. Also using randperm may result in repeated sequence instead of unique sequence.
Here's a picture of what I have done.
I can't save the outputs of randperm because I won't have a searchable function space. I don't want to find the length of the sheet for all sequences. I only need do it for certain sequence identified by certain index determined by genetic algorithm. If I use randperm, I won't have the sequence for all indexes (even though I only need some of them).
For example, take some function, 'y = f(x)', in the range [0,10] say. For each value of x, I get a y. Here y is my sheet length. x is the index of permutation. For any x, I find its sequence (the specific permutation) and then its corresponding sheet length. Based on the results of some random values of x, GA will generate me a new list of x to find a more optimal y.
I need a function that duplicates perms, (I guess perms are following the same order of permutations each time it is run because perms(1:4) will yield same results when run any number of times) without actually storing the values.
Is there a way to write the function? If not, then how do i solve my problem?
Edit (how i approached the problem):
In Genetic Algorithm, you need to crossover parents(permutations), But if you crossover permutations, you will get the numbers repeated. for eg:- crossing over 1 2 3 4 with 3 2 1 4 may result something like 3 2 3 4. Therefore, to avoid repetition, i thought of indexing each parent to a number and then convert the number to binary form and then crossover the binary indices to get a new binary number then convert it back to decimal and find its specific permutation. But then later on, i discovered i could just use ordered crossover of the permutations itself instead of crossing over their indices.
More details on Ordered Crossover could be found here
Below are two functions that together will generate permutations in lexographical order and return the nth permutation
For example, I can call
nth_permutation(5, [1 2 3 4])
And the output will be [1 4 2 3]
Intuitively, how long this method takes is linear in n. The size of the set doesn't matter. I benchmarked nth_permutations(n, 1:1000) averaged over 100 iterations and got the following graph
So timewise it seems okay.
function [permutation] = nth_permutation(n, set)
%%NTH_PERMUTATION Generates n permutations of set in lexographical order and
%%outputs the last one
%% set is a 1 by m matrix
set = sort(set);
permutation = set; %First permutation
for ii=2:n
permutation = next_permute(permutation);
end
end
function [p] = next_permute(p)
%Following algorithm from https://en.wikipedia.org/wiki/Permutation#Generation_in_lexicographic_order
%Find the largest index k such that p[k] < p[k+1]
larger = p(1:end-1) < p(2:end);
k = max(find(larger));
%If no such index exists, the permutation is the last permutation.
if isempty(k)
display('Last permutation reached');
return
end
%Find the largest index l greater than k such that p[k] < p[l].
larger = [false(1, k) p(k+1:end) > p(k)];
l = max(find(larger));
%Swap the value of p[k] with that of p[l].
p([k, l]) = p([l, k]);
%Reverse the sequence from p[k + 1] up to and including the final element p[n].
p(k+1:end) = p(end:-1:k+1);
end
I have a matrix rel nx8 and a second matrix mx3. I want to check if column 3 of matrix rel contains an 8. If yes, I pass to the second condition: if column 3 of matrix rel is equal to to column 2 of matrix A, go to the third condition and create two additional columns in matrix A with the elements of columns 7 and 8 of matrix rel.
n=size(rel)
m=length(A)
for i=1:n
for k=1:m
if rel(i,4)==8
if rel(i,3)==A(k,2)
if (rel(i,2)== A(k,1)) || (rel(i,1)== A(k,1))
A(k,4)=rel(i,7);
A(k,5)=rel(i,8);
end
end
end
i=i+1
end
end
However I get this message error: Attempted to access rel(9508,4); index out of bounds because size(rel)=[9507,8].
Does anybody know how could I fix it?
It is because you are iterating your variable i inside of your k for loop. So when you arrive in your k loop you are stepping up your original i from the first loop to i+m. This is the source of your error, as i+m becomes greater than n.
To see this, gut out your if statements, set n and m to some reasonable values (like 2 and 3) and just run the loops, keeping track of what happens to i.
I have made a simulation and the result each time of the simulation is a matrix and i choose a certain row from the matrix, so if the simulation run=500, i'll have a 500 matrix and ,the row i choose each time will be (at the end of the simulation) 500 rows [one row from the first matrix...last row from the last matrix]...
the problem is some times a matrix dose not contain the certain row i want , the answer is for example empty matrix: 0-by-6
i want to ignor this answer
Note: the row i choose is not necessary to be exist in all matrices
so if the run=600 , result in 600 matrix , the row i choose maybe =400 only and the other 200 will be zero
the simulation STOP when the result is empty matrix: 0-by-any number
I use Matlab
you can use isempty to detect empty arrays, for example
a=zeros(0,5)
isempty(a)
a =
Empty matrix: 0-by-5
ans =
1
For when the index exceeds matrix dimensions, you can add a condition that tests the size of your matrix, specifically, how man rows using size(m,1)
So all together, in your for loop you can code something like:
for n=1:blah
if ~isempty(M) % continue if matrix is non-empty
if size(M,1)<=n % continue if index doesn't exceeds matrix dimensions
....
....