Given the function f(x) = ln(x) with x belonging to [1,e] You must develop an algorithm in matlab that performs the following tasks.
Perform the continuous regression of f(x) onto the subspace 〈1, x, x^2〉, using the symbolic tools in Matlab. Plot the result (the function and the fitting).
Perform the discrete regression of f onto 〈1, x, x^2〉. For that purpose:
2.1. Introduce as regular sampler of the interval [1, e] using 1000 points. Call this sampler xs.
2.2. Evaluate f(x) on xs, and the basis functions 1, x, x^2 to generate {1, x, x^2, f}.
2.3. Perform the regression of f onto 〈1, x, x^2〉.
2.4. Plot the result (the function and the fitting)
i tried with this but it is not giving the right answer, and it is giving an error in plot(xs, f_values)
clear all
close all
clc
syms x
f = log(x);
V = [1 x x^2];
coeffs = V\f;
a0 = coeffs(1);
a1 = coeffs(2);
a2 = coeffs(3);
fitting = a0*1+ a1*x + a2*x^2;
ezplot(f,[1,exp(1)])
hold on
ezplot(fitting,[1,exp(1)])
legend('f(x)','fitting')
xs = linspace(1,exp(1),1000);
linspace(1,exp(1),1000)
f_values = subs(f, x, xs);
basis_1 = ones(1, 1000);
basis_x = xs;
basis_x2 = xs.^2;
V = [basis_1; basis_x; basis_x2];
fitting_values = coeffs(1)*basis_1 + coeffs(2)*basis_x + coeffs(3)*basis_x2;
plot(xs, f_values)
hold on
plot(xs, fitting_values)
legend('f(x)', 'fitting')
Looking solely at your error in plot(xs, f_values):
MATLAB's page for the function plot shows that when accepting two inputs (in your case, xs and f_values), they are either (x, y), or (y, line options). But since one of the values you've inputted are based on x (a symbolic value), it's a symbolic vector. plot can't handle symbolic inputs.
I believe the equivalent for syms is fplot from the symbolic maths toolbox.
Related
Let's say you have some vector z and you compute [f, x] = ecdf(z);, hence your empirical CDF can be plotted with stairs(x, f).
Is there a simple way to compute what all the percentile scores are for z?
I could do something like:
Loop through z, that is for each entry z(i) of z
Binary search through sorted vector x to find where z(i) is. (find index j such that x(j) = z(i))
Find the corresponding value f(j)
It feels like there should be a simpler, already implemented way to do this...
Let f be a monotone function defined at values x, for which you want to compute the inverse function at values p. In your case f is monotone because it is a CDF; and the values p define the desired quantiles. Then you can simply use interp1 to interpolate x, considered as a function of f, at values p:
z = randn(1,1e5); % example data: normalized Gaussian distribution
[f, x] = ecdf(z); % compute empirical CDF
p = [0.5 0.9 0.95]; % desired values for quantiles
result = interp1(f, x, p);
In an example run of the above code, this produces
result =
0.001706069265714 1.285514249607186 1.647546848952448
For the specific case of computing quantiles p from data z, you can directly use quantile and thus avoid computing the empirical CDF:
result = quantile(z, p)
The results may be slightly different depending on how the empirical CDF has been computed in the first method:
>> quantile(z, p)
ans =
0.001706803588857 1.285515826972878 1.647582486507752
For comparison, the theoretical values for the above example (Gaussian distribution) are
>> norminv(p)
ans =
0 1.281551565544601 1.644853626951472
I have a question, because this work for many functions, but I have a trouble when trying to plot the integral of a sine (I am using matlab 2010):
clear all
close all
clc
x = linspace(-10, 10, 100);
f = #(x) sin(x);
I = arrayfun(#(x) quad(f, 0, x), x);
plot(x, f(x),'r', x, I, 'b')
I expect having a -cos(x), but instead I get something with an offset of 1, why is this happening? How should fix this problem?
The Fundamental Theorem of Calculus says that the indefinite integral of a nice function f(x) is equal to the function's antiderivative F(x), which is unique up-to an additive constant. Further, a definite integral has the form:
In this form, the constant of integration will cancel out, and the integral will exactly equal the desired antiderivative only if the lower bound evaluation vanishes. However, -cos(0) does not vanish and has a value of -1. So in order to calculate the desired antiderivative F(x), the lower bound evaluation should be added to the right-hand side.
plot(x, f(x),'r', x, I+ (-cos(0)), 'b');
This is the equivalent of assigning an initial value for the solution of ODEs a la ode45.
What you're trying to do can be achieved using the following:
x = linspace(-10, 10, 100);
syms y;
f = sin(y) %function
I =int(f,y) %integration of f
plot(x, subs(f,y,x),'r', x, subs(I,y,x), 'b')
Output:-
According to Matlab documentation, q = quad(fun,a,b)
Quadrature is a numerical method used to find the area under the graph of a function, that is, to compute a definite integral.
Integral of sin(x) equals -cos(x)
Definite integral of sin(x) from x = pi to x = 0:
-cos(pi) - (-cos(0)) = 2
Since quad compute a definite integral, I can't see any problem.
Same as:
figure;plot(-cos(x) - (-cos(0)))
I want to integrate
f(x) = exp(-x^2/2)
from x=-infinity to x=+infinity
by using the Monte Carlo method. I use the function randn() to generate all x_i for the function f(x_i) = exp(-x_i^2/2) I want to integrate to calculate afterwards the mean value of f([x_1,..x_n]). My problem is, that the result depends on what values I choose for my borders x1 and x2 (see below). My result is going far away from the real value by increasing the value of x1 and x2. Actually the result should be better and better by increasing x1 and x2.
Does someone see my mistake?
Here is my Matlab code
clear all;
b=10; % border
x1 = -b; % left border
x2 = b; % right border
n = 10^6; % number of random numbers
x = randn(n,1);
f = ones(n,1);
g = exp(-(x.^2)/2);
F = ((x2-x1)/n)*f'*g;
The right value should be ~2.5066.
Thanks
Try this:
clear all;
b=10; % border
x1 = -b; % left border
x2 = b; % right border
n = 10^6; % number of random numbers
x = sort(abs(x1 - x2) * rand(n,1) + x1);
f = exp(-x.^2/2);
F = trapz(x,f)
F =
2.5066
Ok, lets start with writing of general case of MC integration:
I = S f(x) * p(x) dx, x in [a...b]
S here is integral sign.
Usually, p(x) is normalized probability density function, f(x) you want to integrate, and algorithm is very simple one:
set accumulator s to zero
start loop of N events
sample x randomly from p(x)
given x, compute f(x) and add to accumulator
back to start loop if not done
if done, divide accumulator by N and return it
In simplest textbook case you have
I = S f(x) dx, x in [a...b]
where it means PDF is equal to uniformly distributed one
p(x) = 1/(b-a)
but what you have to sum is actually (b-a)*f(x), because your integral now looks like
I = S (b-a)*f(x) 1/(b-a) dx, x in [a...b]
In general, if both f(x) and p(x) could serve as PDF, then it is matter of choice whether you integrate f(x) over p(x), or p(x) over f(x). No difference! (Well, except maybe computation time)
So, back to particular integral (which is equal to \sqrt{2\pi}, i believe)
I = S exp(-x^2/2) dx, x in [-infinity...infinity]
You could use more traditional approach like #Agriculturist and write it
I = S exp(-x^2/2)*(2a) 1/(2a) dx, x in [-a...a]
and sample x from U(0,1) in [-a...a] interval, and for each x compute exp() and average it and get the result
From what I understand, you want to use exp() as PDF, so your integral looks like
I = S D * exp(-x^2/2)/D dx, x in [-infinity...infinity]
PDF to be normalized so it shall include normalization factor D, which is exactly equal to \sqrt{2 \pi} from gaussian integral.
Now f(x) is just a constant equal to D. It doesn't depend on x. It means that you for each sampled x should add to accumulator a CONSTANT value of D. After running N samples,
in accumulator you'll have exactly N*D. To find mean you'll divide by N and as a result you'll get perfect D, which is \sqrt{2 \pi}, which, in turn, is
2.5066.
Too rusty to write any matlab, and Happy New Year anyway
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
I have a Matlab function that returns a polynomial of the form:
poly = ax^2 + bx*y + cy^2
where a, b, and c are constants, and x and y are symbolic (class sym).
I want to get the coefficients of the polynomial in the form [a b c], but I'm running into the following problem. If the function returns poly = y^2, then coeffs(poly) = 1. I don't want this – I want it to return [0 0 1].
How can I create a function that will give me the coefficients of a symbolic polynomial in the form that I want?
You can use sym2poly if your polynomial is a function of a single variable like your example y^2:
syms y
p = 2*y^2+3*y+4;
c = sym2poly(p)
which returns
c =
2 3 4
Use fliplr(c) if you really want the coefficients in the other order. If you're going to be working with polynomials it would probably also be a good idea not to create a variable called poly, which is the name of a function you might want to use.
If you actually need to handle polynomials in multiple variables, you can use MuPAD functions from within Matlab. Here is how you can use MuPAD's coeff to get the coefficients in terms of the order of variable they precede (x or y):
syms x y
p = 2*x^2+3*x*y+4*y;
v = symvar(p);
c = eval(feval(symengine,'coeff',p,v))
If you want to extract all of the information from the polynomial, the poly2list function is quite helpful:
syms x y
p = 2*x^2+3*x*y+4*y;
v = symvar(p);
m = eval(feval(symengine,'poly2list',p,v));
c = m(:,1); % Coefficients
degs = m(:,2:end); % Degree of each variable in each term
The polynomial can then be reconstructed via:
sum(c.*prod(repmat(v,[size(m,1) 1]).^degs,2))
By the way, good choice on where you go to school. :-)
There is also an alternative to this problem. For a given degree, this function returns a polynomial of that degree and its coefficients altogether.
function [polynomial, coefficeint] = makePoly(degree)
syms x y
previous = 0 ;
for i=0:degree
current = expand((x+y)^i);
previous= current + previous ;
end
[~,poly] = coeffs(previous);
for j= 1:length(poly)
coefficeint(j) = sym(strcat('a', int2str(j)) );
end
polynomial = fliplr(coefficeint)* poly.' ;
end
Hope this helps.