How to perform indefinite integration of this function in MATLAB? - matlab

I need to perform the following operations as shown in the image. I need to calculate the value of function H for different inputs(x) using MATLAB.
I am giving the following command from Symbolic Math Toolbox
syms y t x;
f1=(1-exp(-y))/y;
f2=-t+3*int(f1,[0,t]);
f3=exp(f2);
H=int(f3,[0,x]);
but the value of 2nd integral i.e. integral in the function H can't be calculated and my output is of the form of
H =
int(exp(3*eulergamma - t - 3*ei(-t) + 3*log(t)), t, 0, x)
If any of you guys know how to evaluate this or have a different idea about this, please share it with me.

Directly Finding the Numerical Solution using integral:
Since you want to calculate H for different values of x, so instead of analytical solution, you can go for numerical solution.
Code:
syms y t;
f1=(1-exp(-y))/y; f2=-t+3*int(f1,[0,t]); f3=exp(f2);
H=integral(matlabFunction(f3),0,100) % Result of integration when x=100
Output:
H =
37.9044
Finding the Approximate Analytical Solution using Monte-Carlo Integration:
It probably is an "Elliptic Integral" and cannot be expressed in terms of elementary functions. However, you can find an approximate analytical solution using "Monte-Carlo Integration" according to which:
where f(c) = 1/n Σ f(xᵢ)
Code:
syms x y t;
f1=(1-exp(-y))/y; f2=-t+3*int(f1,[0,t]); f3=exp(f2);
f3a= matlabFunction(f3); % Converting to function handle
n = 1000;
t = x*rand(n,1); % Generating random numbers within the limits (0,x)
MCint(x) = x * mean(f3a(t)); % Integration
H= double(MCint(100)) % Result of integration when x=100
Output:
H =
35.2900
% Output will be different each time you execute it since it is based
% on generation of random numbers
Drawbacks of this approach:
Solution is not exact but approximated.
Greater the value of n, better the result and slower the code execution speed.
Read the documentation of matlabFunction, integral, Random Numbers Within a Specific Range, mean and double for further understanding of the code(s).

Related

Fitting Data with Linear Combination of Vectors in MATLAB with Constraints

