Matlab ode45 basic setup - matlab

I'm trying to simulate the Morris-Lecar model for neurons with ode45.
I am having trouble initializing the ode45 call, and documentation hasn't been able to help me. I understand that I have to call the ode45 through a function, and call that function from my main script.
I have a limited grasp of ODEs in general, and seem to have trouble understanding the syntax required to initialize the ODE45-call.
Also, I am indicated to use a time range for a variable 'pulse', but there is no input for a time range (which seems to be a variable, not fixed) in the function that takes in input from the main script and sends that with the other function to the ode45 function. The function that feeds into the ode45 has a time input as well, but again I cannot figure out how I can input a time range. The instructions are very clear that the function used in the main script does not take in any time variables.
It would be very appreciated if you could point out any glaring errors I have made in the initialization.
the current (below) version's error code is as following:
Error using ODEequation (line 89)
Not enough input arguments.
Error in odearguments (line 88)
f0 = feval(ode,t0,y0,args{:}); % ODE15I sets args{1} to yp0.
Error in ode45 (line 114)
[neq, tspan, ntspan, next, t0, tfinal, tdir, y0, f0, odeArgs, odeFcn, ...
Error in ODEquestion (line 32)
[t Vm]=ode45(#ODEequation,[-20 20],[-30, 0.1]',[],constants, stim_on, stim_off, amp);
Error in YoonS_Lab3_EBME308_Fall2012 (line 355)
[t Vm] = ODEquestion(20,100,30)
I think this goes back to my non-existing and yet needed time input.
The problem involves
Cm * dVm / dt = -Gm(Vm-Vrest) - Gca Minf (Vm - Eca) - Gk w(Vm - Ek) + pulse(t)
dw/dt = (wInf - w) / Tau-w;
wInf = (1+tanh(Vm/30)) / 2;
mInf = (1+tanh(Vm+1)) / 2;
Tau-w = 5/ (cosh(Vm/60));
Cm = membrane leakage capacticance;
Gm = membrane leakage conductance;
Vm = membrane voltage;
Vrest = membrane voltage # neuron resting
Gca = max Ca conductance through membrane
Gk = max K conductance through membrane;
mInf refers = P ( Ca ion channel open )
wInf refers = P ( K ion channel open )
Tau-w = rate which K channels respond to change in membrane voltage
Eca = reversal potential of Ca
Ek = reversal potential of K
pulse(t) = stimulus applied to neuron
pulse(t) = A (stim-on <= t <= stim-off) or 0 (else);
as the variables.
I have created a function that gets sent to the ode45, as below.
function dy = ODEequation(t, Vm, w, constants, stim_on, stim_off, amp)
wInf = (1 + tan(Vm / 30)) / 2
mInf = (1 + tan((Vm + 1)/ 15)) / 2
tauW = 5/ (cosh(Vm/60))
pulse = amp * ((stim_on < t ) - ( t >= stim_off));
dy(1) = y(1) * ((-constants(2) - constants(4) * constants(9) - constants(5) * y(2)) + (constants(2) * constants(3) + constants(6) * constants(4) * constants(9) + constants(5) * y(2) * constants(7) + constants(11))) / constants(1) ;
dy(2) = = ( constants(8) - y(2) )/constants(10)
dy = dy'
and the function that passes that is as below
function [t Vm] = ODEquestion(stim_on, stim_off, amp)
%i)
Cm = 1;
Gm = 0.5;
Vrest = -50;
Gca = 1.1;
Gk = 2;
Eca = 100;
Ek = -70;
%ii)
Vm(1) = -30;
w(1) = 0.1;
%iii)
wInf = (1 + tan(Vm / 30)) / 2
mInf = (1 + tan((Vm + 1)/ 15)) / 2
tauW = 5/ (cosh(Vm/60))
IC1 = Vm(1) % = -30
IC2 = w(1) % = 0.1
pulse = amp %* ((stim_on < t ) - ( t >= stim_off));
constants = [Cm , Gm, Vrest, Gca, Gk, Eca, Ek, wInf, mInf, tauW, pulse];
[t Vm]=ode45(#ODEequation,[-20 20],[-30, 0.1]',[],constants, stim_on, stim_off, amp);

From help ode45:
ODE45 Solve non-stiff differential equations, medium order method.
[TOUT,YOUT] = ODE45(ODEFUN,TSPAN,Y0) with TSPAN = [T0 TFINAL] integrates
the system of differential equations y' = f(t,y) from time T0 to TFINAL
with initial conditions Y0. ODEFUN is a function handle. For a scalar T
and a vector Y, ODEFUN(T,Y) must return a column vector corresponding
to f(t,y).
So the function ODEFUN expects only two inputs (t and y), whereas your function expects 7 inputs.
You can solve this by following instructions found on this site, or this question:
wrapper = #(t,Vm) ODEequation(t, Vm, w, constants, stim_on, stim_off, amp);
[t Vm]=ode45(wrapper, [-20 20],[-30, 0.1]',[],constants, stim_on, stim_off, amp);
e.g., by creating a small wrapper function that passes all the constants while forwarding the variables inserted by ode45.

Related

MATLAB error using fzero function to solve the loop

My following code generates the plot of V and D values in figure 1. In the graph, the parabolas and straigh lines intersect, and I need to find the roots from the plot from a loop. So I tried to use fzero function, but the error appeared:
Operands to the logical AND (&&) and OR (||) operators must be convertible to logical scalar values. Use the ANY or ALL functions to reduce operands to logical scalar values.
Error in fzero (line 326)
elseif ~isfinite(fx) || ~isreal(fx)
Error in HW1 (line 35)
x=fzero(fun,1);
My code is:
clear all; close all
W = 10000; %[N]
S = 40; %[m^2]
AR = 7;
cd0 = 0.01;
k = 1 / pi / AR;
clalpha = 2*pi;
Tsl=800;
figure(1);hold on; xlabel('V');ylabel('D')
for h=0:1:8;
i=0;
for alpha = 1:0.25:12
i=i+1;
rho(i)=1.2*exp(-h/10.4);
cl(i) = clalpha * alpha * pi/180;
V(i) = sqrt(2*W/rho(i)/S/cl(i));
L(i) = 0.5 * rho(i) * V(i) * V(i) * S * cl(i);
cd(i) = cd0 + k * cl(i) * cl(i);
D(i) = 0.5 * rho(i) * V(i) * V(i) * S * cd(i);
clcd(i) = cl(i)/cd(i);
p(i) = D(i)*V(i);
ang(i) = alpha;
T(i)=Tsl*(rho(i)/1.2).^0.75;
end
figure(1); plot(V,D); hold on
plot(V,T);
end
fun = #(V) 0.5*V.*V.*rho.*S.*cd-T;
x=fzero(fun,1);
Probably, I should not use the fzero function, but the task is to find the roots of V from a plot (figure 1). There are parabolas and straight lines respectively.
From the documentation for fzero(fun,x)
fun: Function to solve, specified as a handle to a scalar-valued function or the name of such a function. fun accepts a scalar x and returns a scalar fun(x).
Your function does not return a scalar value for a scalar input, it always returns a vector which is not valid for a function which is being used with fzero.
1.- Your codes doesn't plot V and D: Your code plots D(V) and T(V)
2.- T is completely flat, despite taking part in the inner for loop calculations with T(i)=Tsl*(rho(i)/1.2).^0.75; as it had to be somehow modified.
But in fact it remains constant for all samples of V, constant temperature (°C ?), and for all laps of the outer for loop sweeping variable h within [0:1:8].
The produced T(V) functions are the flat lines.
3.- Then you try building a 3rd function f that you put as if f(V) only but in fact it's f(V,T) with the right hand side of the function with a numerical expression, without a symbolic expression, the symbolic expression that fzero expects to attempt zero solving.
In MATLAB Zero finding has to be done either symbolically or numerically.
A symbolic zero-finding function like fzero doesn't work with numerical expressions like the ones you have calculated throughout the 2 loops for h and for alpha .
Examples of function expressions solvable by fzero :
3.1.-
fun = #(x)sin(cosh(x));
x0 = 1;
options = optimset('PlotFcns',{#optimplotx,#optimplotfval});
x = fzero(fun,x0,options)
3.2.-
fun = #sin; % function
x0 = 3; % initial point
x = fzero(fun,x0)
3.3.- put the following 3 lines in a separate file, call this file f.m
function y = f(x)
y = x.^3 - 2*x - 5;
and solve
fun = #f; % function
x0 = 2; % initial point
z = fzero(fun,x0)
3.4.- fzeros can solve parametrically
myfun = #(x,c) cos(c*x); % parameterized function
c = 2; % parameter
fun = #(x) myfun(x,c); % function of x alone
x = fzero(fun,0.1)
4.- So since you have already done all the numerical calculations and no symbolic expression is supplied, it's reasonable to solve numerically, not symbolically.
To this purpose there's a really useful function called intersections.m written by Douglas Schwarz available here
clear all; close all;clc
W = 10000; %[N]
S = 40; %[m^2]
AR = 7;
cd0 = 0.01;
k = 1 / pi / AR;
clalpha = 2*pi;
Tsl=800;
figure(1);
ax1=gca
hold(ax1,'on');xlabel(ax1,'V');ylabel(ax1,'D');grid(ax1,'on');
title(ax1,'1st graph');
reczeros={}
for h=0:1:8;
i=0;
for alpha = 1:0.25:12
i=i+1;
rho(i)=1.2*exp(-h/10.4);
cl(i) = clalpha * alpha * pi/180;
V(i) = sqrt(2*W/rho(i)/S/cl(i));
L(i) = 0.5 * rho(i) * V(i) * V(i) * S * cl(i);
cd(i) = cd0 + k * cl(i) * cl(i);
D(i) = 0.5 * rho(i) * V(i) * V(i) * S * cd(i);
clcd(i) = cl(i)/cd(i);
p(i) = D(i)*V(i);
ang(i) = alpha;
T(i)=Tsl*(rho(i)/1.2).^0.75;
end
plot(ax1,V,D); hold(ax1,'on');
plot(ax1,V,T);
[x0,y0]=intersections(V,D,V,T,'robust');
reczeros=[reczeros [x0 y0]];
for k1=1:1:numel(x0)
plot(ax1,x0,y0,'r*');hold(ax1,'on')
end
end
Because at each pair D(V) T(V) there may be no roots, 1 root or more than 1 root, it makes sense to use a cell, reczeros, to store whatever roots obtained.
To read obtained roots in let's say laps 3 and 5:
reczeros{3}
=
55.8850 692.5504
reczeros{5}
=
23.3517 599.5325
55.8657 599.5325
5.- And now the 2nd graph, the function that is defined in a different way as done in the double for loop:
P = 0.5*V.*V.*rho.*S.*cd-T;
figure(2);
ax2=gca
hold(ax2,'on');xlabel(ax2,'V');ylabel(ax2,'P');grid(ax2,'on');
title(ax2,'2nd graph')
plot(ax2,V,P)
plot(ax2,V,T)
[x0,y0]=intersections(V,T,V,P,'robust');
for k1=1:1:numel(x0)
plot(ax2,x0,y0,'r*');hold(ax2,'on')
end
format short
V0=x0
P0=y0
V0 =
86.9993
P0 =
449.2990

Solving 7 equations of first order equations ode45 Matlab

I am trying to solve a system with seven differential equations. And I am having a hard time grapsing the ode45 solver.
These are the equations:
ω2_dot = -0.75 ω1 ω3
ω1_dot = 0.75 ω2 ω3 + 0.2
ω3_dot = 0
q1_dot = 1/2(ω1q4 + ω2q3 - ω3q2)
q2_dot = 1/2(ω2q4 + ω3q1 - ω1q3)
q3_dot = 1/2(ω3q4 + ω1q2 - ω2q2)
q4_dot = -1/2(ω1q1 + ω2q2 + ω3q3)
The initial values are listed in the inital_val in the same order. Here is what I have so far:
inital_val = [1 -1 2 0 0 0 1];
timespan = [0:0.05:3.95];
[result t] = ode45(#soe,timespan,inital_val);
function [results,t]=soe(inital_val, timespan)
omega1_dot = -0.75*omega2*omega3;
omega2_dot = 0.75*omega2*omega3+0.2;
omega3_dot = 0;
q1_dot = (1/2)*(q4*omega1+omega2*q3-omega3*q2);
q2_dot = (1/2)*(q4*omega2+omega3*q1-omega1*q3);
q3_dot = (1/2)*(q4*omega3+omega1*q2-omega2*q2);
q4_dot = (1/2)*(q1*omega1+q2*omega2+q3*omega3);
results = [omega1 omega2 omega3 q1 q2 q3 q4];
end
However, it gives me this error message, which makes sense but I then don't know how to fix it:
Unrecognized function or variable 'omega2'.
Error in ode45_part>soe (line 10)
omega1_dot = -0.75*omega2*omega3;
Error in odearguments (line 90)
f0 = feval(ode,t0,y0,args{:}); % ODE15I sets args{1} to yp0.
Error in ode45 (line 115)
odearguments(FcnHandlesUsed, solver_name, ode, tspan, y0, options, varargin);
Error in ode45_part (line 7)
[result t] = ode45(#soe,timespan,inital_val);
Any help would be much appreciated
There are two fundamental problems with your code. First problem is you don't have the correct signature of the derivative function needed for use with ode45( ). Second problem is that blindly integrating quaternion elements this way will lead to non-unit quaternions. I don't know of an easy way to enforce this restriction when using ode45( ).
Let's tackle the easy problem first, the derivative function signature. Also your use of variables inside this function isn't correct. It needs to be like this:
function dy = soe(t,y) % Required signature is (time,state_vector)
% Pick off the named variables from the state vector y
omega1 = y(1);
omega2 = y(2);
omega3 = y(3);
q1 = y(4);
q2 = y(5);
q3 = y(6);
q4 = y(7);
% Calculate the variable derivatives
omega1_dot = -0.75*omega2*omega3; % IS THIS A TYPO? Should it be omega1*omega3?
omega2_dot = 0.75*omega2*omega3+0.2;
omega3_dot = 0;
q1_dot = (1/2)*(q4*omega1+omega2*q3-omega3*q2);
q2_dot = (1/2)*(q4*omega2+omega3*q1-omega1*q3);
q3_dot = (1/2)*(q4*omega3+omega1*q2-omega2*q2);
q4_dot = (1/2)*(q1*omega1+q2*omega2+q3*omega3);
% Group variable derivatives into a single column vector
dy = [omega1dot; omega2dot; omega3dot; q1_dot; q2_dot; q3_dot; q4_dot];
end
Also your angular rate initial values seem completely unreasonable for a rotation problem. They will be interpreted as [1 -1 2] radians/second. I suspect you wanted degrees/second for this, so you will need to scale down those values.
The second problem, that of keeping the quaternion elements forming a unit quaternion, is not going to be easy to overcome using ode45( ). All of the little integration errors will creep in driving the quaternion magnitude away from 1. Any subsequent use of this quaternion in your other code will have problems because of this. My only advice in this is to maybe abandon ode45( ) altogether and write your own custom integrator (e.g., RK4) so that at each step you can re-normalize the quaternion elements.
I am not sure what your inital_val is supposed to represent, but here you can at least run the following snippet and fix/change accordingly.
clear; clc;
y0 = [1 -1 2 0 0 0 1];
tspan = [0:0.05:3.95];
[t, y] = ode45(#(t, y) odefcn(t, y), tspan, y0);
function dydt = odefcn(t, y)
dydt = zeros(7, 1);
dydt(2) = -0.75 * y(1) * y(3);
dydt(1) = 0.75 * y(2) * y(3) + 0.2;
dydt(3) = 0;
dydt(4) = 1 / 2 * (y(1) * y(7) + y(2) * y(6) - y(3) * y(5));
dydt(5) = 1 / 2 * (y(2) * y(7) + y(3) * y(4) - y(1) * y(6));
dydt(6) = 1 / 2 * (y(3) * y(7) + y(1) * y(5) - y(2) * y(5));
dydt(7) = -1 / 2 * (y(1) * y(4) + y(2) * y(5) + y(3) * y(6));
end
Note that you need dydt = zeros(7, 1) because otherwise the code creates a column vector. Without it, you may run into problems.

MATLAB: Nonlinear fitting with MultiStart finds local but not global minimum

I'm fitting a function to some nonlinear data. However, the output that I get is:
Attempt to execute SCRIPT MultiStart as a function:
/MATLAB Drive/Amsterdam/2 Fitting/MultiStart.m
Error in MultiStart (line 42)
ms = MultiStart('PlotFcn',#gsplotbestf);
This is my code. I've specified the parameters, the initial values, the objective function and the bounds. My code does find a local minimum, but then can't find the global one.
function [EPSC, IPSC, CPSC, t] = generate_current(G_max_chl, G_max_glu, EGlu, EChl, Vm, tau_rise_In, tau_decay_In, tau_rise_Ex, tau_decay_Ex,tmax)
dt = 0.1; % time step duration (ms)
t = 0:dt:tmax-dt;
% Compute compound current
IPSC = ((G_max_chl) .* ((1 - exp(-t / tau_rise_In)) .* exp(-t / tau_decay_In)) * (Vm - EChl));
EPSC = ((G_max_glu) .* ((1 - exp(-t / tau_rise_Ex)) .* exp(-t / tau_decay_Ex)) * (Vm - EGlu));
CPSC = IPSC + EPSC;
end
After generating the data with the previous function, I have the fitting procedure:
% Simulated data
[~,~,CPSC,t] = generate_current(80,15,0,-70,-30,0.44,15,0.73,3,120);
% % Parameters
G_max_chl = 80; % Maximal conductance of Chl
G_max_glu = 15; % Maximal conductance of Glu
tau_rise_Ex = 0.73; % Tau rise for E
tau_rise_In = 0.44; % Tau rise for I
tau_decay_Ex = 3; % Tau decay for E
tau_decay_In = 15; % Tau decay for I
p = [G_max_chl, G_max_glu, tau_rise_In, tau_decay_In, tau_rise_Ex, tau_decay_Ex];
dt = 0.1;
tmax = 121;
t = 1:0.1:tmax-dt;
Vm = -30;
EGlu = 0;
EChl = -70;
% Create the objective function
fitfcn = #(p, t, Vm, EGlu, EChl) ((p(1)) .* ((1 - exp(-t / p(3))) .* exp(-t / p(4))) * (Vm - EChl)) + ((p(2)) .* ((1 - exp(-t / p(5))) .* exp(-t / p(6))) * (Vm - EGlu));
preal = [80,15,0.44,0.73,15,3]; % Real coefficients
xdata = t;
ydata = CPSC; % Response data with noise
% Set bounds and initial point.
lb = [0,0,0,0,0,0];
ub = [150,150,5,5,20,20];
p0 = [50,50,1,1,1,1]; % Arbitrary initial points
% Find the best local fit
[xfitted,errorfitted] = lsqcurvefit(#(p,t)fitfcn(p, t, Vm, EGlu, EChl), p0, xdata, ydata,lb,ub)
%Set up the problem for MultiStart.
problem = createOptimProblem('lsqcurvefit','x0',p0,'objective',fitfcn,...
'lb',lb,'ub',ub,'xdata',xdata,'ydata',ydata);
% Find a global solution
ms = MultiStart('PlotFcn',#gsplotbestf);
[xmulti,errormulti] = run(ms,problem,200)
You have a script called MultiStart.m in the location /MATLAB Drive/Amsterdam/2 Fitting, which is in Matlab's search path. When you call MultiStart(), Matlab assumes that you are calling this script instead of the built-in MultiStart function.
You need to rename the script to something that does not conflict with Matlab's built-in function names or, alternatively, remove /MATLAB Drive/Amsterdam/2 Fitting from Matlab's search path.

`ode45` and tspan error Attempted to access

I'm using ode45 to solve second order differential equation. the time span is determined based on how many numbers in txt file, therefore, the time span is defined as follows
i = 1;
t(i) = 0;
dt = 0.1;
numel(theta_d)
while ( i < numel(theta_d) )
i = i + 1;
t(i) = t(i-1) + dt;
end
Now the time elements should not exceed the size of txt (i.e. numel(theta_d)). In main.m, I have
x0 = [0; 0];
options= odeset('Reltol',dt,'Stats','on');
[t, x] = ode45('ODESolver', t, x0, options);
and ODESolver.m header is
function dx = ODESolver(t, x)
If I run the code, I'm getting this error
Attempted to access theta_d(56); index out of bounds because numel(theta_d)=55.
Error in ODESolver (line 29)
theta_dDot = ( theta_d(i) - theta_dPrev ) / dt;
Why the ode45 is not being fixed with the time span?
Edit: this is the entire code
main.m
clear all
clc
global error theta_d dt;
error = 0;
theta_d = load('trajectory.txt');
i = 1;
t(i) = 0;
dt = 0.1;
numel(theta_d)
while ( i < numel(theta_d) )
i = i + 1;
t(i) = t(i-1) + dt;
end
x0 = [pi/4; 0];
options= odeset('Reltol',dt,'Stats','on');
[t, x] = ode45(#ODESolver, t, x0, options);
%e = x(:,1) - theta_d; % Error theta
plot(t, x(:,2), 'r', 'LineWidth', 2);
title('Tracking Problem','Interpreter','LaTex');
xlabel('time (sec)');
ylabel('$\dot{\theta}(t)$', 'Interpreter','LaTex');
grid on
and ODESolver.m
function dx = ODESolver(t, x)
persistent i theta_dPrev
if isempty(i)
i = 1;
theta_dPrev = 0;
end
global error theta_d dt ;
dx = zeros(2,1);
%Parameters:
m = 0.5; % mass (Kg)
d = 0.0023e-6; % viscous friction coefficient
L = 1; % arm length (m)
I = 1/3*m*L^2; % inertia seen at the rotation axis. (Kg.m^2)
g = 9.81; % acceleration due to gravity m/s^2
% PID tuning
Kp = 5;
Kd = 1.9;
Ki = 0.02;
% theta_d first derivative
theta_dDot = ( theta_d(i) - theta_dPrev ) / dt;
theta_dPrev = theta_d(i);
% u: joint torque
u = Kp*(theta_d(i) - x(1)) + Kd*( theta_dDot - x(2)) + Ki*error;
error = error + (theta_dDot - x(1));
dx(1) = x(2);
dx(2) = 1/I*(u - d*x(2) - m*g*L*sin(x(1)));
i = i + 1;
end
and this is the error
Attempted to access theta_d(56); index out of bounds because numel(theta_d)=55.
Error in ODESolver (line 28)
theta_dDot = ( theta_d(i) - theta_dPrev ) / dt;
Error in ode45 (line 261)
f(:,2) = feval(odeFcn,t+hA(1),y+f*hB(:,1),odeArgs{:});
Error in main (line 21)
[t, x] = ode45(#ODESolver, t, x0, options);
The problem here is because you have data at discrete time points, but ode45 needs to be able to calculate the derivative at any time point in your time range. Once it solves the problem, it will interpolate the results back onto your desired time points. So it will calculate the derivative many times more than at just the time points you specified, thus your i counter will not work at all.
Since you have discrete data, the only way to proceed with ode45 is to interpolate theta_d to any time t. You have a list of values theta_d corresponding to times 0:dt:(dt*(numel(theta_d)-1)), so to interpolate to a particular time t, use interp1(0:dt:(dt*(numel(theta_d)-1)),theta_d,t), and I turned this into an anonymous function to give the interpolated value of theta_p at a given time t
Then your derivative function will look like
function dx = ODESolver(t, x,thetaI)
dx = zeros(2,1);
%Parameters:
m = 0.5; % mass (Kg)
d = 0.0023e-6; % viscous friction coefficient
L = 1; % arm length (m)
I = 1/3*m*L^2; % inertia seen at the rotation axis. (Kg.m^2)
g = 9.81; % acceleration due to gravity m/s^2
% PID tuning
Kp = 5;
Kd = 1.9;
Ki = 0.02;
% theta_d first derivative
dt=1e-4;
theta_dDot = (thetaI(t) - theta(I-dt)) / dt;
%// Note thetaI(t) is the interpolated theta_d values at time t
% u: joint torque
u = Kp*(thetaI(t) - x(1)) + Kd*( theta_dDot - x(2)) + Ki*error;
error = error + (theta_dDot - x(1));
dx=[x(2); 1/I*(u - d*x(2) - m*g*L*sin(x(1)))];
end
and you will have to define thetaI=#(t) interp1(0:dt:(dt*(numel(theta_d)-1)),theta_d,t); before calling ode45 using [t, x] = ode45(#(t,x) ODESolver(t,x,thetaI, t, x0, options);.
I removed a few things from ODESolver and changed how the derivative was computed.
Note I can't test this, but it should get you on the way.

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.