I have this code to try to fit the sum of two populations to a measurements data-series.
dS/dt = (a - b) * S
dR/dt = (a - b - c)* R
X(t) = S(t) + R(t)
I want also to optimize the first point which instead now is fixed, I had thought to use a new variable called f which stand in between 0 and 1 and that represents the initial ratio between population 1 and population 2.
Something like this:
S0 = x_meas[0] * f
R0 = x_meas[0] * (1-f)
Here is the code:
from gekko import GEKKO
m = GEKKO(remote=False)
# data
m.time = [0,0.1,0.2,0.3,0.4,0.5,0.8,0.85,0.9,0.95,1]
x_meas = [1.1,1.2,1.56,1.77,1.89,2.1,2.3,2.5,2.7,2.2,2.1]
# parameters, single value over time horizon
p = m.Array(m.FV,3,lb=0.5,ub=10); a,b,c = p
# turn STATUS On for adjustment by solver
for fv in p:
fv.STATUS=1
f0 = m.FV(value=0.01, lb=0, ub=1)
f0.STATUS=1
# variables
S,R,X = m.Array(m.Var,3,lb=0)
# change initial conditions
S0,R0 = [0.35,0.65]; X0 = S0+R0
S.value=S0; R.value=R0; X.value=X0
# measured values
Xm = m.Param(x_meas)
# equations
m.Equations([S.dt()==(a-b)*S,
R.dt()==(a-b-c)*R,
X==S+R])
# minimize difference to measurements
m.Minimize((X-Xm)**2)
m.options.IMODE = 5 # dynamic estimation
m.options.NODES = 3 # collocation nodes
m.solve(disp=False) # display solver output
print(f'a: {a.value[0]}, b: {b.value[0]}, c: {c.value[0]}')
import matplotlib.pyplot as plt
plt.figure(figsize=(7,3))
plt.plot(m.time,S.value,'b:',linewidth=3,label='S')
plt.plot(m.time,R.value,'r--',linewidth=2,label='R')
plt.plot(m.time,X.value,'k--',label='X')
plt.plot(m.time,Xm.value,'kx',label='Xm')
plt.legend(); plt.grid(); plt.xlabel('Time')
plt.tight_layout()
plt.savefig('fit.png',dpi=300)
plt.show()
By default,
gekkois set up as an initial value problem where the values att=0are fixed and the equations are not solved at that initial point. One way to still fit into this framework with calculated initial values is to setfixed_initial=Falseand the differential equation initial condition is calculated. However, this doesn't fix the issue that the equations for the first node in the time horizon are deactivated.To overcome this, try setting another very small time increment in the time horizon with a very small time-step, such as
1e-5. Create the fractionfas anFVtype and set theSTATUS=1to calculate that single value with the optimizer. I included bounds onfbetween0.2and0.8, just to make the problem more interesting and they can be changed.Activate the equations for the relation between
R,Sandfonly on that small-time step.The remainder of the problem stays the same.
It solves with a successful solution: