Create flexible function handle - matlab

I am using numerical integration in MATLAB, with one varibale to integrate over but the function also contains a variable number of terms depending on the dimension of my data. Right now this looks like the following for the 2-dimensional case:
for t = 1:T
fxt = #(u) exp(-0.5*(x(t,1)-theta*norminv(u,0,1)).^2) .* ...
exp(-0.5*(x(t,2) -theta*norminv(u,0,1)).^2);
f(t) = integral(fxt,1e-4,1-1e-4,'AbsTol',1e-3);
end
I would like to have this function flexible in the sense that there could be any number of data points in, each in the following term:
exp(-0.5*(x(t,i) -theta*norminv(u,0,1)).^2);
I hope this is understandable.

If x and u have a valid dimension match (vector-vector or array-scalar) for the subtraction, you can put the whole matrix x into the handle and pass it to the integral function using the name-parameter pair ('ArrayValued',true):
fxt = #(u) exp(-0.5*(x - theta*norminv(u,0,1)).^2) .* ...
exp(-0.5*(x - theta*norminv(u,0,1)).^2);
f = integral(fxt,1e-4,1-1e-4,'AbsTol',1e-3,'ArrayValued',true);
[Documentation]
You may need a loop if integral ever passes a vector u into the handle.
But in looking at how the integral function is written, the integration nodes are entered as scalars for array-valued functions, so the loop shouldn't be necessary unless some weird dimension-mismatch error is thrown.
Array-Valued Output
In response to the comments below, you could try this function handle:
fx = #(u,t,k) prod(exp(-0.5*(x(t,1:k)-theta*norminv(u,0,1)).^2),2);
Then your current loop would look like
fx = #(u,t,k) prod(exp(-0.5*(x(t,1:k)-theta*norminv(u,0,1)).^2),2);
k = 2;
for t = 1:T
f(t) = integral(#(u)fx(u,t,k),1e-4,1-1e-4,'AbsTol',1e-3,'ArrayValued',true);
end
The ArrayValued flag is needed since x and u will have a dimension mismatch.
In this form, another loop would be needed to sweep through the k indexes.
However, we can improve this function by skipping the loop altogether since each iterate of the loop is independent by using the ArrayValued mode:
fx = #(u,k) prod(exp(-0.5*(x(:,1:k)-theta*norminv(u,0,1)).^2),2);
k = 2;
f = integral(#(u)fx(u,k),1e-4,1-1e-4,'AbsTol',1e-3,'ArrayValued',true);
Vector-Valued Output
If ArrayValued is not desired, which may be the case if the integration requires a lot of subdivisions and a vector-valued u is preferable, you can also try a recursive version of the handle using cell arrays:
% x has size [T,K]
fx = cell(K,1);
fx{1} = #(u,t) exp(-0.5*(x(t,1) - theta*norminv(u,0,1)).^2);
for k = 2:K
fx{k} = #(u,t) fx{k-1}(u,t).*exp(-0.5*(x(t,k) - theta*norminv(u,0,1)).^2);
end
f(T) = 0;
k = 2;
for t = 1:T
f(t) = integral(#(u)fx{k}(u,t),1e-4,1-1e-4,'AbsTol',1e-3);
end

ThanksTroy but now I run into the follwing:
x = [0.3,0.8;1.5,-0.7];
T = size(x,1);
k = size(x,2);
theta= 1;
fx = #(u,t,k) prod(exp(-0.5*(x(t,1:k) - theta*norminv(u,0,1))^2));
for t = 1,T
f(t) = integral(#(u)fx(u,t,k),1e-4,1-1e-4,'AbsTol',1e-3);
end
Error using -
Matrix dimensions must agree.
Error in #(u,t,k)prod(exp(-0.5*(x(t,1:k)-theta*norminv(u,0,1))^2))
Error in #(u)fx(u,t,k)
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);

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.

Matrix Multiplication Error: Matrix dimensions must agree

I have this code:
function main()
a = 1.0e+04 * [0.005055052938847,0.010897917816899,0.022355965424711,0.043081981439108,0.077074049394439,0.127074049394439,0.193081981439108,0.272355965424711,0.360897917816899,0.455055052938847,0.552256864601221,0.650978664311931,0.750415022011379,0.850172973479352,0.950071110045004,1.050028912038499,1.150011648830086]
B = 1.0e+04 * [1.215101736363023,0.697166188613023,0.400000000000000,0.229500515964941,0.131676217070435,0.075549399394941,0.043346565354951,0.024870147785673,0.014269279372341,0.008187017446000,0.004697311820178,0.002695088715947,0.001546310627203,0.000887197716963,0.000509030834515,0.000292057097908,0.000167568136653
m = timeloop(a,B);
end
function m = timeloop(a,B)
st = zeros(49,4);
t = 0:0.001:0.05;
for i = (1:49)
st(i+1,1:4) = next_state(st(i,1:4),a,B,1e-4);
end
m = mean(prod(state,2))
end
function next_state = next_state(state,alpha,beta,dt)
nch = size(state,2);
p01 = rand(1,nch);
alphadt = repmat(alpha,1,nch)*dt;
betadt = repmat(beta,1,nch)*dt;
next_state1 = (p01<alphadt) .* (state==0);
next_state0 = (p01<betadt) .* (state==1);
next_state = state + next_state1 - next_state0;
end
but it gives me the following error:
Matrix dimensions must agree.
Error in q3>next_state (line 59)
next_state1 = (p01<alphadt) .* (state==0);
Error in q3>timeloop (line 49)
st(i+1,1:4) = next_state(st(i,1:4),a,B,1e-4);
Error in q3 (line 4)
m = timeloop(a,B);
Error in run (line 86)
evalin('caller', [script ';']);
I've tried changing the multiplication to just * with no improvement. What I've looked up online hasn't seemed to be able to help me. I don't understand MATLAB very well so you will have to be very specific in your explanation.
If you debugged your code you would quickly realise the issue.
alpha in next_state is the same as a in main, meaning it is of size 1x3.
You then create alphadt using repmat(alpha,1,4), so it is of size 1x12.
Then you try and do the following
(p01<alphadt) .* (state==0)
% 1x12 .* 1x3
As the error clearly states, your matrix dimensions don't agree.
Because you haven't given any context for what you're trying to achieve, it's not obvious what the solution should be. Perhaps you want to also use repmat on state, or loop over single values from a.

Matlab: fmincon throws error

I am implementing the expression given in the image which is the log-likelihood for AR(p) model.
In this case, p=2. I am using fmincon as the optimization tool. I checked the documentation and other examples over internet regarding the syntax of this command. Still, I am unable to mitigate the problem. Can somebody please help in eliminating the problem?
The following is the error
Warning: Options LargeScale = 'off' and Algorithm = 'trust-region-reflective' conflict.
Ignoring Algorithm and running active-set algorithm. To run trust-region-reflective, set
LargeScale = 'on'. To run active-set without this warning, use Algorithm = 'active-set'.
> In fmincon at 456
In MLE_AR2 at 20
Error using ll_AR2 (line 6)
Not enough input arguments.
Error in fmincon (line 601)
initVals.f = feval(funfcn{3},X,varargin{:});
Error in MLE_AR2 (line 20)
[theta_hat,likelihood] =
fmincon(#ll_AR2,theta0,[],[],[],[],low_theta,up_theta,[],opts);
Caused by:
Failure in initial user-supplied objective function evaluation. FMINCON cannot
continue.
The vector of unknown parameters,
theta_hat = [c, theta0, theta1, theta2] where c = intercept in the original model which is zero ; theta0 = phi1 = 0.195 ; theta1 = -0.95; theta2 = variance of the noise sigma2_epsilon.
The CODE:
clc
clear all
global ERS
var_eps = 1;
epsilon = sqrt(var_eps)*randn(5000,1); % Gaussian signal exciting the AR model
theta0 = ones(4,1); %Initial values of the parameters
low_theta = zeros(4,1); %Lower bound of the parameters
up_theta = 100*ones(4,1); %upper bound of the parameters
opts=optimset('DerivativeCheck','off','Display','off','TolX',1e-6,'TolFun',1e-6,...
'Diagnostics','off','MaxIter', 200, 'LargeScale','off');
ERS(1) = 0.0;
ERS(2) = 0.0;
for t= 3:5000
ERS(t)= 0.1950*ERS(t-1) -0.9500*ERS(t-2)+ epsilon(t); %AR(2) model y
end
[theta_hat,likelihood,exit1] = fmincon(#ll_AR2,theta0,[],[],[],[],low_theta,up_theta,[],opts);
exit(1,1)=exit1;
format long;disp(num2str([theta_hat],5))
function L = ll_AR2(theta,Y)
rho0 = theta(1); %c
rho1 = theta(2); %phi1
rho2 = theta(3); %phi2
sigma2_epsilon = theta(4);
T= size(Y,1);
p=2;
mu_p = rho0./(1-rho1-rho2); %mean of Y for the first p samples
%changed sign of the log likelihood expression
cov_p = xcov(Y);
L1 = (Y(3:end) - rho0 - rho1.*Y(1:end-1) - rho2.*Y(1:end-2)).^2;
L = (p/2).*(log(2*pi)) + (p/2).*log(sigma2_epsilon) - 0.5*log(det(inv(cov_p))) + 0.5*(sigma2_epsilon^-1).*(Y(p) - mu_p)'.*inv(cov_p).*(Y(p) - mu_p)+...
(T-p).*0.5*log(2*pi) + 0.5*(T-p).*log(sigma2_epsilon) + 0.5*(sigma2_epsilon^-1).*L1;
L = sum(L);
end
You are trying to pass constant parameters to the objective function (Y) in addition to the optimization variables (theta).
The right way of doing so is using anonymous function:
Y = ...; %// define your parameter here
fmincon( #(theta) ll_AR2(theta, Y), theta0, [],[],[],[],low_theta,up_theta,[],opts);
Now the objective function, as far as fmincon concerns, depends only on theta.
For more information you can read about anonymous functions and passing const parameters.

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;

Cubic spline interpolation of function

I am trying to interpolate the following function using the MATLAB function spline,
at equidistant points xi = i./n, i = 0,1,...,n, and for n = 2^j, j = 4,5,...,14.
For each calculation, I record the maximum error at the points x = 0:0.001:1 and plot these errors against n using a loglog plot.
Below is the code,
index=1
for j = 4:1:14;
n = 2^j;
i = 0:1:n;
xi = i./n;
yi = ((exp(3*xi))*sin(200.*(xi.^2))) ./(1+20.*(xi.^2));
x = 0:.001:1;
ye = ((exp(3*x))*sin(200*x.^2)) ./(1+20*x.^2);
yp = spline(x,xi,yi);
err = ye - yp;
merr(index) = max(err);
index = index+1;
end
n1 = 10:10:170;
loglog(n1, merr,'.')
xlabel('n');
ylabel('errors');
title('Cubic Splines');
but when I run the code, I got the following error:
Error using * Inner matrix dimensions must agree.
Error in (line 9) yi = ((exp(3*xi))sin(200.(xi.^2)))
./(1+20.*(xi.^2));
I'm just starting learning MatLab, can anyone help?
You want element-wise multiplication (.*) for the following part of code:
yi = ((exp(3*xi))*sin(200.*(xi.^2))) ./(1+20.*(xi.^2));
should be
yi = ((exp(3*xi)).*sin(200.*(xi.^2))) ./(1+20.*(xi.^2));
The same issue is present for the computation of ye.
When you use mtimes (*), MATLAB tries to do matrix multiplication, which in your case (1-by-n times 1-by-n) is invalid.
Then you will run into a problem with your spline command. Change it to yp = spline(xi,yi,x); so that the values at which you want to interploate (x) are the last argument.