Plotting logistic map - matlab

I am currently trying to plot f(x) = r*x*(1-x) (where r =3) and y=x on the same graph by using:
syms r x;
f = symfun(r*x*(1-x), x)
r = 3
plot(f,x)
plot(x,x)
But my code keeps resulting in the error:
Error using plot
A numeric or double convertible argument is expected
Please can someone help point out where I am going wrong.

The error's pretty clear: pass a numeric argument to plot. You're feeding it a symbolic function. Just use
r = 3;
x = 0:0.1:10; %// set some x
f = (r.*x.*(1-x)); %// dots make the multiplication element-wise
figure; %// opens figure
hold on %// plots multiple things in one figure
plot(f,x)
plot(x,x,'r') %// produces a red plot

Related

Using Surf and Peaks for non square Matrices

Im trying to use meshgrid with peak. When I use square matrices like:
[x,y] = meshgrid(1:10,1:10)
z = peaks(10)
surf(x,y,z)
Everything works fine.
However, when I use Non square matrices:
[x,y] = meshgrid(-30000:500:0,10:500);
z = peaks(?)
surf(x,y,z)
Im getting the following error:
Data dimensions must agree.
Any idea how to make it work?
Thank you.
When you plot a function using surf the variables you pass it must all be the same size. Although you are changing the x and y matrices to non-square matrices, you are not creating a correspondingly sized z matrix. If you look at the documentation for peaks, this tells you that this function can only produce square outputs, which complicates things somewhat. I would suggest that you try to plot some other example function instead.
If you absolutely must plot the peaks function, you could use some kind of interpolation:
x = 1:10;
y = 1:10;
[x_mesh, y_mesh] = meshgrid(x,y);
z = peaks(10);
x2 = 1:0.1:10;
y2 = 1:0.5:10;
[x2_mesh, y2_mesh] = meshgrid(x2, y2);
z2 = interp2(x_mesh, y_mesh, z, x2_mesh, y2_mesh);
surf(x2_mesh, y2_mesh, z2);
This gives me the following plot:

3d-plotting surface 2x^2 + 3y^2 + z^2 = 6

