Skip to main content

scikit-complexity

Category Tools
Development black ruff mypy docformatter
Testing pytest coverage interrogate
Security pip-audit bandit
Automation nox pre-commit
Package version pythonversion downloads
Documentation properdocs
Communication discussions

Overview

scikit-complexity lets you describe a model from any science in a few lines, and takes care of the rest: it works out the mathematics, picks a solver, runs the simulation, and streams it live to the Rerun viewer.

Flocks, epidemics, markets, fluids, neural networks and cellular automata are usually written in separate tools with separate conventions. Here they share one small vocabulary, in the spirit of scikit-learn: elements carry state, interactions change it through laws, and systems nest and compose. Learn it once, and every field opens up.

Decaying 2D turbulence
Physics
Decaying 2D turbulence
Gray-Scott patterns
Chemistry
Gray-Scott patterns
Boids flocking
Biology
Boids flocking
Sugarscape
Economics
Sugarscape
Nagel-Schreckenberg traffic
Engineering
Nagel-Schreckenberg traffic
Julia sets
Mathematics
Julia sets
Game of Life
Computer science
Game of Life
Schelling segregation
Social science
Schelling segregation

A few of the 549 ready-to-run models, each with a documented example in the gallery.

Features

  • Every kind of dynamics, one interface. Differential equations, stochastic processes, jump processes, discrete maps, cellular automata, agents, networks and hypergraphs, fields and PDEs, quantum systems, and models that learn by gradient descent.
  • The form of your model is inferred. Write the laws; the framework decides whether it is an ODE, an SDE or a jump process, and compiles it for NumPy, Numba, or JAX.
  • Symbols when you want them, code when you don't. Laws are Sage symbolic expressions you can inspect and solve exactly, or plain Python functions.
  • Watch it run. Stream any simulation to Rerun in real time, and change its parameters while it runs.
  • Analysis included. Nearly 50 analyses, from Lyapunov exponents and entropy to network motifs, scaling laws and system identification, plus experiments for parameter sweeps, sensitivity, calibration and basin stability.
  • Standing on mature libraries. SciPy, NetworkX, Mesa, LAMMPS, QuTiP, JAX and others do the heavy lifting.
  • Extend it, don't fork it. Models are written with the same public classes you use, so each one doubles as an example for your own.

Installation

scikit-complexity supports Python 3.12, 3.13, and 3.14 on Linux and on macOS 13 or later with Apple silicon, and is available on PyPI. On Python 3.14 the install builds memory-allocator from source, so it needs a C compiler:

pip install scikit-complexity

The installation includes Sage through the passagemath distributions, LAMMPS, Mesa, Numba, JAX, and Rerun. Windows has no passagemath wheels, so on Windows the package runs in WSL.

For development, clone the repository and install the project with PDM:

git clone https://github.com/georgedouzas/scikit-complexity.git
cd scikit-complexity
pdm install

Usage

Build your own model from a few general classes, or start from one of the 549 ready-made models, which are written with the same classes and work as examples for your own.

Build a model

A predator and prey model assembles from ready-made interactions:

from skcomplex.core.system import System
from skcomplex.models.biology.common.populations import (
    LogisticGrowthInteraction,
    MortalityInteraction,
    PopulationElement,
)
from skcomplex.models.biology.ecology import PredationInteraction

system = System(
    elements=[PopulationElement('rabbits', n=40), PopulationElement('foxes', n=9)],
    interactions=[
        LogisticGrowthInteraction('growth', target='rabbits', r=1.1, K=1000),
        PredationInteraction('hunt', predator='foxes', prey='rabbits', a=0.4, b=0.1),
        MortalityInteraction('death', target='foxes', d=0.4),
    ],
)

A simulation runs it and records the trajectory. Adding a RerunObserver streams the run to the Rerun viewer, and a RealTimeClock paces it against wall time:

from skcomplex.engine.runtime import RealTimeClock, Simulation
from skcomplex.engine.viz import RerunObserver

simulation = Simulation(
    system,
    dt=0.05,
    clock=RealTimeClock(speed=20.0),
    observers=[RerunObserver('lotka-volterra', spawn=True)],
).check().prepare()
trajectory = simulation.run(until=30).trajectory_
print(round(float(trajectory.values('rabbits.n').max())))

