Integration of bivariate lognormal density function - matlab

rho = 0.8;
ff = #(x, y) (exp(-(((log(x)-10).^2 - 2.* rho .* (log(x)-10) .* (log(y)-10)+(log(y)-10).^2)./(2 .* (1-rho.^2))))./(2.*pi.*sqrt(1-rho.^2).*x.*y));
syms x y
vpaintegral(vpaintegral(ff, x, [0 inf]), y, [0 inf])
Why is the above integration of bivariate lognormal density function in Matlab not 1?
Note: the log transformation of this lognormal bivariate random variable is a bivariate normal random variable with a mean (10, 10), and covariance matrix (1, rho, rho, 1).

Using integral2:
we get 0.9994,
% MATLAB R2019a
rho = 0.8;
ff = #(x, y) (exp(-(((log(x)-10).^2-2.*rho.*(log(x)-10).*(log(y)-10)+(log(y)-10).^2)./(2.*(1-rho.^2))))./(2.*pi.*sqrt(1-rho.^2).*x.*y));
area = integral2(ff,0,inf,0,inf) % area = 0.9994
but adjusting the tolerance gives the desired result.
area = integral2(ff,0,inf,0,inf,'Method','iterated','AbsTol',0,'RelTol',1e-10)
ans = 1.0000
format long
area
ans = 0.999999999999998
Not too shabby.
Using vpaintegral from the Symbolic Toolbox:
You can also adjust the tolerance for vpaintegral.
Using a Relative Error Tolerance of 1e-4 got the job done. This parameter greatly affects computation time.
syms x y
area = vpaintegral(vpaintegral(ff, x, [0 inf],'RelTol', 1e-4, 'AbsTol', 0), y, [0 inf],'RelTol', 1e-4, 'AbsTol', 0)
area = 1.0

Related

{OFF} How can I derivate a spline interpolation function on matlab?

I have lab test data from a battery discharge curve. The data consistes in 22 points of voltage versus time. In matlab I have traced an interpolation curve through spline interpolation, but I wish to make the derivative of this plot, how can I do this?
enter image description here
Code
x = [0; 3600 ;7200 ;10800; 14400; 18000; 21600; 25200 ;28800;...
32400; 36000 ;39600 ;43200 ;46800; 50400 ;54000; 57600; 61200;...
64800 ;68400 ;72000; 74880];
y = [12.75; 12.40; 12.38; 12.34; 12.30; 12.26 ;12.21 ;12.17 ;...
12.12; 12.07; 12.02 ;11.97 ;11.91 ;11.85; 11.79; 11.72; 11.65;...
11.56 ;11.46 ;11.35 ;11.17; 10.59];
f = fit( x, y,'cubicinterp')
You can use gradient of y/x:
f = fit( x, y,'cubicinterp')
df = gradient(f(x)); % f'x
dx = gradient(x); % dx
dfx = df ./ dx;
plot(x, y, x, dfx);

Can I use polyfit with a range instead of a scalar for parameter N?

