I want to plot the error in the composite simpson's rule
... Here is my code
for r=1:100
n=600;
a=0;
b=5;
err=[];
x=zeros(1,n);
f=#(x)cos(x)+x.^2;
h=(b-a)/n;
xexact=integral(f,a,b);
p=0;
q=0;
for i=1:n
x(i)=a+(i-1)*h;
end
for i=1:n-1
p=p+2*(f(x(i)))+4*(f(x(i)+h/2));
end
x=(h/6)*(f(a)+f(a+h/2)+p+f(b))
err(end+1)=x-xexact;
plot(r,x,'*')
end
When I run the code I get one point in the plot .. I want to have all the points ploted in the plot , How to do that ?
thanks
The simplest fix is to put hold on; before your code here and hold off; after it. That way, each of your calls to plot will add a point to an existing plot, rather than creating a new one. (What is happening at the moment is that you are plotting a point with r=1, and then replacing that plot with one for r=2, etc. So what you end up with is a plot showing just what happens for r=100.)
You might do better, though, to build up an array containing your xs as your loop runs, and then do a single plot(1:100, xs, '*'); at the end.
There is a conceptual problem in your code: you want to plot the x variable which is not function of r and that will never change for each r value. So you will plot a row of r dots with a fixed x value.
Moreover I think that, if possible, is good to avoid for loops in Matlab because there are more powerful and optimized ways to do things that you do with them. For example I will write this code in this form:
function [x, err] = compSimp(n, a, b)
err = [];
x=zeros(1,n+1);
f=#(x)cos(x)+x.^2;
h=(b-a)/n;
xexact=integral(f,a,b);
% x_0 = a
x(1)=a;
% x_n = b
x(n+1)=b;
p=0;
% x_j = a + j*h with j = 1, 2, ... , n-2, n-1 (no need to set again x_0 and x_n)
x(2:n)= a + (1:(n-1))*h;
% summations
for i=2:2:n
p = p + 2*(f(x(i+1))) + 4*(f(x(i)));
end
x=(h/3)*(f(a) + p + f(b));
err(end+1)=x-xexact;
end
As you can see i've changed some code logic, following wikipedia for theory. If you want, you can also change code so that you can pass a custom f function to the compSimp function.
Related
I am trying to understand these by myself
,
I want to simulate some straight lines, in Matlab, as follows:
f(t,z)=a(z)t+b(z) where a(z) and b(z) are uniformly distributed random variable in the interval [-1,1] and t is time between [-2,2]. More simply: f(t)= at+b, and z is the random index of the constant (a,b) and let say [-1,+1] is the sample space for z and z is uniformly distributed.
Could anyone help me with the code? Is there any way to show the random generation of the straight line as an animation? Thank you very much for any help.
I am trying like this:
a= rand(-1,1);
b=rand(-1,1);
-2<t<2;
f=a*t+b;
plot(t, f);
But I am getting error Unrecognized function or variable 't'.
Your attempt is not valid MATLAB syntax,
-2<t<2 does not do anything, other than produce the error you're seeing because t does not exist
f = a*t+b you can't define functions like this, you probably want to use an anonymous function.
You can't plot t because you haven't defined it, and you can't plot f because you haven't properly defined that either in terms of a valid t.
You need to define some discrete values for t. In this case two values is enough, because you're only plotting straight lines anyway. You could use linspace or the colon operator to create a finer spaced array for whatever reason.
N = 10; % Number of lines to plot
t = [-2,2]; % We want lines between -2 and 2
a = rand(N,1)*2-1; % N random values between -1 and +1
b = rand(N,1)*2-1; % N random values between -1 and +1
f = #(t,z) a(z)*t + b(z); % Define f in terms of axis t and index z
% Plotting
figure; hold on;
for iz = 1:N
plot( t, f(t,iz) );
end
This gives an image something like this:
If you need an "animation", you could add a pause, e.g. pause(1) inside the loop
I made this code for ODE solutions using Runge-Kutta4:
function y=myODE(f,y0,x0,h,x_final)
x=x0;
y=y0;
while x<x_final
h=min(h,x_final-x);
k1=f(x,y);
k2=f(x+h/2,y+h*k1/2);
k3=f(x+h/2,y+h*k2/2);
k4=f(x+h,y+h*k3);
y=y+(h/6)*(k1+2*k2+2*k3+k4)
x=x+h;
end
f is the function y' = f(x,y), y0 is initial value, x0 is where the function starts, h subinterval and x_final is where the function stops.
I tried my code and it solves ODEs for me correctly, but I also want to plot my function over a xy-axis on the interval x0 to x_final with h subintervals. When I try to plot it using plot(x0:h:x_final,y) I only get an empty graph. I understand (guessing) that I have to bind my y to several x in order to plot, but how can I do that without changing my code too much?
How can I plot the graph for y given y0, interval x0 to x_final and given h?
New to MATLAB, appreciate all help I can get!
Edit: To make clear what my code is for;
I need this ODE solver both for solution and graphing. I'm supposed to study the truncation error by looking at values of y on h compared to 2*h and the stability of Runge-Kutta4 by looking at graphs of y with different h.
This is not a very smart refactoring of your code (because it will slow down the solving, also will kill you graphics depending on how many steps you have in your ODE) but I'm sleepy so I go for the hack:
function y=myODE(f,y0,x0,h,x_final)
hold(axes('Parent',figure),'on');
x=x0;
y=y0;
plot(x,y, 'o');
while x<x_final
h=min(h,x_final-x);
k1=f(x,y);
k2=f(x+h/2,y+h*k1/2);
k3=f(x+h/2,y+h*k2/2);
k4=f(x+h,y+h*k3);
y=y+(h/6)*(k1+2*k2+2*k3+k4);
x=x+h;
plot(x,y,'o');
end;
end
Maybe tomorrow I'll re-write this answer to something proper, but—for now—good-night! :-)
function y=myode(f,y0,x0,h,x_final)
x=x0;
y=y0;
plot(x0,y0,'.')
hold on
while x<x_final
h=min(h,x_final-x);
k1=f(x,y);
k2=f(x+h/2,y+h*k1/2);
k3=f(x+h/2,y+h*k2/2);
k4=f(x+h,y+h*k3);
y=y+(h/6)*(k1+2*k2+2*k3+k4);
x=x+h;
plot(x,y,'.')
disp([x,y])
end
The comment box didn't let me to put my fixed-code in "code-format" so post it as an answer.
I would suggest you store the x and y values to vectors and plot them outside the loop. You may want to also output bigX and bigY in order to compare with the exact solution.
function y=myODE(f,y0,x0,h,x_final)
% Example:
% f = #(x,y) (x.^2+cos(y));
% y_final = myODE(f,0,0,0.1,2);
x=x0;
y=y0;
bigX = x0:h:x_final;
if bigX(end)<x_final
% Doesn't occur when x_final = n*h for some integer n
bigX = [bigX,x_final];
end
bigY = zeros(size(bigX));
count = 1;
bigY(1) = y0;
while x<x_final
h=min(h,x_final-x);
k1=f(x,y);
k2=f(x+h/2,y+h*k1/2);
k3=f(x+h/2,y+h*k2/2);
k4=f(x+h,y+h*k3);
y=y+(h/6)*(k1+2*k2+2*k3+k4);
x=x+h;
count = count+1;
bigY(count) = y;
end
plot(bigX,bigY,'b-o')
xlabel('x')
ylabel('y')
I'm working on bisection method which I wrote by myself. The following code works fine - it displays correct results(Tested on x^2-25) and it gave correct results. But that's not all what I wanted to realize.I need draw a plot displaying all correct results on it.
As I told - I took expression
x^2-25
, and results are
5 and -5
Now, I need to draw parabola and display results.
My Code
function [] = bisectionWindow()
clc;
f = #(x) x^2-25; % specified function
a=5;
b=6;
e=0.0001;
syms x;
% Main loop
while abs(b-a)>e
c=(b+a)/2;
if sign(f(c)) == sign(f(a))
a=c;
else
b=c;
end
end
disp(['Answer x='])
solve(f(x))
%note: ans displays because of 'sign' operator presence
My Attempt to draw plot
function [] = checkWin(a,b,x)
%draws plot
Limits = [a b];
len = b-a;
for i=1:len
x = X(i);
y=x^2-25;
%y=0.5*x^3-2*x^2+1;
figure(1),clf,hold on
fplot('x^2-25',Limits),grid
plot(x,y,'o')
end
end
UPD: To clear some things up
I understand how to draw a plot. My objective is:
Show the plot
Show results as o's on it
The problem is - this should be unique code (as for example i took parabola, but let's take another function which has only one result) and it should execute things metioned above. So basically this is why i'm working on.
There's 2 options:
Modify existing code - which i dunno how
Rewrite - no ideas how.
I'm stuck for a long time I guess.
Thanks for Advices.
I don't get why you need the loop in your code. The following script works fine and gives the same result as yours:
f = #(x) x^2-25; % specified function
disp(['Answer x='])
disp(solve(f(x)))
You can plot your function by typing ezplot(f):
Typing ezplot(f,[-5,5]) would plot function with x between -5 and 5
If you want to use plot function, you need to rewrite your function as:
f = #(x) x.^2-25
This is because ^2 operation is regarded as multiplication of matrix by itself that is inapplicable to vectors, whereas .^2 is squaring of each matrix element.
Then, you need to create two vectors with x and y data and use plot function:
x = -10:0.1:10;
y = f(x);
plot(x,y), grid on
where grid on provides your plot with gridlines. There are many other plot options that you can use to customize your graph. You can find them here
UPD. Modified code with comments:
f = #(x) x.^2-25; %//specified function
disp(['Answer x='])
q = solve(f); %//-5 and 5 would be in one vector
disp(q) %//display -5 and 5
h = ezplot(f,[-10,10]); %//plot f(x) from -10 to 10
grid on; %//add grid to plot
set(h,'LineWidth',3); %//set line width to 3px
hold on;%//prevent the current graph from being replaced
plot(q,f(q),'ro','MarkerSize',10,'LineWidth',3)
%//plot two O-s at -5 and 5. Also, make O-s 10px in width and 3px thick
hold off;
This yields:
I want to plot relations like y^2=x^2(x+3) in MATLAB without using ezplot or doing algebra to find each branch of the function.
Does anyone know how I can do this? I usually create a linspace and then create a function over the linspace. For example
x=linspace(-pi,pi,1001);
f=sin(x);
plot(x,f)
Can I do something similar for the relation I have provided?
What you could do is use solve and allow MATLAB's symbolic solver to symbolically solve for an expression of y in terms of x. Once you do this, you can use subs to substitute values of x into the expression found from solve and plot all of these together. Bear in mind that you will need to cast the result of subs with double because you want the numerical result of the substitution. Not doing this will still leave the answer in MATLAB's symbolic format, and it is incompatible for use when you want to plot the final points on your graph.
Also, what you'll need to do is that given equations like what you have posted above, you may have to loop over each solution, substitute your values of x into each, then add them to the plot.
Something like the following. Here, you also have control over the domain as you have desired:
syms x y;
eqn = solve('y^2 == x^2*(x+3)', 'y'); %// Solve for y, as an expression of x
xval = linspace(-1, 1, 1000);
%// Spawn a blank figure and remember stuff as we throw it in
figure;
hold on;
%// For as many solutions as we have...
for idx = 1 : numel(eqn)
%// Substitute our values of x into each solution
yval = double(subs(eqn(idx), xval));
%// Plot the points
plot(xval, yval);
end
%// Add a grid
grid;
Take special care of how I used solve. I specified y because I want to solve for y, which will give me an expression in terms of x. x is our independent variable, and so this is important. I then specify a grid of x points from -1 to 1 - exactly 1000 points actually. I spawn a blank figure, then for as many solutions to the equation that we have, we determine the output y values for each solution we have given the x values that I made earlier. I then plot these on a graph of these points. Note that I used hold on to add more points with each invocation to plot. If I didn't do this, the figure would refresh itself and only remember the most recent call to plot. You want to put all of the points on here generated from all of the solution. For some neatness, I threw a grid in.
This is what I get:
Ok I was about to write my answer and I just saw that #rayryeng proposed a similar idea (Good job Ray!) but here it goes. The idea is also to use solve to get an expression for y, then convert the symbolic function to an anonymous function and then plot it. The code is general for any number of solutions you get from solve:
clear
clc
close all
syms x y
FunXY = y^2 == x^2*(x+3);
%//Use solve to solve for y.
Y = solve(FunXY,y);
%// Create anonymous functions, stored in a cell array.
NumSol = numel(Y); %// Number of solutions.
G = cell(1,NumSol);
for k = 1:NumSol
G{k} = matlabFunction(Y(k))
end
%// Plot the functions...
figure
hold on
for PlotCounter = 1:NumSol
fplot(G{PlotCounter},[-pi,pi])
end
hold off
The result is the following:
n = 1000;
[x y] = meshgrid(linspace(-3,3,n),linspace(-3,3,n));
z = nan(n,n);
z = (y .^ 2 <= x .^2 .* (x + 3) + .1);
z = z & (y .^ 2 >= x .^2 .* (x + 3) - .1);
contour(x,y,z)
It's probably not what you want, but I it's pretty cool!
i have created a function that represents a triangle sign.
this function does not work on vectors. i want to evaluate a vector x:
x=[-2:0.01:2]
and save the answer in vector y, for this purpose i came up with the following code:
for i=1:400, y(i) = triangle(x(i))
after i got the ans i plotted is using plot. in this case it worked ok but i am interested on observing the influence of time shifting and shrinking so when i try to use lets say:
for i=1:200, y(i) = triangle(x(2*i))
i get a vector y not the same length as vector x and i cant even plot them... is there any easy way to achieve it? and how should i plot the answer?
here is my function:
function [ out1 ] = triangle( input1 )
if abs(input1) < 1,
out1 = 1 - abs(input1);
else
out1 = 0;
end
end
y is a different length in each for loop because each loop iterated a different number of times. In the example below, I use the same for loops and plot y2 with the corresponding values of x. i is already defined in matlab so I've changed it to t in the example below.
clear all
x=[-2:0.01:2];
for t=1:400
y(t) = triangle(x(t));
end
for t=1:200
y2(t) = triangle(x(2*t));
end
Or, if you want to see y2 plotted over the same range you can increase the size of x:
clear all
x=[-2:0.01:8];
for t=1:400
y(t) = triangle(x(t));
end
for t=1:400
y2(t) = triangle(x(2*t));
end
plot(x(1:length(y)),y,'r')
hold on
plot(x(1:length(y2)),y2,'b')