I was trying to plot the above surface in octave/matlab and ran into the this problem.
My code is as follows:
x = linspace(-sqrt(3),sqrt(3),1000);
y = linspace(-sqrt(2),sqrt(2),1000);
z = sqrt(6-2*x.^2-3*y.^2);
surf(x,y,z)
I got the error:
error: mesh: X, Y, Z arguments must be real.
I understand this was because some (x,y)s would result in negative 6-2*x.^2-3*y.*2, but I don't know how to tackle this because I can't trim either part of x or y. Any one can help? Thanks
It depends what you want to do with the non-real values of z.
One thing you could do is to set all these values to zero or NaN (as per #hbaderts' comment):
z = sqrt(6-2*x.^2-3*y.^2);
z( imag(z)~=0 ) = NaN;
One more thing though: your code might have a problem because z is a length-1000 vector, and you want it to be a 1000x1000 matrix. You should use meshgrid() on x and y to get two-dimensional matrices everywhere:
x = linspace(-sqrt(3),sqrt(3),1000);
y = linspace(-sqrt(2),sqrt(2),1000);
[xx,yy] = meshgrid(x,y);
z = sqrt(6-2*xx.^2-3*yy.^2);
z( imag(z)~=0 ) = NaN;
surf(xx,yy,z,'edgecolor','none')
(thanks #LuisMendo for the 'edgecolor','none' suggestion for better visualization.)
Running the above piece of code on octave gives this plot:

Plot symbolic equation using standard plot function in Matlab

In order to obtain a graphical representation of the behaviour of a fluid it is common practice to plot its streamlines.
For a given two-dimensional fluid with speed components u = Kx and v = -Ky (where K is a constant, for example: K = 5), the streamline equation can be obtained integrating the flow velocity field components as follows:
Streamline equation: ∫dx/u = ∫dy/v
The solved equation looks like this: A = B + C (where A is the solution of the first integral, B is the solution of the second integral and C is an integration constant).
Once we have achieved this, we can start plotting a streamline by simply assigning a value to C, for example: C = 1, and plotting the resulting equation. That would generate a single streamline, so in order to get more of them you need to iterate this last step assigning a different value of C each time.
I have successfully plotted the streamlines of this particular flow by letting matlab integrate the equation symbolically and using ezplot to produce a graphic as follows:
syms x y
K = 5; %Constant.
u = K*x; %Velocity component in x direction.
v = -K*y; %Velocity component in y direction.
A = int(1/u,x); %First integral.
B = int(1/v,y); %Second integral.
for C = -10:0.1:10; %Loop. C is assigned a different value in each iteration.
eqn = A == B + C; %Solved streamline equation.
ezplot(eqn,[-1,1]); %Plot streamline.
hold on;
end
axis equal;
axis([-1 1 -1 1]);
This is the result:
The problem is that for some particular regions of the flow ezplot is not accurate enough and doesn't handle singularities very well (asymptotes, etc.). That's why a standard "numeric" plot seems desirable, in order to obtain a better visual output.
The challenge here is to convert the symbolic streamline solution into an explicit expression that would be compatible with the standard plot function.
I have tried to do it like this, using subs and solve with no success at all (Matlab throws an error).
syms x y
K = 5; %Constant.
u = K*x; %Velocity component in x direction.
v = -K*y; %Velocity component in y direction.
A = int(1/u,x); %First integral.
B = int(1/v,y); %Second integral.
X = -1:0.1:1; %Array of x values for plotting.
for C = -10:0.1:10; %Loop. C is assigned a different value in each iteration.
eqn = A == B + C; %Solved streamline equation.
Y = subs(solve(eqn,y),x,X); %Explicit streamline expression for Y.
plot(X,Y); %Standard plot call.
hold on;
end
This is the error that is displayed on the command window:
Error using mupadmex
Error in MuPAD command: Division by zero.
[_power]
Evaluating: symobj::trysubs
Error in sym/subs>mupadsubs (line 139)
G =
mupadmex('symobj::fullsubs',F.s,X2,Y2);
Error in sym/subs (line 124)
G = mupadsubs(F,X,Y);
Error in Flow_Streamlines (line 18)
Y = subs(solve(eqn,y),x,X); %Explicit
streamline expression for Y.
So, how should this be done?
Since you are using subs many times, matlabFunction is more efficient. You can use C as a parameter, and solve for y in terms of both x and C. Then the for loop is very much faster:
syms x y
K = 5; %Constant.
u = K*x; %Velocity component in x direction.
v = -K*y; %Velocity component in y direction.
A = int(1/u,x); %First integral.
B = int(1/v,y); %Second integral.
X = -1:0.1:1; %Array of x values for plotting.
syms C % C is treated as a parameter
eqn = A == B + C; %Solved streamline equation.
% Now solve the eqn for y, and make it into a function of `x` and `C`
Y=matlabFunction(solve(eqn,y),'vars',{'x','C'})
for C = -10:0.1:10; %Loop. C is assigned a different value in each iteration.
plot(X,Y(X,C)); %Standard plot call, but using the function for `Y`
hold on;
end

plotting scatter3 and surf plots from loop in matlab

I want to plot scatter3 and surf plots from a loop. Below is my code but it isn't working...not sure where I'm going wrong but clearly something is wrong with the z matrix?
for e = 1:10;
x = rand(1,3);
y = rand(1,3);
A = x+y;
subplot(2,2,1)
p = find(A(:,1) > 1.1 & A(:,1) < 1.6);
Result = A(p,:);
scatter3(Result(:,1), Result(:,2), Result(:,3))
hold on
z(e,:) = [Result(1) Result(2) Result(3)];
end
subplot(2,2,2)
surf(z)
I will reiterate what I said in my comment to you. I got this error message when trying to run your code: Attempted to access Result(1); index out of bounds because numel(Result)=0. This is because your p condition isn't satisfied - MATLAB could not find any elements in the first column that are between 1.1 and 1.6.
As such, what I would suggest you do is check to see if Result is empty before trying to access the value itself. However, I would suggest you don't write a loop and generate all of the random values at once, then do the filtering with the Boolean conditions. Therefore, the equivalent code without using a loop would be this:
x = rand(10,3);
y = rand(10,3);
A = x+y;
p = A(:,1) > 1.1 & A(:,1) < 1.6;
z = A(p,:);
figure;
subplot(2,1,1);
scatter3(z(:,1), z(:,2), z(:,3));
subplot(2,1,2);
surf(z);
We generate 10 3D points for x and y at the beginning, then add these and store this into A. Next, we find the rows in A that are between 1.1 and 1.6 in the first column and store this as a logical array. We then use this array to index into A and store the results into z. This is the recommended approach if you want to extract certain elements into an array rather than using find.
Once we obtain z, we plot these points with scatter, then also find a surface plot with surf for the same matrix. BTW, I've fixed your subplot as you are only creating two plots, yet you are allocating space for 4 plots.
If you're absolutely bent on using your code, you would simply do this:
z = []; %// Change
for e = 1:10
x = rand(1,3);
y = rand(1,3);
A = x+y;
subplot(2,1,1)
p = find(A(:,1) > 1.1 & A(:,1) < 1.6);
Result = A(p,:);
scatter3(Result(:,1), Result(:,2), Result(:,3))
hold on
if ~isempty(Result) %// Change here
z = [z; Result(1) Result(2) Result(3)]; %// Change
end
end
subplot(2,1,2)
surf(z)
What's important is the initialization of z. I made this empty, and we only add to z if Result is not empty - this will happen if you generate a number that is not between 1.1 and 1.6.

Matlab plot ksdensity without first storing its arguments

In MATLAB, if I want to plot density of a variable V I have to do
[x, y] = ksdensity(V);
plot (y, x);
If I do plot(ksdensity(V)), it only plots x and not x Vs y.
Is there an easier alternative to give ksdensity() as an argument to plot() and do the same job as plot(y, x)?
You can refactor it into a function that takes in V and plots y vs x:
function h = plot_ksdensity(V, varargin)
[x, y] = ksdensity(V);
h = plot (y, x, varargin{:});
end
using varargin means you will still have access to plot options like colours. hold on will also still work because this just calls the regular plot function.
Unfortunately no. If you don't specify explicitly the outputs, a function will return always the leftmost one from output parameter list. To convince yourself about that, create the function ftest() somewhere in your MATLAB path:
function [x, y] = ftest( )
x = 1;
y = 2;
end
then call it in the Command Window without specifying the outputs
>> ftest()
ans =
1