I'm pretty rusty with Matlab programming and I'm stuck writing a for loop. I want to generate n random numbers using the formula x(i+1)=mod(a*x(i), m);
What I have is
for i=1:n
x(i+1)=mod(a*x(i),m);
end
What I don't know, is
How do I set x?
Once I set x, would the index be correct?
You should preallocate x for a case like this. Given your for loop, the minimum index is 1 and maximum index is n+1 so x needs to be a vector with n+1 elements. You could use zeros, for example:
x = zeros(n+1,1); % An n+1 by 1 column vector
It looks like you should also set the value of x(1) to some kind of initial value too. Your for loop is effectively a recurrence relation where the i+1-th value of x depends on the i-th value.
Related
Please correct me if there are somethings unclear in this question. I have two matrices pop, and ben of 3 dimensions. Call these dimensions as c,t,w . I want to repeat the exact same process I describe below for all of the c dimensions, without using a for loop as that is slow. For the discussion below, fix a value of the dimension c, to explain my thinking, later I will give a MWE. So when c is fixed I have a 2D matrix with dimension t,w.
Now I repeat the entire process (coming below!) for all of the w dimension.
If the value of u is zero, then I find the next non zero entry in this same t dimension. I save both this entry as well as the corresponding t index. If the value of u is non zero, I simply store this value and the corresponding t index. Call the index as i - note i would be of dimension (c,t,w). The last entry of every u(c,:,w) is guaranteed to be non zero.
Example if the u(c,:,w) vector is [ 3 0 4 2 0 1], then the corresponding i values are [1,3,3,4,6,6].
Now I take these entries and define a new 3d array of dimension (c,t,w) as follows. I take my B array and do the following what is not a correct syntax but to explain you: B(c,t,w)/u(c,i(c,t,w),w). Meaning I take the B values and divide it by the u values corresponding to the non zero indices of u from i that I computed.
For the above example, the denominator would be [3,4,4,2,1,1]. I hope that makes sense!!
QUESTION:
To do this, as this process simply repeats for all c, I can do a very fast vectorizable calculation for a single c. But for multiple c I do not know how to avoid the for loop. I don't knw how to do vectorizable calculations across dimensions.
Here is what I did, where c_size is the dimension of c.
for c=c_size:-1:1
uu=squeeze(pop(c,:,:)) ; % EXTRACT A 2D MATRIX FROM pop.
BB=squeeze(B(c,:,:)) ; % EXTRACT A 2D MATRIX FROM B
ii = nan(size(uu)); % Start with all nan values
[dum_row, ~] = find(uu); % Get row indices of non-zero values
ii(uu ~= 0) = dum_row; % Place row indices in locations of non-zero values
ii = cummin(ii, 1, 'reverse'); % Column-wise cumulative minimum, starting from bottomi
dum_i = ii+(time_size+1).*repmat(0:(scenario_size-1), time_size+1, 1); % Create linear index
ben(c,:,:) = BB(dum_i)./uu(dum_i);
i(c,:,:) = ii ;
clear dum_i dum_row uu BB ii
end
The central question is to avoid this for loop.
Related questions:
Vectorizable FIND function with if statement MATLAB
Efficiently finding non zero numbers from a large matrix
Vectorizable FIND function with if statement MATLAB
suppose that we have some vector y in matlab and let us suppose that there is such linear relationship between values of y
of course first vector can be easily implemented by
y(L:N-1), but related to matrix, we dont have index y[0] in matlab, so how can i solve this issue? there is another picture
should i use index y1 and instead of index y(l-1),start from y(l)?
Your equation is zero-based, while Matlab is one-based in terms of array indexing. Therefore, the best solution is to add 1 every index in the equation: the vector on the left hand side runs from L+1:N, instead of L:N-1, and the elements in the matrix from 1 to L or N-L (whichever is larger), instead of 0 to L-1 or N-L-1.
Let I have a vector x in Matlab of size 1000. I want to produce a vector y of length 10 where each component contains the average of 100 records from the vector x.
My attempt is quite simple
for i=1:10
y(i) = mean(x((1:100)+(i-1)*100));
end
I wonder if there is a build in command or more elegant solution for this.
You can use the reshape-function to generate a 2d-array and then calculate the mean over the correct dimension.
This works as replacement for your loop:
y = mean(reshape(x,[100,10]),1);
Note: It does not matter if x is a column-vector or a row-vector.
I have a Matrix M and I want to run a loop in Matlab whereby the loop variables i,j run through all M(i,j). Can someone provide the syntax please?
First you should first look whether there is a way you could do something using vector operations rather than loops, this is Matlab's strength and usually runs faster. However, if you need to use loops (which sometimes you cannot get around), there are two ways you could do this, the first is to use a single indexing variable (numel is the number of elements in the matrix), this goes through the matrix column by column.
for i = 1:numel(M)
M(i) = %your code here
end
or through each row and column the way you specified (size(M, n) where n is an integer is the size of the nth dimension (1st is number of rows, 2nd is number of columns, 3rd is the number of levels, ...))
for i = 1:size(M, 1)
for j = 1:size(M, 2)
M(i, j) = %your code here
end
end
Please see the following issue:
P=rand(4,4);
for i=1:size(P,2)
for j=1:size(P,2)
[r,p]=corr(P(:,i),P(:,j))
end
end
Clearly, the loop will cause the number of correlations to be doubled (i.e., corr(P(:,1),P(:,4)) and corr(P(:,4),P(:,1)). Does anyone have a suggestion on how to avoid this? Perhaps not using a loop?
Thanks!
I have four suggestions for you, depending on what exactly you are doing to compute your matrices. I'm assuming the example you gave is a simplified version of what needs to be done.
First Method - Adjusting the inner loop index
One thing you can do is change your j loop index so that it only goes from 1 up to i. This way, you get a lower triangular matrix and just concentrate on the values within the lower triangular half of your matrix. The upper half would essentially be all set to zero. In other words:
for i = 1 : size(P,2)
for j = 1 : i
%// Your code here
end
end
Second Method - Leave it unchanged, but then use unique
You can go ahead and use the same matrix like you did before with the full two for loops, but you can then filter the duplicates by using unique. In other words, you can do this:
[Y,indices] = unique(P);
Y will give you a list of unique values within the matrix P and indices will give you the locations of where these occurred within P. Note that these are column major indices, and so if you wanted to find the row and column locations of where these locations occur, you can do:
[rows,cols] = ind2sub(size(P), indices);
Third Method - Use pdist and squareform
Since you're looking for a solution that requires no loops, take a look at the pdist function. Given a M x N matrix, pdist will find distances between each pair of rows in a matrix. squareform will then transform these distances into a matrix like what you have seen above. In other words, do this:
dists = pdist(P.', 'correlation');
distMatrix = squareform(dists);
Fourth Method - Use the corr method straight out of the box
You can just use corr in the following way:
[rho, pvals] = corr(P);
corr in this case will produce a m x m matrix that contains the correlation coefficient between each pair of columns an n x m matrix stored in P.
Hopefully one of these will work!
this works ?
for i=1:size(P,2)
for j=1:i
Since you are just correlating each column with the other, then why not just use (straight from the documentation)
[Rho,Pval] = corr(P);
I don't have the Statistics Toolbox, but according to http://www.mathworks.com/help/stats/corr.html,
corr(X) returns a p-by-p matrix containing the pairwise linear correlation coefficient between each pair of columns in the n-by-p matrix X.