Unable to meet integration tolerances in fmincon to solve ODE optimization problem - matlab

I have constrained ODE optimization problem to be solved using Matlab, I started by solving the ODE using ode15s which working will this initial values, also I had very good results without constraints using fminsearch, the problem started when I used fmincon it gave me these warnings:
Warning: Length of lower bounds is < length(x); filling in missing lower bounds with -Inf.
> In checkbounds (line 33)
In fmincon (line 318)
In Optimization (line 64)
Warning: Length of upper bounds is < length(x); filling in missing upper bounds with +Inf.
> In checkbounds (line 47)
In fmincon (line 318)
In Optimization (line 64)
Warning: Failure at t=2.340250e+01. Unable to meet integration tolerances without reducing the step size below the smallest value
allowed (5.684342e-14) at time t.
> In ode15s (line 668)
In ObjFun (line 6)
In barrier
In fmincon (line 813)
In Optimization (line 64)
I tried to remove constraints, but nothing changed...
y1_max = 5; y2_max = 2.3;
y01 = 1; y02 = 1.6;
%Control function parameter
Umin = -0.3; Umax = -0.1;
%Creation the structure of model parameters
params.T0=T0; params.Tf=Tf;
params.y1d=y1d; params.y2d=y2d;
params.y01=y01; params.y02=y02;
params.y2_max=y2_max;
n=2;
U0=-0.2*ones(1,n);
params.n=n;
params.U=U0; params.Umax=Umax; params.Umin=Umin;
params.dt=(Tf-T0)/n;
%for initial value of optimization parameters
options = odeset('RelTol',1e-7,'AbsTol',1e-7);
U=U0;
[t,y]=ode15s(#ODEsolver,[T0,Tf],[y01 y02],options,params);
%adding the ode solution as input prameters
params.t=t; params.y1= y(:,1); params.y2= y(:,2);
U0=-0.2*ones(1,n);
params.n=n; params.U=U0;
params.dt=(Tf-T0)/n;
A = [];
B = [];
Aq = []; Bq = [];
options1 = optimset('MaxIter',5000);
[x,fval,exitflag,output] = fmincon(#ObjFun,U0,A,B,Aq,Bq,Umin,Umax,IneqConst(U0,params),options1,params)
function y = ODEsolver(t,y,params)
dt = params.dt;
nu = floor(t/dt)+1;
nu = min(nu,params.n-1);
t1 = (nu-1)*dt;
Ut = params.U(nu) + ((t-t1)/dt)*(params.U(nu+1) - params.U(nu));
dy1a = ((0.63*y(1))/(1 + y(1)));
dy1b = (Ut*y(1)*y(2))/(1+0.6*y(1));
dy1 = dy1a + dy1b;
dy2a = (0.15*y(2))/(0.05-0.2*y(2));
dy2 = -0.2*y(2) + dy1b * dy2a;
y = [dy1; dy2];
end
function ObjFun1 = ObjFun(u,params)
% Calculating the value of the optimization criteria
params.U=u;
options = odeset('RelTol',1e-8,'AbsTol',1e-8);
[t,y]=ode15s(#ODEsolver,[0,100],[params.y01,
params.y02],options,params);
ObjFun1 =trapz(t,(y(:,1)-params.y1d).^2);
end
function [c,Const] = IneqConst(u, params)
params.U=u;
options = odeset('RelTol',1e-8,'AbsTol',1e-8);
[t,y]=ode15s(#ODEsolver,[0,100],[params.y01, params.y02],options,params);
c =[];
yCon = y(:,2)-params.y2_max;
Const = trapz(t,(abs(yCon)+yCon).^2);
end

The bug in this code is that the dimension of the bounds (Umin, Umax) should be an array with the same size of the control function U
so if the control function parameters n = 2 then Umin = [-0.3 -0.3] & Umax = [-0.1 -0.1]

Related

fsolve issue with initial condition for ODE

I am trying to solve the following ODE:
function [eta, sol] = compressible_similarity_wo
global Gamm Ma Pr omega;
Gamm = 1.4;
Ma = 2;
Pr = 0.7;
omega=0.76;
global eta_max_ode;
eta_max_ode = 20;
opt = optimset('Display','off','TolFun',1E-20);
F = fsolve(#(F) eval_boundary(F),[0,0,0.4,1,0],opt);
[eta_ode, fg_ode] = solve_ode(F);
sol = [fg_ode];
eta = eta_ode;
end
function [eta_ode, fg_ode] = solve_ode(F)
global eta_max_ode
options = odeset('RelTol',1e-9,'AbsTol',1e-9);
[eta_ode, fg_ode] = ode45(#BLFunc,[0,eta_max_ode],F,options);
end
function [g] = eval_boundary(F)
% Get the solution to the ODE with inital condition F
[eta_ode, fg_ode] = solve_ode(F);
% Get the function values (for BCs) at the starting/end points
f_start = fg_ode(1,1); %f(0) = 0
df_start = fg_ode(1,2); %f'(0) = 0
df_end = fg_ode(end,2); %f'(inf) - 1 = 0
t_end = fg_ode(end,4); %T(inf) - 1 = 0
dt_start = fg_ode(1,5); %T'(0) = 0
% Evaluate the boundary function
g = [f_start
df_start
df_end - 1
t_end - 1
dt_start];
end
function [df] = BLFunc(f)
global Gamm Ma Pr omega;
df = zeros(5,1);
df(1) = f(2);
df(2) = f(3);
df(3) = -f(1)*f(3)/(f(4)^(omega-1))-(omega-1)*f(3)/f(4);
df(4) = f(5);
df(5) = -Pr*f(1)*f(5)/(f(4)^(omega-1)) - Pr*(Gamm - 1.0)*Ma*Ma*f(3)*f(3) - (omega-1)*f(5)/f(4);
end
but fsolve returns the following problem
Error using BLFunc
Too many input arguments.
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 solve_ode (line 5)
[eta_ode, fg_ode] = ode45(#BLFunc,[0,eta_max_ode],F,options);
Error in eval_boundary (line 3)
[eta_ode, fg_ode] = solve_ode(F);
Error in compressible_similarity_wo>#(F)eval_boundary(F) (line 15)
F = fsolve(#(F) eval_boundary(F),[0,0,0.4,1,0],opt);
Error in fsolve (line 230)
fuser = feval(funfcn{3},x,varargin{:});
Error in compressible_similarity_wo (line 15)
F = fsolve(#(F) eval_boundary(F),[0,0,0.4,1,0],opt);
Error in launch (line 3)
[eta, sol] = compressible_similarity_wo;
Caused by:
Failure in initial objective function evaluation. FSOLVE cannot continue.
Do you have an idea of what's going on?
I'll cite you the friendly manual page
The function dydt = odefun(t,y), for a scalar t and a column vector y, must return a column vector dydt of data type single or double that corresponds to f(t,y). odefun must accept both input arguments, t and y, even if one of the arguments is not used in the function.
That is, you simply need to change to
function [df] = BLFunc(t,f)
to get a result (no guarantee that it is THE result).
Try to replace BLFunc signature to
function [df] = BLFunc(t, f)
You need to provide odefun to ode45, which takes 2 arguments, as stated in documentation:
The function dydt = odefun(t,y), for a scalar t and a column vector y, must return a column vector dydt of data type single or double that corresponds to f(t,y). odefun must accept both input arguments, t and y, even if one of the arguments is not used in the function.

Implementing an Optimization problem using matlab

I am trying to implement an Optimization problem using matlab
Where N=100 , M=(N-1/k) and L=50.
N=100;
L = 50;
for K= 101:1:1000
M = (N-1)/K;
R=#(x) -((1./x(2)).*(N- (x(1).*M)-((min ( N./(L.*x(2)), K)-x(1))*(max(0,N-(L.*x(2).*x(1)))))/(x(1)+(min ( N./(L.*x(2)), K)-x(2)))) - (max(0,N-(L.*K*x(2)))));
LB = [1 1];
b=1:min((ceil(N/L)), K) ;
UB = [min((ceil(N./L)), K) ((N./(L*b))) ];
options = optimoptions('fmincon','Algorithm','interior-point'); % run interior-point algorithm
[xopt, vopt] = fmincon(R,1,[],[],[],[],LB,UB,[],options);
v(K) = -vopt;
end
plot(101:1000,v,'v-','LineWidth',2);
xlabel('Number of Users (K)');
ylabel('Delivery Rate (R)');
The following error appears:
Warning: Length of lower bounds is > length(x); ignoring extra bounds.
> In checkbounds (line 27)
In fmincon (line 318)
In R1 (line 19)
Warning: Length of upper bounds is > length(x); ignoring extra bounds.
> In checkbounds (line 41)
In fmincon (line 318)
In R1 (line 19)
Index exceeds array bounds.
Error in
R1>#(x)-((1./x(2)).*(N-(x(1).*M)-((min(N./(L.*x(2)),K)-x(1))*(max(0,N-(L.*x(2).*x(1)))))/(x(1)+(min(N./(L.*x(2)),K)-x(2))))-(max(0,N-(L.*K*x(2)))))
Error in fmincon (line 546)
initVals.f = feval(funfcn{3},X,varargin{:});
Error in R1 (line 19)
[xopt, vopt] = fmincon(R,1,[],[],[],[],LB,UB,[],options);
Caused by:
Failure in initial objective function evaluation. FMINCON cannot continue.
The output graph should be the one shown here:
(the lower bound curve)
Couples of mistakes
First, the initial guess should be an 1D array of length 2, kindly
replace 1 by [1, 1]
Better initialize the variable v first , it will speed up your
computation
The most important is the upper bound of l, as you can see it
depends on s and it's in the denominator, consider it as non linear
constraint then set UB = [] You will need to include nonlcon into
fmincon
The code is as follow
N=100;
L = 50;
t = 101:1:1000;
le = length(t);
v = zeros(1, le);
for K= 100:1:1000
M = (N-1)/K;
R = #(x) -(1./(x(1))).*(N-x(1).*((N-1)./K)-((min(ceil(N./(L.*x(2))), K)).*...
max(N -L.*x(1).*x(2), 0))./((x(1) +(min(ceil(N./(L.*x(2))), K))))...
-(max(N - K.*L.*x(2), 0)));
LB = [1 1];
options = optimoptions('fmincon','Algorithm','interior-point');
[xopt, vopt] = fmincon(R,[1, 1],[],[],[],[],LB,[],...
#(x)nonlincon(x(1), x(2),N, L, K ),options);
v(K-101+1) = -vopt;
end
plot(101:1000,v,'v-','LineWidth',2);
xlabel('Number of Users (K)');
ylabel('Delivery Rate (R)');
function [c, ceq] = nonlincon(s, l,N, L, K )
c(1) = l -N./(L.*s);
c(2) = s - min((ceil(N./L)), K) ;
ceq = [];
end

Matlab : system of four coupled odes

So, I've been working on this physics problem where I face a system of four coupled differential equations which I can't seem to find the answer to
TT0 = 0; %initial release angle Theta
l0 = 1; %initial left line length (in meters)
m = 1;
M = 3;
R = 0.3;
g = 9.8;
mu = 0.5;
syms t Ti(t) Tx(t) TT(t) l(t);
ode1 = (M*g) - Tx == -M*(diff(l,t,2)+R*diff(TT,t,2));
ode2 = m*g*sin(TT) - Ti == m*(R*diff(TT,t,2)-l*(diff(TT,t))^2 + diff(l,t,2));
ode3 = m*g*cos(TT) == m*(R*(diff(TT,t))^2 + 2*diff(l,t)*diff(TT,t) + l*diff(TT,t,2));
ode4 = Tx == Ti*exp(mu*(pi/2 + TT));
odes = [ode1; ode2; ode3; ode4];
conds = [TT(0) == TT0; l(0) == l0;Ti(0) == 0; Tx(0) == M*g];
D = dsolve(odes,conds);
Here's the code I've written. There are four equations and four indeterminates but I get this error when I run the code:
Error using mupadengine/feval (line 163)
Cannot reduce to the square system because the number of equations
differs from the number of indeterminates.
Error in dsolve>mupadDsolve (line 332)
T = feval(symengine,'symobj::dsolve',sys,x,options);
Error in dsolve (line 193)
sol = mupadDsolve(args, options);
Error in Untitled (line 16)
D = dsolve(odes,conds)
I've searched the internet and altered my code several times but it didn't seem to work. I'll highly appreciate any kind of help.

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.

Create flexible function handle

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);