How to calculate the integral of log-normal distribution with MATLAB - matlab

I want to calculate the part-expectation of log-normal distribution via:
m = 1;
v = 2;
mu = log((m^2)/sqrt(v+m^2));
sigma = sqrt(log(v/(m^2)+1));
syms x;
d = x*lognpdf(x,mu,sigma);
int(d, x, 0, 10);
However, MATLAB says:
Error using symfun>validateArgNames (line 211) Second input must be a
scalar or vector of unique symbolic variables.
Error in symfun (line 45)
y.vars = validateArgNames(inputs);
Error in sym/subsasgn (line 771)
C = symfun(B,[inds{:}]);
Error in lognpdf (line 36) x(x <= 0) = Inf;
Error in untitled (line 7) d = x*lognpdf(x,mu,sigma);
I even tried to just calculate the integral of the pdf by:
m = 1;
v = 2;
mu = log((m^2)/sqrt(v+m^2));
sigma = sqrt(log(v/(m^2)+1));
syms x;
d = lognpdf(x,mu,sigma);
int(d, x, 0, 10);
But there are still errors, and MATLAB says:
Error using symfun>validateArgNames (line 211) Second input must be a
scalar or vector of unique symbolic variables.
Error in symfun (line 45)
y.vars = validateArgNames(inputs);
Error in sym/subsasgn (line 771)
C = symfun(B,[inds{:}]);
Error in lognpdf (line 36) x(x <= 0) = Inf;
Error in untitled (line 7) d = lognpdf(x,mu,sigma);
I really don't know what happened. Should the integral of the pdf be the cdf?

Similar to an answer several months ago, the Statistics Toolbox doesn't support the Symbolic Toolbox currently.
Therefore, you can proceed by hard coding the PDF itself and integrating it:
d = exp(-(log(x)-mu)^2/(2*sigma^2))/(x*sigma*sqrt(2*pi));
int(d, x, 0, 10);
Or you can use the logncdf function, which may be cleaner.

Related

iterating matlab symbolic solve function

I am trying to solve the equation below for array d. I have used the snippet below:
channel_size = 9e-3;
d = [11e-3, 12e-3];
sigma = 0.49;
ee = 727/9806.65;
alpha = d-channel_size;
sym('p',[1 2])
for i = 1:2
eqn = alpha == (4.3^(1/7))*(p^(3/11))*(((1-(sigma^2))/ee)^(7/5))/(d.^(1/6))
S = solve(eqn, p)*0.015;
vpa(S/13e-12)
end
In fact, I should get two number corresponding to d(1) and d(2), but it does not work and this error appears:
Error using mupadmex
Error in MuPAD command: Operands are invalid. [linalg::matlinsolve]
Error in sym/privBinaryOp (line 1693)
Csym = mupadmex(op,args{1}.s, args{2}.s, varargin{:});
Error in sym/mrdivide (line 232)
X = privBinaryOp(A, B, 'symobj::mrdivide');
Declaring (d.^(1/6)) is wrong and instead (d(i)^(1/6)) should be used. In addition, as alpha = d-channel_size, in the equation, I should also declare alpha(i) instead of simple alpha.

Evaluate symbolic function in Matlab

I've defined a function in Matlab like this:
clg = 2*pi*(alpha-alphai+0.5*A(1));
where A is an array which depends on alpha.
I want to evaluate clg for aplha=0.53.
I've tried subs(clg, alpha, 0.53), but It gives me a bunch of weird errors:
Error using sym/subs>normalize (line 210)
Entries in second argument must be scalar.
Error in sym/subs>mupadsubs (line 136)
[X2,Y2,symX,symY] = normalize(X,Y); %#ok
Error in sym/subs (line 124)
G = mupadsubs(F,X,Y);
Error in integral (line 45)
subs(clg, alpha, 0.53)
Any idea on how to achieve that?
Thanks!
I have no problem about your question.
>> syms x x1 x2
>> clg = 2*pi*(x-x1+0.5*x2);
>> subs(clg,x,0.53)
ans =
2*pi*(x2/2 - x1 + 53/100)
I am trying to reproduce the problem, but this works:
syms x
%A is a symbolic matrix that depends on x
A = inv([10*x, 2*x, 3*x;
4*x, 10, 6*x;
7*x, 8*x, 10*x])
%y is a symbolic expression defined such that
%it depends on A, but collapses to an expression of x
y = x + 0.5*A(2,2)
%subs returns a symbolic (in this case fraction) evaluation:
subs(y, x, 3)
%eval returns a numeric evaluation:
x = 3
eval(y)
(I have encountered the same error message as you in my own code, but have not yet hunted down its source.)