Working in MATLAB. I have the following equation:
S = aW + bX + cY + dZ
where S,W,X,Y, and Z are all known n x 1 vectors. I am trying to fit the data of S with a linear combination of the basis vectors W,X,Y, and Z with the constraint of the constants (a,b,c,d) being greater than 0. I have managed to do this in Excel's solver, and have attempted to figure it out on MATLAB, being directed towards functions like fmincon, but I am not overly familiar with MATLAB and feel I am misunderstanding the use of fmincon.
I am looking for help with understanding fmincon's use towards my problem, or redirection towards a more efficient method for solving.
Currently I have:
initials = [0.2 0.2 0.2 0.2];
fun = #(x)x(1)*W + x(2)*X + x(3)*Y + x(4)*Z;
lb = [0,0,0,0];
soln = fmincon(fun,initials,data,b,Aeq,beq,lb,ub);
I am receiving an error stating "A must have 4 column(s)". Where A is referring to my variable data which corresponds to my S in the above equation. I do not understand why it is expecting 4 columns. Also to note the variables that are in my above snippet that are not explicitly defined are defined as [], serving as space holders.
Using fmincon is a huge overkill in this case. It's like using big heavy microscope to crack nuts... or martian rover to tow a pushcart or... anyway :) May be it's OK if you don't have to process large sets of vectors. If you need to fit hundreds of thousands of such vectors it can take hours. But this classic solution will be faster by several orders of magnitude.
%first make a n x 4 matrix of your vectors;
P=[W,X,Y,Z];
% now your equation looks like this S = P*m where m is 4 x 1 vectro
% containing your coefficients ( m = [a,b,c,d] )
% so solution will be simply
m_1 = inv(P'*P)*P'*S;
% or you can use this form
m_2 = (P'*P)\P'*S;
% or even simpler
m_3 = (S'/P')';
% all three solutions should give exactly same resul
% third solution is the neatest but may not work in every version of matlab
% Your modeled vector will be
Sm = P*m_3; %you can use any of m_1, m_2 or m_3;
% And your residual
R = S-Sm;
If you need to procees many vectors don't use for cycle. For cycles are very slow in Matlab and you should use matrices instead, if possible. S can also be nk matrix, where k is number vectors you want to process. In this case m will be 4k matrix.
What you are trying to do is similar to the answer I gave at is there a python (or matlab) function that achieves the minimum MSE between given set of output vector and calculated set of vector?.
The procedure is similar to what you are doing in EXCEL with solver. You create an objective function that takes (a, b, c, d) as the input parameters and output a measure of fit (mse) and then use fmincon or similar solver to get the best (a, b, c, d) that minimize this mse. See the code below (no MATLAB to test it but it should work).
function [a, b, c, d] = optimize_abcd(W, X, Y, Z)
%=========================================================
%Second argument is the starting point, second to the last argument is the lower bound
%to ensure the solutions are all positive
res = fmincon(#MSE, [0,0,0,0], [], [], [], [], [0,0,0,0], []);
a=res(1);
b=res(2);
c=res(3);
d=res(4);
function mse = MSE(x_)
a_=x_(1);
b_=x_(2);
c_=x_(3);
d_=x_(4);
S_ = a_*W + b_*X + c_*Y + d_*Z
mse = norm(S_-S);
end
end

Using "subs" Function to Evaluate Output of "dsolve" Give Extra Output in Maltab

Introduction
If you want to know the grand scheme... read the introduction. If not, Just skip down to My Problem.
I have a project for my Differential Equations and Linear Algebra course where I have to use a computer algebra system to solve both linear, ordinary differential equations of the first degree with constant coefficients and a non-linear ODE with constant coefficients. I have to show this being done both analytically and numerically. My plan is to have 2 functions that make use of the dsolve function for the analytical part and a function called ODE1 I learned about through this tutorial by Matlab. This function is defined to approximate the solution to the differential equation using Euler's Method. The functions would all use the same input parameters so each input could be defined once and the functions would all understand what inputs to use (maybe nest the functions under one calling function). The goal is to evaluate the analytical solution over the same interval being used to find the numerical approximation and compare the results in both a table and graph. I got the numerical solution to give me a "table" in the form of a row vector and also graph that row vector. I began having an issue with the Analytic solution...
My Problem
To solve a linear ODE of the first order, I generated this function
function [s1] = L_Analytic(eqn,t0,h,numstep,y0)
% eqn is the differential equation to be solved
% t0 is the start of the interval that the resulting equation is to be evaluated at
% h is the stepsize
% numstep is the number of steps
% y0 is the initial condition
syms y(x)
cond = y(0) == y0;
A = dsolve(eqn,cond);
s1 = A;
S1 = s1;
for t = t0 : h : h*(numstep-2)
S1 = [subs(S1); vpa(subs(s1))]
end
end
The list generated by this function L_Analytic(diff(y)==y, 0, 0.1, 5, 1) is
1
1.0
1.105170...
1.221402...
1.349858...
When using the numerical method in a different function in Matlab using the same inputs, I get the list:
1.0000
1.1000
1.2100
1.3310
1.4641
For those who know their way around differential equations or are proficient in calculus, the solution to y' = y is e^x, and when evaluated over the interval 0:0.4 using 5 steps, the list should be
1
1.105...
1.2214...
1.3498...
1.4918...
after some rounding.
So the issue here is that I have an extra entry of 1 in my analytical solutions. I'm confident it has something to do with the subs(S1) part of S1 = [subs(S1); vpa(subs(s1))] in the for loop but I am stumped as to how to fix this.
I kind of understand why I need to use the subs function, in that I am using symbolic variables to use the dsolve function which outputs symbolic variables in its answer. Also, in order for the for loop to iterate and change, the symbolic variables must be substituted for real values of t each time. I did try moving the vpa(subs(s1)) just before the for loop, but this just returned the same value in the vector 5 times. I also tried not using subs(S1) and it gave me
exp(t)
1.0
1.1051709...
1.2214027...
1.3498588...
so I'm positive it's this part of the code.
Side Note: I understand the analytical method outputs a column vector as does the ODE1 shown in the video that's linked. In order to have Matlab plot this as one line, I transposed the column vector to make a row vector and will do the same with the analytical solution once the solution part is fixed.
By changing the internals of the for loop I made it work. My final function code turned out to be this:
function [s1] = L_Analytic3(eqn,t0,h,numstep,y0)
%Differential Equation solver for specific inputs
% eqn is the differential equation
% t0 is start of evaluation interval
% h is stepize
% numstep is the number of steps
% y0 is the initial condition
syms y(x)
cond = y(0) == y0;
A = dsolve(eqn, cond);
s1 = A;
S1 = s1;
for x = t0 : h : h*(numstep)
subs(x);
if x == t0
S1 = subs(s1,x);
else
S1 = [subs(S1), subs(s1,vpa(x))];
end
end
end

Solving a complex double-integral equation for a third variable

I'm trying to solve the following equation for the variable h:
F is the normal cumulative distribution function
f is the probability density function of chi-square distribution.
I want to solve it numerically using Matlab.
First I tried to solve the problem with a simpler version of function F and f.
Then, I tried to solve the problem as below:
n = 3; % n0 in the equation
k = 2;
P = 0.99; % P* in the equation
F = #(x,y,h) normcdf(h./sqrt((n-1)*(1./x+1./y)));
g1 = #(y,h)integral(#(x) F(x,y,h).*chi2pdf(x,n),0,Inf, 'ArrayValued', true);
g2 = #(h) integral(#(y) (g1(y,h).^(k-1)).*chi2pdf(y,n),0,Inf)-P;
bsolve = fzero(g2,0)
I obtained an answer of 5.1496. The problem is that this answer seems wrong.
There is a paper which provides a table of h values obtained by solving the above equation. This paper was published in 1984, when the computer power was not good enough to solve the equation quickly. They solved it with various values:
n0 = 3:20, 30:10:50
k = 2:10
P* = 0.9, 0.95 and 0.99
They provide the value of h in each case.
Now I'm trying to solve this equation and get the value of h with different values of n0, k and P* (for example n0=25, k=12 and P*=0.975), where the paper does not provide the value of h.
The Matlab code above gives me different values of h than the paper.
For example:
n0=3, k=2 and P*=0.99: my code gives h = 5.1496, the paper gives h = 10.276.
n0=10, k=4 and P*=0.9: my code gives h = 2.7262, the paper gives h = 2.912.
The author says
The integrals were evaluated using 32 point Gauss-Laguerre numerical quadrature. This was accomplished by evaluating the inner integral at the appropriate 32 values of y which were available from the IBM subroutine QA32. The inner integral was also evaluated using 32 point Gauss-Laguerre numerical quadrature. Each of the 32 values of the inner integral was raised to the k-1 power and multiplied by the appropriate constant.
Matlab seems to use the same method of quadrature:
q = integral(fun,xmin,xmax) numerically integrates function fun from xmin to xmax using global adaptive quadrature and default error tolerances.
Does any one have any idea which results are correct? Either I have made some mistake(s) in the code, or the paper could be wrong - possibly because the author used only 32 values in estimating the integrals?
This does work, but the chi-squared distribution has (n-1) degrees of freedom, not n as in the code posted. If that's fixed then the Rinott's constant values agree with literature. Or at least, the literature that isn't behind a paywall. Can't speak to the 1984 Wilcox.

Unexpected result with DFT in MATLAB

I have a problem when calculate discrete Fourier transform in MATLAB, apparently get the right result but when plot the amplitude of the frequencies obtained you can see values very close to zero which should be exactly zero. I use my own implementation:
function [y] = Discrete_Fourier_Transform(x)
N=length(x);
y=zeros(1,N);
for k = 1:N
for n = 1:N
y(k) = y(k) + x(n)*exp( -1j*2*pi*(n-1)*(k-1)/N );
end;
end;
end
I know it's better to use fft of MATLAB, but I need to use my own implementation as it is for college.
The code I used to generate the square wave:
x = [ones(1,8), -ones(1,8)];
for i=1:63
x = [x, ones(1,8), -ones(1,8)];
end
MATLAB version: R2013a(8.1.0.604) 64 bits
I have tried everything that has happened to me but I do not have much experience using MATLAB and I have not found information relevant to this issue in forums. I hope someone can help me.
Thanks in advance.
This will be a numerical problem. The values are in the range of 1e-15, while the DFT of your signal has values in the range of 1e+02. Most likely this won't lead to any errors when doing further processing. You can calculate the total squared error between your DFT and the MATLAB fft function by
y = fft(x);
yh = Discrete_Fourier_Transform(x);
sum(abs(yh - y).^2)
ans =
3.1327e-20
which is basically zero. I would therefore conclude: your DFT function works just fine.
Just one small remark: You can easily vectorize the DFT.
n = 0:1:N-1;
k = 0:1:N-1;
y = exp(-1j*2*pi/N * n'*k) * x(:);
With n'*k you create a matrix with all combinations of n and k. You then take the exp(...) of each of those matrix elements. With x(:) you make sure x is a column vector, so you can do the matrix multiplication (...)*x which automatically sums over all k's. Actually, I just notice, this is exactly the well-known matrix form of the DFT.

Get integrated vector values

I am trying to integrate the sine-function. My goal is to get not just the value of the area inbetween a certain distance but the specific values of the integrated course.
One way to achieve this is by using cumtrapz. I want to get the same result using integral or quad. So I am wondering if there is something like cumquad?
I tried to write something for myself but it works very slow and seems to be even worse than cumtrapz. Later on I want to integrate measured data. So it won't be as simple as a sine.
Here is my current code:
a = 0; b = 10;
x = a:0.1:b;
y = 2*sin(3*x);
pp = spline(x,y);
y2=zeros(1,length(y));
y3=zeros(1,length(y));
y2(1)=integral(#(x)ppval(pp,x),x(1),x(2));
y3(1)=integral(#(x)ppval(pp,x),x(1),x(2));
for a=2:(length(y)-1)
y2(a) = y2(a-1)+integral(#(x)ppval(pp,x),x(a-1),x(a));
y3(a) = y3(a-1)+quad(#(x)ppval(pp,x),x(a-1),x(a));
end
y4=cumtrapz(x,y);
% y5=cumsum(y);
plot(x,y)
hold on
plot(x,y2,'-ro')
plot(x,y3,'-kx')
plot(x,y4,'g')
syms x % compare with analytical result
ya=2*sin(3*x);
ya5=int(ya)+(2/3);
ezplot(x,ya5)
Using integral
I don't think there is a way to have MATLAB return the integral along the path, so you are correct in performing the integration one Δx at a time.
The slowness comes from the loop and subsequent restart of every integral call.
You can avoid the loop by posing the integral over every interval as a vector-valued function.
The Math
Suppose we divide x into N-1 intervals with N total boundaries and denote an interval boundary as xn where n ∈{1,2,3...,N} such that x1 ≤ x2 ≤ x3 ... ≤ xN.
Then any integral over the interval would be
Using the u-substitution:
The integral becomes:
where Δxn = xn - xn-1
The Code
So now, we can pose the interval integration of any function by specifying the lower bound xn-1, specifying the interval width Δx, and integrating from 0 to 1.
The best part is that if the lower bound and interval widths are vectors, we can create a vector-valued function in terms of u and have integral integrate with the option 'ArrayValued' = true.
x = a:0.1:b;
xnm1 = x(1:end-1);
dx = x(2:end) - xnm1;
fx = #(x) 2*sin(3*x);
f = #(u) dx .* fx(dx*u+xnm1);
y = cumsum([0,integral(#(u)f(u),0,1,'ArrayValued',true)]);
The cumsum accounts for the fact that each integral over a given interval needs to have the value of the previous interval added to it.
On my machine, this is at least order of magnitude faster than the loop version and gets better as the interval count increases.
Using ode45
Use can also use ode45 to perform the integration.
It is not nearly as efficient as the integral method, but it may be easier conceptually and look cleaner.
In fact, ode45 is about 10 times slower than the integral method above when required to return an absolute error on par with that of integral.
a = 0;
b = 10;
% These options are necessary to approach the accuracy of integral
opt = odeset('RelTol',100*eps(),'AbsTol',eps());
sol = ode45(#(x,y) 2*sin(3*x),[a,b],0,opt);
x = a:0.01:b;
yint = deval(sol,x);