I am using ode45 to solve a system with 4 variables. For each time I execute the code:
[t y] = ode45(#func, tspan, y0);
t will be a one dimensional matrix, while y will be a 2 dimensional matrix, with 4 columns, each of which is the solution for one of the variables in question.
I want to run multiple trials of this, and keep them in a 3D matrix my_y_results and my_t_results. I want to be able to, for example, plot the final value of a certain variable for a particular initial condition, as I change the initial condition. How would I do this?
So, on each iteration of the loop below, I want to place the new values in a new matrix.
for i = 1:1:10
y0 = **some value**
[t_temp, y_temp] = ode45(#func, tspan, y0);
my_t_results = **something**
my_y_results = *something* //your code here
end
Also, how would I access the different values after setting them? For example, to get the last value of the variable y(1) for each of the 10 trials, what code would I use?
Higher dimensions can be accessed similar to the usual row and column dimensions. Let's assume t is Nx1 and y is Nx4, and that we are running M trials (note that each trial will have to have the same number of points, N, in order to store the data in a 3-dimensional array).
Your array my_t_results doesn't have to be 3-dimensional and can simply be NxM, where each column is the time vector for a different trial.
The array my_y_results would be Nx4xM and can be defined in MATLAB with:
my_y_results = zeros(N,4,M);
At the end of each i'th trial you would store the results like this:
my_y_results(:,:,i) = y;
And of course accessing the data is similar:
y_i = my_y_results(:,:,i);
Related
I'm trying to plot a probability mass function for the probability of certain sums when rolling three dices and I found this example in MathCad and wondered if there is anything like it in MatLab?
I imagine you’d build that as a lookup table rather than a series of if/else statements. It is easy to compute the probabilities using convolution:
f1 = ones(1,6);
f2 = conv(f1,f1);
f = conv(f2,f1);
% because f contains values from x=3 to 18,
% rather than starting at 1 as MATLAB arrays do,
% we add two zeros to the front:
f = [0,0,f];
Now f(x) returns the probability of throwing x.
I am still wrapping my head around vectorization and I'm having a difficult time trying to resolve the following function I made...
for i = 1:size(X, 1)
min_n = inf;
for j=1:K
val = X(i,:)' - centroids(j,:)';
diff = val'*val;
if (diff < min_n)
idx(i) = j;
min_n = diff;
end
end
end
X is an array of (x,y) coordinates...
2 5
5 6
...
...
centroids in this example is limited to 3 rows. It is also in (x,y) format as shown above.
For every pair in X I am computing the closest pair of centroids. I then store the index of the centroid in idx.
So idx(i) = j means that I am storing the index j of the centroid at index i, where i corresponds to the index of X. This means the closest centroid to pair X(i, :) is at idx(i).
Can I possibly simplify this via vectorization? I struggle with just vectorizing the inner loop.
Here are three options. But please note that the disadvantage of vectorization, as compared to your double loops, is that it stores all the difference operation results at once, which means that if your matrices have many rows, you might run out of memory. On the other hand, the vectorized approach is probably much faster.
Option 1
If you have access to Statistics and Machine Learning Toolbox, you can use the function pdist2 to get all the pairwise distances between rows of two matrices. Then, the min function gives you the minimum of each column of the result. Its first returned value are the minimal values, and its second are the indices, which is what you need for idx:
diff = pdist2(centroids,X);
[~,idx] = min(diff);
Option 2
If you don't have access to the toolbox, you can use bsxfun. This will let you compute the difference operation between the two matrices even if their dimensions don't agree. All you need to do is to use shiftdim to reshape X' to have size [1,size(X,2),size(X,1)], and then reshapedX and and centroids are compatible with their dimensions (see documentation of bsxfun). This lets you take the difference between their values. The result is a three dimensional array, which you need to sum along the second dimension to get the norm of the differences between rows. At this point you can proceed as in option 1.
reshapedX = shiftdim(X',-1);
diff = bsxfun(#minus,centroids,reshapedX);
diff = squeeze(sum(diff.^2,2));
[~,idx] = min(diff);
Note: Starting in the Matlab version 2016b, the bsxfun is used implicitly and you do not need to call it anymore. So the line with bsxfun can be replaced with the simpler line diff = centroids-reshapedX.
Option 3
Use the function dsearchn, which performs exactly what you need:
idx = dsearchn(centroids,X);
it could be done using pdist2 - pairwise distances between rows of two matrices:
% random data
X = rand(500,2);
centroids = rand(3,2);
% pairwise distances
D = pdist2(X,centroids);
% closest centroid index for each X coordinates
[~,idx] = min(D,[],2)
% plot
scatter(centroids(:,1),centroids(:,2),300,(1:size(centroids,1))','filled');
hold on;
scatter(X(:,1),X(:,2),30,idx);
legend('Centroids','data');
I have a matlab indexing question. I have a vector of 34 elements that I would like to plot in a for loop. However, I do not wish to plot them all at once. It would be great if I were able to plot elements 1:6, then 7:11, then 12:20, and so on. Is it possible to do this type of plotting in a for loop? If it is, I am having trouble with the indexing. Since these elements are all in sequential order, matlab seems to want to plot them all together. Any help would be appreciated. Thanks!
Here is an example of what I am trying to do:
for i = 1: [1:6, 7:11, 12:20]
plot(x(i), y(i))
end
Hopefully, I can get three plot, one with data from elements 1:6, another from elements 7:11, and the last one from elements 12:20.
You can just use a cell to store the variable-length vectors containing the various indices:
x = linspace(0, 1, 20);
y = x;
i_cell = {1:6, 7:11, 12:20};
for i = 1:length(i_cell)
figure
indices = i_cell{i}
plot(x(indices), y(indices))
end
I have two matrices A and B. The size of A is 200*1000 double (here: 1000 represents 1000 different features). Matrix A belongs to group 1, where I use ones(200,1) as the label vector. The size of B is also 200*1000 double (here: 1000 also represents 1000 different features). Matrix B belongs to group 2, where I use -1*ones(200,1) as the label vector.
My question is how do I visualize matrices A and B so that I can clearly distinguish them based on the given groups?
I'm assuming each sample in your matrices A and B is determined by a row in either matrix. If I understand you correctly, you want to draw a series of 1000-dimensional vectors, which is impossible. We can't physically visualize anything beyond three dimensions.
As such, what I suggest you do is perform a dimensionality reduction to reduce your data so that each input is reduced to either 2 or 3 dimensions. Once you reduce your data, you can plot them normally and assign a different marker to each point, depending on what group they belonged to.
If you want to achieve this in MATLAB, use Principal Components Analysis, specifically the pca function in MATLAB, that calculates the residuals and the reprojected samples if you were to reproject them onto a lower dimensionality. I'm assuming you have the Statistics Toolbox... if you don't, then sorry this won't work.
Specifically, given your matrices A and B, you would do this:
[coeffA, scoreA] = pca(A);
[coeffB, scoreB] = pca(B);
numDimensions = 2;
scoreAred = scoreA(:,1:numDimensions);
scoreBred = scoreB(:,1:numDimensions);
The second output of pca gives you reprojected values and so you simply have to determine how many dimensions you want by extracting the first N columns, where N is the desired number of dimensions you want.
I chose 2 for now, and we can see what it looks like in 3 dimensions after. Once we have what we need for 2 dimensions, it's just a matter of plotting:
plot(scoreAred(:,1), scoreAred(:,2), 'rx', scoreBred(:,1), scoreBred(:,2), 'bo');
This will produce a plot where the samples from matrix A are with red crosses while the samples from matrix B are with blue circles.
Here's a sample run given completely random data:
rng(123); %// Set seed for reproducibility
A = rand(200,1000); B = rand(200,1000); %// Generate random data
%// Code as before
[coeffA, scoreA] = pca(A);
[coeffB, scoreB] = pca(B);
numDimensions = 2;
scoreAred = scoreA(:,1:numDimensions);
scoreBred = scoreB(:,1:numDimensions);
%// Plot the data
plot(scoreAred(:,1), scoreAred(:,2), 'rx', scoreBred(:,1), scoreBred(:,2), 'bo');
We get this:
If you want three dimensions, simply change numDimensions = 3, then change the plot code to use plot3:
plot3(scoreAred(:,1), scoreAred(:,2), scoreAred(:,3), 'rx', scoreBred(:,1), scoreBred(:,2), scoreBred(:,3), 'bo');
grid;
With those changes, this is what we get:
I have created a X-by-Y matrix . Multiplies each element of the matrix with the X(length) and Y(breadth) which generates a rectangular matrix(This is done in order to plot the points throughout the length and breadth of the matrix).
But I am not able to store all the values generated from the for loop into y and x.
1) Kindly please tell me how to store the values into a single variable in the below program
2) And I am not able to plot two unequal dimensions which are generated after the operations are performed in the below program.
X=input('enter the dimension of the matrix:');
Y=input('enter the dimension of the matrix:');
a=rand(X,Y)
for i=1:X
x=a(i,:)
px=x.*X
end
for j=1:Y
y=a(:,j)
py=y.*Y
end
Each iteration of your "for" loops overwrites x, px, y, and py with new values, so it drops all of the old values. To be honest, I wouldn't even bother with the for loops. Assuming that what you really need is px and py, I would just do this-
px = a * X;
py = a * Y;
There are a number of MATLAB functions that could be used to get a matrix with random values.
randi(maxi, X, Y) looks like the one more useful here.
Get ride of the for loops:
X=input('enter the dimension of the matrix:');
Y=input('enter the dimension of the matrix:');
maxi = 100;
a=randi(maxi,X,Y);
and if you want to visualize it do:
imagesc(a);