Introduction
Suppose I have N points x(1:N) at which I have function values f(1:N), for example:
x = [ 0.0795, 0.1327, 0.1395, 0.5133, 0.6470, 0.7358, 0.7640 ];
f = [ 0.0388, 0.4774, 0.4547, 0.0784, 0.3241, 0.2818, 0.9667 ];
I want to calculate the cumulative integral of f with respect to x using these data.
Low-Order Solution
In MATLAB, I can do this easily using cumtrapz():
>> result = cumtrapz( x, f )
result =
0 0.0137 0.0169 0.1165 0.1434 0.1703 0.1879
Problem
Unfortunately, cumtrapz() uses the trapezoidal method for numerical integration, which is insufficient for my purposes.
Higher-order methods exist, like Simpson's Rule, but to my knowledge there isn't a function that performs the cumulative version of Simpson's Rule for nonuniform grids at the MATLAB File Exchange, or anywhere else.
Does a higher-order version of cumtrapz() already exist? If not, what would I have to do to implement it myself?
I don't know of another method however you could use an interpolation with a pchip, spline, or some other method to increase the resolution. Then use cumtrapz to get a closer approximation of the numeric integral.
It would be up to you to determine what method is applicable to your function.
Example using a sine function and spline
>> x = linspace(0,pi,5);
>> f = sin(x);
>> intF = cumtrapz(x,f);
error = 2-intF(end)
error =
0.1039
>> x2 = linspace(x(1),x(end),numel(x)*10); %Up sample by 10x
>> f2 = interp1(x,f,x2,'spline'); %Interpolate with spline
>> intF2 = cumtrapz(x2,f2);
>> error = 2-intF2(end) %MUCH LESS ERROR
error =
-0.0038
Related
I have the situation like on this image below:
This plot is the result of two vectors:
fi = [41.309180589278, 41.8087915220215, 42.8081880760916, ...
43.8078181874395, 44.8076823745539, 45.8077808710707, 46.3079179803177]
m = [1.00047608139868, 1.00013712198767, 0.999680989440986, ...
0.999524195487826, 0.999671686649694, 1.00012913666266, 1.00047608139868]
I need to get the values of fi where m is equal to 1. So approximately that will be 42.2 and 42.5.
I tried to do spline interpolation:
xq = [fi(1):0.25:fi(7)];
vq1 = interp1(fi,m,xq);
[fi1, fi2] = interp1(m, xq, 1)
But that is not working. Can someone help me with this?
One way to find a zero crossing is to "turn the graph sideways", having fi be a function of m, and interpolate to find m=0. But interp1 requires the m input to be monotonic, which this is not. In fact, this function has two different values for each m.
MATLAB knows the fzeros function, which finds a zero crossing of a function numerically. It requires a function as input. We can define an anonymous function using interp1, which returns m-1 for any value of x. Here, x is defined by fi and f(x) by m:
fi = [41.309180589278, 41.8087915220215, 42.8081880760916, ...
43.8078181874395, 44.8076823745539, 45.8077808710707, 46.3079179803177];
m = [1.00047608139868, 1.00013712198767, 0.999680989440986, ...
0.999524195487826, 0.999671686649694, 1.00012913666266, 1.00047608139868];
fun = #(x)interp1(fi,m,x)-1;
x1 = fzero(fun,42)
x2 = fzero(fun,46)
This gives me:
x1 = 42.109
x2 = 45.525
Note that we needed to know the approximate locations for these two zeros. There is no easy way around this that I know of. If one knows that there are two zero crossings, and the general shape of the function, one can find the local minimum:
[~,fimin] = min(m);
fimin = fi(fimin);
and then find the zero crossings between each of the end points and the local minimum:
x1 = fzero(fun,[fi(1),fimin])
x2 = fzero(fun,[fimin,fi(end)])
You need to use an anonymous function so that you can pass additional arguments to interp1.
Try this
fi = [41.309180589278, 41.8087915220215, 42.8081880760916, ...
43.8078181874395, 44.8076823745539, 45.8077808710707, 46.3079179803177];
m = [1.00047608139868, 1.00013712198767, 0.999680989440986, ...
0.999524195487826, 0.999671686649694, 1.00012913666266, 1.00047608139868];
fzero(#(x) 1-interp1(fi,m,x), 43)
fzero(#(x) 1-interp1(fi,m,x), 45)
The 43 and 45 are the initialization for x for fzero. You need to run the fzero twice to find the two solutions.
I am working on an assignment that requires me to use the trapz function in MATLAB in order to evaluate an integral. I believe I have written the code correctly, but the program returns answers that are wildly incorrect. I am attempting to find the integral of e^(-x^2) from 0 to 1.
x = linspace(0,1,2000);
y = zeros(1,2000);
for iCnt = 1:2000
y(iCnt) = e.^(-(x(iCnt)^2));
end
a = trapz(y);
disp(a);
This code currently returns
1.4929e+03
What am I doing incorrectly?
You need to just specify also the x values:
x = linspace(0,1,2000);
y = exp(-x.^2);
a = trapz(x,y)
a =
0.7468
More details:
First of all, in MATLAB you can use vectors to avoid for-loops for performing operation on arrays (vectors). So the whole four lines of code
y = zeros(1,2000);
for iCnt = 1:2000
y(iCnt) = exp(-(x(iCnt)^2));
end
will be translated to one line:
y = exp(-x.^2)
You defined x = linspace(0,1,2000) it means that you need to calculate the integral of the given function in range [0 1]. So there is a mistake in the way you calculate y which returns it to be in range [1 2000] and that is why you got the big number as the result.
In addition, in MATLAB you should use exp there is not function as e in MATLAB.
Also, if you plot the function in the range, you will see that the result makes sense because the whole page has an area of 1x1.
I'm trying to implement this integral representation of Bessel function of the first kind of order n.
here is what I tried:
t = -pi:0.1:pi;
n = 1;
x = 0:5:20;
A(t) = exp(sqrt(-1)*(n*t-x*sin(t)));
B(t) = integral(A(t),-pi,pi);
plot(A(t),x)
the plot i'm trying to get is as shown in the wikipedia page.
it said:
Error using * Inner matrix dimensions must agree.
Error in besselfn (line 8) A(t) = exp(sqrt(-1)*(n*t-x*sin(t)));
so i tried putting x-5;
and the output was:
Subscript indices must either be real positive integers or logicals.
Error in besselfn (line 8) A(t) = exp(sqrt(-1)*(n*t-x*sin(t)));
How to get this correct? what am I missing?
To present an anonymous function in MATLAB you can use (NOT A(t)=...)
A = #(t) exp(sqrt(-1)*(n*t-x.*sin(t)));
with element-by-element operations (here I used .*).
Additional comments:
You can use 1i instead of sqrt(-1).
B(t) cannot be the function of the t argument, because t is the internal variable for integration.
There are two independent variables in plot(A(t),x). Thus you can display plot just if t and x have the same size. May be you meant something like this plot(x,A(x)) to display the function A(x) or plot(A(x),x) to display the inverse function of A(x).
Finally you code can be like this:
n = 1;
x = 0:.1:20;
A = #(x,t) exp(sqrt(-1)*(n*t-x.*sin(t)));
B = #(x) integral(#(t) A(x,t),-pi,pi);
for n_x=1:length(x)
B_x(n_x) = B(x(n_x));
end
plot(x,real(B_x))
I am trying to optimise this: function [ LPS, LCE ] = runProject( Nw, Np, Nb) which calls some other functions I have written before. The idea is to find the optimum combination of Nw, Np, Nb AND keep the LPS=0, while LCE is minimum. Nw, Np, Nb should be positive integers. LCE will also be positive.
function [ LPS, LCE ] = runProject( Nw, Np, Nb)
%
% Detailed explanation goes here
[Pg, Pw, Pp] = Pgener();
[Pb, LPS] = Bat( Pg );
[LCE] = Constr(Pw, Pp, Nb)
end
However, I tried the gamultiobj solver from the Global Optimization Toolbox of matlab2015 (trial version) for a different approach with pareto front, but I got the error:
"Optimization running.
Error running optimization.
Not enough input arguments."
You should write your objective function like the following example:
function scores = rastriginsfcn(pop)
%RASTRIGINSFCN Compute the "Rastrigin" function.
% pop = max(-5.12,min(5.12,pop));
scores = 10.0 * size(pop,2) + sum(pop .^2 - 10.0 * cos(2 * pi .* pop),2);
As you can see, the function accepts all the inputs as a single vector pop.
With such representation I can evaluate the function as follows:
rastriginsfcn([2 3])
>> ans
13
Still for running the optimization from the toolbox you have to mention the number of variables, for instance, in my example it is equal to 2:
[x fval exitflag] = ga(#rastriginsfcn, 2)
It is the same for the multi-objective optimization. Check the following image from MATHWORKS:
We have an equation similar to the Fredholm integral equation of second kind.
To solve this equation we have been given an iterative solution that is guaranteed to converge for our specific equation. Now our only problem consists in implementing this iterative prodedure in MATLAB.
For now, the problematic part of our code looks like this:
function delta = delta(x,a,P,H,E,c,c0,w)
delt = #(x)delta_a(x,a,P,H,E,c0,w);
for i=1:500
delt = #(x)delt(x) - 1/E.*integral(#(xi)((c(1)-c(2)*delt(xi))*ms(xi,x,a,P,H,w)),0,a-0.001);
end
delta=delt;
end
delta_a is a function of x, and represent the initial value of the iteration. ms is a function of x and xi.
As you might see we want delt to depend on both x (before the integral) and xi (inside of the integral) in the iteration. Unfortunately this way of writing the code (with the function handle) does not give us a numerical value, as we wish. We can't either write delt as two different functions, one of x and one of xi, since xi is not defined (until integral defines it). So, how can we make sure that delt depends on xi inside of the integral, and still get a numerical value out of the iteration?
Do any of you have any suggestions to how we might solve this?
Using numerical integration
Explanation of the input parameters: x is a vector of numerical values, all the rest are constants. A problem with my code is that the input parameter x is not being used (I guess this means that x is being treated as a symbol).
It looks like you can do a nesting of anonymous functions in MATLAB:
f =
#(x)2*x
>> ff = #(x) f(f(x))
ff =
#(x)f(f(x))
>> ff(2)
ans =
8
>> f = ff;
>> f(2)
ans =
8
Also it is possible to rebind the pointers to the functions.
Thus, you can set up your iteration like
delta_old = #(x) delta_a(x)
for i=1:500
delta_new = #(x) delta_old(x) - integral(#(xi),delta_old(xi))
delta_old = delta_new
end
plus the inclusion of your parameters...
You may want to consider to solve a discretized version of your problem.
Let K be the matrix which discretizes your Fredholm kernel k(t,s), e.g.
K(i,j) = int_a^b K(x_i, s) l_j(s) ds
where l_j(s) is, for instance, the j-th lagrange interpolant associated to the interpolation nodes (x_i) = x_1,x_2,...,x_n.
Then, solving your Picard iterations is as simple as doing
phi_n+1 = f + K*phi_n
i.e.
for i = 1:N
phi = f + K*phi
end
where phi_n and f are the nodal values of phi and f on the (x_i).