Questions with integral2 , Double, Syms and Dot calucations

I got 2 questions here.
1. If I have y = a*x^2 + 5. What function can make it into y = a.*x.^2 +5. As you seen, dot was inserted.
It's easy, but kinda diffcult to describe, but please have patience with me. Thank you so much.
First, let me make a very simple example of my problem.
If I want to calucate Y = F(x=1)+ 2.^2, and I know F(x=1) = a+b,(a and b are syms). This means Y = a + b + 4. Problem is here,
Matlab give me error if I write down as.
F = function( .... ); <==== output of function is F(X=1), and = F(x=1) = a+b
Y = integral2( F + 2.^2, .. , .. ,..)
However, if I just copy the output of F as
Y = integral2( a+b + 2.^2, .. , .. ,..)
Now it works!!!
Ok. Please allow me to talk about my code here. I am trying to find a double interation by using integral2. One part of my equcation(which is Y) is from another int output(which is F). Matlab will give ERROR for code below:
clear all;
a=4;
la1=1/(pi*500^2); la2= la1*5;
p1=25; p2=p1/25;
sgma2=10^(-11);
index=1;
g=2./a;
syms r u1 u2
powe= -2 ;
seta= 10^powe;
xNor = ( (u2./u1).^(a./2) + 1 ).^(2./a);
x = (xNor).^(0.5) * seta^(-1/a);
fun1 = r./(1+ r.^a );
out1 = int(fun1, x, Inf) ; %== This is my F in my example
q=pi.*(la1.*p1.^(2./a)+la2.*p2.^(2./a));
yi = #(u2,u1) exp(-u2.*(1+2.*...
( out1 )./... %=== out1 is the problem here.
( (( (u2./u1).^(a./2) + 1 ).^(2./a)).*seta.^(-2./a)))).*...
exp(-sgma2.*q.^(-a./2).* seta.*u2.^(a./2)./...
((( (u2./u1).^(a./2) + 1 ).^(2./a)).^(a./2)) );
maxF =#(u2) u2;
out2 = integral2(yi,0,Inf,0 ,maxF) % == this is Y in my previous example.
However, since I know the out1 = pi/4 - atan(10*(u2^2/u1^2 + 1)^(1/2))/2 (no dot,1/2, not 1./2). Instead of writing down out1, I will just type the equaction and add dot in the
yi = #(u2,u1) exp(-u2.*(1+2.*...
( pi./4 - atan(10.*(u2.^2./u1.^2 + 1).^(1./2))./2 )./... %=== not "out1"
( (( (u2./u1).^(a./2) + 1 ).^(2./a)).*seta.^(-2./a)))).*...
exp(-sgma2.*q.^(-a./2).* seta.*u2.^(a./2)./...
((( (u2./u1).^(a./2) + 1 ).^(2./a)).^(a./2)) );
Now the code is working!!!! The final output is = 0.9957.
Dear friends, I already spend a long time on this, but I still can not find out the problem. Could you please take a deeper look for me. Please copy the code to you matlab and test. Thank you so much.
Below is the error given by matlab, if I just use "out1" in yi = #(u2,u1) ......
Error using integralCalc/finalInputChecks (line 511)
Input function must return 'double' or 'single' values. Found 'sym'.
Error in integralCalc/iterateScalarValued (line 315)
finalInputChecks(x,fx);
Error in integralCalc/vadapt (line 133)
[q,errbnd] = iterateScalarValued(u,tinterval,pathlen);
Error in integralCalc (line 76)
[q,errbnd] = vadapt(#AtoBInvTransform,interval);
Error in
integral2Calc>#(xi,y1i,y2i)integralCalc(#(y)fun(xi*ones(size(y)),y),y1i,y2i,opstruct.integralOptions)
(line 18)
innerintegral = #(x)arrayfun(#(xi,y1i,y2i)integralCalc( ...
Error in
integral2Calc>#(x)arrayfun(#(xi,y1i,y2i)integralCalc(#(y)fun(xi*ones(size(y)),y),y1i,y2i,opstruct.integralOptions),x,ymin(x),ymax(x))
(line 18)
innerintegral = #(x)arrayfun(#(xi,y1i,y2i)integralCalc( ...
Error in integralCalc/iterateScalarValued (line 314)
fx = FUN(t);
Error in integralCalc/vadapt (line 133)
[q,errbnd] = iterateScalarValued(u,tinterval,pathlen);
Error in integralCalc (line 84)
[q,errbnd] = vadapt(#AToInfInvTransform,interval);
Error in integral2Calc>integral2i (line 21)
[q,errbnd] = integralCalc(innerintegral,xmin,xmax,opstruct.integralOptions);
Error in integral2Calc (line 8)
[q,errbnd] = integral2i(fun,xmin,xmax,ymin,ymax,optionstruct);
Error in integral2 (line 107)
Q = integral2Calc(fun,xmin,xmax,yminfun,ymaxfun,opstruct);
Error in ref7_equ11n2 (line 129)
out2 = integral2(yi,0,Inf,0 ,maxF)
The documentation of the function integral2 states:
integral2 - Numerically evaluate double integral
You won't be able to use integral2 with symbolic expressions, unless you convert them to function handles using matlabfunction.

MATLAB strange error Gamma function numerical integration

i try to run the following in order to integrate numerically:
nu = 8;
psi=-0.2;
lambda = 1;
git = #(u) tpdf((0 - lambda * skewtdis_inverse(u, nu, psi)), nu);
g(t,i) = integral(git,1e-10,1-1e-10,'AbsTol',1e-16);
where tpdf is a matlab function and skewtdis:inverse looks like this:
function inv = skewtdis_inverse(u, nu, lambda)
% PURPOSE: returns the inverse cdf at u of Hansen's (1994) 'skewed t' distribution
c = gamma((nu+1)/2)/(sqrt(pi*(nu-2))*gamma(nu/2));
a = 4*lambda*c*((nu-2)/(nu-1));
b = sqrt(1 + 3*lambda^2 - a^2);
if (u<(1-lambda)/2);
inv = (1-lambda)/b*sqrt((nu-2)./nu)*tinv(u/(1-lambda),nu)-a/b;
elseif (u>=(1-lambda)/2);
inv = (1+lambda)/b*sqrt((nu-2)./nu).*tinv(0.5+1/(1+lambda)*(u-(1-lambda)/2),nu)-a/b;
end
What i get out is:
Error in skewtdis_inverse (line 6)
c = gamma((nu+1)/2)/(sqrt(pi*(nu-2))*gamma(nu/2));
Output argument "inv" (and maybe others) not assigned during call to "F:\Xyz\skewtdis_inverse.m>skewtdis_inverse".
Error in #(u)tpdf((0-lambda*skewtdis_inverse(u,nu,psi)),nu)
Error in integralCalc/iterateScalarValued (line 314)
fx = FUN(t);
Error in integralCalc/vadapt (line 133)
[q,errbnd] = iterateScalarValued(u,tinterval,pathlen);
Error in integralCalc (line 76)
[q,errbnd] = vadapt(#AtoBInvTransform,interval);
Error in integral (line 89)
Q = integralCalc(fun,a,b,opstruct);
If i , however call the function in thr handle directly there are no Problems:
tpdf((0 - lambda * skewtdis_inverse(1e-10, nu, psi)), nu)
ans =
1.4092e-11
tpdf((0 - lambda * skewtdis_inverse(1-1e-10, nu, psi)), nu)
ans =
7.0108e-10
Your effort is highly appreciated!
By default, integral expects the function handle to take a vector input.
In your code, the if-statement creates a complication since the condition will evaluate to true only if all elements of u satisfy it.
So, if u is a vector that has elements both greater than and less than (1-lambda)/2, inv will never be assigned.
There are two options:
Put the if-statement in a for-loop and iterate over all of the elements of u.
Use logical indexes for the assignment.
The second option is faster for large element count and, in my opinion, cleaner:
inv = u; % Allocation
IsBelow = u < (1-lambda)/2; % Below the threshold
IsAbove = ~IsBelow ; % Above the threshold
inv(IsBelow) = (1-lambda)/b*sqrt((nu-2)./nu)*tinv(u(IsBelow)/(1-lambda),nu)-a/b;
inv(IsAbove) = (1+lambda)/b*sqrt((nu-2)./nu)*tinv(0.5+1/(1+lambda)*(u(IsAbove)-(1-lambda)/2),nu)-a/b;

How to write Lognormal Distribution using matlab

I am facing this problem.
Error using lognfit (line 52)
The data in X must be positive.
Error in testing (line 173)
[a(i-100,j) b(i-100,j)] = lognfit(x);
My code is as follows:
for i = 101:401
for j = 1:37
x = Gco(i-100:i,j).';
[f,xv] = ecdf(x);
[a(i-100,j) b(i-100,j)] = lognfit(x); % a is mu and b is sigma