A simulation started with start runs in the background, and its parameters can change while it runs:

from skcomplex.engine.runtime import RealTimeClock, Simulation

simulation = Simulation(system, dt=0.05, clock=RealTimeClock(speed=20.0)).check().prepare().start(until=30)
simulation.update_parameters({'hunt.a': 0.2})
simulation.wait()

A new interaction takes a few lines. It declares its roles and parameters as annotated arguments of its constructor, and returns its laws from _get_laws, where the namespace s holds the symbols of its parameters and of the elements bound to its roles:

from typing import Annotated

from sage.all__sagemath_symbolics import oo
from sage.sets.real_set import RealSet

from skcomplex.analysis import SymbolicAnalysis
from skcomplex.core.interactions import Interaction
from skcomplex.core.laws import RateLaw
from skcomplex.specs import ParameterSpec, RoleSpec
from skcomplex.core.system import System
from skcomplex.models.biology.common.populations import LogisticGrowthInteraction, PopulationElement


class HarvestInteraction(Interaction):
    def __init__(
        self,
        label,
        *,
        target: Annotated[str, RoleSpec()],
        h: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.1,
    ):
        super().__init__(label)
        self.target = target
        self.h = h

    def _get_laws(self, s):
        return [RateLaw(s.target.n, -s.h * s.target.n)]


harvested = System(
    elements=[PopulationElement('fish', n=500)],
    interactions=[
        LogisticGrowthInteraction('growth', target='fish', r=0.5, K=1000),
        HarvestInteraction('fishing', target='fish', h=0.1),
    ],
)
print(SymbolicAnalysis().check().prepare(harvested).run().equations_['fish.n'])

Use a ready-made model

Every model comes with a description, tags, parameters and references, so you can browse the catalog from Python:

from skcomplex.models import catalog, describe

for model in catalog(field='biology/ecology'):
    print(model.name, '-', model.description)

print([model.name for model in catalog() if 'oscillation' in model.tags])

entry = describe('lotka_volterra')
print(entry.description, entry.formalism, entry.parameters, entry.references)

Run any of them in one line:

from skcomplex.models import run

trajectory = run('sir').trajectory_
print(trajectory.values('I.n').max().round())

Each run can stream to the Rerun viewer:

Prey and predators cycle
lotka_volterra
Prey and predators cycle
An epidemic rises and fades
sir
An epidemic rises and fades
Wolves, sheep and grass on a grid
wolf_sheep
Wolves, sheep and grass on a grid

Spec-driven development

The project's engineering constitution lives in openspec/constitution.md and binds all work. The project uses OpenSpec for spec-driven development, and openspec/config.yaml names the constitution as binding.

Metadata

Release files for scikit-complexity 0.3.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for scikit-complexity 0.3.0
File Size Uploaded Provenance Actions
scikit_complexity-0.3.0.tar.gz 2.5 MB With provenance Details for scikit_complexity-0.3.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for scikit-complexity 0.3.0
File Interpreter ABI Platform Actions
scikit_complexity-0.3.0-py3-none-any.whl Python 3 none any Details for scikit_complexity-0.3.0-py3-none-any.whl

Total release size: 5.4 MB

Release files / scikit_complexity-0.3.0.tar.gz

Download URL scikit_complexity-0.3.0.tar.gz
Size 2.5 MB
Tags Source
SHA-256 checksum
How to use checksums
a25ade21a5109b4d3b74ce125313cf3af33b49b870eed61f8cdf22f3128fa4ab
BLAKE2b-256 checksum
How to use checksums
6b1d7fe0250094ae8f8c253548a0780e2d6fc34de0394a29108af159244a710e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 3, 2026.

Transparency log

Release files / scikit_complexity-0.3.0-py3-none-any.whl

Download URL scikit_complexity-0.3.0-py3-none-any.whl
Size 2.9 MB
Tags Python 3
SHA-256 checksum
How to use checksums
3b595d940b32e37ce48b6346247720c4c181027499150dce657b7e0357e9b7aa
BLAKE2b-256 checksum
How to use checksums
1afea7d585c0980a1699d03c9be0fd23a77f98a2f8361bf08224125b524d387d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 3, 2026.

Transparency log

Security for scikit-complexity 0.3.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

Both files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for scikit_complexity-0.3.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 3, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page