I'm trying to convert to Mathematica a simple backward/forward sweep (with RK4 integrator) code to solve an optimal control problem in epidemiology, but I'm getting some error messages and I cannot identify where I'm coding wrong. The original code is written in MatLab and is in the reference "Maia Martcheva - An Introduction to Mathematical Epidemiology":
function ocmodel1
% This function computes the optimal control
% and the corresponding solution using forward-backward ...
sweep
clc;
clear all;
test = -1;
Δ = 0.001; %set tolerance
N = 100; %number of subdivisions
h = 1/N; %step
t = 0:h:1; % t-variable mesh
u = zeros(1,length(t)); %initialization
x = zeros(1,length(t));
lam = zeros(1,length(t));
x(1) = 10; %initial value assigned to x(0)
beta = 0.05; %parameters
mu = 0.01;
gamma = 0.5;
P = 100;
w1 = 1;
while (test<0) % while the tolerance is reached, repeat
oldu = u;
oldx = x;
oldlam = lam;
for i=1:N %loop that solve the forward ...
differential equation
k1 = beta*(P-x(i))*x(i) -(mu + gamma)*x(i) - ...
u(i)*x(i);
k2 = beta*(P-x(i)-0.5*k1*h)*(x(i)+0.5*k1*h) - ...
(mu+gamma)*(x(i)+0.5*k1*h)...
-0.5*(u(i)+u(i+1))*(x(i)+0.5*k1*h);
k3 = beta*(P-x(i)-0.5*k2*h)*(x(i)+0.5*k2*h) - ...
(mu+gamma)*(x(i)+0.5*k2*h)...
-0.5*(u(i)+u(i+1))*(x(i)+0.5*k2*h);
k4 = beta*(P-x(i)-k3*h)*(x(i)+k3*h) - ...
(mu+gamma)*(x(i)+k3*h)...
-u(i+1)*(x(i)+k3*h);
x(i+1) = x(i) + (h/6)*(k1+2*k2+2*k3+k4);
end
for i=1:N %loop that solves the backward ...
differential equation of the adjoint system
j = N + 2 -i;
k1 = ...
-w1-lam(j)*(beta*(P-x(j))-beta*x(j)-(mu+gamma) ...
- u(j));
k2 = ...
-w1-(lam(j)-0.5*k1*h)*(beta*(P-x(j)+0.5*k1*h) ...
-(mu+gamma) -0.5*(u(j)+u(j-1)));
k3 = ...
-w1-(lam(j)-0.5*k2*h)*(beta*(P-x(j)+0.5*k2*h) ...
-(mu+gamma) -0.5*(u(j)+u(j-1)));
k4 = -w1 -(lam(j)-k3*h)*(beta*(P-x(j)+k3*h) ...
-(mu+gamma) - u(j-1));
lam(j-1) = lam(j) - (h/6)*(k1+2*k2+2*k3+k4);
end
u1 = min(100,max(0,lam.*x/2));
u = 0.5*(u1 + oldu);
temp1 = Δ *sum(abs(u)) - sum(abs(oldu - u));
temp2 = Δ *sum(abs(x)) - sum(abs(oldx - x));
temp3 = Δ *sum(abs(lam)) - sum(abs(oldlam -lam));
test = min(temp1,min(temp2,temp3));
end
figure(1) %plotting
plot(t,u)
figure(2)
plot(t,x)
end
My attempt to write this code in Mathematica is in the following:
(* This function computes the optimal control
% and the corresponding solution using forward-backward...
sweep *)
Clear[ all]
test = -1;
Δ = 0.001;
n = 100;
h = 1/n;
t = Range[0, 1, h];
u = {};
x = {};
lam = {};
For[i = 1, i < n,
AppendTo[u, 0];
AppendTo[x, 0];
AppendTo[lam, 0];
i++]
x = ReplacePart[x, 1 -> 10]; (* initial value assigned to x(0) *)
beta = 0.05;(* parameters *)
mu = 0.01;
gamma = 0.5;
P = 100;
w1 = 1;
While[test < 0, (* while the tolerance is reached,repeat*)
oldu = u;
oldx = x;
oldlam = lam;
For[ i = 1, i < n,
k1 = beta*(P - x[[i]])*x[[i]] - (mu + gamma)*x[[i]] - u[[i]]*x[[i]];
k2 = (beta*(P - x[[i]]) - 0.5*k1*h)*(x[[i]] + 0.5*k1*h) - (mu +
gamma)*(x[[i]] + 0.5*k1*h) -
0.5*(u[[i]] + u[[i + 1]])*(x[[i]] + 0.5*k1*h);
k3 = beta*(P - x[[i]] - 0.5*k2*h)*(x[[i]] + 0.5*k2*h) - (mu +
gamma)*(x[[i]] + 0.5*k2*h) -
0.5*(u[[i]] + u[[i + 1]])*(x[[i]] + 0.5*k2*h);
k4 = beta*(P - x[[i]] - k3*h)*(x[[i]] + k3*h) - (mu +
gamma)*(x[[i]] + k3*h) - u[[i + 1]]*(x[[i]] + k3*h);
ReplacePart[x, i + 1 -> x[[i]] + (h/6)*(k1 + 2*k2 + 2*k3 + k4)];
i++ ];
For[i = 1, i < n, j = n + 2 - i;
k1 = -w1 -
lam[[j]]*(beta*(P - x[[j]]) - beta*x[[j]] - (mu + gamma) -
u[[j]]);
k2 = -w1 - (lam[[j]] -
0.5*k1*h)*(beta*(P - x[[j]] + 0.5*k1*h) - (mu + gamma) -
0.5*(u[[j]] + u[[j - 1]]));
k3 = -w1 - (lam[[j]] -
0.5*k2*h)*(beta*(P - x[[j]] + 0.5*k2*h) - (mu + gamma) -
0.5*(u[[j]] + u[[j - 1]]));
k4 = -w1 - (lam[[j]] -
k3*h)*(beta*(P - x[[j]] + k3*h) - (mu + gamma) - u[[j - 1]]);
ReplacePart[lam,
j - 1 -> lam[[j]] - (h/6)*(k1 + 2*k2 + 2*k3 + k4)]; i++];
u1 = Min[100, Max[0, lam.x/2]];
u = 0.5*(u1 + oldu);
temp1 = Δ*Sum[Abs[u], {1, Length[u]}] -
Sum[Abs[oldu - u], {1, Length[u]}];
temp2 = Δ*Sum[Abs[x], {1, Length[x]}] -
Sum[Abs[oldx - x], {1, Length[x]}];
temp3 = Δ*Sum[Abs[lam], {1, Length[lam]}] -
Sum[Abs[oldlam - lam], {1, Length[lam]}];
test = Min[temp1, Min[temp2, temp3]]; i++]
ListPlot[t, u]
ListPlot[t, x]
I'm getting error messages related to the indices, but I can't see what I did wrong.


Clear[all]does not clear everything, it only clearsall.Fortakes 4 arguments, you passed 3. To iterate from 1 to n, you'd usei <=nand noti < ninFor. But I suggest you do not useForat all. Even for a procedural loop, start withDo. – Szabolcs Apr 05 '20 at 19:48AppendTo. Do it like in the Matlab coe and initialize the vectors. E.g., initialize withx = ConstantArray[0.,n];x[[1]]=10.;Same forlamandu. That should solve already quite a lot of indexing problems. – Henrik Schumacher Apr 05 '20 at 19:50Sum[Abs[u], {1, Length[u]}]will return the vectorAbs[u] Length[u]. You are probably looking forTotal[Abs[u]]. – Henrik Schumacher Apr 05 '20 at 19:52ReplacePart[lam, j - 1 -> lam[[j]] - (h/6)*(k1 + 2*k2 + 2*k3 + k4)]does nothing unless you writelam=ReplacePart[lam, j - 1 -> lam[[j]] - (h/6)*(k1 + 2*k2 + 2*k3 + k4)]. But that would be highly inefficient. Better uselam[[j - 1]] = lam[[j]] - (h/6)*(k1 + 2*k2 + 2*k3 + k4);– Henrik Schumacher Apr 05 '20 at 19:53