Adjoint function in an optimal control problem returns NaN values

39 views (last 30 days)
I am performing optimal control simulations for the first time, but almost all entries of control functions (vectors) u1 and u2 go to the upper bound which is 1. I found out that this is because the adjoint functions lamda1, lambda2, ..., lambda11 return NaN values. I already carefully checked the adjoint equations to check for possible singularities. I suspect that it's because of the looping. What else could be the possible reason and how could I fix it? Thank you so much in advance.
close all
clf
clear
clc
beta1 = 0.2945;
beta2 = 0.3711;
rho = 0.3081;
Lambda = 3148798;
mu = 0.01444;
db = 0.01;
dh = 0.333;
dbh = 0.01;
du = 0.2;
epsilonH = 0.1;
epsilonB = 0.5;
epsilonU = 0.75;
xi = 1.1;
zeta1 = 1.5;
zeta2 = 1.3;
etaA = 1.35;
etaBH = 1.155;
pi=0.006;
tau1=0.33;
tau2=0.3079;
tau3=0.3;
tau4=0.015;
kappa = 0.002;
omega = 0.01;
phi = 0.2;
varphi=0.25;
p = 0.63;
r = 0.025;
T = 20;
N0 = 109465287;
IB0 = 72598;
IH0 = 9688;
AH0 = 1415;
IBH0 = 143;
P0 = 0.001*N0;
TB0=0.1*IB0;
TH0=9405;
TBH0=0.5*IBH0;
U0 = 200000;
S0 = N0-U0-IB0-IH0-AH0-IBH0-P0-TB0-TH0-TBH0;
x0 = [S0; P0; U0; IB0; IH0; AH0; IBH0; TB0; TH0; TBH0; N0];
test = -1;
delta= 0.001;
N = 1000;
t = linspace(2017,2037,N+1);
h = T/N;
h2 = h/2;
u1 = zeros(1,N+1);
u2 = zeros(1,N+1);
x = zeros(11,N+1);
x(:,1) = x0;
lambda = zeros(11,N+1);
lambda(T)=0;
while(test < 0) % test for convergence
oldu1 = u1;
oldu2 = u2;
oldx = x;
oldlambda = lambda;
%New values of x and lambda
x = RK4fwd(t,x,u1,u2,Lambda,mu,db,dh,dbh,du,beta1,beta2,xi,zeta1,zeta2,etaA,etaBH,epsilonH,epsilonB,epsilonU,pi,rho,tau1,tau2,tau3,tau4,kappa,omega,phi,varphi,p,r,N,h,h2);
lambda = RK4bwd(t,x,u1,u2,lambda,mu,db,dh,dbh,du,beta1,beta2,xi,zeta1,zeta2,etaA,etaBH,epsilonH,epsilonB,epsilonU,rho,tau1,tau2,tau3,tau4,kappa,omega,phi,varphi,p,r,N,h,h2);
c1 = 10^6;
c2 = 10^5;
N1 = x(1,:) + x(2,:) + x(3,:) + x(4,:) + x(5,:) + x(6,:) + x(7,:) + x(8,:) + x(9,:) + x(10,:);
%Updating controls u1 and u2 using the new x and lambda
opt1 = ((lambda(5,:)-lambda(1,:)).*epsilonH*beta2.*(x(5,:)+etaA.*x(6,:)+etaBH.*x(7,:)+zeta2.*x(3,:)).*x(1,:)./N1 + (lambda(4,:)-lambda(1,:)).*(1-epsilonH)*epsilonB*beta1.*(x(4,:)+xi.*x(7,:)+zeta1.*x(3,:)).*x(1,:)./N1)./c1;
u1new = max(0,min(opt1,1));
u1 = 0.5.*(oldu1 + u1new);
opt2 = ((lambda(1,:)-lambda(2,:)).*(1-epsilonH)*(1-epsilonB)*(1-epsilonU).*x(1,:))./c2;
u2new = max(0,min(opt2,1));
u2 = 0.5*(oldu2 + u2new);
temp1 = delta*sum(abs(u1)) - sum(abs(oldu1 - u1));
temp2 = delta*sum(abs(u2)) - sum(abs(oldu2 - u2));
temp3 = delta*sum(abs(x)) - sum(abs(oldx - x));
temp4 = delta*sum(abs(lambda)) - sum(abs(oldlambda - lambda));
test = min(temp1,min(temp2,min(temp3,temp4)));
end
%Plotting
X = x(3,:)+x(4,:)+x(5,:);
figure(1)
set(gcf, 'Units', 'Normalized', ...
'OuterPosition', [0, 0, 0.45, 0.75]);
set(gcf,'Color','white')
subplot(3,1,1)
plot(t,X,'LineWidth',3)
%set(gca,'FontSize',24)
%ylabel({'$U+I_{B}+I_{H}$'},'Interpreter','latex')
xlim([2017 2037])
subplot(3,1,2)
plot(t,u1,'LineWidth',3)
%set(gca,'FontSize',24)
%ylabel({'$u_{1}(t)$'},'Interpreter','latex')
xlim([2017 2037])
subplot(3,1,3)
plot(t,u2,'LineWidth',3)
%set(gca,'FontSize',24)
xlabel('Time','Interpreter','latex')
%ylabel({'$u_{2}(t)$'},'Interpreter','latex')
xlim([2017 2037])
%optimal control problem
function dx = state_func(t,x,u1,u2,Lambda,mu,db,dh,dbh,du,beta1,beta2,xi,zeta1,zeta2,etaA,etaBH,epsilonH,epsilonB,epsilonU,pi,rho,tau1,tau2,tau3,tau4,kappa,omega,phi,varphi,p,r)
S = x(1);
P = x(2);
U = x(3);
IB = x(4);
IH = x(5);
AH = x(6);
IBH = x(7);
TB = x(8);
TH = x(9);
TBH = x(10);
N1 = S + P + U + IB + AH + IH + IBH + TB + TH + TBH;
dS = Lambda*(1-pi) - (1-u1)*epsilonH*beta2*(IH+etaA*AH+etaBH*IBH+zeta2*U)*S/N1 - (1-u1)*(1-epsilonH)*epsilonB*beta1*(IB+xi*IBH+zeta1*U)*S/N1 - (1-epsilonH)*(1-epsilonB)*epsilonU*(beta1*(IB+xi*IBH+zeta1*U)/N1 + beta2*(IH+etaA*AH+etaBH*IBH+zeta2*U)/N1)*S - (1-epsilonH)*(1-epsilonB)*(1-epsilonU)*u2*S - mu*S;
dP = Lambda*pi + (1-epsilonH)*(1-epsilonB)*(1-epsilonU)*u2*S + r*TB - mu*P;
dU = (1-epsilonH)*(1-epsilonB)*epsilonU*(beta1*(IB+xi*IBH+zeta1*U)/N1 + beta2*(IH+etaA*AH+etaBH*IBH+zeta2*U)/N1)*S - (du+mu)*U;
dIB = (1-u1)*(1-epsilonH)*epsilonB*beta1*(IB+xi*IBH+zeta1*U)*S/N1 + phi*TB - beta2*(IH+etaA*AH+etaBH*IBH+zeta2*U)*IB/N1 - (tau1+db+mu)*IB;
dIH = (1-u1)*epsilonH*beta2*(IH+etaA*AH+etaBH*IBH+zeta2*U)*S/N1 + omega*TH - beta1*(IB+xi*IBH+zeta1*U)*IH/N1 - (rho+tau2+mu)*IH;
dAH = rho*IH + kappa*rho*TH - beta1*(IB+xi*IBH+zeta1*U)*AH/N1 - (tau3+dh+mu)*AH;
dIBH = beta2*(IH+etaA*AH+etaBH*IBH+zeta2*U)*IB/N1 + beta1*(IB+xi*IBH+zeta1*U)*(IH+AH)/N1 + varphi*TBH - (tau4+dbh+mu)*IBH;
dTB = tau1*IB - (phi+r+mu)*TB;
dTH = tau2*IH + tau3*AH + p*TBH - (omega+kappa*rho+mu)*TH;
dTBH = tau4*IBH - (varphi+p+mu)*TBH;
dN1 = Lambda - du*U - db*IB - dh*IH - dbh*IBH - mu*N1;
dx = [dS; dP; dU; dIB; dIH; dAH; dIBH; dTB; dTH; dTBH; dN1];
end
%Solves states forward in time using initial values and controls
function x = RK4fwd(t,x,u1,u2,Lambda,mu,db,dh,dbh,du,beta1,beta2,xi,zeta1,zeta2,etaA,etaBH,epsilonH,epsilonB,epsilonU,pi,rho,tau1,tau2,tau3,tau4,kappa,omega,phi,varphi,p,r,N,h,h2)
h2 = 0.5*h;
for i = 1:N
k1 = state_func(t,x(:,i),u1(i),u2(i),Lambda,mu,db,dh,dbh,du,beta1,beta2,xi,zeta1,zeta2,etaA,etaBH,epsilonH,epsilonB,epsilonU,pi,rho,tau1,tau2,tau3,tau4,kappa,omega,phi,varphi,p,r);
k2 = state_func(t+h2,x(:,i)+h2.*k1,0.5*(u1(i)+u1(i+1)),0.5*(u2(i)+u2(i+1)),Lambda,mu,db,dh,dbh,du,beta1,beta2,xi,zeta1,zeta2,etaA,etaBH,epsilonH,epsilonB,epsilonU,pi,rho,tau1,tau2,tau3,tau4,kappa,omega,phi,varphi,p,r);
k3 = state_func(t+h2,x(:,i)+h2.*k2,0.5*(u1(i)+u1(i+1)),0.5*(u2(i)+u2(i+1)),Lambda,mu,db,dh,dbh,du,beta1,beta2,xi,zeta1,zeta2,etaA,etaBH,epsilonH,epsilonB,epsilonU,pi,rho,tau1,tau2,tau3,tau4,kappa,omega,phi,varphi,p,r);
k4 = state_func(t+h,x(:,i)+h.*k3,u1(i+1),u2(i+1),Lambda,mu,db,dh,dbh,du,beta1,beta2,xi,zeta1,zeta2,etaA,etaBH,epsilonH,epsilonB,epsilonU,pi,rho,tau1,tau2,tau3,tau4,kappa,omega,phi,varphi,p,r);
x(:,i+1) = x(:,i)+(h/6).*(k1 + 2.*k2 + 2.*k3 + k4);
end
end
% adjoint system
function dlambda = lambda_func(t,x,u1,u2,lambda,mu,db,dh,dbh,du,beta1,beta2,xi,zeta1,zeta2,etaA,etaBH,epsilonH,epsilonB,epsilonU,rho,tau1,tau2,tau3,tau4,kappa,omega,phi,varphi,p,r)
N1 = x(1,:) + x(2,:) + x(3,:) + x(4,:) + x(5,:) + x(6,:) + x(7,:) + x(8,:) + x(9,:) + x(10,:);
lambda1 = lambda(1);
lambda2 = lambda(2);
lambda3 = lambda(3);
lambda4 = lambda(4);
lambda5 = lambda(5);
lambda6 = lambda(6);
lambda7 = lambda(7);
lambda8 = lambda(8);
lambda9 = lambda(9);
lambda10 = lambda(10);
lambda11 = lambda(11);
dlambda1 = (lambda1-lambda2)*(1-epsilonH)*(1-epsilonB)*(1-epsilonU)*u2 + (lambda1-lambda3)*(1-epsilonH)*(1-epsilonB)*epsilonU*((beta1*(x(4,:)+xi*x(7,:)+zeta1*x(3,:))/N1) + beta2*(x(5,:)+etaA*x(6,:)+etaBH*x(7,:)+zeta2*x(3,:))/N1) + (lambda1-lambda4)*(1-u1)*(1-epsilonH)*epsilonB*beta1*(x(4,:)+xi*x(7,:)+zeta1*x(3,:))/N1 + (lambda1-lambda5)*(1-u1)*epsilonH*beta2*(x(5,:)+etaA*x(6,:)+etaBH*x(7,:)+zeta2*x(3,:))/N1;
dlambda2 = lambda2*mu;
dlambda3 = (lambda1-lambda5)*(1-u1)*epsilonH*beta2*zeta2*x(1,:)/N1 + (lambda1-lambda4)*(1-u1)*(1-epsilonH)*epsilonB*beta1*zeta1*x(1,:)/N1 + (lambda1-lambda3)*(1-epsilonH)*(1-epsilonB)*epsilonU*(beta1*zeta1+beta2*zeta2)*x(1,:)/N1 + (lambda4-lambda7)*beta2*zeta2*x(4,:)/N1 + (lambda5-lambda7)*beta1*zeta1*x(5,:)/N1 + (lambda6-lambda7)*beta1*zeta1*x(6,:)/N1 + lambda3*(du+mu) + lambda11*du - 1;
dlambda4 = (lambda1-lambda3)*(1-epsilonH)*(1-epsilonB)*epsilonU*beta1*x(1,:)/N1 + (lambda1-lambda4)*(1-u1)*(1-epsilonH)*epsilonB*beta1*x(1,:)/N1 + (lambda5-lambda7)*beta1*x(5,:)/N1 + (lambda6-lambda8)*beta1*x(6,:)/N1 + (lambda4-lambda7)*beta2*(x(5,:)+etaA*x(6,:)+etaBH*x(7,:)+zeta2*x(3,:))*x(1,:)/N1 + (lambda4-lambda8)*tau1 + lambda4*(db+mu) + lambda11*db - 1;
dlambda5 = (lambda1-lambda5)*(1-u1)*epsilonH*beta2*x(1,:)/N1 + (lambda1-lambda3)*(1-epsilonH)*(1-epsilonB)*epsilonU*beta2*x(1,:)/N1 + (lambda4-lambda7)*beta2*x(4,:)/N1 + (lambda5-lambda7)*beta1*(x(4,:)+xi*x(7,:)+zeta1*x(3,:))*x(1,:)/N1 + (lambda5-lambda6)*rho + (lambda5-lambda9)*tau2 + lambda5*mu - 1;
dlambda6 = (lambda1-lambda5)*(1-u1)*epsilonH*beta2*etaA*x(1,:)/N1 + (lambda1-lambda3)*(1-epsilonH)*(1-epsilonB)*epsilonU*beta2*etaA*x(1,:)/N1 + (lambda4-lambda7)*beta2*etaA*x(4,:)/N1 + (lambda6-lambda7)*beta1*(x(4,:)+xi*x(7,:)+zeta1*x(3,:))*x(1,:)/N1 + (lambda6-lambda9)*tau3 + lambda6*(dh+mu) + lambda11*dh;
dlambda7 = (lambda1-lambda5)*(1-u1)*epsilonH*beta2*etaBH*x(1,:)/N1 + (lambda1-lambda4)*(1-u1)*(1-epsilonH)*epsilonB*beta1*xi*x(1,:)/N1 + (lambda1-lambda3)*(1-epsilonH)*(1-epsilonB)*epsilonU*beta2*etaBH*x(1,:)/N1 + (lambda4-lambda7)*beta2*etaBH*x(4,:)/N1 + (lambda5-lambda7)*beta1*xi*x(5,:)/N1 + (lambda6-lambda7)*beta1*xi*x(6,:)/N1 + (lambda7-lambda10)*tau4 + lambda7*(dbh+mu) + lambda11*dbh;
dlambda8 = (lambda8-lambda2)*r + (lambda8-lambda4)*phi;
dlambda9 = (lambda9-lambda5)*omega + (lambda9-lambda6)*kappa*rho + lambda9*mu;
dlambda10 = (lambda10-lambda7)*varphi + (lambda10-lambda9)*p + lambda10*mu;
dlambda11 = (lambda5-lambda1)*(1-u1)*epsilonH*beta2*(x(5,:)+etaA*x(6,:)+etaBH*x(7,:)+zeta2*x(3,:))*x(1,:)/N1^2 + (lambda4-lambda1)*(1-u1)*(1-epsilonH)*epsilonB*beta1*(x(4,:)+xi*x(7,:)+zeta1*x(3,:))*x(1,:)/N1^2 + (lambda3-lambda1)*(1-epsilonH)*(1-epsilonB)*epsilonU*(beta2*(x(5,:)+etaA*x(6,:)+etaBH*x(7,:)+zeta2*x(3,:))*x(1,:) + beta1*(x(4,:)+xi*x(7,:)+zeta1*x(3,:))*x(1,:))/N1^2 + (lambda7-lambda4)*beta2*(x(5,:)+etaA*x(6,:)+etaBH*x(7,:)+zeta2*x(3,:))*x(4,:)/N1^2 + (lambda7-lambda5)*beta1*(x(4,:)+xi*x(7,:)+zeta1*x(3,:))*x(5,:)/N1^2 + (lambda7-lambda6)*beta1*(x(4,:)+xi*x(7,:)+zeta1*x(3,:))*x(6,:)/N1^2 + lambda11*mu;
dlambda = [dlambda1; dlambda2; dlambda3; dlambda4; dlambda5; dlambda6; dlambda7; dlambda8; dlambda9; dlambda10; dlambda11];
end
%Solves adjoint system backward in time using new values of states and the controls
function lambda = RK4bwd(t,x,u1,u2,lambda,mu,db,dh,dbh,du,beta1,beta2,xi,zeta1,zeta2,etaA,etaBH,epsilonH,epsilonB,epsilonU,rho,tau1,tau2,tau3,tau4,kappa,omega,phi,varphi,p,r,N,h,h2)
for i = 1:N
j = N + 2 - i;
k1 = lambda_func(t,x(:,j),u1(j),u2(j),lambda(:,j),mu,db,dh,dbh,du,beta1,beta2,xi,zeta1,zeta2,etaA,etaBH,epsilonH,epsilonB,epsilonU,rho,tau1,tau2,tau3,tau4,kappa,omega,phi,varphi,p,r);
k2 = lambda_func(t-h2,0.5*(x(:,j)+x(:,j-1)),0.5*(u1(j)+u1(j-1)),0.5*(u2(j)+u2(j-1)),lambda(:,j)-h2*k1,mu,db,dh,dbh,du,beta1,beta2,xi,zeta1,zeta2,etaA,etaBH,epsilonH,epsilonB,epsilonU,rho,tau1,tau2,tau3,tau4,kappa,omega,phi,varphi,p,r);
k3 = lambda_func(t-h2,0.5*(x(:,j)+x(:,j-1)),0.5*(u1(j)+u1(j-1)),0.5*(u2(j)+u2(j-1)),lambda(:,j)-h2*k2,mu,db,dh,dbh,du,beta1,beta2,xi,zeta1,zeta2,etaA,etaBH,epsilonH,epsilonB,epsilonU,rho,tau1,tau2,tau3,tau4,kappa,omega,phi,varphi,p,r);
k4 = lambda_func(t-h,x(:,j-1),u1(j-1),u2(j-1),lambda(:,j)-h*k3,mu,db,dh,dbh,du,beta1,beta2,xi,zeta1,zeta2,etaA,etaBH,epsilonH,epsilonB,epsilonU,rho,tau1,tau2,tau3,tau4,kappa,omega,phi,varphi,p,r);
lambda(:,j-1) = lambda(:,j) - (h/6).*(k1 + 2.*k2 + 2.*k3 + k4);
end
end
  4 Comments
Gerald
Gerald on 9 Oct 2025
Thank you for your comments. I already tried to solve a simpler optimal control problem with 3 equations. It worked using the same method. I am able to produce graphs of the control functions that do not reach the upper bound (i.e., 1) since the adjoint functions (lambdas) are not returning NaN values. In addition, I think the reason why the adjoint functions in the more complex problem I posted above are returning NaN values is because the values are very large. For example, lambda1 values are multiples of 1.0e+275. Please see attached image.
What's your take on this?
Torsten
Torsten on 9 Oct 2025
Edited: Torsten on 9 Oct 2025
Maybe scaling your problem such that the lambda values get normalized to smaller values ?
Maybe the stepsize of your integration is too large such that the explixit method diverges ?
Maybe using a MATLAB ode integrator (ode45,ode15s) instead of the self-written RK4 code ?
Maybe using a solver for boundary value problems (bvp4c) instead of an initial value solver ?
We only have your code and neither a mathematical formulation of your problem nor a description of your solution method. So it's difficult to give advice.

Sign in to comment.

Answers (0)

Categories

Find more on Robust Control Toolbox in Help Center and File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!