Exponential growth observed at exponential random times
Exponential growth observed at exponentially distributed times, whose observed values follow a power law.
- Name:
exponential_growth_at_random_times - Field:
mathematics/stochastic_processes - Formalism: ordinary differential equations
- References: Reed and Hughes 2002; Thurner et al. 2018
Select this system
from skcomplex.systems import create_simulation, create_system, describe
system = create_system('exponential_growth_at_random_times')
entry = describe('exponential_growth_at_random_times')
trajectory = create_simulation('exponential_growth_at_random_times').prepare().run().trajectory_
Factory
@register_system(
field='mathematics/stochastic_processes',
tags=('power law', 'renewal', 'exponential growth', 'random observation'),
references=('Reed and Hughes 2002', 'Thurner et al. 2018'),
defaults={'until': 20.0, 'dt': 1.0, 'solver': RK4Solver(dt=0.01)},
)
def exponential_growth_at_random_times(
n_samples: int = 2000,
*,
mu: float = 1.0,
lam: float = 1.5,
x0: float = 1.0,
) -> System:
"""Return exponential growth observed at exponentially distributed times, whose observed values follow a power law.
Every sample grows as `x0 exp(mu t)` and is observed and restarted after a waiting time drawn from the
exponential distribution of rate `lam`. The observed values, and the values of the samples at any later time,
follow the power law `p(x) ~ x^(-lam / mu - 1)` (Thurner et al. 2018, section 3.3.6.1, after Reed and Hughes 2002).
Args:
n_samples:
The number of independent samples.
mu:
The growth rate.
lam:
The rate of the observation times.
x0:
The value every growth starts from.
Returns:
system:
The system, with the group `samples` of state `x` and the observations `samples.observations`.
Examples:
>>> from skcomplex.systems.mathematics.stochastic_processes import exponential_growth_at_random_times
>>> exponential_growth_at_random_times(10).elements[0].prepare().size_
10
"""
return System(
elements=[
GroupElement(
'samples',
element=ObservedGrowthElement,
size=n_samples,
values={'x': x0, 'x0': x0, 'mu': mu, 'lam': lam},
),
],
)
Components
Elements:
ObservedGrowthElement, fromElement
class ObservedGrowthElement(Element):
"""Quantity that grows exponentially and is observed and restarted at exponentially distributed times.
The quantity follows `x' = mu x` from `x0`, and after a waiting time drawn from the exponential distribution of
rate `lam` it is observed and starts again from `x0`.
Args:
label:
The label of the element or the group.
visual:
How the element is drawn, or `None` for `default_visual_`.
x:
The initial value.
x0:
The value every growth starts from.
mu:
The growth rate.
lam:
The rate of the observation times.
Examples:
>>> from skcomplex.systems.mathematics.stochastic_processes import ObservedGrowthElement
>>> ObservedGrowthElement('growth', lam=2.0).lam
2.0
"""
def __init__(
self,
label: str,
visual: VisualSpec | None = None,
*,
x: Annotated[float, StateSpec(domain=RealSet.open(0, oo))] = 1.0,
x0: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 1.0,
mu: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 1.0,
lam: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 1.5,
) -> None:
super().__init__(label, visual=visual)
self.x = x
self.x0 = x0
self.mu = mu
self.lam = lam
def _get_laws(self, s: SimpleNamespace) -> list[BaseLaw]:
"""Return the growth and the restart at the observation times.
Args:
s:
The namespace of the symbols the laws can use.
Returns:
laws:
The laws of the element.
"""
return [
RateLaw(s.x, s.mu * s.x),
JumpLaw(waiting=draw('wait', 'expon', scale=1 / s.lam), reset={s.x: s.x0}, label='observations'),
]
Equations
samples.x[i]: diff(x_samples(t), t) == mu_samples*x_samples(t)