Concepts
Learn the few words every custom system is written in. You describe what the system is, and scikit-complexity decides
how to solve it.
from skcomplex.core.components.elements import CompartmentElement
from skcomplex.core.components.interactions import RateInteraction
from skcomplex.core.components.system import System
from skcomplex.core.engine.runtime import Simulation
rabbits = CompartmentElement('rabbits', n=10)
growth = RateInteraction('growth', target='rabbits', state='n', rate=lambda s: 0.5 * s.target.n)
system = System(elements=[rabbits], interactions=[growth])
Simulation(system, dt=0.1).prepare().run(until=2).trajectory_.values('rabbits.n')[-1].round(2)
27.18
The element rabbits carries the state n, the interaction growth adds the rate 0.5 n to it, and the system holds
both. The simulation speaks the same two verbs as the parts: prepare checks the system, and run advances it and
records the value of n at every frame in its trajectory.
An element of your own declares its states as arguments of its __init__, each annotated with a spec. StateSpec
marks n as a state, and the default of the argument is its initial value. CompartmentElement is such an element of
the core.
from typing import Annotated
from skcomplex.core.components.elements import Element
from skcomplex.core.specs import StateSpec
class PopulationElement(Element):
def __init__(self, label, *, n: Annotated[float, StateSpec()] = 1.0):
super().__init__(label)
self.n = n
system = System(elements=[PopulationElement('rabbits', n=10)], interactions=[growth])
Simulation(system, dt=0.1).prepare().run(until=2).trajectory_.values('rabbits.n')[-1].round(2)
27.18
Defining elements covers states, parameters, roles, and their specs in full.
Parts
A system is made of parts: its elements, its interactions, the laws they return, and the system itself.
- An element is an entity that carries state, such as a particle, a population, a compartment, or a market.
- A group holds many identical elements of one type as arrays.
- An interaction couples elements through roles and describes its effect with laws.
- A system holds elements, interactions, nested systems, an optional space, and an optional time.
These concepts carry no field-specific meaning. A population, a particle, a firm, and a cell are all elements. So a
system in any field of science is a configuration of the same interface, and every ready-made system in
skcomplex.systems is a factory that builds such a configuration.
Two verbs
Every part speaks two verbs, and both return the part itself.
prepare(...)validates the part and prepares it against what it works on.run(...)sets what the part contributes. An element, an interaction, or a system sets its laws inlaws_. A law sets invalue_its value at given values of the symbols it reads, such as the rate of aRateLaw.
A part must be prepared before it runs.
The interaction growth returns a RateLaw on n. A law speaks the two verbs on its own too, so you can check it
before it joins a system. Here it gives its rate at n = 10.
from sage.all__sagemath_symbolics import var
from skcomplex.core.components.laws import RateLaw
n = var('n')
RateLaw(n, 0.5 * n).prepare('growth').run({'n': 10.0}).value_
5.0
Laws
A law says how a state changes. Every law is a class, and these four are the most common.
RateLawadds a term to the time derivative of a state. Rates on one state add up.NoiseLawdrives a state with a Wiener process, independent unless laws name a shared or correlated one.JumpLawfires a random event that changes states by fixed increments.UpdateLawgives the next value of a state after one discrete step.
A space gives vector states, such as positions, their dimension. A time says whether the system evolves continuously, in discrete steps, or not at all.
Runs
A run records observables, named values computed from the states at every frame, and checks the invariants it is given.
skcomplex.core.components holds the parts. skcomplex.core.engine compiles a system, infers its mathematical form
from its laws, and builds fast numeric functions that its solvers advance. The laws decide the form, and the form
decides the default solver.
| Laws | Form | Default solver |
|---|---|---|
RateLaw |
ordinary differential equations | ScipyODESolver with LSODA |
RateLaw and NoiseLaw |
stochastic differential equations | EulerMaruyamaSolver |
JumpLaw |
jump process | GillespieSolver |
UpdateLaw |
discrete map | IterationSolver |