Mackey-Glass
The Mackey-Glass equation x' = beta x(t - tau) / (1 + x(t - tau)^n) - gamma x of blood cell production.
- Name:
mackey_glass - Field:
biology/physiology - Formalism: ordinary differential equations
- References: Mackey and Glass 1977; Erneux 2009
Factory
@register_model(
field='biology/physiology',
tags=('chaos', 'delay', 'physiology'),
references=('Mackey and Glass 1977', 'Erneux 2009'),
defaults={'until': 500.0, 'dt': 0.5},
)
def mackey_glass(
x: float = 0.5,
*,
beta: float = 0.2,
gamma: float = 0.1,
n: float = 10.0,
tau: float = 17.0,
) -> System:
"""Return the Mackey-Glass equation `x' = beta x(t - tau) / (1 + x(t - tau)^n) - gamma x` of blood cell production.
It is periodic for `tau = 6` and chaotic for `tau = 17`. The history before the start is the initial value.
Args:
x:
The initial concentration, also its history.
beta:
The production rate.
gamma:
The decay rate.
n:
The steepness of the production feedback.
tau:
The delay of production.
Returns:
system:
The model, with the concentration `cells.x`.
Examples:
>>> from skcomplex.models.biology.physiology import mackey_glass
>>> mackey_glass(tau=6.0).elements[0].tau
6.0
"""
return System(elements=[MackeyGlassElement('cells', x=x, beta=beta, gamma=gamma, n=n, tau=tau)])
Components
class MackeyGlassElement(Element):
"""Concentration `x` of circulating blood cells, made at a delayed Hill rate and lost at a constant rate.
The concentration follows `x' = beta x(t - tau) / (1 + x(t - tau)^n) - gamma x`.
Args:
label:
The label of the element.
visual:
How the element is drawn, or `None` for `default_visual_`.
x:
The initial concentration, also its history.
beta:
The production rate.
gamma:
The loss rate.
n:
The Hill coefficient of the production.
tau:
The delay of the production.
Examples:
>>> from skcomplex.models.biology.physiology import MackeyGlassElement
>>> MackeyGlassElement('blood', tau=6.0).tau
6.0
"""
def __init__(
self,
label: str,
visual: VisualSpec | None = None,
*,
x: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.5,
beta: Annotated[float, ParameterSpec()] = 0.2,
gamma: Annotated[float, ParameterSpec()] = 0.1,
n: Annotated[float, ParameterSpec()] = 10.0,
tau: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 17.0,
) -> None:
super().__init__(label, visual=visual)
self.x = x
self.beta = beta
self.gamma = gamma
self.n = n
self.tau = tau
def _get_laws(self, s: SimpleNamespace) -> list[BaseLaw]:
"""Return the delayed production and the loss of the cells.
Args:
s:
The namespace of the symbols the laws can use.
Returns:
laws:
The laws of the component.
"""
history = delayed(s.x, s.tau)
return [RateLaw(s.x, s.beta * history * (1 - hill(history, 1, s.n)) - s.gamma * s.x)]
Equations
cells.x: diff(x_cells(t), t) == -beta_cells*(x_cells(t - tau_cells)^n_cells/(x_cells(t - tau_cells)^n_cells + 1) - 1)*x_cells(t - tau_cells) - gamma_cells*x_cells(t)