Source code for aftercovid.models._base_sir_sim
# coding: utf-8
"""
Common methods about simulation for :epkg:`SIR` models.
"""
import numpy
from sympy import Symbol, diff as sympy_diff
[docs]class BaseSIRSimulation:
"""
Common methods about simulation for :epkg:`SIR` models.
"""
[docs] def eqsign(self, eqname, name):
"""
Returns the sign of the second derivative for equation
*eqname* against *name*.
:param eqname: equation name
:param name: symbol name
:return: boolean
"""
leqname = 'd' + eqname + '/d' + name
eql = self._lambdified_(leqname)
if eql is None:
eq = self._eq[eqname]
df = sympy_diff(eq, Symbol(name))
self._lambdify_(leqname, df)
eval1 = self.evalf_eq(df)
eval2 = self.evalf_leq(leqname)
if abs(eval1 - eval2) > 1e-5:
raise ValueError( # pragma: no cover
"Lambdification failed for derivative '{}' by '{}' "
"({} != {})".format(eqname, name, eval1, eval2))
ev = self.evalf_leq(leqname)
return 1 if ev >= 0 else -1
[docs] def iterate(self, n=10, t=0, derivatives=False):
"""
Evalues the quantities for *n* iterations.
Returns a list of dictionaries.
If *derivatives* is True, it returns two dictionaries.
:param n: number of iterations
:param t: first *t*
:param derivatives: returns the derivative as well
:return: iterator on dictionaries
"""
for i in range(t, t + n):
x = self.vect(t=i)
diff = {k: v(*x) for k, v in self._leq.items()}
vals = {k[0]: v for k, v in zip(self._q, x)}
if derivatives:
yield vals.copy(), diff
else:
yield vals.copy()
for k, v in diff.items():
vals[k] += v
self.update(**vals)
[docs] def iterate2array(self, n=10, t=0, derivatives=False):
"""
Evalues the quantities for *n* iterations.
Returns matrices.
:param n: number of iterations
:param t: first *t*
:param derivatives: returns the derivative as well
:return: quantities or (quantities, derivatives)
if *derivatives* is True
"""
clq = self.quantity_names
pos = {n: i for i, n in enumerate(clq)}
res = list(self.iterate(n=n, t=t, derivatives=derivatives))
qu = numpy.zeros((len(res), len(clq)), dtype=numpy.float32)
if derivatives:
de = numpy.zeros((len(res), len(clq)), dtype=numpy.float32)
for i, (r, d) in enumerate(res):
for j, n in enumerate(pos):
qu[i, j] = r.get(n, numpy.nan)
for j, n in enumerate(pos):
de[i, j] = d.get(n, numpy.nan)
return qu, de
else:
for i, r in enumerate(res):
for j, n in enumerate(pos):
qu[i, j] = r.get(n, numpy.nan)
return qu
[docs] def R0(self, t=0):
'''Returns R0 coefficient.'''
raise NotImplementedError()