The polyfit function expects a scalar value for the polynomial degree n, e.g.
P = polyfit(X, Y, 3)
which suggests a for loop should be used to determine a range of polynomials (say degree 2 to degree 4) fitting the same curve:
% Fit a given curve with a series of polynomials
% of given degrees
X = 1:6; % Range of x in the sample
Y0 = [10, 11, 21, 2, 3, 7]; % Sample
DEG = 2:6; % Degrees to use for polynomials
plot(X, Y0) % Plot sample for reference
for n = DEG
hold on
P = polyfit(X, Y0, n); % Fitting polynomial, degree n
Y = polyval(P, X); % Compute y for this polynomial
plot(X, Y)
endfor
Is there a way to simplify this code and turn it into 'all array' by using the range DEG directly in the function? I tried several variation around polyfit(X, Y0, DEG), but Octave keeps telling me:
error: polyfit: N must be a non-negative integer
Any help appreciated.
This is what arrayfun is for:
octave:1> X = 1:6;
octave:2> Y0 = [10, 11, 21, 2, 3, 7];
octave:3> DEG = 2:6;
octave:4> arrayfun (#(n) polyfit (X, Y0, n), DEG, "UniformOutput", false)
ans =
{
[1,1] =
-0.37500 0.96786 11.30000
[1,2] =
1.0833 -11.7500 35.3095 -16.0000
[1,3] =
0.43750 -5.04167 17.43750 -18.94048 15.50000
[1,4] =
-1.2750 22.7500 -150.9583 456.2500 -612.7667 296.0000
[1,5] =
-0.31438 5.32693 -32.26604 80.10905 -54.29889 -58.20494 69.64828
}

How to fit polynomial into some error bars data

I need to fit data e.g. x, y, CI (where CI is confidence index of y) in Matlab.
Now, I use this code:
pf = polyfit(x, y, 2);
x1 = min(x):.1:max(x);
y1 = polyval(pf, x1);
figure
hold on
errorbar(x, y, CI, 'ko');
plot(x1, y1, 'k');
hold off
Of course, the fit comes out of some errors bars, and it's correct.
I would like obtain a fit curve closer to the points with a low confidence index, and discard the points with a high confidence index.
Thank you and bye,
Giacomo
What you are looking for are Weighted Least Squares. You can compute them with the function lscov. There is a nice example in its help page, but I'll try to make it clearer.
Let us construct a simple parabola, with a corrupted point
x = (0:0.1:1)';
y = 0.5*x.^2;
y(5) = 3*y(5);
and give some weights
w = ones(size(y));
w(5) = 0.1;
Next build the Vandermonde matrix (see here for the code) and solve the system
%// V = [x.^2 x ones(size(x))];
V = bsxfun(#power, x, 2:-1:0);
coeff = lscov(V, y, w);
The estimated coefficients, with and without the weights, are
x^2 x 1
with weights [0.4797 0.0186 -0.0004]
no weights [0.3322 0.1533 -0.0034]
Note that in your case w will have to be inverted.
If you don't like to build the Vandermonde matrix, and you have a license for the Curve Fitting Toolbox, you can use the following code
ft = fittype('poly2');
opts = fitoptions('Method', 'LinearLeastSquares');
opts.Weights = w;
fitresult = fit(x, y, ft, opts);
and you'll obtain the same result.

Computing an ODE in Matlab

Given a system of the form y' = A*y(t) with solution y(t) = e^(tA)*y(0), where e^A is the matrix exponential (i.e. sum from n=0 to infinity of A^n/n!), how would I use matlab to compute the solution given the values of matrix A and the initial values for y?
That is, given A = [-2.1, 1.6; -3.1, 2.6], y(0) = [1;2], how would I solve for y(t) = [y1; y2] on t = [0:5] in matlab?
I try to use something like
t = 0:5
[y1; y2] = expm(A.*t).*[1;2]
and I'm finding errors in computing the multiplication due to dimensions not agreeing.
Please note that matrix exponential is defined for square matrices. Your attempt to multiply the attenuation coefs with the time vector doesn't give you what you'd want (which should be a 3D matrix that should be exponentiated slice by slice).
One of the simple ways would be this:
A = [-2.1, 1.6; -3.1, 2.6];
t = 0:5;
n = numel(t); %'number of samples'
y = NaN(2, n);
y(:,1) = [1;2];
for k =2:n
y(:,k) = expm(t(k)*A) * y(:,1);
end;
figure();
plot(t, y(1,:), t, y(2,:));
Please note that in MATLAB array are indexed from 1.

matlab pdf estimation (ksdensity) not working

I'm estimating a probability density function (pdf) using matlab.
The code is like this
xi = -2:0.1:2;
a1 = normpdf(xi, 1, 0.3);
a2 = normpdf(xi, -1, 0.3);
subplot(211);
plot(xi, a1+a2);
[f, xs] = ksdensity(a1+a2);
subplot(212);
plot(xs, f);
and pics like this
You see the estimation is not working at all.
So what's wrong here? BTW is there other pdf estimation methods in matlab?
Is this closer to what you expect?
The ksdensity function expects a vector of samples from the distribution, whereas you were feeding it the values of the probability density function.
>> xi = -3:0.1:3;
>> p1 = normpdf(xi, 1, 0.3);
>> p2 = normpdf(xi,-1, 0.3);
>> subplot(211)
>> plot(xi, 0.5*p1+0.5*p2)
>> a1 = 1 + 0.3 * randn(10000,1); % construct the same distribution
>> a2 = -1 + 0.3 * randn(10000,1); % construct the same distribution
>> [f, xs] = ksdensity([a1;a2]);
>> subplot(212)
>> plot(xs, f)
ksdensity gives you the probability distribution (100 points by default) of the input values. Your input value a1+a2 has values that range between 0 and 1.5, with a large potion of those close to 0 and a smaller portion near 1.5. The second plot you see reflects this distribution.
If you want to see two similar plots, put as an input to ksdensity a vector with elements concentrated near -1 and 1.