Analysis
Analyse systems, trajectories, and measured data by kind of data: series, paths, fields, agents, and networks.
AlignmentAnalysis(kind='mean-vector', variables=None, *, group=None, vectors=False)
Bases: BaseAnalysis
Alignment of the members of a source at every frame, of one kind.
The members are the agents of a group, the sites of a field, or the columns of a set of series, and each holds an
angle or a vector. A trajectory gives the agents of a group with their directions or phases, velocities, and
positions, else every frame of a field of angles, or of vectors with vectors=True, else the series of variables
or the states with the role 'phase', one column per member and one row per sample.
'mean-vector': the length of the mean unit vector, 1 when every member points the same way and about1 / sqrt(n)for random directions. It reads vectors when the source has them, and angles otherwise.'mean-rotation': the mean normalized angular momentum of agents about their centre in a plane, 1 when every agent turns the same way and near 0 for a polarized or disordered group. It reads positions and velocities.'axial':|<exp(2 i theta)>|of the angles, which ignores the sign of a direction.'mean-phase': the modulusrand the argumentpsiof the meanr exp(i psi) = <exp(i theta)>of the angles, the synchrony and the mean phase.'principal-axis': the eigenvector of the largest eigenvalue of a symmetric tensor at every site,axes_, and the scalar order of the tensor at every site,order_. It reads a field of a symmetric tensor state, or an array of its independent components on the last axis, whose number gives the symmetry and the dimension: 2 and 5 for a symmetric traceless tensor in 2 and 3 dimensions, and 3 and 6 for a symmetric tensor.
Angles are derived from the first two components of vectors when a source has no angles, and a vector of one
component points at the angle 0 or pi by its sign. An array of angles holds
one snapshot when it has one dimension, and one frame per row of its first axis otherwise, every other axis
indexing members. An array of vectors, with vectors=True, holds the components along its last axis, and one
snapshot when it has two dimensions. An array for 'mean-rotation' holds the positions followed by the
velocities of every agent along its last axis.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
kind
|
str
|
The alignment to compute, one of the kinds above. |
'mean-vector'
|
variables
|
Sequence[str] | None
|
The field or the series of a trajectory to read, or |
None
|
group
|
str | None
|
The path of the agent group of a trajectory, or |
None
|
vectors
|
bool
|
Whether the members hold vectors rather than angles. |
False
|
Attributes:
| Name | Type | Description |
|---|---|---|
angles_ |
Array | None
|
The angles, frames by members, or |
vectors_ |
Array | None
|
The vectors or velocities, frames by members by components, or |
positions_ |
Array | None
|
The positions of agents, frames by agents by dimensions, or |
order_ |
Array | None
|
The alignment of every frame, between 0 and 1, or the scalar order of every site of every frame. |
tensors_ |
Array | None
|
The independent components of the tensors, with one frame per row of the first axis, for |
axes_ |
Array | None
|
The principal axis of every site of every frame, with the components on the last axis, for
|
phase_ |
Array | None
|
The mean phase of every frame, for |
Examples:
>>> import numpy as np
>>> from skcomplex.analysis import AlignmentAnalysis
>>> AlignmentAnalysis().check().prepare([0.0, 0.0, 0.0]).run().order_.tolist()
[1.0]
>>> AlignmentAnalysis('axial').check().prepare([0.0, np.pi]).run().order_.round(6).tolist()
[1.0]
>>> angles = np.linspace(0, 2 * np.pi, 8, endpoint=False)
>>> ring = np.column_stack([np.cos(angles), np.sin(angles)])
>>> mill = np.hstack([ring, np.column_stack([-ring[:, 1], ring[:, 0]])])
>>> AlignmentAnalysis('mean-rotation').check().prepare(mill).run().order_.round(6).tolist()
[1.0]
>>> phases = AlignmentAnalysis('mean-phase').check().prepare([[0.5, 0.5], [0.0, np.pi]]).run()
>>> phases.order_.round(6).tolist(), phases.phase_.round(6)[:1].tolist()
([1.0, 0.0], [0.5])
>>> tensors = AlignmentAnalysis('principal-axis').check().prepare([[0.5, 0.0], [0.0, 0.5]]).run()
>>> tensors.order_.tolist()
[[1.0, 1.0]]
Source code in src/skcomplex/analysis/_alignment.py
126 127 128 129 130 131 132 133 134 135 136 137 | |
AutomatonAnalysis(kind='injective', *, method='auto', window=None, infinite=False, tries=200, random_state=None, max_radius=2, second=None, configuration=None, site=0, steps=1, windows=None, base=2.0)
Bases: BaseAnalysis
Decisions and measures of a cellular automaton on a finite universe, of a linear automaton, or of a subshift.
The kinds read the automaton, the linear automaton, or the subshift a user builds, such as Automaton,
LinearAutomaton, and Subshift of the automata models. The analysis tells them apart by their methods: a linear
automaton has laurent_polynomial, a subshift has violations, and an automaton with a rule has local_map.
'injective','surjective', and'pre-injective': whether two different configurations never share their image, whether every configuration has a preimage, which on a finite universe holds exactly when it is injective, and whether two configurations that differ only inside a window never share their image. Small universes are decided by enumerating every configuration, and larger ones by a SAT encoding solved by PySAT. A linear automaton is decided from its matrix, all three holding exactly when the matrix is invertible, or onZ^dfrom its Laurent polynomial, injective when it is a monomial and surjective and pre-injective when it is not zero.'garden-of-eden': a pattern on a window that no configuration maps to. Small universes enumerate the images of every configuration, and larger ones draw random patterns and keep the first one whose preimage constraints a SAT solver finds unsatisfiable.'inverse': an automaton whose composition with a reversible automaton is the identity, with the smallest memory. The search tries the neighbourhoods of every radius up tomax_radius, a box of offsets on a lattice or the ball of group elements on a group space, and keeps the first on which the image determines every cell.'compose': the automaton that applies the automaton and thensecondon the same space, whose neighbourhood holds the compositet sof every elementtread by the second andsread by the first.'difference': where two runs differ when one starts fromconfigurationand the other from it with the cell atsitechanged to its next value modulo the number of states.'entropy': the entropylog |X_F| / |F|of the configurations of a subshift, or of the image of an automaton whose rule and neighbourhood are applied on every window.X_Fis the set of admissible configurations of a windowF, or the set of images on the sites ofFwhose cells lie inside it. Along a Følner sequence of windows the values approach the topological entropy.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
kind
|
str
|
The decision or measure, one of the kinds above. |
'injective'
|
method
|
str
|
|
'auto'
|
window
|
Sequence[int] | None
|
The sites where configurations may differ, or of the Garden of Eden pattern, or |
None
|
infinite
|
bool
|
Whether to decide a linear automaton on |
False
|
tries
|
int
|
The number of random patterns tried by SAT. |
200
|
random_state
|
int | Generator | None
|
The seed or generator of the random patterns. |
None
|
max_radius
|
int
|
The largest radius of the memory of the inverse. |
2
|
second
|
AutomatonProtocol | None
|
The automaton applied after the analysed one. |
None
|
configuration
|
ArrayLike | None
|
The initial values of the sites of the difference pattern. |
None
|
site
|
int
|
The site of the changed cell. |
0
|
steps
|
int
|
The number of steps of the difference pattern. |
1
|
windows
|
Sequence[BaseSpace] | None
|
The windows of the entropy, such as lattices with fixed edges of growing size. |
None
|
base
|
float
|
The base of the logarithm. |
2.0
|
Attributes:
| Name | Type | Description |
|---|---|---|
automaton_ |
The automaton, the linear automaton, or the subshift. |
|
injective_ |
Whether the automaton is injective. |
|
surjective_ |
Whether the automaton is surjective. |
|
pre_injective_ |
Whether no two configurations that differ only inside the window share their image. |
|
pattern_ |
A configuration whose values on the window have no preimage, or |
|
inverse_ |
The inverse automaton with a table rule, or |
|
composition_ |
The automaton of the composition, with a function rule. |
|
differences_ |
One row per step, the initial one first, true where the runs differ. |
|
entropy_ |
One entropy per window. |
Raises:
| Type | Description |
|---|---|
AnalysisError
|
The model is not one the kind reads, the method is unknown, enumeration is asked for too many configurations, or composed automata differ in space or number of states. |
Examples:
>>> from skcomplex.analysis import AutomatonAnalysis
>>> from skcomplex.specs import TableSpec, TotalisticSpec
>>> from skcomplex.core.spaces import BoxNeighborhood, LatticeNeighborhood, LatticeSpace
>>> from skcomplex.models.computer_science.automata import Automaton, Subshift
>>> shift = Automaton(LatticeSpace(8), LatticeNeighborhood(((1,),)), TableSpec({(1,): 1}))
>>> AutomatonAnalysis().check().prepare(shift).run().injective_
True
>>> majority = Automaton(LatticeSpace(5), BoxNeighborhood(), TotalisticSpec(lambda total: total >= 2))
>>> AutomatonAnalysis('garden-of-eden').check().prepare(majority).run().pattern_.tolist()
[0, 0, 1, 0, 1]
>>> golden = Subshift(LatticeNeighborhood(((0,), (1,))), [(1, 1)])
>>> analysis = AutomatonAnalysis('entropy', windows=[LatticeSpace(20, boundary='fixed')])
>>> analysis.check().prepare(golden).run().entropy_.round(3).tolist()
[0.706]
Source code in src/skcomplex/analysis/_automata.py
204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 | |
BaseAnalysis
Bases: BaseConfig[Source, object], ABC
Base of every analysis: it stores its settings, checks them, prepares on a source, and runs.
A child stores its settings in __init__ and implements four hooks that the verbs call:
_check()validates the settings._get_data_kind()returns the kind of data the analysis reads, such as'series'or'field'._prepare(source)reads the data from the source with the readers of the base and sets the attributes that end in_._run()computes the results and sets them as attributes that end in_.
The readers _read_series, _read_path, _read_fields, _read_snapshots, and _read_networks take a trajectory,
and pass an array or a graph through.
Examples:
>>> import numpy as np
>>> from skcomplex.analysis import BaseAnalysis
>>> class MeanAnalysis(BaseAnalysis):
... def __init__(self, variables=None):
... self.variables = variables
...
... def _get_data_kind(self):
... return 'series'
...
... def _prepare(self, source):
... self.series_ = self._read_series(source, self.variables)
...
... def _run(self, inputs):
... self.mean_ = self.series_.values.mean(axis=0)
>>> MeanAnalysis().check().prepare(np.array([1.0, 2.0, 3.0])).run().mean_.tolist()
[2.0]
prepare(source=None)
Read the data of the checked analysis from a source.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
source
|
Source
|
The trajectory, array, graph, or system the analysis measures. |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
analysis |
Self
|
The analysis itself. |
Raises:
| Type | Description |
|---|---|
NotCheckedError
|
The analysis was not checked with |
Source code in src/skcomplex/analysis/_base.py
641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 | |
run(inputs=None, final=False)
Compute the results of the prepared analysis from the data it read.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
inputs
|
object
|
Nothing: an analysis computes from the source it was prepared on. |
None
|
final
|
bool
|
Whether this is the last call. |
False
|
Returns:
| Name | Type | Description |
|---|---|---|
analysis |
Self
|
The analysis itself, with its results in the attributes that end in |
Raises:
| Type | Description |
|---|---|
NotPreparedError
|
The analysis was not prepared with a source. |
Source code in src/skcomplex/analysis/_base.py
659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 | |
ClusterAnalysis(kind='labels', variables=None, *, periodic=False, diagonal=False, axis=0, radius=None)
Bases: BaseAnalysis
Clusters of the occupied cells of a grid, the components of a graph, or the contacts of points, of one kind.
The grid is a boolean array of any dimension, the last frame of a field of a trajectory, or a graph, the last
network of a trajectory. Cells are connected through shared faces, or also corners with diagonal=True.
With a radius, the source holds points instead, an array with one row per point, a stack of such arrays for the
kind 'spanning', or the positions of a group of a trajectory in its last frame. Points closer than twice the
radius are connected, and a cluster joins two opposite faces along axis when it holds points within the radius of
both. The faces are those of the space of a trajectory, and those of the bounding box of an array.
'labels': the label of every cell and the size of every cluster of a grid, in label order, and whether a cluster joins the two opposite edges ofaxis.'sizes': the size of every cluster of a grid or of every component of a graph, largest first.'percolation': the cluster sizes, the strength of the largest cluster, the mean cluster size, and spanning.'spanning': the share of the grids of an ensemble, stacked on the first axis or the frames of a trajectory, with a cluster joining the opposite edges ofaxis.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
kind
|
str
|
The measure to compute, one of the kinds above. |
'labels'
|
variables
|
Sequence[str] | None
|
The field of a trajectory to read, or |
None
|
periodic
|
bool
|
Whether clusters of a grid wrap around its edges. |
False
|
diagonal
|
bool
|
Whether cells that share only a corner are connected. |
False
|
axis
|
int
|
The axis whose two opposite edges a spanning cluster joins. |
0
|
radius
|
float | None
|
The contact radius of points, or |
None
|
Attributes:
| Name | Type | Description |
|---|---|---|
points_ |
The arrays of points, one per entry of the first axis, or |
|
grids_ |
The grids, one per entry of the first axis, or |
|
graph_ |
The graph, or |
|
labels_ |
The label of every cell, 0 for empty cells and 1 onwards for clusters. |
|
sizes_ |
The size of every cluster, in label order for |
|
strength_ |
The share of all sites or nodes in the largest cluster. |
|
mean_size_ |
The mean size of the cluster of an occupied site outside the largest, |
|
spanning_ |
Whether a cluster of the grid joins the two opposite edges of |
|
probability_ |
The spanning probability of the ensemble. |
Examples:
>>> import networkx as nx
>>> from skcomplex.analysis import ClusterAnalysis
>>> ClusterAnalysis('sizes').check().prepare([[1, 1, 0], [0, 0, 1]]).run().sizes_.tolist()
[2, 1]
>>> ClusterAnalysis('sizes').check().prepare(nx.path_graph(3)).run().sizes_.tolist()
[3]
>>> result = ClusterAnalysis('percolation').check().prepare([[1, 1, 0], [1, 0, 1]]).run()
>>> result.strength_, result.mean_size_, result.spanning_
(0.5, 1.0, True)
>>> ClusterAnalysis('sizes', radius=0.6).check().prepare([[0, 0], [1, 0], [5, 5]]).run().sizes_.tolist()
[2, 1]
Source code in src/skcomplex/analysis/_clusters.py
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 | |
CoarseGrainAnalysis(shape=(32, 32), *, box=None, values=None, over=None, state=None)
Bases: BaseAnalysis
Agents coarse-grained into a field on a grid, or members into a density over the values of a state.
An array holds one snapshot, one row per agent in the box. A trajectory gives the positions of its first agent or
particle group at every frame, in the box of its space unless box is set, and one grid per frame.
With over, the analysis coarse-grains in state space instead: every member counts at the given value nearest to
its value of a state, and the field is the fraction of members at every value, which sums to 1. An array holds the
values of one snapshot, one per member, or one row per frame, and a trajectory gives the values of the state state
at every frame. The densities are the initial values of a distribution site group with one member per value.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
shape
|
Sequence[int]
|
The number of cells along every side. |
(32, 32)
|
box
|
Sequence[float] | None
|
The sides of the box, or |
None
|
values
|
ArrayLike | None
|
One value or one row of values per agent of an array, such as unit directions for a polarization field, or
|
None
|
over
|
ArrayLike | None
|
The increasing values of a state to coarse-grain the members over, or |
None
|
state
|
str | None
|
The dotted name of the state whose values a trajectory gives, such as |
None
|
Attributes:
| Name | Type | Description |
|---|---|---|
positions_ |
The positions, one row per agent, with one leading axis of frames for a trajectory, or the values of the
state of every member with |
|
box_ |
The sides of the box, or |
|
field_ |
The grid of counts, or of sums with the value components last, with one grid per frame for a trajectory,
ready for field analyses, or the fractions of members at every value of |
Examples:
>>> from skcomplex.analysis import CoarseGrainAnalysis
>>> positions = [[0.1, 0.1], [0.2, 0.1], [0.9, 0.9]]
>>> CoarseGrainAnalysis([2, 2], box=[1.0, 1.0]).check().prepare(positions).run().field_.tolist()
[[2.0, 0.0], [0.0, 1.0]]
>>> wealth = [-1.0, 0.4, 0.6, 1.5, 9.0]
>>> CoarseGrainAnalysis(over=[0.0, 1.0, 2.0]).check().prepare(wealth).run().field_.tolist()
[0.4, 0.4, 0.2]
Source code in src/skcomplex/analysis/_coarse_grain.py
68 69 70 71 72 73 74 75 76 77 78 79 80 81 | |
CollapseAnalysis(kind='scaling', *, parameters=None, critical=None, nu=None, exponent=0.0, fit=(), waiting=None, lags=None, ratios=None)
Bases: BaseAnalysis
Collapse of curves or distributions of several sizes or ages onto one, of one kind.
The kinds read the curves or the samples of every size or age:
'scaling': the finite-size scaling collapse of curvesy_L(p) = L^a f((p - p_c) L^(1/nu))of every sizeL, against the controlparameters, with the names offitamong'critical','nu', and'exponent'fitted by minimizing the quality.'aging': how far correlation curves of several waiting times stay apart against the lag and againsttau / t_w, from one curve per waiting time, as the two-time correlation ofCorrelationAnalysisgives them.'distribution': the densitiest P(tau, t)of samples oftauat several agestagainsttau / t, which collapse under aging.'crossings': where the curves of consecutive sizes cross against the controlparameters, by linear interpolation of their difference, such as the Binder cumulants of several lattice sizes at the critical point.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
kind
|
str
|
The collapse to compute, one of the kinds above. |
'scaling'
|
parameters
|
Sequence[float] | None
|
The control parameter values, shared by every curve of |
None
|
critical
|
float | None
|
The critical value, or the starting value of a fit. |
None
|
nu
|
float | None
|
The correlation length exponent, or the starting value of a fit. |
None
|
exponent
|
float
|
The exponent |
0.0
|
fit
|
Sequence[str]
|
The names among |
()
|
waiting
|
Sequence[float] | None
|
The waiting times of the curves of |
None
|
lags
|
Sequence[float] | None
|
The lags shared by every curve of |
None
|
ratios
|
Sequence[float] | None
|
The edges of the bins of |
None
|
Attributes:
| Name | Type | Description |
|---|---|---|
values_ |
The curve of every size, the curves of every waiting time, or the samples of every age. |
|
labels_ |
The size, waiting time, or age of every curve. |
|
critical_ |
The critical value used or fitted. |
|
nu_ |
The correlation length exponent used or fitted. |
|
exponent_ |
The exponent |
|
quality_ |
The mean squared relative distance between the scaled curves, 0 for a perfect collapse. |
|
time_spread_ |
The largest difference between the curves against the lag, 0 without aging. |
|
ratio_spread_ |
The largest difference between the curves against |
|
ratios_ |
The centres of the bins of |
|
densities_ |
One row per age of |
|
spread_ |
The largest relative difference between the rows where every row is positive. |
|
crossings_ |
The first crossing of the curves of every pair of consecutive sizes, |
Examples:
>>> import numpy as np
>>> from skcomplex.analysis import CollapseAnalysis
>>> grid = np.linspace(-1, 1, 401)
>>> curves = {size: np.tanh(grid * size) for size in (8, 16, 32)}
>>> collapse = CollapseAnalysis(parameters=grid, critical=0.2, nu=1.5, fit=('critical', 'nu'))
>>> round(collapse.check().prepare(curves).run().nu_, 1)
1.0
>>> lags = np.linspace(1, 100, 100)
>>> curves = [np.exp(-lags / tw) for tw in (10, 100)]
>>> aging = CollapseAnalysis('aging', waiting=[10, 100], lags=lags).check().prepare(curves).run()
>>> round(aging.ratio_spread_, 2), aging.time_spread_ > 0.5
(0.0, True)
>>> curves = {8: [0.6, 0.5, 0.2], 16: [0.65, 0.5, 0.1]}
>>> CollapseAnalysis('crossings', parameters=[1.0, 2.0, 3.0]).check().prepare(curves).run().crossings_.tolist()
[2.0]
Source code in src/skcomplex/analysis/_collapse.py
130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 | |
ComplexityAnalysis(variables=None, *, dimension=6, delay=1, ties='order', random_state=None)
Bases: BaseAnalysis
Place of every series of a source, or of every frame of a field, on Rosso's complexity-entropy plane.
The entropy is the normalized permutation entropy of the ordinal patterns, and the complexity is that entropy times
the Jensen-Shannon divergence of the patterns from uniform ones, computed with ordpy. Noise has entropy near 1 and
complexity near 0, regular series both near 0, and chaos lies in between with high complexity.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
variables
|
Sequence[str] | None
|
The variables of a trajectory to read, or |
None
|
dimension
|
int | tuple[int, int]
|
The length of the patterns of a series, or the window |
6
|
delay
|
int
|
The number of steps between the values of a pattern. |
1
|
ties
|
str
|
|
'order'
|
random_state
|
int | None
|
The seed of the random ranks of equal values. |
None
|
Attributes:
| Name | Type | Description |
|---|---|---|
values_ |
The series, one per column, or the frames of the field. |
|
labels_ |
The label of every series, or of the field. |
|
entropy_ |
The normalized permutation entropy of every series or frame. |
|
complexity_ |
The statistical complexity of every series or frame. |
|
minimum_ |
The curve of least complexity, one row of entropy and complexity per point. |
|
maximum_ |
The curve of largest complexity, one row of entropy and complexity per point. |
Examples:
>>> import numpy as np
>>> from skcomplex.analysis import ComplexityAnalysis
>>> noise = np.random.default_rng(0).standard_normal(50_000)
>>> plane = ComplexityAnalysis(dimension=4).check().prepare(noise).run()
>>> plane.entropy_.round(2).tolist(), plane.complexity_.round(2).tolist()
([1.0], [0.0])
Source code in src/skcomplex/analysis/_complexity.py
69 70 71 72 73 74 75 76 77 78 79 80 81 82 | |
CorrelationAnalysis(kind='auto', variables=None, *, max_lag=None, dt=1.0, waiting=None, lags=None, connected=False, max_distance=None, method='moment', spacing=1.0, frames=False)
Bases: BaseAnalysis
Correlation of every series of a source, of an ensemble at two times, or of a field in space, of one kind.
The kinds read series, ensembles, or fields:
'auto': the autocorrelation of every series at lags 0 tomax_lag, computed with the FFT, and its integrated autocorrelation timedt (1/2 + Σ r(k)), summed to the first negative correlation.'two-time': the two-time correlationC(t_w + tau, t_w) = <x(t_w) x(t_w + tau)>of an ensemble with one row per run and one column per frame, any further axes, such as sites, averaged over.'function': the radially averaged spatial correlation of a field on a periodic grid, 1 at distance 0.'length': the correlation length of a field. The'moment'method fits the Ornstein-Zernike form1 / S(q) ∝ 1 + xi² Σ 4 sin²(q_i / 2)over the modes withq̂² xi² <= 1, and the'fit'method fitsC(r) ~ r^-a exp(-r / xi). Several frames are taken as fluctuations about their common mean.'overlap': the overlapq = <s_i t_i>of two configurationssandtof the same sites, ±1 for identical or reversed configurations of ±1 values and near 0 for independent ones, per frame for frames. It reads a pair of trajectories, whose fields it compares at every frame, or two arrays stacked on the first axis.
The kinds 'function' and 'length' read the last frame of a trajectory, or every frame when frames is true.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
kind
|
str
|
The correlation to compute, one of the kinds above. |
'auto'
|
variables
|
Sequence[str] | None
|
The variables of a trajectory to read, or |
None
|
max_lag
|
int | None
|
The largest lag in steps, or |
None
|
dt
|
float
|
The time between samples. |
1.0
|
waiting
|
Sequence[int] | None
|
The waiting times |
None
|
lags
|
Sequence[int] | None
|
The lags |
None
|
connected
|
bool
|
Whether to subtract the product of the means at the two times. |
False
|
max_distance
|
int | None
|
The largest distance in cells, or |
None
|
method
|
str
|
The method of the correlation length, |
'moment'
|
spacing
|
float
|
The distance between neighbouring sites. |
1.0
|
frames
|
bool
|
Whether the first axis of an array indexes frames, and whether to read every frame of a trajectory. |
False
|
Attributes:
| Name | Type | Description |
|---|---|---|
values_ |
The series, one per column, the ensemble, the field, or the two configurations. |
|
labels_ |
The label of every series, of the ensemble or field, or of the two configurations. |
|
lags_ |
The lags in time of |
|
correlation_ |
One autocorrelation per series for |
|
time_ |
The integrated autocorrelation time of every series, for |
|
distances_ |
The distances of |
|
length_ |
The correlation length, for |
|
overlap_ |
The overlap of the two configurations, one per frame for frames. |
Examples:
>>> import numpy as np
>>> from skcomplex.analysis import CorrelationAnalysis
>>> analysis = CorrelationAnalysis(max_lag=1).check().prepare([1.0, -1.0, 1.0, -1.0]).run()
>>> analysis.correlation_.round(2).tolist()
[[1.0, -0.75]]
>>> two_time = CorrelationAnalysis('two-time', waiting=[2], lags=[0, 3])
>>> two_time.check().prepare(np.ones((4, 10))).run().correlation_.tolist()
[[1.0, 1.0]]
>>> CorrelationAnalysis('overlap').check().prepare([[1, -1, 1, 1], [1, -1, -1, 1]]).run().overlap_
0.5
Source code in src/skcomplex/analysis/_correlation.py
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 | |
DefectAnalysis(period=np.pi, variables=None, *, periodic=True)
Bases: BaseAnalysis
Point defects of a two-dimensional field of angles, with their topological charges, at every frame.
The winding around a plaquette of four neighbouring sites is the sum of the differences of the angles along its
edges, each wrapped to one period around 0, over 2 pi. A plaquette with a winding that is not 0 holds a defect of
that charge. The charges of a periodic lattice sum to 0.
An array of two dimensions holds one snapshot, and an array of three dimensions one frame per row of its first axis.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
period
|
float
|
The period of the angles, |
pi
|
variables
|
Sequence[str] | None
|
The field of a trajectory to read, or |
None
|
periodic
|
bool
|
Whether the lattice joins its opposite edges, or has plaquettes only between its sites. |
True
|
Attributes:
| Name | Type | Description |
|---|---|---|
angles_ |
The angles, with one frame per row of the first axis. |
|
positions_ |
list[Array]
|
The centres of the plaquettes with a defect at every frame, each an array of defects by dimensions. |
charges_ |
list[Array]
|
The charges of the defects at every frame, each an array in the order of |
Examples:
>>> import numpy as np
>>> from skcomplex.analysis import DefectAnalysis
>>> rows, columns = np.meshgrid(np.arange(8.0), np.arange(8.0), indexing='ij')
>>> vortex = np.arctan2(rows - 3.5, columns - 3.5)
>>> defects = DefectAnalysis(2 * np.pi, periodic=False).check().prepare(vortex).run()
>>> defects.positions_[0].tolist(), defects.charges_[0].tolist()
([[3.5, 3.5]], [1.0])
Source code in src/skcomplex/analysis/_defects.py
61 62 63 64 65 66 67 68 69 70 | |
DiscoveryAnalysis
Bases: BaseAnalysis
Analyses that apply to a trajectory, a system, or an array, listed under the kind of data they read.
Preparing reads the kinds of data the source holds. Running builds every analysis of the library that takes no required setting, once per kind of a family, asks each for its data kind, and keeps those whose kind the source holds. A one-dimensional array is one series, and an array of more dimensions is one field and a set of series, one per column.
Attributes:
| Name | Type | Description |
|---|---|---|
kinds_ |
The data kinds of the source, in the order agents, field, network, path, series. |
|
readings_ |
How the analyses of every data kind read the source, by data kind. |
|
analyses_ |
The unprepared analyses that apply to the source, by data kind. |
Examples:
>>> import numpy as np
>>> from skcomplex.analysis import DiscoveryAnalysis
>>> discovery = DiscoveryAnalysis().check().prepare(np.zeros((16, 16))).run()
>>> discovery.kinds_
['field', 'series']
>>> discovery.readings_['series']
'every column of the array as a series'
>>> any(type(item).__name__ == 'EntropyAnalysis' for item in discovery.analyses_['series'])
True
DisplacementAnalysis(group=None, *, dt=1.0, lags=None, fit_range=None)
Bases: BaseAnalysis
Mean squared displacement of particles over all lags, its scaling exponent, and the diffusion coefficient.
The displacement of every particle is computed for all lags at once with the FFT of tidynamics, so positions
must be unwrapped across periodic boundaries, as a trajectory gives them.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
group
|
str | None
|
The path of the agent group of a trajectory, or |
None
|
dt
|
float
|
The time between frames. |
1.0
|
lags
|
Sequence[int] | None
|
The lags in frames to keep, or |
None
|
fit_range
|
tuple[float, float] | None
|
The smallest and largest lags in time of the fits, or |
None
|
Attributes:
| Name | Type | Description |
|---|---|---|
positions_ |
The unwrapped positions, frames by particles by dimensions. |
|
lags_ |
The lags in time. |
|
msd_ |
The mean squared displacement at every lag. |
|
exponent_ |
The slope of |
|
diffusion_ |
The coefficient |
Examples:
>>> import numpy as np
>>> from skcomplex.analysis import DisplacementAnalysis
>>> walks = np.cumsum(np.random.default_rng(0).standard_normal((2000, 500)), axis=0)
>>> displacement = DisplacementAnalysis().check().prepare(walks).run()
>>> round(displacement.exponent_, 1), round(displacement.diffusion_, 1)
(1.0, 0.5)
Source code in src/skcomplex/analysis/_displacement.py
68 69 70 71 72 73 74 75 76 77 78 79 | |
DistributionAnalysis(kind='histogram', variables=None, *, group=None, bins=30, log=False, absolute=False, orders=(4, 2), tail=10)
Bases: BaseAnalysis
Distribution of the values of a source, of one kind.
The source gives samples as columns: the series of a trajectory or an array, or the speeds of the agents of a trajectory, one sample per frame. The first kinds pool every sample into one:
'histogram': the edges and the probability density ofbinsbins, equally spaced in the logarithm of the values withlog=Truefor heavy tails.'ccdf': the complementary cumulative distribution, the share of samples at or above every distinct value.'gini': the Gini coefficient of nonnegative values, 0 for equality and close to 1 when one holds everything.'tail-index': the Hill estimate of the tail index from thetaillargest positive samples, the exponentalpha - 1of the survival function of a densityp(x) ∝ x^-alpha.
The other kinds describe every sample:
'moments': the mean, the variance, the skewness, and the excess kurtosis of every sample, or of its absolute values withabsolute=True.'moment-ratio': the ratio<x^p> / <x^q>^(p / q)of the moments of the evenorders(p, q), and the cumulant1 - ratio / ratio_gauss, normalized by the ratio of a centred Gaussian so that it is 0 for Gaussian samples. For the orders 4 and 2 the ratio is the kurtosis about 0 and the cumulant1 - <x^4> / (3 <x^2>^2), 2/3 for samples at ±1.'dispersion-index': the variance over the mean of every sample of counts, 1 for Poisson counts, above 1 for overdispersed and below 1 for underdispersed counts.'records': the number of records of every series, the values larger than every value before them, about the harmonic number of the length for independent values.'total-variation': the total variation distance1/2 Σ_u |a_u / A - b_u / B|between the distributions of two groups across units, from one row per item with its group and its unit, 0 for identical distributions and 1 for disjoint ones.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
kind
|
str
|
The description to compute, one of the kinds above. |
'histogram'
|
variables
|
Sequence[str] | None
|
The variables of a trajectory to read, or |
None
|
group
|
str | None
|
The path of the agent or particle group whose speeds are read, or |
None
|
bins
|
int
|
The number of bins of the histogram. |
30
|
log
|
bool
|
Whether the bins of the histogram are equally spaced in the logarithm of the values, which needs positive values. |
False
|
absolute
|
bool
|
Whether the moments are those of the absolute values. |
False
|
orders
|
tuple[int, int]
|
The positive even orders |
(4, 2)
|
tail
|
int
|
The number of largest samples of the Hill estimate. |
10
|
Attributes:
| Name | Type | Description |
|---|---|---|
values_ |
The pooled sample, or the samples, one per column. |
|
labels_ |
The label of every sample. |
|
edges_ |
The bin edges of the histogram. |
|
density_ |
The probability density in every bin of the histogram. |
|
support_ |
The sorted distinct values of the complementary cumulative distribution. |
|
survival_ |
The share of samples at or above every distinct value, |
|
mean_ |
The mean of every sample. |
|
variance_ |
The variance of every sample. |
|
skewness_ |
The skewness of every sample. |
|
kurtosis_ |
The excess kurtosis of every sample, 0 for Gaussian samples. |
|
ratio_ |
The moment ratio of every sample. |
|
cumulant_ |
The normalized cumulant of every sample. |
|
index_ |
The dispersion index of every sample. |
|
gini_ |
The Gini coefficient. |
|
tail_index_ |
The Hill estimate of the tail index. |
|
records_ |
The number of records of every series, the first value included. |
|
distance_ |
The total variation distance between the two groups. |
Examples:
>>> from skcomplex.analysis import DistributionAnalysis
>>> histogram = DistributionAnalysis('histogram', bins=3, log=True).check().prepare([1, 2, 4, 8]).run()
>>> histogram.edges_.round(2).tolist()
[1.0, 2.0, 4.0, 8.0]
>>> DistributionAnalysis('ccdf').check().prepare([1, 1, 2, 4]).run().survival_.tolist()
[1.0, 0.5, 0.25]
>>> DistributionAnalysis('gini').check().prepare([0, 0, 0, 4]).run().gini_
0.75
>>> DistributionAnalysis('moment-ratio').check().prepare([1.0, -1.0, 1.0]).run().cumulant_.round(4).tolist()
[0.6667]
>>> DistributionAnalysis('dispersion-index').check().prepare([1, 3, 1, 3]).run().index_.tolist()
[0.5]
>>> DistributionAnalysis('total-variation').check().prepare([[0, 0], [0, 0], [1, 1], [1, 1]]).run().distance_
1.0
Source code in src/skcomplex/analysis/_distribution.py
176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 | |
DomainAnalysis(kind='size', variables=None, *, method='moment', spacing=1.0, fit_range=None, times=None, attribute='state')
Bases: BaseAnalysis
Domains of every frame of a field, or of the states on a network, of one kind.
The kinds read frames of a field on a periodic grid:
'size': the characteristic domain size,2 pi / <k>over the structure factor withmethod='moment', or the first zero of the correlation function withmethod='zero'.'growth': the domain size of every frame and the exponent of its growth in time, the slope oflog sizeagainstlog timeover the fit range, 1/2 for non-conserved and 1/3 for conserved order parameters.'wavelength': the dominant wavelength and wavenumber of a pattern, the peak of its structure factor, and the nematic order of the wave vectors near the peak, 1 for parallel stripes and near 0 for labyrinths or spots.'interface-density': the share of neighbouring pairs, on a periodic grid without corners or along the edges of a network, whose states differ, 0 for one domain and 1/2 for random binary states.
A trajectory gives the frames of a lattice state and their times. An array is one frame, or one frame per entry of
times along its first axis. A graph carries the states on its nodes for 'interface-density'.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
kind
|
str
|
The domain measure to compute, one of the kinds above. |
'size'
|
variables
|
Sequence[str] | None
|
The lattice state of a trajectory to read, or |
None
|
method
|
str
|
The domain size method, |
'moment'
|
spacing
|
float
|
The distance between neighbouring sites. |
1.0
|
fit_range
|
tuple[float, float] | None
|
The first and last times of the growth fit, or |
None
|
times
|
Sequence[float] | None
|
The time of every frame of an array, or |
None
|
attribute
|
str
|
The node attribute of the states of a graph. |
'state'
|
Attributes:
| Name | Type | Description |
|---|---|---|
frames_ |
The frames of the field, or the graph. |
|
times_ |
The time of every frame. |
|
size_ |
The domain size of every frame. |
|
exponent_ |
The growth exponent of the domain size. |
|
wavelength_ |
The wavelength of the peak of every frame. |
|
wavenumber_ |
The wavenumber of the peak of every frame. |
|
orientation_ |
The orientation order of the wave vectors near the peak of every frame. |
|
density_ |
The interface density of every frame. |
Examples:
>>> import numpy as np
>>> from skcomplex.analysis import DomainAnalysis
>>> x = np.arange(256)
>>> stripes = np.sign(np.cos(2 * np.pi * x / 16))
>>> DomainAnalysis(method='zero').check().prepare(stripes[:64]).run().size_.tolist()
[4.0]
>>> stack = [np.sign(np.cos(2 * np.pi * x / (8 * t))) for t in (1, 2, 4)]
>>> growth = DomainAnalysis('growth', method='zero', times=[1, 2, 4]).check().prepare(stack).run()
>>> round(growth.exponent_, 2)
1.0
>>> DomainAnalysis('interface-density').check().prepare([[1, 1, -1, -1]] * 4).run().density_.tolist()
[0.25]
Source code in src/skcomplex/analysis/_domains.py
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 | |
EmbeddingAnalysis(kind='delay', variables=None, *, delay=None, dimension=None, threshold=0.01, max_delay=100, max_dimension=10, bins=16, ratio=10.0, escape=2.0)
Bases: BaseAnalysis
Delay embedding of one series, with the delay and the dimension chosen from the data unless given, of one kind.
The kinds read one series:
'delay': the delay vectors(x_t, x_{t+delay}, ..., x_{t+(dimension-1) delay}). Without a delay, the delay is the first minimum of the auto mutual information. Without a dimension, the dimension is the first one whose fraction of false nearest neighbours lies belowthreshold.'false-nearest-neighbors': Kennel's fraction of false nearest neighbours of the embeddings of dimensions 1 tomax_dimension. A nearest neighbour in dimensiondis false when the next coordinate moves it away by more thanratiotimes their distance, or by more thanescapetimes the standard deviation of the series.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
kind
|
str
|
The embedding measure to compute, one of the kinds above. |
'delay'
|
variables
|
Sequence[str] | None
|
The one variable of a trajectory to read, or |
None
|
delay
|
int | None
|
The delay in steps, or |
None
|
dimension
|
int | None
|
The dimension, or |
None
|
threshold
|
float
|
The fraction of false nearest neighbours accepted. |
0.01
|
max_delay
|
int
|
The largest delay tried. |
100
|
max_dimension
|
int
|
The largest dimension tried. |
10
|
bins
|
int
|
The number of equally populated bins of the auto mutual information. |
16
|
ratio
|
float
|
The threshold on the relative growth of the distance of a false neighbour. |
10.0
|
escape
|
float
|
The threshold on the distance of a false neighbour in the next dimension, in standard deviations. |
2.0
|
Attributes:
| Name | Type | Description |
|---|---|---|
values_ |
The series, as one column. |
|
labels_ |
The label of the series. |
|
delay_ |
The delay in steps. |
|
dimension_ |
The dimension of |
|
points_ |
One row per delay vector of |
|
mutual_information_ |
The auto mutual information at every delay from 0, or |
|
false_neighbors_ |
The fraction of false nearest neighbours in every dimension from 1, or |
Examples:
>>> import numpy as np
>>> from skcomplex.analysis import EmbeddingAnalysis
>>> EmbeddingAnalysis(delay=2, dimension=2).check().prepare([0, 1, 2, 3, 4]).run().points_.tolist()
[[0.0, 2.0], [1.0, 3.0], [2.0, 4.0]]
>>> embedding = EmbeddingAnalysis(delay=31).check().prepare(np.sin(np.arange(5000) * 0.05)).run()
>>> embedding.delay_, embedding.dimension_
(31, 2)
Source code in src/skcomplex/analysis/_embedding.py
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 | |
EmergenceAnalysis(kind='causal', variables=None, *, partition=None, weighting='uniform', search='greedy', lag=1, history=1, estimator='plugin', k=3, base=2.0)
Bases: BaseAnalysis
Emergence of a macro scale over a micro scale, of one kind.
The kinds read a transition matrix or the series of micro variables:
'effective-information': the effective information of a transition matrix,H(mean row) - mean H(row)over the states with observed transitions, split into determinism and degeneracy. A matrix of counts is normalised by row first.'causal': the causal emergence of a transition matrix, the gain in effective information of the macro matrix of a given or searched partition over the micro matrix. The macro matrix sums the micro transitions from every block to every block, weighting the micro states of a block uniformly, as Hoel, Albantakis, and Tononi (2013) do, or by the stationary distribution, as Klein and Hoel (2020) do. The greedy search of Klein and Hoel (2020) merges the pair of blocks with the largest macro effective information while that grows, so it can miss the best partition. The exhaustive search tries every partition of at most 10 states.'criteria': the criteria Ψ, Δ, and Γ of Rosas et al. (2020) for the macro feature of the micro series given bypartition, estimatedlagsteps ahead with the minimum mutual information redundancy.'closure': how well the macro past and the micro past of the macro series given bypartitionpredict the macro future. The coarse-graining is closed when the gap is zero up to the bias of the plug-in estimator.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
kind
|
str
|
The emergence to measure, one of the kinds above. |
'causal'
|
variables
|
Sequence[str] | None
|
The micro variables of a trajectory to read, or |
None
|
partition
|
Partition | None
|
The macro label of every integer micro state, numbered 0, 1, and so on, or a function from an array of
micro states, or from the micro series with one column per variable, to their macro labels. |
None
|
weighting
|
str
|
|
'uniform'
|
search
|
str
|
|
'greedy'
|
lag
|
int
|
The number of steps between the present and the future of the criteria. |
1
|
history
|
int
|
The number of past steps the closure conditions on. |
1
|
estimator
|
str
|
|
'plugin'
|
k
|
int
|
The number of neighbours of the |
3
|
base
|
float
|
The base of the logarithm, 2 for bits. |
2.0
|
Attributes:
| Name | Type | Description |
|---|---|---|
matrix_ |
The micro transition matrix, for |
|
values_ |
The micro series, one column per micro variable, for |
|
labels_ |
The label of every micro series. |
|
information_ |
The effective information in bits, for |
|
determinism_ |
|
|
degeneracy_ |
|
|
states_ |
The states with observed transitions, the rows the effective information uses. |
|
partition_ |
The macro label of every micro state, for |
|
macro_matrix_ |
The macro transition matrix of the partition, every row summing to one. |
|
micro_information_ |
The effective information of the micro matrix. |
|
macro_information_ |
The effective information of the macro matrix. |
|
gain_ |
The macro minus the micro effective information in bits. |
|
psi_ |
|
|
delta_ |
|
|
gamma_ |
|
|
macro_uncertainty_ |
|
|
micro_uncertainty_ |
|
|
gap_ |
The information the micro past adds about the macro future, zero for a closed coarse-graining. |
Raises:
| Type | Description |
|---|---|
AnalysisError
|
The matrix is not square or has no observed transition, the partition is not valid, or the exhaustive search gets more than 10 states. |
Warns:
| Type | Description |
|---|---|
UnobservedStatesWarning
|
Some rows of the micro matrix hold no transition, and the warning names their states. |
Examples:
>>> import numpy as np
>>> from skcomplex.analysis import EmergenceAnalysis
>>> EmergenceAnalysis('effective-information').check().prepare(np.eye(4)).run().information_
2.0
>>> matrix = np.zeros((4, 4))
>>> matrix[:3, :3], matrix[3, 3] = 1 / 3, 1.0
>>> found = EmergenceAnalysis('causal').check().prepare(matrix).run()
>>> found.partition_.tolist(), round(found.gain_, 3)
([0, 0, 0, 1], 0.189)
>>> micro = np.random.default_rng(0).integers(0, 4, 5000)
>>> round(EmergenceAnalysis('closure', partition=[0, 0, 1, 1]).check().prepare(micro).run().gap_, 2)
0.0
Source code in src/skcomplex/analysis/_emergence.py
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 | |
EntropyAnalysis(kind='shannon', variables=None, *, order=2.0, base=2.0, probabilities=False, dimension=3, delay=1, tolerance=0.2, scales=tuple(range(1, 11)), normalize=True, dt=1.0, measure='shannon', ties='order', random_state=None, reference=None)
Bases: BaseAnalysis
Entropy of every series of a source, or of every frame of a field, of one kind.
The kinds read symbols, patterns, or real values:
'shannon','renyi', and'tsallis': the entropy of the distribution of the symbols, or of a probability vector withprobabilities=True, the Rényi order and the Tsallis index given byorder.'block','rate', and'excess': the block entropiesS_0toS_m, the entropy rate, and the excess entropy of the blocks of up todimensionsymbols, or of square patches of a field.'lempel-ziv': the number of new phrases of the LZ76 parsing.'permutation': the entropy of the ordinal patterns of lengthdimension, or of the windows(columns, rows)of a field, measured withmeasure.'sample'and'approximate': the regularity of patterns of lengthdimension, close withintolerancestandard deviations.'multiscale': the sample entropy of the means of non-overlapping windows of every scale ofscales.'spectral': the Shannon entropy of the normalized periodogram.'ensemble': the Shannon entropy in bits of the outcomes of an ensemble at every frame, and their Kullback-Leibler divergence from thereferencelaw, as in the H-theorem. The ensemble has one row per run and one column per frame of integer outcomes, such asExperimentResult.ensemblereturns.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
kind
|
str
|
The entropy to compute, one of the kinds above. |
'shannon'
|
variables
|
Sequence[str] | None
|
The variables of a trajectory to read, or |
None
|
order
|
float
|
The order of the Rényi entropy or the index of the Tsallis entropy. |
2.0
|
base
|
float
|
The base of the logarithm, 2 for bits. |
2.0
|
probabilities
|
bool
|
Whether every series is already a probability vector. |
False
|
dimension
|
int | tuple[int, int]
|
The length of patterns or the largest block length, or the window |
3
|
delay
|
int
|
The number of steps between the values of an ordinal pattern. |
1
|
tolerance
|
float
|
The largest distance of close patterns, as a fraction of the standard deviation. |
0.2
|
scales
|
Sequence[int]
|
The window lengths of the multiscale entropy. |
tuple(range(1, 11))
|
normalize
|
bool
|
Whether to divide by the largest value, so the entropy lies between 0 and 1. |
True
|
dt
|
float
|
The time between samples of the spectral entropy. |
1.0
|
measure
|
str
|
The entropy of the ordinal patterns: |
'shannon'
|
ties
|
str
|
|
'order'
|
random_state
|
int | None
|
The seed of the random ranks of equal values. |
None
|
reference
|
ArrayLike | None
|
The probability of every outcome under the reference law of an ensemble, such as the stationary law. |
None
|
Attributes:
| Name | Type | Description |
|---|---|---|
values_ |
The series, one per column, or the frames of the field. |
|
labels_ |
The label of every series, or of the field. |
|
entropy_ |
One entropy per series or frame, with one column per block length for |
|
divergence_ |
The divergence in bits of the outcomes of every frame of an ensemble from the reference law. |
|
error_ |
The expected divergence of a sample of the reference law of the ensemble's size, |
Examples:
>>> import numpy as np
>>> from skcomplex.analysis import EntropyAnalysis
>>> EntropyAnalysis().check().prepare([0, 1, 0, 1]).run().entropy_.tolist()
[1.0]
>>> EntropyAnalysis('excess', dimension=4).check().prepare([0, 0, 1, 1] * 100).run().entropy_.round(3).tolist()
[2.0]
Source code in src/skcomplex/analysis/_entropy.py
148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 | |
EpsilonMachineAnalysis(variables=None, *, max_length=3, significance=0.001)
Bases: BaseAnalysis
Epsilon-machine of a discrete series reconstructed by causal-state splitting (CSSR).
Histories up to max_length symbols join the state whose law of the next symbol they share by a chi-square
test, and states are then split until their transitions are deterministic.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
variables
|
Sequence[str] | None
|
The variable of a trajectory to read, a list of one name, or |
None
|
max_length
|
int
|
The longest history, kept well below the logarithm of the series length in the alphabet size. |
3
|
significance
|
float
|
The significance level of the test that splits a history from a state. |
0.001
|
Attributes:
| Name | Type | Description |
|---|---|---|
values_ |
The series of symbols. |
|
labels_ |
The label of the series. |
|
alphabet_ |
The distinct symbols, whose positions are the codes of the histories and of the columns. |
|
histories_ |
The histories of every causal state, as codes of their symbols, oldest first. |
|
transitions_ |
The state reached from every state on every symbol, -1 for symbols a state never emits. |
|
probabilities_ |
The probability of every symbol from every state. |
|
stationary_ |
The fraction of time spent in every state. |
|
statistical_complexity_ |
The entropy of the stationary distribution of the causal states in bits. |
|
entropy_rate_ |
The mean entropy of the next symbol given the causal state in bits. |
Examples:
>>> from skcomplex.analysis import EpsilonMachineAnalysis
>>> machine = EpsilonMachineAnalysis(max_length=3).check().prepare([0, 0, 1] * 300).run()
>>> len(machine.histories_), round(machine.statistical_complexity_, 3), round(machine.entropy_rate_, 3)
(3, 1.585, 0.0)
Source code in src/skcomplex/analysis/_computational_mechanics.py
69 70 71 72 73 74 75 76 77 78 | |
ErgodicityAnalysis(kind='breaking', variables=None, *, start=0.01, dt=1.0, bins=None, value_range=None, edges=None, samples=100)
Bases: BaseAnalysis
Ergodicity of an ensemble of runs, or invariant density of a map or a flow, of one kind.
The ensemble kinds read one row per run and one column per time, such as ExperimentResult.ensemble returns:
'breaking': the variance across runs of the time averages over the variance of all the values, near 0 for ergodic runs longer than their relaxation time and near 1 when every run is frozen in its own state.'metric': the fluctuation metric of Thirumalai and Mountain, the mean square deviation of the running time averages from their ensemble mean, which decays as1 / tfor ergodic runs and levels off for frozen ones.'distance': the median total-variation distance between the values one run visits over time and the values of all runs, after Lesmana et al. (2026), near 0 for ergodic runs and near1 - pwhen every run stays in its own state of ensemble weightp.
The density kinds read one coordinate of a long run, or a one-dimensional map:
'invariant-density': the histogram density of the values of a long run.'ulam': the Markov chain of a map coarse-grained on the cells betweenedgesby Ulam's method, and the density of its stationary vector.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
kind
|
str
|
The diagnostic, one of the kinds above. |
'breaking'
|
variables
|
Sequence[str] | None
|
The variable of a trajectory whose values |
None
|
start
|
float
|
The fraction of the run after which the exponent of the metric is fitted, at 50 log-spaced times. |
0.01
|
dt
|
float
|
The time between the columns of the runs. |
1.0
|
bins
|
int | ArrayLike | None
|
The number of bins or their edges, or |
None
|
value_range
|
tuple[float, float] | None
|
The range of the bins, or |
None
|
edges
|
ArrayLike | None
|
The increasing edges of the cells of |
None
|
samples
|
int
|
The number of evenly spaced points per cell of |
100
|
Attributes:
| Name | Type | Description |
|---|---|---|
values_ |
The runs, one row per run, or the values of the run. |
|
mapping_ |
The map of |
|
ergodicity_breaking_ |
The ergodicity-breaking parameter, of |
|
times_ |
The times of the columns, of |
|
metric_ |
The fluctuation metric at every time, of |
|
exponent_ |
The slope of |
|
ergodicity_distance_ |
The median distance between the law of every run and that of the ensemble, of |
|
edges_ |
The edges of the bins or of the cells, of the density kinds. |
|
density_ |
The density in every bin or cell, of the density kinds. |
|
transition_matrix_ |
The probability that a point of every cell lands in every cell, of |
Examples:
>>> import numpy as np
>>> from skcomplex.analysis import ErgodicityAnalysis
>>> runs = [[1.0, -1.0, 1.0, -1.0], [-1.0, 1.0, -1.0, 1.0]]
>>> ErgodicityAnalysis().check().prepare(runs).run().ergodicity_breaking_
0.0
>>> ErgodicityAnalysis('distance').check().prepare([[0.0, 0.0], [1.0, 1.0]]).run().ergodicity_distance_
0.5
>>> ulam = ErgodicityAnalysis('ulam', edges=np.linspace(0, 1, 5))
>>> ulam.check().prepare(lambda x: np.mod(2 * x, 1)).run().density_.round(2).tolist()
[1.0, 1.0, 1.0, 1.0]
Source code in src/skcomplex/analysis/_ergodicity.py
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 | |
EventAnalysis(kind='detect', variables=None, *, threshold=0.0, window=None, start=0.0, end=None, max_step=40, dt=1.0)
Bases: BaseAnalysis
Events of one series or of event times, of one kind.
The kinds read one series or the times of events:
'detect': the events of a series, every maximal run of consecutive values abovethreshold, with their starts, sizes, durations, peaks, and the waiting times between them. For avalanches recorded as topplings per drive step, an event is an avalanche and its size is the total number of topplings.'counts': the number of events in consecutive windows of lengthwindow, from the times of the events, or from the jump times of a discrete state of a trajectory.'laminar-durations': the durations of the laminar phases of a series, the complete runs of values withinthresholdof 0 between two bursts, such as the distance from an invariant manifold of on-off intermittency.'excursions': the excursions of a series abovethreshold, every maximal run of values above it, with the profile of every excursion, its values minus the threshold, its size, the sum of the profile, and its duration, the number of its samples. A sequence of records with asizeand aduration, such as the cascade records of a lattice, holds excursions already.'branching': the branching ratio of the series by the multistep regression estimator ofmrestimator, which fitsr_k ∝ m^kto the regression slopesr_kof the valuesksteps apart, and stays unbiased when only a fraction of the units is observed. Every series is one trial.
Times are the times of a trajectory, and the step indices of an array.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
kind
|
str
|
The events to measure, one of the kinds above. |
'detect'
|
variables
|
Sequence[str] | None
|
The one variable of a trajectory to read, or |
None
|
threshold
|
float
|
The value an event must exceed, or the largest absolute value of a laminar phase. |
0.0
|
window
|
float | None
|
The length of every window of |
None
|
start
|
float
|
The start of the first window. |
0.0
|
end
|
float | None
|
The end of the last full window, or |
None
|
max_step
|
int
|
The largest step |
40
|
dt
|
float
|
The duration of a step of the branching ratio. |
1.0
|
Attributes:
| Name | Type | Description |
|---|---|---|
times_ |
The time of every value, or of every event for |
|
values_ |
The series, as one column, or one column per trial for |
|
labels_ |
The label of the series or the state. |
|
starts_ |
The time at which every event starts. |
|
sizes_ |
The sum of the values of every event. |
|
durations_ |
The time every event lasts for |
|
shapes_ |
The profile of every excursion of a series, empty for records. |
|
peaks_ |
The largest value of every event. |
|
waiting_times_ |
The time between the end of every event and the start of the next. |
|
counts_ |
The number of events in every window. |
|
branching_ratio_ |
The branching ratio |
Examples:
>>> from skcomplex.analysis import EventAnalysis
>>> events = EventAnalysis().check().prepare([0, 3, 1, 0, 0, 2, 0]).run()
>>> events.sizes_.tolist(), events.durations_.tolist(), events.waiting_times_.tolist()
([4.0, 2.0], [2.0, 1.0], [2.0])
>>> EventAnalysis('counts', window=1.0, end=3.0).check().prepare([0.1, 0.2, 1.5, 2.2]).run().counts_.tolist()
[2.0, 1.0, 1.0]
>>> laminar = EventAnalysis('laminar-durations', threshold=0.5)
>>> laminar.check().prepare([1, 0, 0, 1, 0, 1]).run().durations_.tolist()
[2.0, 1.0]
>>> excursions = EventAnalysis('excursions').check().prepare([0, 1, 2, 1, 0, 3, 0]).run()
>>> excursions.sizes_.tolist(), excursions.durations_.tolist()
([4.0, 3.0], [3.0, 1.0])
>>> import numpy as np
>>> rng = np.random.default_rng(0)
>>> activity = np.zeros(20_000)
>>> activity[0] = 100
>>> for t in range(1, activity.size):
... activity[t] = rng.poisson(0.9 * activity[t - 1] + 10)
>>> round(EventAnalysis('branching').check().prepare(activity).run().branching_ratio_, 1)
0.9
Source code in src/skcomplex/analysis/_events.py
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 | |
FitAnalysis(law='power', variables=None, *, group=None, minimum=None, maximum=None, discrete=False, bootstrap=100, candidates=50, compare_with=ALTERNATIVES, block=None, fixed=None, simulations=199, random_state=0)
Bases: BaseAnalysis
Law fitted to the values of a source, pooled into one sample.
The source gives the series of a trajectory or an array, or the speeds of the agents of a trajectory at every frame.
The laws are:
'power': a power lawp(x) ∝ x^-alphafitted to the tail of the positive samples by maximum likelihood, with Clauset, Shalizi, and Newman's method. The lower cutoff minimises the Kolmogorov-Smirnov distance between the tail and the fit, unlessminimumfixes it. The goodness of fit is the share ofbootstrapsamples whose distance exceeds the data's, and the power law is compared with every alternative ofcompare_withby a likelihood-ratio test. Discrete samples use the exact discrete likelihood. The warnings ofpowerlawabout its optimiser are silenced during the run.'stable': the Lévy stable law fitted by McCulloch's quantile method, in SciPy'sS1parameterization.'extreme-value': the generalized extreme-value law fitted by maximum likelihood to the maxima of blocks ofblocksamples.'exponential','normal','lognormal','gamma','maxwell','rayleigh', and'uniform': the named law with its free parameters fitted, tested with a Monte Carlo Kolmogorov-Smirnov test that accounts for the fit.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
law
|
str
|
The law to fit, one of the laws above. |
'power'
|
variables
|
Sequence[str] | None
|
The variables of a trajectory to read, or |
None
|
group
|
str | None
|
The path of the agent or particle group whose speeds are read, or |
None
|
minimum
|
float | None
|
A fixed lower cutoff of the power law, or |
None
|
maximum
|
float | None
|
A fixed upper cutoff of the power law, or |
None
|
discrete
|
bool
|
Whether the samples of the power law are integers, such as avalanche sizes. |
False
|
bootstrap
|
int
|
The number of bootstrap samples for the p-value of the power law, 0 for none. |
100
|
candidates
|
int
|
The largest number of lower cutoffs tried. |
50
|
compare_with
|
Sequence[str]
|
The alternatives the power law is compared with, among |
ALTERNATIVES
|
block
|
int | None
|
The number of samples per block of the extreme-value law. |
None
|
fixed
|
Mapping[str, float] | None
|
The parameters of a named law held fixed by SciPy name, such as |
None
|
simulations
|
int
|
The number of Monte Carlo samples of the null distribution of a named law. |
199
|
random_state
|
int | None
|
The seed of the bootstrap of the power law and of the Monte Carlo samples of a named law. |
0
|
Attributes:
| Name | Type | Description |
|---|---|---|
values_ |
The pooled sample. |
|
labels_ |
The label of every series. |
|
exponent_ |
The exponent |
|
minimum_ |
The lower cutoff of the power law. |
|
maximum_ |
The upper cutoff of the power law, or |
|
statistic_ |
The Kolmogorov-Smirnov distance between the tail and the power law, or between the sample and a named law. |
|
p_value_ |
For the power law, the share of bootstrap samples from the fit whose distance exceeds |
|
tail_ |
The number of samples between the cutoffs of the power law. |
|
comparisons_ |
For every alternative of |
|
index_ |
The stability index of the stable law, 2 for the normal law. |
|
skewness_ |
The skewness of the stable law. |
|
shape_ |
The shape |
|
location_ |
The location of the stable or the extreme-value law. |
|
scale_ |
The scale of the stable or the extreme-value law. |
|
maxima_ |
The maximum of every block of the extreme-value law. |
|
parameters_ |
The fitted and fixed parameters of a named law. |
Examples:
>>> import numpy as np
>>> from skcomplex.analysis import FitAnalysis
>>> samples = (1 - np.random.default_rng(0).random(5000)) ** (-1 / 1.5)
>>> round(FitAnalysis('power', minimum=1.0, bootstrap=0).check().prepare(samples).run().exponent_, 1)
2.5
>>> fit = FitAnalysis('exponential', fixed={'loc': 0}).check()
>>> fit = fit.prepare(np.random.default_rng(0).exponential(2.0, 1000)).run()
>>> round(fit.parameters_['scale'], 0), fit.p_value_ > 0.05
(2.0, True)
Source code in src/skcomplex/analysis/_fit.py
168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 | |
InformationAnalysis(kind='mutual', variables=None, *, symbols=None, bins=2, order=3, delay=1, history=1, lag=1, max_delay=100, dimension=8, estimator='plugin', k=3, base=2.0)
Bases: BaseAnalysis
Information among the series of a source, of one kind.
The kinds measure pairs of series, every series, or all series together:
'mutual': the mutual informationH(X) + H(Y) - H(X, Y)of every pair of series, by plug-in counts.'transfer': the transfer entropyH(Y_t | Y_past) - H(Y_t | Y_past, X_{t-lag})from every series to every series, the target conditioned onhistorypast values, by plug-in counts or by the Kraskov-Stögbauer-Grassberger nearest-neighbour estimate ofkneighbours.'kl-divergence': the Kullback-Leibler divergence of every series, a probability vector, from every series.'auto-mutual': the mutual information of every series with itself delayed by 0 tomax_delaysteps.'active-storage': the information the pasthistoryvalues of every series hold about its next value.'correlation-information': Lindgren's correlation informationk_m = ΔS_{m-1} - ΔS_mof every series for block lengths 2 todimension.'total-correlation','dual-total-correlation','o-information': the information all series share at any order, the information two or more of them share, and their difference, positive for redundancy and negative for synergy, by plug-in counts withdit, the closed form of a fitted Gaussian, or chains of neighbour estimates.'o-information-gradients': the O-information every series adds to the others.
Every kind but 'kl-divergence' reads the series as symbols, or first turns them into symbols with symbols:
'bins' for bins bins of equal width, 'quantiles' for bins equally populated bins, or 'ordinal' for the
rank pattern of every order values spaced by delay steps.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
kind
|
str
|
The information to compute, one of the kinds above. |
'mutual'
|
variables
|
Sequence[str] | None
|
The variables of a trajectory to read, or |
None
|
symbols
|
str | None
|
|
None
|
bins
|
int
|
The number of symbols of bins and quantiles. |
2
|
order
|
int
|
The length of ordinal patterns. |
3
|
delay
|
int
|
The number of steps between the values of an ordinal pattern. |
1
|
history
|
int
|
The number of past values of the target of the transfer entropy, or of the series of the storage. |
1
|
lag
|
int
|
The delay of the source of the transfer entropy. |
1
|
max_delay
|
int
|
The largest delay of the auto mutual information. |
100
|
dimension
|
int
|
The largest block length of the correlation information. |
8
|
estimator
|
str
|
|
'plugin'
|
k
|
int
|
The number of neighbours of the |
3
|
base
|
float
|
The base of the logarithm, 2 for bits. |
2.0
|
Attributes:
| Name | Type | Description |
|---|---|---|
values_ |
The series, one per column. |
|
labels_ |
The label of every series. |
|
symbols_ |
The symbols the kinds measure, one column per series, the series themselves without |
|
information_ |
A matrix with the measure from the series of every row to the series of every column for |
Examples:
>>> import numpy as np
>>> from skcomplex.analysis import InformationAnalysis
>>> x = np.random.default_rng(0).integers(0, 2, 10000)
>>> transfer = InformationAnalysis('transfer').check().prepare(np.column_stack([x, np.roll(x, 1)])).run()
>>> transfer.information_.round(1).tolist()
[[nan, 1.0], [0.0, nan]]
>>> xor = [[0, 0, 0], [0, 1, 1], [1, 0, 1], [1, 1, 0]]
>>> round(InformationAnalysis('o-information').check().prepare(xor).run().information_, 6)
-1.0
Source code in src/skcomplex/analysis/_information.py
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 | |
InvariantAnalysis(kind='conservation', *, expressions=(), symmetry=None, samples=16, random_state=None)
Bases: BaseAnalysis
Poisson brackets, conserved quantities, and symmetries of a system, with the Noether charge of a symmetry.
The canonical pairs and the Hamiltonian H are those of the system's HamiltonianInteractions, whose
Hamiltonians sum, and the Lagrangian L is the sum of those of its EulerLagrangeInteractions. The expressions are
ObservableSpecs whose expression is a function of the namespace of the system, where s.<element>.<state> is the
symbol of a state, or a symbolic expression of those symbols. The kinds:
'brackets': the Poisson bracket{f, g} = sum df/dq dg/dp - df/dp dg/dqof every pair of expressions, summed over the canonical pairs.'conservation': the rate of changedf/dtof every expression, which isdiff(f, t) + {f, H}for a system whose dynamics all come from Hamiltonian interactions, and the Lie derivative along the vector field of its equations otherwise. An expression is conserved when its rate simplifies to zero, or, when simplification does not decide, when the rate vanishes within a tolerance at random states with the parameters at their values.'symmetry': whether the Hamiltonian, or else the Lagrangian, is unchanged to first order by the variation of aSymmetrySpec, and the Noether charge of the symmetry,sum p dqfor a Hamiltonian andsum dL/dq' dqfor a Lagrangian, with the variation of the velocitiesdq' = sum_j d(dq)/dq_j q_j'.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
kind
|
str
|
The analysis to run, one of the kinds above. |
'conservation'
|
expressions
|
Sequence[ObservableSpec]
|
The expressions to bracket or to check. |
()
|
symmetry
|
SymmetrySpec | None
|
The symmetry to check. |
None
|
samples
|
int
|
The number of random states of the numeric check. |
16
|
random_state
|
int | Generator | None
|
The seed or generator of the random states. |
None
|
Attributes:
| Name | Type | Description |
|---|---|---|
problem_ |
The compiled problem. |
|
system_ |
The system. |
|
dynamics_ |
The first-order equations of the system, with the values of its parameters. |
|
namespace_ |
The namespace of the symbols of the states and parameters of the system. |
|
brackets_ |
A mapping from every pair of labels to the Poisson bracket of their expressions. |
|
rates_ |
A mapping from every label to the rate of change of its expression. |
|
conserved_ |
A mapping from every label to whether its expression is conserved. |
|
methods_ |
A mapping from every label to the method that decided, |
|
invariant_ |
Whether the Hamiltonian or the Lagrangian is unchanged to first order by the symmetry. |
|
remainder_ |
The first-order change of the Hamiltonian or the Lagrangian under the symmetry, zero when it is invariant. |
|
charge_ |
The Noether charge of the symmetry. |
Raises:
| Type | Description |
|---|---|
AnalysisError
|
The source is not a system, the system is not an ODE, an expression or the symmetry is missing or invalid, or the system has no Hamiltonian interaction for brackets, or neither a Hamiltonian nor an Euler-Lagrange interaction for a symmetry. |
Examples:
>>> from typing import Annotated
>>> from skcomplex.analysis import InvariantAnalysis
>>> from skcomplex.core.elements import Element
>>> from skcomplex.core.interactions import HamiltonianInteraction
>>> from skcomplex.core.system import System
>>> from skcomplex.specs import ObservableSpec, StateSpec
>>> class OscillatorElement(Element):
... def __init__(self, label, q: Annotated[float, StateSpec()] = 1.0, p: Annotated[float, StateSpec()] = 0):
... super().__init__(label)
... self.q = q
... self.p = p
>>> energy = lambda s: (s.target.p**2 + s.target.q**2) / 2
>>> system = System(
... elements=[OscillatorElement('mass')],
... interactions=[HamiltonianInteraction('spring', target='mass', hamiltonian=energy)],
... )
>>> expressions = [
... ObservableSpec('energy', lambda s: s.mass.q**2 + s.mass.p**2),
... ObservableSpec('position', lambda s: s.mass.q),
... ]
>>> analysis = InvariantAnalysis(expressions=expressions).check().prepare(system).run()
>>> analysis.conserved_
{'energy': True, 'position': False}
>>> analysis.rates_['position']
p_mass
Source code in src/skcomplex/analysis/_invariants.py
139 140 141 142 143 144 145 146 147 148 149 150 151 152 | |
IrreversibilityAnalysis(kind='entropy-production', variables=None, *, rates=None, duration=None, drive=1.0, intensity=1.0, dt=1.0, n_states=None, significance=0.05, bins=40, entropy=None, resamples=200, random_state=None, unperturbed=None, field=1.0, correlation=None)
Bases: BaseAnalysis
Irreversibility of jump and Langevin dynamics, of one kind.
The kinds read a rate matrix, jump paths, Langevin paths, samples, or ensembles:
'entropy-production': the stationary entropy production rate of a jump process from its rate matrix,Σ_{i<j} (p_i k_ij - p_j k_ji) ln(p_i k_ij / (p_j k_ji)), 0 under detailed balance.'jump-entropy-production': the entropy every jump path produces in the medium,Σ ln(k_ij / k_ji)over its jumps with therates, and the mean rate over thedurationof the paths.'langevin-entropy-production': the entropy every overdamped Langevin path produces, the work of thedrivetimes theintensity,b ∫ F(x) ∘ dx, and the mean rate.'count-entropy-production': the entropy production rate of a discrete path from its transition counts alone,Σ_{i<j} (N_ij - N_ji) ln(N_ij / N_ji)per unit time.'detailed-balance': the chi-squared test of detailed balance on the transition counts of discrete paths.'fluctuation-theorem': the log ratio of the probabilities of producingsand-sfrom samples of the entropy, and its slope againsts, 1 when the theorem holds.'uncertainty-relation': the squared relative fluctuationVar(J) / ⟨J⟩²of samples of an integrated current times the meanentropyproduced over the same duration, at least 2 (Barato and Seifert 2015).'response': the integrated responsechi(t) = (<x(t)>_h - <x(t)>_0) / hof an ensemble with the field against theunperturbedensemble.'fluctuation-dissipation': the response, and the slope ofchi / bagainstC(t_w, t_w) - C(t, t_w)of the two-timecorrelationover the same lags, 1 in equilibrium and below 1 in an aging system.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
kind
|
str
|
The measure to compute, one of the kinds above. |
'entropy-production'
|
variables
|
Sequence[str] | None
|
The discrete state or the position of a trajectory to read, or |
None
|
rates
|
ArrayLike | None
|
The rate of every jump, one row per origin. |
None
|
duration
|
float | None
|
The duration of every jump path, or |
None
|
drive
|
Callable[[Array], Array] | float
|
The drift along a Langevin path, a function of position or a constant. |
1.0
|
intensity
|
float
|
The factor |
1.0
|
dt
|
float
|
The time between frames of Langevin paths, or between records of a discrete path. |
1.0
|
n_states
|
int | None
|
The number of states, or |
None
|
significance
|
float
|
The level below which the p-value rejects detailed balance. |
0.05
|
bins
|
int
|
The number of bins of entropy, symmetric about 0. |
40
|
entropy
|
float | None
|
The mean entropy produced along a path over the duration of the currents. |
None
|
resamples
|
int
|
The number of bootstrap resamples of the standard error of the uncertainty product. |
200
|
random_state
|
int | None
|
The seed of the bootstrap. |
None
|
unperturbed
|
ArrayLike | None
|
The ensemble without the field, one row per run and one column per frame. |
None
|
field
|
float
|
The strength of the field. |
1.0
|
correlation
|
ArrayLike | None
|
The two-time correlation over lags from 0. |
None
|
Attributes:
| Name | Type | Description |
|---|---|---|
values_ |
The rate matrix, the paths one row per path, or the samples the kind reads. |
|
duration_ |
The duration of the jump paths, the setting or the duration of a trajectory. |
|
entropy_production_ |
The entropy production per unit time in units of |
|
entropies_ |
The entropy produced along every path, of |
|
currents_ |
The net number of transitions from every state to every other per step, of |
|
statistic_ |
The statistic |
|
p_value_ |
The chi-squared p-value of the statistic under detailed balance, of |
|
balanced_ |
Whether the p-value exceeds the significance level, of |
|
centres_ |
The centres of the bins of entropy whose mirror bin is also populated, of |
|
log_ratios_ |
|
|
slope_ |
The slope of the log ratio against the entropy, of |
|
mean_ |
The mean of the current over the paths, of |
|
variance_ |
The variance of the current over the paths, of |
|
product_ |
The squared relative fluctuation of the current times the entropy, of |
|
error_ |
The standard error of the product from bootstrap resamples of the paths, of |
|
holds_ |
Whether the product is at least 2 within two standard errors, of |
|
response_ |
The integrated response at every frame, of |
|
fluctuation_dissipation_ratio_ |
The fluctuation-dissipation ratio, of |
Examples:
>>> import numpy as np
>>> from skcomplex.analysis import IrreversibilityAnalysis
>>> ring = 2 * np.roll(np.eye(5), 1, axis=1) + np.roll(np.eye(5), -1, axis=1)
>>> production = IrreversibilityAnalysis().check().prepare(ring).run().entropy_production_
>>> bool(abs(production - np.log(2)) < 1e-12)
True
>>> jumps = IrreversibilityAnalysis('jump-entropy-production', rates=[[0, 2], [1, 0]], duration=3.0)
>>> jumps.check().prepare([0, 1, 0, 1]).run().entropies_.round(3).tolist()
[0.693]
>>> IrreversibilityAnalysis('detailed-balance').check().prepare([0, 1, 2] * 1000).run().balanced_
False
Source code in src/skcomplex/analysis/_irreversibility.py
199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 | |
KramersMoyalAnalysis(variables=None, *, dt=1.0, bins=50, bandwidth=None)
Bases: BaseAnalysis
Kramers-Moyal drift and diffusion of one series, estimated with kernels from its increments by kramersmoyal.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
variables
|
Sequence[str] | None
|
The variable of a trajectory to read, or |
None
|
dt
|
float
|
The time between samples. |
1.0
|
bins
|
int
|
The number of bins of values. |
50
|
bandwidth
|
float | None
|
The width of the Epanechnikov kernel, or |
None
|
Attributes:
| Name | Type | Description |
|---|---|---|
values_ |
The series. |
|
positions_ |
The centres of the bins of values. |
|
drift_ |
The first coefficient |
|
diffusion_ |
The second coefficient |
Examples:
>>> import numpy as np
>>> from skcomplex.analysis import KramersMoyalAnalysis
>>> rng = np.random.default_rng(0)
>>> x = np.zeros(100_000)
>>> for t in range(1, x.size):
... x[t] = x[t - 1] - x[t - 1] * 0.01 + np.sqrt(0.02) * rng.standard_normal()
>>> analysis = KramersMoyalAnalysis(dt=0.01, bins=21).check().prepare(x).run()
>>> round(float(analysis.diffusion_[10]), 1)
1.0
Source code in src/skcomplex/analysis/_kramers_moyal.py
57 58 59 60 61 62 63 64 65 66 67 68 | |
LargeDeviationAnalysis(kind='tilted', variables=None, *, weights=None, tilts=1.0, values=None, block=10, dt=1.0, observable=None, population=1000, interval=1.0, until=20.0, random_state=None, simulation=None, bins=41, value_range=None, log_weights=None)
Bases: BaseAnalysis
Large deviations of a time-additive observable or of an order parameter, of one kind.
The kinds estimate the scaled cumulant generating function lambda(k) at the tilts, or the rate function I:
'tilted': exactly, for a counting observable of a jump process that addsweights[i, j]at every jump fromitoj, as the largest eigenvalue of the tilted generatorrates * exp(k weights) - diag(escape rates)of the rate matrix. A diagonal rate counts jumps that keep the state, such as the events of a Poisson process.'block': from blocks ofblocksteps of one long run of the increments of the observable, asln <exp(k A)> / (block dt).'cloning': by the fixed-population cloning of Giardinà, Kurchan, and Peliti, which advances every clone of a system byintervalthrough the simulation's steppers, weights it byexp(k A)for the incrementAof the observable, and resamples the population by the weights. The system is compiled once, and every segment restarts the clock at zero, so the laws must not depend on time explicitly. A warning names a population whose effective size falls below a tenth of the clones or below 10 clones.'histogram': the rate function ofP_N(m) ≍ exp(-N I(m))from the samples of an order parameter at several sizesN, fitting-ln P_Nlinearly inNin every bin.'reweight': samples reweighted to another law by the logarithms of the likelihood ratios, such asbeta dh M.
With values, the generating function kinds also give the rate function, its Legendre transform
I(a) = max_k (k a - lambda(k)) over the tilts.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
kind
|
str
|
The estimate, one of the kinds above. |
'tilted'
|
variables
|
Sequence[str] | None
|
The series of a trajectory whose values are the increments of |
None
|
weights
|
ArrayLike | None
|
The increment of the observable at every jump of |
None
|
tilts
|
float | ArrayLike
|
The values of the tilt |
1.0
|
values
|
ArrayLike | None
|
The values |
None
|
block
|
int
|
The number of steps of every block. |
10
|
dt
|
float
|
The time of one step. |
1.0
|
observable
|
str | Callable[[Trajectory], float] | None
|
The dotted name of a state whose increment over each interval is the observable, such as a counter, or a function of the trajectory of one interval that returns the increment. |
None
|
population
|
int
|
The number of clones. |
1000
|
interval
|
float
|
The time between two selection steps. |
1.0
|
until
|
float
|
The simulated time of every clone, a multiple of the interval. |
20.0
|
random_state
|
int | None
|
The seed of the clones and of the selection. |
None
|
simulation
|
Mapping[str, object] | None
|
Other settings of |
None
|
bins
|
int | ArrayLike
|
The number of bins or their edges of |
41
|
value_range
|
tuple[float, float] | None
|
The range of the bins, or |
None
|
log_weights
|
ArrayLike | None
|
The logarithm of the ratio of the new to the old probability of every sample. |
None
|
Attributes:
| Name | Type | Description |
|---|---|---|
rates_ |
The rate matrix of |
|
increments_ |
The increments of |
|
system_ |
The system or its compiled problem of |
|
samples_ |
The samples at every size of |
|
observations_ |
The samples of |
|
tilts_ |
The tilts of the generating function. |
|
scgf_ |
The scaled cumulant generating function at every tilt. |
|
effective_population_ |
The smallest effective number of clones over the selection steps at every tilt, |
|
values_ |
The values of the rate function, the centres of the bins of |
|
rate_function_ |
The rate function at every value, 0 at its minimum and |
|
weights_ |
The normalized weight of every sample of |
|
mean_ |
The weighted mean of the samples of |
|
effective_size_ |
The effective number of samples |
Examples:
>>> import numpy as np
>>> from skcomplex.analysis import LargeDeviationAnalysis
>>> tilted = LargeDeviationAnalysis(weights=[[1.0]], tilts=[0.0, 1.0])
>>> tilted.check().prepare([[2.0]]).run().scgf_.round(4).tolist()
[0.0, 3.4366]
>>> tilts = np.linspace(-3, 3, 6001)
>>> rate = LargeDeviationAnalysis(weights=[[1.0]], tilts=tilts, values=[3.0])
>>> round(float(rate.check().prepare([[2.0]]).run().rate_function_[0]), 4)
0.2164
>>> LargeDeviationAnalysis('reweight', log_weights=[0.0, 0.0]).check().prepare([-1.0, 1.0]).run().mean_
0.0
Source code in src/skcomplex/analysis/_large_deviations.py
171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 | |
LinearizationAnalysis(controls=None, outputs=None, at=None, *, state_weights=None, control_weights=None)
Bases: BaseAnalysis
Linear state-space model x' = A x + B u, y = C x + D u of a system near an operating point.
The matrices are the Jacobians of the rates and of the outputs, derived symbolically and evaluated at the
operating point. The controls are adaptive parameters, named by their dotted names, and the outputs are states or
controls. The system is controllable when the rank of [B, AB, ..., A^(n-1) B] equals the number of states, and
observable when the rank of [C; CA; ...; C A^(n-1)] does. With weights of the states and the controls, the gain
K of the linear-quadratic regulator u = -K x minimises ∫ (x' Q x + u' R u) dt over an infinite horizon, from
the continuous algebraic Riccati equation that SciPy solves.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
controls
|
Sequence[str] | None
|
The dotted names of the adaptive parameters that are inputs, or |
None
|
outputs
|
Sequence[str] | None
|
The dotted names of the states and controls that are outputs, or |
None
|
at
|
Mapping[str, float] | None
|
The values of states and controls at the operating point, by dotted name, or |
None
|
state_weights
|
ArrayLike | None
|
The weight |
None
|
control_weights
|
ArrayLike | None
|
The weight |
None
|
Attributes:
| Name | Type | Description |
|---|---|---|
problem_ |
The compiled problem. |
|
A_ |
The state matrix, the Jacobian of the rates by the states. |
|
B_ |
The input matrix, the Jacobian of the rates by the controls. |
|
C_ |
The output matrix, the Jacobian of the outputs by the states. |
|
D_ |
The feedthrough matrix, the Jacobian of the outputs by the controls. |
|
states_ |
The names of the state components, in the order of the rows of |
|
controls_ |
The names of the controls, in the order of the columns of |
|
outputs_ |
The names of the outputs, in the order of the rows of |
|
controllability_ |
The rank of the controllability matrix. |
|
observability_ |
The rank of the observability matrix. |
|
gain_ |
The gain of the regulator, one row per control and one column per state, or |
Examples:
>>> from typing import Annotated
>>> from skcomplex.analysis import LinearizationAnalysis
>>> from skcomplex.core.elements import Element
>>> from skcomplex.core.laws import RateLaw
>>> from skcomplex.specs import ParameterSpec, StateSpec
>>> from skcomplex.core.system import System
>>> class CartElement(Element):
... def __init__(
... self,
... label,
... x: Annotated[float, StateSpec()] = 0.0,
... v: Annotated[float, StateSpec()] = 0.0,
... force: Annotated[float, ParameterSpec(adaptive=True, bounds=(-1, 1))] = 0.0,
... ):
... super().__init__(label)
... self.x = x
... self.v = v
... self.force = force
...
... def _get_laws(self, namespace):
... return [RateLaw(namespace.x, namespace.v), RateLaw(namespace.v, namespace.force)]
>>> analysis = LinearizationAnalysis().check().prepare(System(elements=[CartElement('cart')])).run()
>>> analysis.B_.tolist(), analysis.controllability_
([[0.0], [1.0]], 2)
Source code in src/skcomplex/analysis/_linearization.py
110 111 112 113 114 115 116 117 118 119 120 121 122 123 | |
LocalInformationAnalysis(kind='entropy', variables=None, *, history=1, lag=1, estimator='plugin', base=2.0)
Bases: BaseAnalysis
Information of the series of a source sample by sample, whose mean over the samples is the global measure.
The kinds measure every series or every pair of series:
'entropy': the local entropy-log p(x)of every sample of every series.'mutual': the local mutual informationlog p(x, y) / (p(x) p(y))of every sample of every pair of series, negative where the series mislead about each other.'transfer': the local transfer entropylog p(y_t | y_past, x_{t-lag}) / p(y_t | y_past)from every series to every series at every time frommax(history, lag)on.
The probabilities are the frequencies of symbols, or the densities of a fitted Gaussian.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
kind
|
str
|
The local information to compute, one of the kinds above. |
'entropy'
|
variables
|
Sequence[str] | None
|
The variables of a trajectory to read, or |
None
|
history
|
int
|
The number of past target values of the transfer entropy. |
1
|
lag
|
int
|
The delay of the source of the transfer entropy. |
1
|
estimator
|
str
|
|
'plugin'
|
base
|
float
|
The base of the logarithm, 2 for bits. |
2.0
|
Attributes:
| Name | Type | Description |
|---|---|---|
values_ |
The series, one per column. |
|
labels_ |
The label of every series. |
|
information_ |
One row of local entropies per series for |
Examples:
>>> from skcomplex.analysis import LocalInformationAnalysis
>>> local = LocalInformationAnalysis('mutual').check().prepare([[0, 0], [0, 0], [1, 1], [1, 0]]).run()
>>> local.information_[0, 1].round(3).tolist()
[0.415, 0.415, 1.0, -0.585]
Source code in src/skcomplex/analysis/_local_information.py
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | |
LoopAnalysis(kind='loops', *, at=None, frame=-1, quantity=None)
Bases: BaseAnalysis
Feedback loops of the signed dependency graph of a system, their dominance in time, or its flow matrix.
The signed dependency graph of a system has the state variables as nodes and an edge from x_j to x_i when the
rate of x_i depends on x_j, with the sign of the partial derivative df_i/dx_j, the entry of the Jacobian. The
rate of a map is the change of its state in one step, its next value minus itself. When a system declares flows,
the flows are nodes too: an edge goes from each state to every flow whose amount depends on it, with the sign of
the partial derivative, and from each flow to its sink with sign + and to its source with sign -, so the
graph shows the path of every influence through the flows. Rate laws of single elements give the edges into the
states they change, and the Jacobian, as StabilityAnalysis derives it with the parameters at their values,
gives the edges into every other state, such as the members of a group or the velocity of a state of second
order. Delays and smoothings pass their input with gain one.
The kinds read a system or a trajectory:
'loops': the signed dependency graph and its feedback loops, the elementary cycles of the graph found with Johnson's algorithm. The gain of a loop is the product of the partial derivatives along it, and its polarity the sign of the gain.'dominance': the gains of the loops along a trajectory, at every frame, and the dominant loop, with the largest absolute gain, at every frame.'flow-matrix': the transaction-flow matrix of one frame of a trajectory, with flows as rows and holders as columns. Every row holds the outflow of its flow at the source, negative, and the inflow at the sink, positive, so every row sums to zero. Flows of a group sum over its members. The matrix books the amounts the flows move between holders, which the Jacobian does not hold, so it is defined only for systems that declare flows.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
kind
|
str
|
The analysis of the loops, one of the kinds above. |
'loops'
|
at
|
ArrayLike | None
|
The state vector the signs of |
None
|
frame
|
int
|
The index of the frame of the flow matrix. |
-1
|
quantity
|
str | None
|
The quantity whose flows form the rows of the flow matrix, or |
None
|
Attributes:
| Name | Type | Description |
|---|---|---|
problem_ |
The compiled problem. |
|
trajectory_ |
The trajectory of |
|
graph_ |
The signed dependency graph from each state or flow to every node whose amount or rate depends on it, with
the edge attributes |
|
loops_ |
The nodes of every loop, in the order of their influence, starting at its first state by name, or at its first node by name when it holds no state. |
|
polarities_ |
The polarity of every loop, at the first frame for |
|
gains_ |
The gain of every loop, with one row per frame for |
|
times_ |
The time of every frame of |
|
dominant_ |
The index of the loop with the largest absolute gain at every frame of |
|
flows_ |
The paths of the flows of the flow matrix. |
|
holders_ |
The states and environments the flows connect. |
|
matrix_ |
The outflow, negative, and the inflow, positive, of every flow for every holder. |
Examples:
>>> from skcomplex.analysis import LoopAnalysis
>>> from skcomplex.engine.runtime import Simulation
>>> from skcomplex.models import create
>>> LoopAnalysis().check().prepare(create('bass_diffusion')).run().polarities_
['reinforcing', 'balancing']
>>> trajectory = Simulation(create('bass_diffusion'), dt=1).check().prepare().run(2).trajectory_
>>> LoopAnalysis('dominance').check().prepare(trajectory).run().gains_.shape
(3, 2)
Source code in src/skcomplex/analysis/_loops.py
273 274 275 276 277 278 279 280 281 282 283 284 | |
LyapunovAnalysis(kind='spectrum', variables=None, *, n_exponents=None, until=None, dt=None, transient=None, parameters=None, dimension=3, delay=1, min_separation=None, trajectory_length=20, skip=0)
Bases: BaseAnalysis
Lyapunov exponents of a system from its tangent dynamics, or the largest exponent of recorded series.
The kinds read a system or data:
'spectrum': the largestn_exponentsexponents of a flow or a map from the system's initial state. The tangent dynamics use the symbolic Jacobian, in whichabs(u)has the derivativesign(u), and the compiled functions take the parameters as an argument, so a sweep over parameter values compiles them once. Tangent vectors are re-orthonormalised by QR after every step, as in the Benettin algorithm, and the exponents are the average logarithmic growth of the diagonal ofR. The Kaplan-Yorke dimension and the Kolmogorov-Sinai entropy, by Pesin's identity the sum of the positive exponents, follow from the spectrum. An array of exponents passes through as the spectrum.'largest': Rosenstein's estimate of the largest exponent of every series, from the divergence of neighbours of its delay embedding.
A positive largest exponent indicates chaos.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
kind
|
str
|
The exponents to compute, one of the kinds above. |
'spectrum'
|
variables
|
Sequence[str] | None
|
The variables of a trajectory to read for |
None
|
n_exponents
|
int | None
|
The number of exponents of the spectrum, or |
None
|
until
|
float | None
|
The time averaged over, or the number of iterations of a map, or |
None
|
dt
|
float | None
|
The fixed step of the RK4 integration of flows, or the time between samples of a series, or |
None
|
transient
|
float | None
|
The time, or the number of iterations, run before averaging, or |
None
|
parameters
|
Mapping[str, float] | None
|
Values of parameters by dotted path that replace the system's values. |
None
|
dimension
|
int
|
The dimension of the delay embedding. |
3
|
delay
|
int
|
The delay of the embedding in steps. |
1
|
min_separation
|
int | None
|
The fewest steps between neighbours, or |
None
|
trajectory_length
|
int
|
The number of steps over which the divergence of neighbours is followed and fitted. |
20
|
skip
|
int
|
The number of first steps of the divergence left out of the fit, while neighbours align with the unstable direction. |
0
|
Attributes:
| Name | Type | Description |
|---|---|---|
problem_ |
The compiled problem of the spectrum of a system, or |
|
exponents_ |
The exponents of the spectrum in decreasing order, per unit of time for flows and per iteration for maps. |
|
kaplan_yorke_dimension_ |
The Kaplan-Yorke dimension of the spectrum, with |
|
kolmogorov_sinai_entropy_ |
The entropy rate of the dynamics in nats per unit time, the sum of the positive exponents. |
|
values_ |
The series of |
|
labels_ |
The label of every series of |
|
largest_exponent_ |
The largest exponent per unit time of every series of |
Examples:
>>> from skcomplex.analysis import LyapunovAnalysis
>>> from skcomplex.models.mathematics.dynamical_systems import logistic_map
>>> analysis = LyapunovAnalysis(until=20000).check().prepare(logistic_map(r=4.0)).run()
>>> float(analysis.exponents_[0].round(2))
0.69
>>> round(LyapunovAnalysis().check().prepare([0.906, 0.0, -14.572]).run().kaplan_yorke_dimension_, 2)
2.06
Source code in src/skcomplex/analysis/_lyapunov.py
172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 | |
MarkovAnalysis(kind='transition-matrix', variables=None, *, matrix=None, n_states=None, lag=1, lags=(1,), n_timescales=1, n_metastable=None, reversible=True, dt=1.0)
Bases: BaseAnalysis
Markov chain of discrete paths, or of a transition or rate matrix, of one kind.
The kinds read the integer states of one path, or one row per path, or a matrix with matrix:
'transition-matrix': the transitions afterlagsteps counted along the paths and normalized by row.'stationary': the stationary lawpiof the matrix,pi P = piorpi Q = 0for rates.'spectral-gap': the gap1 - |lambda_2|, or-Re lambda_2for rates, and the relaxation time of every mode.'state-model': the maximum-likelihood Markov state model of the largest connected set, with its metastable sets found by PCCA+.'timescales': the slowest implied timescales of Markov state models at every lag oflags, which do not depend on the lag for a Markovian discretization.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
kind
|
str
|
The quantity to compute, one of the kinds above. |
'transition-matrix'
|
variables
|
Sequence[str] | None
|
The discrete state of a trajectory to read, or |
None
|
matrix
|
str | None
|
|
None
|
n_states
|
int | None
|
The number of states of the paths, or |
None
|
lag
|
int
|
The lag time in steps. |
1
|
lags
|
Sequence[int]
|
The lag times in steps of the implied timescales. |
(1,)
|
n_timescales
|
int
|
The number of implied timescales. |
1
|
n_metastable
|
int | None
|
The number of metastable sets PCCA+ groups the states into, or |
None
|
reversible
|
bool
|
Whether the state models obey detailed balance, which PCCA+ needs. |
True
|
dt
|
float
|
The time of one step. |
1.0
|
Attributes:
| Name | Type | Description |
|---|---|---|
path_ |
The integer states of the paths, one row per path, read without a matrix. |
|
matrix_ |
The matrix read with |
|
counts_ |
The transition counts, one row per origin, of |
|
transition_matrix_ |
The probability of every destination after one lag from every origin, of |
|
stationary_ |
The stationary law, of |
|
spectral_gap_ |
The spectral gap, of |
|
relaxation_times_ |
|
|
states_ |
The states of the largest connected set, which index the rows of the matrix, of |
|
timescales_ |
The implied timescales |
|
metastable_sets_ |
The states of every metastable set, empty without a number of sets, of |
Examples:
>>> import numpy as np
>>> from skcomplex.analysis import MarkovAnalysis
>>> MarkovAnalysis().check().prepare([0, 1, 0, 1, 1]).run().transition_matrix_.tolist()
[[0.0, 1.0], [0.5, 0.5]]
>>> stationary = MarkovAnalysis('stationary', matrix='transition')
>>> stationary.check().prepare([[0.5, 0.5], [0.25, 0.75]]).run().stationary_.round(3).tolist()
[0.333, 0.667]
>>> path = np.random.default_rng(0).integers(0, 2, 10_000)
>>> MarkovAnalysis('state-model').check().prepare(path).run().transition_matrix_.round(1).tolist()
[[0.5, 0.5], [0.5, 0.5]]
Source code in src/skcomplex/analysis/_markov.py
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 | |
ModeDecompositionAnalysis(variables=None, *, rank=None, dictionary=None, validation=0.2, horizon=0, dt=1.0, label='surrogate')
Bases: BaseAnalysis
Linear system fitted to series by dynamic mode decomposition, computed with PyDMD.
The decomposition fits the exact DMD of the one-sample map g(t + dt) = A g(t) to the pairs of consecutive samples
of every run. With a dictionary, g holds the observables the dictionary computes from the variables, which is
extended DMD, and the dictionary should keep the variables among its observables. The fitted system follows the
rate law dg/dt = L g with L = Phi diag(ln(mu) / dt) Phi^+ under continuous time and starts at the first sample
of the first run. The forecast sums the modes from the last sample of the last run.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
variables
|
Sequence[str] | None
|
The variables of trajectories, or |
None
|
rank
|
float | None
|
The rank of the truncated singular value decomposition: a number of modes, 0 for the optimal hard
threshold, a share of the energy below 1, or |
None
|
dictionary
|
TransformerMixin | None
|
A scikit-learn transformer that computes the observables, such as |
None
|
validation
|
float
|
The share of the samples of every run held out at its end to measure the validation error. |
0.2
|
horizon
|
int
|
The number of samples to forecast after the last sample of the last run. |
0
|
dt
|
float
|
The time between the rows of an array. |
1.0
|
label
|
str
|
The label of the surrogate element. |
'surrogate'
|
Attributes:
| Name | Type | Description |
|---|---|---|
samples_ |
The series of every run, the names of the variables, and the step, set by |
|
system_ |
The system of one surrogate element under continuous time, whose states follow |
|
labels_ |
The variables, or the observables of the dictionary, in the order of the states. |
|
states_ |
The names of the states of the surrogate element. |
|
last_state_ |
The values of the states at the last sample of the last run, where the forecast starts. |
|
dt_ |
The time between the samples it was fitted to. |
|
training_error_ |
The relative error of the predicted increments over one sample on the training samples. |
|
validation_error_ |
The relative error on the held-out samples, NaN when none are held out. |
|
eigenvalues_ |
The continuous eigenvalues |
|
modes_ |
The modes, one column per mode and one row per state. |
|
amplitudes_ |
The amplitudes of the modes at the last sample of the last run. |
|
generator_ |
The matrix |
|
forecast_ |
The states at the |
Examples:
>>> import numpy as np
>>> from skcomplex.analysis import ModeDecompositionAnalysis
>>> times = np.arange(0.0, 10.0, 0.1)
>>> values = np.column_stack([np.cos(times), np.sin(times)])
>>> analysis = ModeDecompositionAnalysis(['x', 'y'], horizon=5, dt=0.1).check().prepare(values).run()
>>> np.sort(analysis.eigenvalues_.imag).round(6).tolist()
[-1.0, 1.0]
>>> bool(np.allclose(analysis.forecast_[:, 0], np.cos(times[-1] + 0.1 * np.arange(1, 6))))
True
Source code in src/skcomplex/analysis/_mode_decomposition.py
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 | |
MotifAnalysis(kind='counts', *, size=3, null='switch', samples=100, random_state=None)
Bases: BaseAnalysis
Motifs of three or four nodes of the network of every frame of a trajectory, or of a graph.
The kinds count or score motifs:
'counts': the number of connected induced subgraphs of every kind. Directed triads carry the names of the triadic census, such as'030T'for the feed-forward loop. Undirected motifs are named by their shape, and directed motifs of four nodes by their smallest adjacency code.'z-scores': the counts against random graphs that keep the degrees,(count - null_mean) / null_stdof every motif,nanwhere the null count never varies.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
kind
|
str
|
|
'counts'
|
size
|
int
|
The number of nodes of the motifs, 3 or 4. |
3
|
null
|
str
|
|
'switch'
|
samples
|
int
|
The number of random graphs. |
100
|
random_state
|
int | None
|
The seed of the ensemble. |
None
|
Attributes:
| Name | Type | Description |
|---|---|---|
graphs_ |
The graph of every frame. |
|
counts_ |
The count of every motif of every frame. |
|
null_mean_ |
The mean count of every motif over the null ensemble of every frame. |
|
null_std_ |
The standard deviation of every count over the null ensemble of every frame. |
|
z_scores_ |
The z-score of every motif of every frame. |
Examples:
>>> import networkx as nx
>>> from skcomplex.analysis import MotifAnalysis
>>> MotifAnalysis().check().prepare(nx.complete_graph(4)).run().counts_
[{'path': 0, 'triangle': 4}]
>>> MotifAnalysis(size=4).check().prepare(nx.complete_graph(4)).run().counts_
[{'clique': 1}]
>>> graph = nx.gnm_random_graph(30, 60, seed=0)
>>> sorted(MotifAnalysis('z-scores', samples=10, random_state=0).check().prepare(graph).run().z_scores_[0])
['path', 'triangle']
Source code in src/skcomplex/analysis/_motifs.py
101 102 103 104 105 106 107 108 109 110 111 112 113 114 | |
NeighborAnalysis(kind='distances', group=None, *, variables=None, box=None, bins=100, r_max=None, attribute='state', empty=None, diagonal=True)
Bases: BaseAnalysis
Neighbours of agents in space, or of cells of a grid or nodes of a network, of one kind.
The kinds read positions, or states on grids and networks:
'distances': the distance from every agent to its nearest neighbour, across periodic edges in a box.'clark-evans': the mean nearest-neighbour distance over its value for uniform random points in a periodic box, 1 for random points, below 1 for clustered ones, and up to 2.15 for a triangular lattice in a plane.'radial-distribution': the radial distribution functiong(r)in a periodic box, averaged over frames, 1 for an ideal gas.'like-share': the mean share of an agent's occupied neighbours that share its state, on a periodic grid or along the edges of a network, near 1 when segregated.
An array of positions holds one snapshot, one row per agent, or one snapshot per frame along its first axis. A
trajectory gives the positions of an agent group with the sides of its periodic space as the box, or its lattice
frames for 'like-share'. A grid array is one frame of states, and a graph carries the states on its nodes.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
kind
|
str
|
The neighbour statistic to compute, one of the kinds above. |
'distances'
|
group
|
str | None
|
The path of the agent group of a trajectory, or |
None
|
variables
|
Sequence[str] | None
|
The lattice state of a trajectory whose frames |
None
|
box
|
Sequence[float] | None
|
The sides of a periodic box, or |
None
|
bins
|
int
|
The number of distance bins of |
100
|
r_max
|
float | None
|
The largest distance of |
None
|
attribute
|
str
|
The node attribute of the states of a graph. |
'state'
|
empty
|
float | None
|
The state of empty cells, left out as agents and as neighbours, or |
None
|
diagonal
|
bool
|
Whether grid cells that share only a corner are neighbours, as in Schelling's Moore neighbourhood. |
True
|
Attributes:
| Name | Type | Description |
|---|---|---|
positions_ |
The positions, frames by agents by dimensions, for the agent kinds. |
|
box_ |
The sides of the periodic box, or |
|
frames_ |
The grids of states, or the graphs, of |
|
distances_ |
The nearest-neighbour distances, frames by agents, of |
|
ratio_ |
One Clark-Evans ratio per frame. |
|
radii_ |
The bin centres of |
|
distribution_ |
|
|
share_ |
One like share per frame. |
Examples:
>>> import numpy as np
>>> from skcomplex.analysis import NeighborAnalysis
>>> positions = [[0.5, 0.0], [9.5, 0.0]]
>>> NeighborAnalysis(box=[10.0, 10.0]).check().prepare(positions).run().distances_.tolist()
[[1.0, 1.0]]
>>> points = np.random.default_rng(0).random((5000, 2))
>>> NeighborAnalysis('clark-evans', box=[1.0, 1.0]).check().prepare(points).run().ratio_.round(1).tolist()
[1.0]
>>> NeighborAnalysis('like-share', diagonal=False).check().prepare([[1, 1, 2, 2]] * 4).run().share_.tolist()
[0.75]
Source code in src/skcomplex/analysis/_neighbors.py
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 | |
NetworkAnalysis(kind='summary', *, orders=(1, 2), attribute=None, numeric=False, measure='degree', method='louvain', reference=None, random_state=None)
Bases: BaseAnalysis
Measures of the network of every frame of a trajectory, or of a graph, of one kind.
The kinds read the graph of every frame:
'degrees': the degree of every node, the moments<k^n>of the degree distribution for every order oforders, and the fitted exponent of a heavy-tailed degree distribution,nanbelow 50 nodes or for a narrow one.'assortativity': the assortativity by degree, or by a node attribute, positive when linked nodes are alike.'centrality': the degree, betweenness, closeness, eigenvector, or PageRank centrality of every node.'communities': the communities by Louvain modularity maximization or label propagation, their modularity, and their agreement with a reference partition.'neighbor-degree': the mean degree of the neighbours of nodes against their degree, rising in assortative networks.'summary': the size, mean degree, clustering, path length, diameter, and components, with the path measures on the largest component.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
kind
|
str
|
The measure to compute, one of the kinds above. |
'summary'
|
orders
|
Sequence[int]
|
The orders |
(1, 2)
|
attribute
|
str | None
|
The node attribute of the assortativity, or |
None
|
numeric
|
bool
|
Whether the attribute is a number compared by correlation rather than a category compared by equality. |
False
|
measure
|
str
|
The centrality: |
'degree'
|
method
|
str
|
The community detection: |
'louvain'
|
reference
|
Sequence[object] | str | None
|
The reference community of every node in node order, the name of a node attribute that holds it, or
|
None
|
random_state
|
int | None
|
The seed of the Louvain method. |
None
|
Attributes:
| Name | Type | Description |
|---|---|---|
graphs_ |
The graph of every frame. |
|
degrees_ |
The degree of every node of every frame. |
|
moments_ |
The degree moments, frames by orders. |
|
exponent_ |
The fitted degree exponent of every frame. |
|
assortativity_ |
The assortativity of every frame. |
|
centrality_ |
A mapping from node to its centrality for every frame. |
|
labels_ |
The community of every node of every frame. |
|
modularity_ |
The modularity of every frame. |
|
agreement_ |
The normalized mutual information with the reference of every frame, or |
|
distinct_degrees_ |
The distinct degrees of every frame. |
|
neighbor_degree_ |
The mean neighbour degree of the nodes of every distinct degree of every frame. |
|
nodes_, |
(edges_, mean_degree_, clustering_, path_length_, diameter_)
|
The summary measures of every frame. |
components_ |
(edges_, mean_degree_, clustering_, path_length_, diameter_)
|
The sizes of the connected components of every frame, largest first. |
Examples:
>>> import networkx as nx
>>> from skcomplex.analysis import NetworkAnalysis
>>> summary = NetworkAnalysis().check().prepare(nx.cycle_graph(10)).run()
>>> summary.mean_degree_.tolist(), summary.clustering_.tolist(), summary.diameter_.tolist()
([2.0], [0.0], [5])
>>> NetworkAnalysis('degrees').check().prepare(nx.star_graph(3)).run().moments_.tolist()
[[1.5, 3.0]]
>>> centrality = NetworkAnalysis('centrality', measure='betweenness').check().prepare(nx.star_graph(3)).run()
>>> centrality.centrality_[0][0]
1.0
Source code in src/skcomplex/analysis/_networks.py
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 | |
OperatorAnalysis(kind='spectrum', *, n_states=6, parameters=None, sector=None, subsystems=None)
Bases: BaseAnalysis
Spectrum and ground state of an operator system, or the purity and entanglement of the states of its trajectory.
The kinds read a system or a trajectory:
'spectrum': the lowest eigenvalues and eigenstates of the generator, by exact diagonalisation. QuTiP diagonalises small spaces densely and larger ones with a sparse eigensolver. A sector restricts the basis to the states with a given eigenvalue of a conserved operator that is diagonal in the product basis, such as the total magnetisation.'ground-state': the lowest eigenvalue and eigenstate of the generator.'purity': the purityTr(rho^2)of the state of a trajectory at every frame, 1 for pure states.'entanglement': the von Neumann entropy of the reduced state of some subsystems at every frame of a trajectory, in nats.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
kind
|
str
|
The quantity to compute, one of the kinds above. |
'spectrum'
|
n_states
|
int
|
The number of eigenvalues of the spectrum. |
6
|
parameters
|
Mapping[str, object] | None
|
Parameter values by dotted name that replace the initial ones. |
None
|
sector
|
SectorSpec | None
|
The sector of a conserved diagonal operator whose basis states the spectrum keeps, or |
None
|
subsystems
|
Sequence[str] | None
|
The keys of the subsystems to keep, such as |
None
|
Attributes:
| Name | Type | Description |
|---|---|---|
problem_ |
The compiled operator problem. |
|
trajectory_ |
The trajectory of |
|
energies_ |
The eigenvalues of the spectrum in increasing order. |
|
states_ |
The eigenstates of the spectrum as columns over the whole space. |
|
energy_ |
The ground state energy. |
|
state_ |
The ground state vector. |
|
purity_ |
The purity at every frame. |
|
entropy_ |
The entanglement entropy at every frame. |
Raises:
| Type | Description |
|---|---|
AnalysisError
|
The system or the trajectory holds no operators, the sector operator is not diagonal or lacks the eigenvalue, or a subsystem is not part of the trajectory. |
ParameterError
|
A parameter name is not part of the system. |
Examples:
>>> from typing import Annotated
>>> import numpy as np
>>> from sage.all__sagemath_symbolics import CC, SR
>>> from skcomplex.analysis import OperatorAnalysis
>>> from skcomplex.core.elements import Element, GroupElement
>>> from skcomplex.core.laws import GeneratorLaw
>>> from skcomplex.core.laws.utils import local_operator
>>> from skcomplex.specs import HilbertSpec, StateSpec
>>> from skcomplex.core.system import System
>>> from skcomplex.engine.compile import OperatorCompiler
>>> from skcomplex.engine.runtime import Simulation
>>> operators = {'z': (np.diag([1, -1]), True), 'minus': (np.array([[0, 0], [1, 0]]), False)}
>>> QUBIT = HilbertSpec(2, operators, basis={'up': 0, 'down': 1})
>>> class TwoLevelElement(Element):
... def __init__(
... self, label, psi: Annotated[object, StateSpec(domain=CC**2)] = 'up', hilbert=QUBIT
... ):
... super().__init__(label)
... self.psi = psi
... self.hilbert = hilbert
...
... def _get_laws(self, s):
... return [GeneratorLaw(local_operator(s.psi, SR.symbol('z')))]
>>> system = System(elements=[TwoLevelElement('q')])
>>> OperatorAnalysis(n_states=2).check().prepare(system).run().energies_.round(6).tolist()
[-1.0, 1.0]
>>> singlet = np.array([0, 1, -1, 0]) / np.sqrt(2)
>>> pair = System(elements=[GroupElement('pair', element=TwoLevelElement, size=2)])
>>> trajectory = Simulation(
... pair, compiler=OperatorCompiler(), dt=1.0, initial_state={'system.state': singlet},
... ).check().prepare().run(until=1.0).trajectory_
>>> analysis = OperatorAnalysis('entanglement', subsystems=['pair[0]']).check().prepare(trajectory).run()
>>> bool(np.allclose(analysis.entropy_, np.log(2)))
True
Source code in src/skcomplex/analysis/_operator.py
139 140 141 142 143 144 145 146 147 148 149 150 151 152 | |
PartialInformationAnalysis(variables=None, *, redundancy='mmi', base=2.0)
Bases: BaseAnalysis
Partial information decomposition of what two series of symbols tell about a third, the target.
The source holds three series: the first source, the second source, and the target. The mutual information of the
two sources together with the target splits into the information both give, the information only one of them
gives, and the information only the two together give, with a redundancy measure of dit.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
variables
|
Sequence[str] | None
|
The variables of a trajectory to read, the two sources and the target, or |
None
|
redundancy
|
str
|
The redundancy measure of |
'mmi'
|
base
|
float
|
The base of the logarithm, 2 for bits. |
2.0
|
Attributes:
| Name | Type | Description |
|---|---|---|
values_ |
The symbols of the two sources and the target, one per column. |
|
labels_ |
The label of every series. |
|
redundancy_ |
The information both sources give. |
|
unique_first_ |
The information only the first source gives. |
|
unique_second_ |
The information only the second source gives. |
|
synergy_ |
The information only the two sources together give. |
|
total_ |
The mutual information of the two sources together with the target, the sum of the four parts. |
Examples:
>>> from skcomplex.analysis import PartialInformationAnalysis
>>> xor = [[0, 0, 0], [0, 1, 1], [1, 0, 1], [1, 1, 0]]
>>> parts = PartialInformationAnalysis().check().prepare(xor).run()
>>> round(parts.synergy_, 6), round(parts.redundancy_, 6)
(1.0, 0.0)
Source code in src/skcomplex/analysis/_partial_information.py
76 77 78 79 | |
PassageAnalysis(kind='first-passage', variables=None, *, threshold=None, target=None, origin=None, direction='up', level=0.0, lag=1, dt=1.0)
Bases: BaseAnalysis
Passages of paths to a level or a set of states, or of a Markov chain between two sets, of one kind.
The kinds read paths, one row per path on common times, or a transition matrix:
'first-passage': the first time every path reachesthreshold, from below fordirection='up'and from above for'down', or enters thetargetstates.'hitting': the share of paths that reach each of the absorbingtargetstates before the others.'return-times': the times between successive returns of a series tolevel, by visit or by crossing.'committor': the forward committor of a transition matrix, the probability that the chain reaches thetargetstates before theoriginstates.'mean-first-passage': the mean first-passage time of a transition matrix atlagfrom theoriginstates, started in their stationary weights, to thetargetstates.
The matrix kinds estimate the transition matrix at lag of the jump path of a trajectory.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
kind
|
str
|
The passage to measure, one of the kinds above. |
'first-passage'
|
variables
|
Sequence[str] | None
|
The discrete state of a trajectory to read, or the series for |
None
|
threshold
|
float | None
|
The level a first passage reaches. |
None
|
target
|
Sequence[float] | None
|
The states that end a passage, the absorbing states, or the target set of the chain. |
None
|
origin
|
Sequence[float] | None
|
The origin set of the chain. |
None
|
direction
|
str
|
|
'up'
|
level
|
float
|
The level of the returns. |
0.0
|
lag
|
int
|
The lag of the transition matrix in steps. |
1
|
dt
|
float
|
The time of one step of an array, while a trajectory gives its own times. |
1.0
|
Attributes:
| Name | Type | Description |
|---|---|---|
values_ |
The paths, one row per path, or the series of |
|
times_ |
The common times of the steps. |
|
matrix_ |
The transition matrix of the matrix kinds. |
|
passage_times_ |
The time from the start to the first passage of every path, |
|
hitting_probabilities_ |
The share of paths that hit every target state first, of |
|
return_times_ |
The time between every return and the next, of |
|
committor_ |
The committor of every state, 0 on the origin and 1 on the target, of |
|
mean_first_passage_time_ |
The mean first-passage time, of |
Examples:
>>> from skcomplex.analysis import PassageAnalysis
>>> passage = PassageAnalysis(threshold=2).check().prepare([[0, 1, 2, 3], [0, 0, 0, 0]]).run()
>>> passage.passage_times_.tolist()
[2.0, nan]
>>> PassageAnalysis('return-times').check().prepare([0, 1, 0, -1, -2, -1, 0]).run().return_times_.tolist()
[2.0, 4.0]
>>> walk = [[0.5, 0.5, 0.0], [0.25, 0.5, 0.25], [0.0, 0.5, 0.5]]
>>> PassageAnalysis('committor', origin=[0], target=[2]).check().prepare(walk).run().committor_.tolist()
[0.0, 0.5, 1.0]
Source code in src/skcomplex/analysis/_passage.py
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 | |
RecurrenceAnalysis(variables=None, *, radius=None, rate=0.05, min_line=2, theiler=1, random_state=0)
Bases: BaseAnalysis
Recurrence quantification of the points of a source: rate, determinism, laminarity, lines, and entropy.
Every row of the series of a source is a point, and every series a coordinate, so an embedded series or the states of a trajectory give a point set. Two points recur when they lie within the radius of each other.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
variables
|
Sequence[str] | None
|
The variables of a trajectory to read as coordinates, or |
None
|
radius
|
float | None
|
The recurrence radius, or |
None
|
rate
|
float
|
The share of recurrent pairs when the radius is not given. |
0.05
|
min_line
|
int
|
The shortest diagonal or vertical line counted. |
2
|
theiler
|
int
|
The number of diagonals about the main one left out, 1 to leave out the main diagonal alone. |
1
|
random_state
|
int | None
|
The seed of the sample of pairs that sets the radius of large sets. |
0
|
Attributes:
| Name | Type | Description |
|---|---|---|
values_ |
The points, one per row. |
|
labels_ |
The label of every coordinate. |
|
radius_ |
The recurrence radius. |
|
matrix_ |
The symmetric sparse boolean recurrence matrix, with a true diagonal. |
|
rate_ |
The share of recurrent pairs off the Theiler window. |
|
determinism_ |
The share of recurrent points on diagonal lines of at least the minimum length. |
|
laminarity_ |
The share of recurrent points on vertical lines of at least the minimum length. |
|
mean_diagonal_ |
The mean length of those diagonal lines. |
|
longest_diagonal_ |
The length of the longest diagonal line. |
|
trapping_time_ |
The mean length of those vertical lines. |
|
entropy_ |
The Shannon entropy in nats of the distribution of those diagonal line lengths. |
Examples:
>>> import numpy as np
>>> from skcomplex.analysis import EmbeddingAnalysis, RecurrenceAnalysis
>>> sine = EmbeddingAnalysis(delay=15, dimension=2).check().prepare(np.sin(np.arange(2000) * 0.1)).run()
>>> bool(RecurrenceAnalysis().check().prepare(sine.points_).run().determinism_ > 0.95)
True
>>> recurrence = RecurrenceAnalysis(radius=0.5).check().prepare([0.0, 0.1, 5.0, 5.1]).run()
>>> recurrence.matrix_.toarray().astype(int).tolist()
[[1, 1, 0, 0], [1, 1, 0, 0], [0, 0, 1, 1], [0, 0, 1, 1]]
Source code in src/skcomplex/analysis/_recurrence.py
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 | |
ReservoirAnalysis(variables=None, *, kind='next_generation', delay=2, order=2, units=300, spectral_radius=0.9, leak=1.0, input_scaling=0.5, ridge=0.0001, warmup=None, validation=0.2, horizon=0, dt=1.0, random_state=0, label='surrogate')
Bases: BaseAnalysis
Reservoir system whose ridge readout gives the increments of the variables over one sample, from ReservoirPy.
The reservoir is driven by the standardized variables, and a ridge regression from its features to the increments
of the variables over one sample is fitted on the training samples. A next-generation reservoir takes as features
the variables at delay consecutive samples and their monomials of degree order. An echo state network takes
the activities of units leaky tanh units with random recurrent weights. The fitted system runs under discrete
time, one step per sample, and starts at the last sample of the last run with the memory the runs left, so a run of
the system is the autonomous forecast.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
variables
|
Sequence[str] | None
|
The variables of trajectories, or |
None
|
kind
|
str
|
The reservoir, |
'next_generation'
|
delay
|
int
|
The number of consecutive samples of a next-generation reservoir. |
2
|
order
|
int
|
The degree of the monomials of a next-generation reservoir. |
2
|
units
|
int
|
The number of units of an echo state network. |
300
|
spectral_radius
|
float
|
The spectral radius of the recurrent weights of an echo state network. |
0.9
|
leak
|
float
|
The leak rate of the units of an echo state network, 1 for no leak. |
1.0
|
input_scaling
|
float
|
The scale of the input weights of an echo state network. |
0.5
|
ridge
|
float
|
The strength of the ridge penalty of the readout. |
0.0001
|
warmup
|
int | None
|
The number of first samples of every series left out of the fit while the memory fills, or |
None
|
validation
|
float
|
The share of the samples of every run held out at its end to measure the validation error. |
0.2
|
horizon
|
int
|
The number of samples to forecast after the last sample of the last run. |
0
|
dt
|
float
|
The time between the rows of an array. |
1.0
|
random_state
|
int | None
|
The seed of the random weights of an echo state network. |
0
|
label
|
str
|
The label of the surrogate element. |
'surrogate'
|
Attributes:
| Name | Type | Description |
|---|---|---|
samples_ |
The series of every run, the names of the variables, and the step, set by |
|
system_ |
The system of one surrogate element under discrete time, one step per sample, whose states are the variables and then the memory of the reservoir. |
|
labels_ |
The variables the surrogate was fitted to. |
|
states_ |
The names of the states of the surrogate element, the variables first. |
|
last_state_ |
The variables at the last sample of the last series and the memory the series left, where forecasts start. |
|
dt_ |
The time between the samples it was fitted to, which one step of the system stands for. |
|
training_error_ |
The relative error of the predicted increments on the training samples, with the reservoir driven by the series. |
|
validation_error_ |
The relative error on the held-out samples, NaN when none are held out. |
|
step_ |
The map from the states to the states one step later, which the update law calls. |
|
forecast_ |
The variables at the |
Raises:
| Type | Description |
|---|---|
AnalysisError
|
The reservoir kind is unknown, or no training sample is left after the warmup. |
Examples:
>>> import numpy as np
>>> from skcomplex.analysis import ReservoirAnalysis
>>> times = np.arange(400.0)
>>> analysis = ReservoirAnalysis(['x'], horizon=10).check().prepare(np.sin(0.1 * times)).run()
>>> analysis.states_
['x', 'memory_0', 'memory_1']
>>> bool(abs(analysis.forecast_[-1, 0] - np.sin(0.1 * 409)) < 0.01)
True
Source code in src/skcomplex/analysis/_reservoirs.py
227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 | |
RollingAnalysis(kind='variance', variables=None, *, window=None, detrend=False)
Bases: BaseAnalysis
Statistic of every series of a source in rolling windows, of one kind, and its trend.
Every window holds the window values that end at a sample, possibly with a linear trend removed first, and the
statistic of the window is set at that sample. The trend of the statistic is Kendall's tau against time.
'variance': the variance of the window.'autocorrelation': the lag-one autocorrelation of the window.'skewness': the skewness of the window.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
kind
|
str
|
The statistic to compute, one of the kinds above. |
'variance'
|
variables
|
Sequence[str] | None
|
The variables of a trajectory to read, or |
None
|
window
|
int | None
|
The number of values in every rolling window. |
None
|
detrend
|
bool
|
Whether to remove a linear trend in every window first. |
False
|
Attributes:
| Name | Type | Description |
|---|---|---|
values_ |
The series, one per column. |
|
labels_ |
The label of every series. |
|
statistic_ |
The statistic of every series in every window, one row per series, |
|
trend_ |
Kendall's tau of the statistic of every series against time, positive when it rises. |
Examples:
>>> import numpy as np
>>> from skcomplex.analysis import RollingAnalysis
>>> rng = np.random.default_rng(0)
>>> x = np.zeros(2000)
>>> for t in range(1, 2000):
... x[t] = (0.2 + 0.79 * t / 2000) * x[t - 1] + rng.standard_normal()
>>> rolling = RollingAnalysis('autocorrelation', window=200, detrend=True).check().prepare(x).run()
>>> bool(rolling.trend_[0] > 0.5)
True
Source code in src/skcomplex/analysis/_rolling.py
69 70 71 72 73 74 75 76 77 78 79 80 | |
ScalingAnalysis(kind='detrended-fluctuation', variables=None, *, scales=None, order=1, fit_sums=(0.0001, 0.01), random_state=0, against='mean', parameters=None, critical=None, above=False)
Bases: BaseAnalysis
Scaling exponent of every series of a source, fractal dimension of a set of cells or points, or scaling law.
The kinds read series, fields, points, or samples at several sizes:
'detrended-fluctuation': the slope of the log fluctuation of the integrated series, detrended in windows by a polynomial of degreeorder, against the log window size. It is 0.5 for white noise, the Hurst exponentHfor fractional Gaussian noise, andH + 1for its integral, such as 1.5 for a random walk.'rescaled-range': the Hurst exponent by the rescaled range, 0.5 for uncorrelated noise, above 0.5 for persistent and below 0.5 for anti-persistent noise.'box-counting': the box-counting dimension of the occupied cells of a field, the slope of the log box count against the log box size, read from the last frame of a trajectory.'correlation-dimension': the Grassberger-Procaccia correlation dimension of a point set, one row per point, such as the columns of an embedded series, from tree counts of close pairs.'variance-mean': the mean and the standard deviation of a quantity at every scale, and the slope oflog deviationagainstlog meanwithagainst='mean', or oflog (deviation / mean)againstlog sizewithagainst='size'. It reads the counts of a density field in square boxes of growing side over every frame, where the slope against the mean is 1/2 for independent particles and above for giant fluctuations, or a mapping from size to samples, where the slope against the size is -1/2 for the sums of independent parts.'power': the exponentbof the power lawy ~ |p - p_c|^bof every series against the distance of the controlparametersto thecriticalvalue, fitted on the side above or below it whereyis positive, such as the exponentbetaof an order parameter.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
kind
|
str
|
The scaling to measure, one of the kinds above. |
'detrended-fluctuation'
|
variables
|
Sequence[str] | None
|
The variables of a trajectory to read, or |
None
|
scales
|
Sequence[float] | None
|
The window sizes, the box sides in cells, or the radii, or |
None
|
order
|
int
|
The order of the detrending polynomial. |
1
|
fit_sums
|
tuple[float, float]
|
The smallest and largest correlation sums of the scaling region the slope is fitted in. |
(0.0001, 0.01)
|
random_state
|
int | None
|
The seed of the sample of pairs that sets the default radii. |
0
|
against
|
str
|
What the variance-mean law is fitted against, |
'mean'
|
parameters
|
Sequence[float] | None
|
The control parameter value of every row of the series of |
None
|
critical
|
float | None
|
The value of the control parameter the distance is measured to. |
None
|
above
|
bool
|
Whether the fit uses the values above the critical value, as for couplings, rather than below it, as for temperatures. |
False
|
Attributes:
| Name | Type | Description |
|---|---|---|
values_ |
The series, one per column, the field or its frames, or the points, and an empty array for samples by size. |
|
samples_ |
The samples by size, or |
|
labels_ |
The label of every series, of the field, or of every size. |
|
scales_ |
The window sizes, the box sides, the radii, or the sizes. |
|
fluctuations_ |
The fluctuation, or the rescaled range, of every series at every window size. |
|
counts_ |
The number of occupied boxes of every side. |
|
sums_ |
The share of pairs of points closer than every radius. |
|
means_ |
The mean of the quantity at every scale. |
|
deviations_ |
The standard deviation of the quantity at every scale. |
|
fit_range_ |
The smallest and largest radii of the fit of the correlation dimension. |
|
exponent_ |
float | Array
|
The exponent of every series for the fluctuation kinds and |
Examples:
>>> import numpy as np
>>> from skcomplex.analysis import ScalingAnalysis
>>> walk = np.cumsum(np.random.default_rng(0).standard_normal(5000))
>>> ScalingAnalysis().check().prepare(walk).run().exponent_.round(1).tolist()
[1.5]
>>> round(ScalingAnalysis('box-counting').check().prepare(np.ones((256, 256))).run().exponent_, 2)
2.0
>>> points = np.random.default_rng(0).random((5000, 2))
>>> round(ScalingAnalysis('correlation-dimension').check().prepare(points).run().exponent_, 1)
2.0
>>> counts = np.random.default_rng(0).poisson(5.0, (20, 64, 64))
>>> round(ScalingAnalysis('variance-mean').check().prepare(counts).run().exponent_, 1)
0.5
>>> power = ScalingAnalysis('power', parameters=[0.9, 0.99], critical=1.0)
>>> power.check().prepare([0.1**0.5, 0.01**0.5]).run().exponent_.round(6).tolist()
[0.5]
Source code in src/skcomplex/analysis/_scaling.py
153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 | |
SectionAnalysis(kind='poincare', variables=None, *, state=None, value=0.0, direction=1, until=1000.0, transient=None, period=None, n_points=1000, solver=None, random_state=None)
Bases: BaseAnalysis
Section of a system: the states where a flow crosses a value, or at multiples of a period.
The kinds run the system:
'poincare': the states where the scalar statestatecrossesvaluein a direction, located like an event.'stroboscopic': the states of a periodically forced flow at multiples of the forcing period.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
kind
|
str
|
The section to take, one of the kinds above. |
'poincare'
|
variables
|
Sequence[str] | None
|
The dotted names of the states whose values to read at the points of a section, or |
None
|
state
|
str | None
|
The dotted name of the scalar state that defines a Poincaré section, such as |
None
|
value
|
float
|
The value of the state on the Poincaré section. |
0.0
|
direction
|
int
|
|
1
|
until
|
float
|
The time a Poincaré section runs until. |
1000.0
|
transient
|
float | None
|
The time before which crossings are discarded, or the number of periods discarded before the first
stroboscopic point. |
None
|
period
|
float | None
|
The period of the forcing, such as |
None
|
n_points
|
int
|
The number of points of a stroboscopic section. |
1000
|
solver
|
Solver | None
|
The solver, as in |
None
|
random_state
|
int | None
|
The seed of stochastic solvers. |
None
|
Attributes:
| Name | Type | Description |
|---|---|---|
problem_ |
The compiled problem of a Poincaré or stroboscopic section. |
|
times_ |
The time of every point of a section. |
|
states_ |
One state vector per point of a section. |
|
values_ |
A mapping from the name of every read state to its values at the points of a section, one row per point for a vector state. |
Examples:
>>> from skcomplex.analysis import SectionAnalysis
>>> from skcomplex.models.physics.mechanics import harmonic_oscillator
>>> section = SectionAnalysis(state='mass.x', until=20.0).check().prepare(harmonic_oscillator()).run()
>>> len(section.times_) > 2
True
Source code in src/skcomplex/analysis/_sections.py
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 | |
SignatureAnalysis
Bases: BaseAnalysis
Default analysis of every kind of data of a trajectory, with its curves, axis labels, title, and values.
A series gives its power spectrum with the autocorrelation time, or its return map for a map. A jump path gives the survival function of its waiting times with the dispersion index of jumps per frame. A field gives the structure factor of its last frame with the peak wavelength or the correlation length. Agents give their polar and milling orders over time, or their nearest-neighbour distances against the Poisson law. A network gives its degree distribution.
Attributes:
| Name | Type | Description |
|---|---|---|
kinds_ |
The data kinds of the trajectory, in the order agents, field, network, path, series. |
|
snapshots_ |
The agents of the first group at every frame, for the agents kind. |
|
frames_ |
The frames of the first lattice state, for the field kind. |
|
graphs_ |
The network of every frame, for the network kind. |
|
path_ |
The jump path of the first discrete state, for the path kind. |
|
jumps_ |
The size of the jumps of that state between frames, for the path kind. |
|
series_ |
The scalar series, for the series kind. |
|
discrete_ |
Whether the trajectory is that of a map, whose series give a return map. |
|
signatures_ |
One signature per data kind, in the order of |
Examples:
>>> from skcomplex.analysis import SignatureAnalysis
>>> from skcomplex.models import run
>>> trajectory = run('lotka_volterra', settings={'until': 20.0}).trajectory_
>>> [signature.title for signature in SignatureAnalysis().check().prepare(trajectory).run().signatures_]
['Power spectrum']
SparseIdentificationAnalysis(variables=None, *, degree=2, threshold=0.1, alpha=0.05, validation=0.2, horizon=0, dt=1.0, label='surrogate')
Bases: BaseAnalysis
Sparse symbolic system fitted to series by sparse identification of nonlinear dynamics, computed with PySINDy.
SINDy writes the derivative of every variable as a sparse sum of the monomials of the variables up to a degree. It estimates the derivatives by centred finite differences and selects the terms by sequentially thresholded least squares. The fitted system holds one rate law per variable under continuous time and starts at the first sample of the first run, and the forecast simulates it from the last sample of the last run.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
variables
|
Sequence[str] | None
|
The variables of trajectories, or |
None
|
degree
|
int
|
The highest degree of the candidate monomials. |
2
|
threshold
|
float
|
The smallest magnitude of a kept coefficient. |
0.1
|
alpha
|
float
|
The strength of the ridge penalty of every least-squares fit. |
0.05
|
validation
|
float
|
The share of the samples of every run held out at its end to measure the validation error. |
0.2
|
horizon
|
int
|
The number of samples to forecast after the last sample of the last run. |
0
|
dt
|
float
|
The time between the rows of an array. |
1.0
|
label
|
str
|
The label of the surrogate element. |
'surrogate'
|
Attributes:
| Name | Type | Description |
|---|---|---|
samples_ |
The series of every run, the names of the variables, and the step, set by |
|
system_ |
The system of one surrogate element under continuous time, with one rate law per variable. |
|
labels_ |
The variables the system was fitted to, in the order of its states. |
|
states_ |
The names of the states of the surrogate element. |
|
last_state_ |
The values of the states at the last sample of the last run, where the forecast starts. |
|
dt_ |
The time between the samples it was fitted to. |
|
training_error_ |
The relative error of the predicted derivatives on the training samples. |
|
validation_error_ |
The relative error on the held-out samples, NaN when none are held out. |
|
features_ |
The candidate monomials of the states, such as |
|
coefficients_ |
The coefficient of every monomial in the rate of every state, one row per state and one column per monomial, zero where the term is absent. |
|
forecast_ |
The variables at the |
Examples:
>>> import numpy as np
>>> from skcomplex.analysis import SparseIdentificationAnalysis
>>> times = np.arange(0.0, 2.0, 0.001)
>>> analysis = SparseIdentificationAnalysis(['x'], degree=1, dt=0.001)
>>> analysis = analysis.check().prepare(np.exp(-2 * times)).run()
>>> analysis.features_, analysis.coefficients_.round(3).tolist()
(['1', 'x'], [[0.0, -2.0]])
Source code in src/skcomplex/analysis/_sparse_identification.py
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 | |
SpectrumAnalysis(kind='power', variables=None, *, dt=1.0, spacing=1.0, frames=False)
Bases: BaseAnalysis
Spectrum of every series of a source, or of a field.
The kinds read series or fields:
'power': the power spectral density of every series by Welch's method.'structure-factor': the radially averaged structure factorS(k)of a field on a periodic grid of any dimension, in shells of width2 pi / (side spacing), averaged over frames whenframesis true.
A structure factor reads the last frame of a trajectory, or every frame when frames is true.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
kind
|
str
|
The spectrum to compute, one of the kinds above. |
'power'
|
variables
|
Sequence[str] | None
|
The variables of a trajectory to read, or |
None
|
dt
|
float
|
The time between samples. |
1.0
|
spacing
|
float
|
The distance between neighbouring sites. |
1.0
|
frames
|
bool
|
Whether the first axis of an array indexes frames, and whether to read every frame of a trajectory. |
False
|
Attributes:
| Name | Type | Description |
|---|---|---|
values_ |
The series, one per column, or the field. |
|
labels_ |
The label of every series, or of the field. |
|
frequencies_ |
The frequencies of |
|
power_ |
One density per series and frequency for |
|
wavenumbers_ |
The wavenumbers of the shells, without 0, for |
Examples:
>>> import numpy as np
>>> from skcomplex.analysis import SpectrumAnalysis
>>> times = np.arange(4096) * 0.01
>>> spectrum = SpectrumAnalysis(dt=0.01).check().prepare(np.sin(2 * np.pi * 5 * times)).run()
>>> round(float(spectrum.frequencies_[spectrum.power_[0].argmax()]))
5
>>> stripes = np.cos(2 * np.pi * np.arange(64) / 8)[:, None] * np.ones(64)
>>> factor = SpectrumAnalysis('structure-factor').check().prepare(stripes).run()
>>> round(float(2 * np.pi / factor.wavenumbers_[factor.power_.argmax()]), 1)
8.0
Source code in src/skcomplex/analysis/_spectrum.py
83 84 85 86 87 88 89 90 91 92 93 94 95 96 | |
StabilityAnalysis(kind='fixed-points', parameters=None, points=None, *, at=None)
Bases: BaseAnalysis
Linear stability of a system, of one kind.
'fixed-points': the fixed points of a flow or a map, their linear stability, and the Jacobian, nullclines, and divergence.'dispersion': the growth rate of every Fourier mode of a system of one field, a site group on a periodic lattice whose laws are rate laws. The laws are linearised symbolically around a uniform state, and every Laplacian, nested ones included, becomes its eigenvalue on a Fourier mode of the lattice,Σ (2 cos(k h) - 2) / h²for finite differences and-|k|²for a spectral field. Withoutat, the uniform state is the fixed point of the laws nearest the mean initial values.
The fixed points of a flow are where every rate is 0, and those of a map where every state equals its next value. Sage solves the equations symbolically, and when it finds no closed form, roots are searched numerically from a grid of starting points with the parameters at their values. The stability of every point comes from the eigenvalues of the Jacobian there, evaluated at the parameter values.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
kind
|
str
|
The stability to derive, one of the kinds above. |
'fixed-points'
|
parameters
|
Mapping[str, float] | None
|
Values of parameters by dotted path that replace the system's values. They are substituted before solving, and without them the symbolic fixed points keep the parameters as symbols. |
None
|
points
|
Sequence[Point] | None
|
The points whose stability to analyse, each a mapping from state component name to its value, symbolic
or numeric, or |
None
|
at
|
Mapping[str, float] | None
|
The uniform state of the dispersion relation by state name, or |
None
|
Attributes:
| Name | Type | Description |
|---|---|---|
problem_ |
The compiled problem. |
|
names_ |
The state component names, in the order of the rows of the Jacobian. |
|
jacobian_ |
The Sage matrix of the partial derivatives of the right sides by the states. |
|
divergence_ |
The trace of the Jacobian, 0 for volume-preserving flows. |
|
nullclines_ |
A mapping from state component name to its nullcline as a Sage relation, where its rate is 0 or where it is its own next value. |
|
fixed_points_ |
One mapping from state component name to its value per point, the fixed points found or the given points. |
|
eigenvalues_ |
The eigenvalues of the Jacobian at every point. |
|
classifications_ |
The class of every point: |
|
system_ |
The system of one field, for |
|
wavenumbers_ |
The wave vector of every mode, one row per mode, for |
|
magnitudes_ |
The length of every wave vector. |
|
growth_rates_ |
The largest real part of the eigenvalues of the linearisation at every mode. |
|
frequencies_ |
The imaginary part of the leading eigenvalue at every mode, nonzero for travelling or oscillating modes. |
|
uniform_ |
The uniform state the model is linearised around, by state name. |
|
band_ |
The lengths of the wave vectors whose modes grow. |
Examples:
>>> from skcomplex.analysis import StabilityAnalysis
>>> from skcomplex.models.biology.ecology import logistic_growth
>>> analysis = StabilityAnalysis().check().prepare(logistic_growth()).run()
>>> sorted(str(point['population.n']) for point in analysis.fixed_points_)
['0', 'K_growth']
>>> analysis = StabilityAnalysis(points=[{'population.n': 100.0}]).check().prepare(logistic_growth())
>>> analysis.run().classifications_
['stable node']
>>> from skcomplex.models.chemistry.pattern_formation import brusselator
>>> relation = StabilityAnalysis('dispersion').check().prepare(brusselator((64,), b=1.9, Dv=8.0)).run()
>>> bool(relation.growth_rates_.max() > 0), bool(relation.growth_rates_[0] < 0)
(True, True)
Source code in src/skcomplex/analysis/_stability.py
137 138 139 140 141 142 143 144 145 146 147 148 | |
SurrogateTestAnalysis(analysis, attribute, variables=None, *, n=99, alternative='two-sided', random_state=None)
Bases: BaseAnalysis
Test of an analysis of many variables against surrogates that shuffle every variable independently.
The analysis runs on the data and on n surrogates, and the attribute it sets gives the value of each. The p-value
is the fraction of surrogates, with the data counted among them, at least as extreme as the data.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
analysis
|
BaseAnalysis
|
The unprepared analysis of the variables, cloned for the data and for every surrogate. |
required |
attribute
|
str
|
The scalar attribute of the analysis that measures the dependence, such as |
required |
variables
|
Sequence[str] | None
|
The variables of a trajectory, or |
None
|
n
|
int
|
The number of surrogates. |
99
|
alternative
|
str
|
|
'two-sided'
|
random_state
|
int | None
|
The seed of the shuffles. |
None
|
Attributes:
| Name | Type | Description |
|---|---|---|
values_ |
The data, one row per sample and one column per variable. |
|
value_ |
The measure on the data. |
|
surrogates_ |
The measure on every surrogate. |
|
p_value_ |
The p-value of the data against the surrogates. |
Examples:
>>> import numpy as np
>>> from skcomplex.analysis import InformationAnalysis, SurrogateTestAnalysis
>>> bit = np.random.default_rng(0).integers(0, 2, 500)
>>> test = SurrogateTestAnalysis(InformationAnalysis('o-information'), 'information_', n=19, random_state=0)
>>> test = test.check().prepare(np.column_stack([bit, bit, bit])).run()
>>> round(test.value_, 1), test.p_value_
(1.0, 0.05)
Source code in src/skcomplex/analysis/_surrogates.py
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 | |
SymbolicAnalysis(kind='equations', *, use_initial_state=False)
Bases: BaseAnalysis
Symbolic form of a system: its equations, their exact solution, its Hamiltonian, or its boundary flows.
The kinds read the equations of a system:
'equations': one equation per state component, a Sage relation. Each state component is a function of timet. Continuous forms give its time derivative, the drift for stochastic systems, and discrete maps give its value att + 1. States of higher order give their highest derivative,diff(x(t), t, k), with their companions written as derivatives, and lagged states read their past values asx(t - j). The equations of a group hold for every member and are named with the member indexi. Components driven by a callable law or by a sum over members or pairs are left out.'solve': the exact solution of the equations of an ODE system as functions of time, with Maxima through Sage. One equation of order 1 or 2 is solved withdesolve, one of higher order withdesolve_laplace, and several withdesolve_systemafter reduction to first order, which solves linear systems with constant coefficients. A result that still contains unevaluated transforms, integrals, or the unknown functions is not a solution, and raises the error. Parameters give Maxima their sign from their domain, or from their value when their domain is real. One linear fractional relaxationD^alpha x = c xhas the solutionx(0) E_alpha(c t^alpha), written with the symbolic functionmittag_leffler(alpha, beta, z).'hamiltonian': the Hamiltonian of an operator system, the sum of the operators of its generator laws, whose subsystems are the symbols of the states of the elements, named<state>_<path>, and whose parameters are named<parameter>_<path>.'conservation': the net inflow from the environment of every quantity of a system with a transfer network, after checking that its internal flows cancel, so the total changes only through the boundary.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
kind
|
str
|
The symbolic form to derive, one of the kinds above. |
'equations'
|
use_initial_state
|
bool
|
Whether |
False
|
Attributes:
| Name | Type | Description |
|---|---|---|
problem_ |
The compiled problem. |
|
equations_ |
A mapping from state component name to its equation. |
|
solutions_ |
A mapping from state component name to its solution, a relation |
|
hamiltonian_ |
The Hamiltonian, a Sage expression of local operators. |
|
inflows_ |
The symbolic rate, or amount per step, at which each quantity enters the system from the environment. |
Raises:
| Type | Description |
|---|---|
AnalysisError
|
The system has no form of the kind, Maxima cannot solve its equations, or needs the sign of a parameter. |
ConservationError
|
The internal flows of a quantity do not cancel. |
Examples:
>>> from skcomplex.analysis import SymbolicAnalysis
>>> from skcomplex.core.system import System
>>> from skcomplex.models.biology.common.populations import ExponentialGrowthInteraction, PopulationElement
>>> system = System(
... elements=[PopulationElement('a', n=2)],
... interactions=[ExponentialGrowthInteraction('g', target='a', r=0.5)],
... )
>>> SymbolicAnalysis().check().prepare(system).run().equations_['a.n']
diff(n_a(t), t) == r_g*n_a(t)
>>> SymbolicAnalysis('solve', use_initial_state=True).check().prepare(system).run().solutions_['a.n']
n_a(t) == 2*e^(r_g*t)
Source code in src/skcomplex/analysis/_symbolic.py
164 165 166 | |