Laws
Define laws, the rules by which states change.
BaseLaw(label)
Bases: BasePart[str, object]
Base of every law, a rule by which states change, which an element, an interaction, or a system returns.
A law takes the states it changes and the expressions it reads as arguments of its own __init__, which stores each
under its own name, as in scikit-learn. It returns the states it changes from _get_targets, what it requires of a
system, such as continuous or discrete time, from _get_requirements, and its value at given values of the symbols
it reads from _run, which sets it as value_.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The name of the law, or the empty string for a law without one. |
required |
Attributes:
| Name | Type | Description |
|---|---|---|
targets_ |
The states the law changes. |
|
reads_ |
The symbols the law reads. |
|
owner_ |
The path of the element or interaction that returns the law, or |
|
value_ |
object
|
The value of the law at the values of the symbols of its last run. |
Examples:
>>> from sage.all__sagemath_symbolics import var
>>> from skcomplex.core.laws import RateLaw
>>> x, k = var('x'), var('k')
>>> law = RateLaw(x, -k * x).check().prepare('decay')
>>> law.targets_, sorted(map(str, law.reads_)), law.owner_
((x,), ['k', 'x'], 'decay')
>>> law.run({'x': 2.0, 'k': 0.5}).value_
-1.0
Source code in src/skcomplex/core/base.py
60 61 62 63 64 65 66 67 | |
BilinearLaw(target, first, second, rate, outcomes=None, *, label='')
Bases: BaseLaw
Gain or loss of a target density at a signed rate of the product of two densities.
The amount of the first density f in class h that meets the amount of the second density g in class k adds
to class i of the target at the rate r[h, k] with probability B[h, k, i], so the law adds
sum_hk r[h, k] B[h, k, i] f_h g_k to the rate of the target at i. A positive rate gives a gain that leaves the
first density in place, and a negative rate with the first density as the target gives a loss.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
target
|
Expression
|
The symbol of the density the law changes. |
required |
first
|
Expression
|
The symbol of the first density. |
required |
second
|
Expression
|
The symbol of the second density. |
required |
rate
|
object
|
The signed rate, a number or a parameter expression, or an array |
required |
outcomes
|
object
|
The array |
None
|
label
|
str
|
The name of the law, or the empty string for a law without one. |
''
|
Examples:
>>> from sage.all__sagemath_symbolics import var
>>> from skcomplex.core.laws import BilinearLaw
>>> f, g = var('f'), var('g')
>>> BilinearLaw(f, f, g, -0.5).check().prepare().run({}).value_
(-0.5, None)
Source code in src/skcomplex/core/laws/_bilinear.py
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | |
BoundaryLaw(target, value, *, label='')
Bases: BaseLaw
Value a state takes after every solver step, such as a reflection at a wall or a wrap around a periodic box.
Boundaries leave the form of a system as is, so they combine with every other law in any time.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
target
|
Target
|
The symbol of a scalar state, or the column of symbols of a vector state. |
required |
value
|
object
|
A symbolic expression, a |
required |
label
|
str
|
The name of the law, or the empty string for a law without one. |
''
|
Examples:
>>> from sage.all__sagemath_symbolics import floor, var
>>> from skcomplex.core.laws import BoundaryLaw
>>> x = var('x')
>>> BoundaryLaw(x, x - floor(x)).check().prepare().run({'x': 2.25}).value_
0.25
Source code in src/skcomplex/core/laws/_boundary.py
35 36 37 38 | |
CascadeLaw(drive, relax, stable, max_iterations=100000, activity=None, *, label='')
Bases: BaseLaw
Cascade of a lattice: drive laws once per step, then the laws that relax it until it is stable.
Every cascade that changes the lattice is recorded as an event with its size, the number of site updates, its
duration, the number of iterations, and its area, the number of distinct sites updated. A site update is a site
that changes in an iteration, or a site that activity marks as active before it, such as a toppling site.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
drive
|
Sequence[BaseLaw]
|
The laws applied once per step, local rules or drives. |
required |
relax
|
Sequence[BaseLaw]
|
The laws applied in turn until the lattice is stable. |
required |
stable
|
Callable[..., bool]
|
A function of the arrays of the targets of the laws that relax the lattice, in lattice shape, that returns whether the lattice is stable. |
required |
max_iterations
|
int
|
The largest number of iterations in one step. |
100000
|
activity
|
Callable[..., object] | None
|
A function of the arrays of the targets that returns a boolean array of the active sites of an iteration,
or |
None
|
label
|
str
|
The name of the cascade events, or the empty string for the path of the element. |
''
|
Examples:
>>> from sage.all__sagemath_symbolics import var
>>> from skcomplex.core.laws import CascadeLaw, LocalRuleLaw
>>> from skcomplex.core.spaces import VonNeumannNeighborhood
>>> height = var('height')
>>> topple = LocalRuleLaw(height, VonNeumannNeighborhood(center=True), lambda z, *n: z - 4 * (z >= 4))
>>> CascadeLaw([], [topple], lambda z: bool((z < 4).all())).check().prepare().targets_
(height,)
Source code in src/skcomplex/core/laws/_cascade.py
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | |
CrossingLaw(guard, reset=None, direction=0, terminal=False, *, label='')
Bases: BaseLaw
Event at the crossing of zero by a guard, when states take new values or the run ends.
Solvers locate the crossing within their tolerance. Crossings leave the form of a system as is, so they combine with rate laws, and the trajectory records every crossing with its time and the states before and after it.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
guard
|
object
|
A symbolic expression of states and time whose crossing of zero triggers the event, or a function
|
required |
reset
|
Mapping[Expression, object] | None
|
A mapping from state symbol to its new value, applied all at once, or |
None
|
direction
|
int
|
|
0
|
terminal
|
bool
|
Whether the crossing ends the run. |
False
|
label
|
str
|
The name of the crossing in the trajectory, or the empty string for the path of the element. |
''
|
Examples:
>>> from sage.all__sagemath_symbolics import var
>>> from skcomplex.core.laws import CrossingLaw
>>> y, z = var('y'), var('z')
>>> law = CrossingLaw(y, {z: -0.8 * z}, direction=-1).check().prepare()
>>> law.run({'z': -2.0}).value_
{z: 1.6}
Source code in src/skcomplex/core/laws/_crossing.py
51 52 53 54 55 56 57 58 59 60 61 62 63 64 | |
DissipatorLaw(operator, rate=1.0, *, label='')
Bases: BaseLaw
Lindblad term of a Markovian master equation, with a collapse operator and a rate.
The master equation gains rate * (L rho L^† - (L^† L rho + rho L^† L) / 2).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
operator
|
object
|
The collapse operator |
required |
rate
|
object
|
The non-negative rate, a number or a Sage expression of parameters and time. |
1.0
|
label
|
str
|
The name of the law, or the empty string for a law without one. |
''
|
Examples:
>>> from sage.all__sagemath_symbolics import SR, var
>>> from skcomplex.core.laws import DissipatorLaw
>>> from skcomplex.core.laws.utils import local_operator
>>> minus = local_operator(SR.symbol('q'), SR.symbol('minus'))
>>> DissipatorLaw(minus, 2 * var('gamma')).check().prepare().run({'gamma': 0.05}).value_
(local_operator(q, minus), 0.1)
Source code in src/skcomplex/core/laws/_dissipator.py
40 41 42 43 | |
DriveLaw(target, function, *, label='')
Bases: BaseLaw
Change of a whole lattice state at once by a function of its array, such as adding 1 at a random site.
The function receives the state as an array of the lattice shape, keyword arguments for the parameters of the
element that it names, and random, the random generator of the simulation, and returns the new array.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
target
|
Expression
|
The symbol of a lattice state. |
required |
function
|
Callable[..., object]
|
The function |
required |
label
|
str
|
The name of the law, or the empty string for a law without one. |
''
|
Examples:
>>> from sage.all__sagemath_symbolics import var
>>> from skcomplex.core.laws import DriveLaw
>>> DriveLaw(var('height'), lambda values, *, random: values + 1).check().prepare().targets_
(height,)
Source code in src/skcomplex/core/laws/_drive.py
39 40 41 42 | |
EmissionLaw(target, source, matrix, *, label='')
Bases: BaseLaw
Observation of a hidden Markov source, a state drawn from the row of an emission matrix a hidden state selects.
The emission reads the hidden state's value after the same step, so the hidden and observed sequences align.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
target
|
Expression
|
The symbol of the observed scalar state. |
required |
source
|
Expression
|
The symbol of the hidden state, which an update or transition law of the same element sets. |
required |
matrix
|
Sequence[Sequence[object]]
|
The emission matrix, one row per value of the hidden state and one column per value of the observed state, as numbers or expressions of parameters. |
required |
label
|
str
|
The name of the law, or the empty string for a law without one. |
''
|
Examples:
>>> from sage.all__sagemath_symbolics import var
>>> from skcomplex.core.laws import EmissionLaw
>>> observed, hidden = var('observed'), var('hidden')
>>> EmissionLaw(observed, hidden, [[0.7, 0.3], [0.2, 0.8]]).check().prepare().targets_
(observed,)
Source code in src/skcomplex/core/laws/_emission.py
43 44 45 46 47 48 49 50 51 52 53 54 | |
EncounterLaw(candidate, field, rate, transition, test=None, *, label='')
Bases: BaseLaw
Bilinear transfer of a density between its classes at the rate of its product with a second density.
The amount of the candidate density f in class h meets the amount of the field density g in class k at the
rate eta[h, k], and moves to class i with the probability A[h, k, i]. The law adds the gain and the loss
df_i/dt = sum_hk eta[h, k] A[h, k, i] f_h g_k - f_i sum_k eta[i, k] g_k,
where the loss acts on the candidate and the gain on the test density, the candidate itself by default, so the total over the classes is conserved. The candidate, the field, and the test are states of groups on the sites of lattices of classes, one member per class. A field density that no law changes is a fixed external input.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
candidate
|
Expression
|
The symbol of the candidate density, a state of a group read member by member. |
required |
field
|
Expression | None
|
The symbol of the field density, or |
required |
rate
|
object
|
The encounter rate, a number or a parameter expression, or an array |
required |
transition
|
object
|
The array |
required |
test
|
Expression | None
|
The symbol of the density the candidate moves into, or |
None
|
label
|
str
|
The name of the law, or the empty string for a law without one. |
''
|
Examples:
>>> import numpy as np
>>> from sage.all__sagemath_symbolics import var
>>> from skcomplex.core.laws import EncounterLaw
>>> f, g = var('f'), var('g')
>>> rate, transition = EncounterLaw(f, g, 1.0, np.full((2, 2, 2), 0.5)).check().prepare().run({}).value_
>>> rate, np.shape(transition)
(1.0, (2, 2, 2))
Source code in src/skcomplex/core/laws/_encounter.py
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | |
EquationLaw(lhs, rhs=None, *, target=None, label='')
Bases: BaseLaw
Implicit relation in which the highest time derivatives of states appear, such as Newton's second law.
The states are Sage functions of time, such as function('theta')(t), and their derivatives are Sage derivatives,
theta.diff(t, 2). The compiler solves all equations of a system jointly for the highest derivatives, which must
appear linearly, and adds the rate laws on the same states to the solution. An equation may name the state whose
equation it is, its target, and the equations of one target, from any element or interaction, add into one
before the solve, so a term of it may hold no highest derivative, such as the part a coupling Lagrangian adds to
the Euler-Lagrange equation of a coordinate.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
lhs
|
object
|
The left side, or a Sage relation |
required |
rhs
|
object
|
The right side, or |
None
|
target
|
object
|
The state whose equation this is, so that the equations of one target add, or |
None
|
label
|
str
|
The name of the law, or the empty string for a law without one. |
''
|
Attributes:
| Name | Type | Description |
|---|---|---|
lhs_ |
The left side. |
|
rhs_ |
The right side. |
Examples:
>>> from sage.all__sagemath_symbolics import function, sin, var
>>> from skcomplex.core.laws import EquationLaw
>>> t, g, l = var('t g l')
>>> theta = function('theta')(t)
>>> EquationLaw(l * theta.diff(t, 2) == -g * sin(theta)).check().prepare().rhs_
-g*sin(theta(t))
Source code in src/skcomplex/core/laws/_equation.py
55 56 57 58 59 | |
ExtremalLaw(targets, over, rule, *, key=None, extremum='min', repeat=1, label='')
Bases: BaseLaw
Rule applied to the site with the smallest or largest value of a key state and to its neighbours.
Every application finds the extremal site, with ties broken by the random stream of the simulation, gathers the
site and its neighbours without duplicates, the site first, and calls f(*values, random, **parameters) with one
array per target and a uniform random array of the same length. Every application is recorded as an event.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
targets
|
Expression | tuple[Expression, ...]
|
The symbol of a lattice state, or a tuple of them that the rule updates together. |
required |
over
|
BaseNeighborhood
|
The neighbourhood of the extremal site that the rule also updates. |
required |
rule
|
Callable[..., object]
|
The function |
required |
key
|
Expression | None
|
The lattice state whose extremum is searched, or |
None
|
extremum
|
str
|
|
'min'
|
repeat
|
int
|
The number of applications per step. |
1
|
label
|
str
|
The name of the events, or the empty string for the path of the element. |
''
|
Examples:
>>> from sage.all__sagemath_symbolics import var
>>> from skcomplex.core.laws import ExtremalLaw
>>> from skcomplex.core.spaces import BoxNeighborhood
>>> law = ExtremalLaw(var('fitness'), BoxNeighborhood(), lambda values, *, random: random).check()
>>> law.extremum, law.repeat
('min', 1)
Source code in src/skcomplex/core/laws/_extremal.py
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | |
FluxLaw(target, flux, *, limiter='minmod', riemann='rusanov', speed=None, label='')
Bases: BaseLaw
Flux of a conserved state of a finite-volume field, du/dt + divergence(flux) = 0.
The flux is a symbolic expression of the field's states for one dimension, or one expression per dimension. The states of a field with fluxes form a system of conservation laws, whose wave speeds come from the eigenvalues of the flux Jacobians. Rate laws on the same states add sources.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
target
|
Target
|
The symbol of the conserved state. |
required |
flux
|
object
|
The flux, an expression or one expression per dimension. |
required |
limiter
|
str | None
|
The slope limiter of the MUSCL reconstruction, |
'minmod'
|
riemann
|
str
|
The numerical flux, |
'rusanov'
|
speed
|
object
|
A function |
None
|
label
|
str
|
The name of the law, or the empty string for a law without one. |
''
|
Examples:
>>> from sage.all__sagemath_symbolics import var
>>> from skcomplex.core.laws import FluxLaw
>>> u = var('u')
>>> FluxLaw(u, u**2 / 2, riemann='godunov').check().prepare().run({'u': 2.0}).value_
2.0
Source code in src/skcomplex/core/laws/_flux.py
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | |
FractionalNoiseLaw(target, value, order=None, *, hurst, convention='ito', label='')
Bases: NoiseLaw
Amplitude of a fractional Brownian motion of a Hurst index that drives the highest time derivative of a state.
The increments are fractional Gaussian noise, correlated over the whole run. A Hurst index of 1/2 gives the
process of a NoiseLaw, below 1/2 the increments anticorrelate, and above 1/2 they correlate. For other indices
than 1/2 the amplitude must not depend on any state.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
target
|
Target
|
The symbol of a scalar state, or the column of symbols of a vector state. |
required |
value
|
object
|
A symbolic expression of parameters and time. A vector target gets one fractional Brownian motion per component. |
required |
order
|
int | None
|
The order of the derivative the noise drives, checked against the state's order, or |
None
|
hurst
|
object
|
The Hurst index |
required |
convention
|
str
|
The stochastic calculus of the law, |
'ito'
|
label
|
str
|
The name of the law, or the empty string for a law without one. |
''
|
Examples:
>>> from sage.all__sagemath_symbolics import var
>>> from skcomplex.core.laws import FractionalNoiseLaw
>>> x, D = var('x'), var('D')
>>> FractionalNoiseLaw(x, 2 * D, hurst=0.7).check().hurst
0.7
Source code in src/skcomplex/core/laws/_fractional_noise.py
47 48 49 50 51 52 53 54 55 56 57 58 | |
GeneratorLaw(operator, *, label='')
Bases: BaseLaw
Hermitian operator that adds to the generator H of the linear evolution dx/dt = -i H x on a tensor product.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
operator
|
object
|
The Hermitian operator, an expression of local operators of the namespaces the law receives. |
required |
label
|
str
|
The name of the law, or the empty string for a law without one. |
''
|
Examples:
>>> from sage.all__sagemath_symbolics import SR, var
>>> from skcomplex.core.laws import GeneratorLaw
>>> from skcomplex.core.laws.utils import local_operator
>>> z = local_operator(SR.symbol('q'), SR.symbol('z'))
>>> GeneratorLaw(var('h') * z).check().prepare().run({'h': 0.5}).value_
0.5*local_operator(q, z)
Source code in src/skcomplex/core/laws/_generator.py
35 36 37 | |
GradientStepLaw(trained, loss, data, optimizer, batch_size, *, truncation=None, metrics=(), label='')
Bases: BaseLaw
Optimizer steps on adaptive parameters of a nested system, on the gradient of a loss over unrolled runs.
One step of the discrete time that holds the law is one epoch. In an epoch the sequences of the dataset are shuffled and split into batches, and for every batch the nested system runs from its initial states over every sequence, the loss is averaged over the steps and sequences with the step weights, and the optimizer changes the trained parameters by the gradient of that mean. The gradient is exact, by automatic differentiation of the unrolled runs. The law records the mean batch loss of the epoch and every metric over the whole dataset at the end of the epoch.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
trained
|
Sequence[str]
|
The dotted paths of the adaptive parameters of the nested system that the law trains, such as
|
required |
loss
|
ObservableSpec
|
The observable of the nested system whose weighted mean over the steps of a batch is minimized. |
required |
data
|
DatasetSpec
|
The sequences of the parameters of the nested system that set its inputs and targets at every step. |
required |
optimizer
|
str
|
The name of the optimizer, |
required |
batch_size
|
int
|
The number of sequences of a batch. The last batch of an epoch holds the rest. |
required |
truncation
|
int | None
|
The number of inner steps the gradient flows back through the inner states, or |
None
|
metrics
|
Sequence[ObservableSpec]
|
The observables of the nested system recorded at the end of every epoch, as weighted means over every sequence. |
()
|
label
|
str
|
The name of the law, or the empty string for a law without one. |
''
|
Examples:
>>> import numpy as np
>>> from skcomplex.core.laws import GradientStepLaw
>>> from skcomplex.specs import DatasetSpec, ObservableSpec
>>> data = DatasetSpec({'inputs.x': np.zeros((4, 3, 1))})
>>> law = GradientStepLaw(['readout.W'], ObservableSpec('error', 0.0), data, 'adam', 2).check()
>>> law.prepare('training').targets_
()
Source code in src/skcomplex/core/laws/_gradient_step.py
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | |
JumpLaw(rate=None, changes=None, waiting=None, reset=None, *, label='')
Bases: BaseLaw
Random event that changes states, on an exponential clock of a given rate or on a clock of drawn waiting times.
With a rate, the event fires at the times of a Poisson process of that propensity and changes states by fixed
increments, as in continuous-time Markov chains. With a waiting time instead, it fires after a waiting time drawn
anew at every firing, and applies its reset, as in renewal processes such as the jumps of a random walk. Every
member of a group then fires on its own clock, and the trajectory records every firing and counts them in
<label>.renewals. Jumps combine with rate and noise laws, which evolve the states between firings.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
rate
|
object
|
The propensity of the event, a symbolic expression, a |
None
|
changes
|
Mapping[Expression, object] | None
|
A mapping from the symbol of a scalar state to its increment when the event fires. In a law of a group, a
target may also be a member offset read |
None
|
waiting
|
object
|
The waiting time until the next firing, usually a draw from a distribution with nonnegative support, such
as |
None
|
reset
|
Mapping[Expression, object] | None
|
With a waiting time, a mapping from state symbol to its new value, which may hold draws, or |
None
|
label
|
str
|
With a waiting time, the name of the firings in the trajectory, or the empty string for the path of the element. |
''
|
Examples:
>>> from sage.all__sagemath_symbolics import var
>>> from skcomplex.core.laws import JumpLaw
>>> from skcomplex.core.laws.utils import draw
>>> s, i = var('s'), var('i')
>>> JumpLaw(0.1 * s * i, {s: -1, i: 1}).check().prepare().targets_
(s, i)
>>> n = var('n')
>>> JumpLaw(waiting=draw('wait', 'expon'), reset={n: 0}).check().prepare().targets_
(n,)
Source code in src/skcomplex/core/laws/_jump.py
57 58 59 60 61 62 63 64 65 66 67 68 69 70 | |
LocalRuleLaw(targets, over, rule, *, reads=None, schedule='synchronous', stochastic=False, label='')
Bases: BaseLaw
Next value of lattice cells computed from the ordered values of their neighbourhoods.
A function rule receives one array per neighbour of every read state, in neighbourhood order, with one value per
site, and keyword arguments for the parameters of the element that it names, plus random, an array of uniform
numbers per site, when the rule is stochastic, and degree, the number of neighbours of every site besides the
site itself, when it names it. It returns the next values of the target, or a tuple with one array per target.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
targets
|
Expression | tuple[Expression, ...]
|
The symbol of a lattice state, or a tuple of them that the rule updates together. |
required |
over
|
BaseNeighborhood
|
The neighbourhood whose values the rule reads: a lattice neighbourhood of offsets, an adjacency on a network, or a memory of group elements on a group space. |
required |
rule
|
object
|
A function, a |
required |
reads
|
tuple[Expression, ...] | None
|
The lattice states whose neighbourhoods a function rule reads, or |
None
|
schedule
|
str
|
|
'synchronous'
|
stochastic
|
bool
|
Whether a function rule receives the uniform random array |
False
|
label
|
str
|
The name of the law, or the empty string for a law without one. |
''
|
Examples:
>>> from sage.all__sagemath_symbolics import var
>>> from skcomplex.core.laws import LocalRuleLaw
>>> from skcomplex.specs import TotalisticSpec
>>> from skcomplex.core.spaces import BoxNeighborhood
>>> LocalRuleLaw(var('cell'), BoxNeighborhood(), TotalisticSpec({2: 1})).check().prepare().targets_
(cell,)
Source code in src/skcomplex/core/laws/_local_rule.py
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | |
MatchLaw(left, right=None, pairing=None, capacity=1, phase=None, *, label='match')
Bases: BaseLaw
Pairing of the members of one agent group, or of two, every step, which the rules of the step read.
The members are paired uniformly at random by default. Any other pairing, such as stable matching, an order book,
or an auction, is a function given as pairing, and a selection of partners within reach or among neighbours is
a PartnerSpec. Rules read the pairs of the step with matches(model, label). Transfers, matchings, and groupings
read their pairs from get_pairs.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
left
|
str
|
The path of the first agent group. |
required |
right
|
str | None
|
The path of the second agent group, or |
None
|
pairing
|
Pairing | PartnerSpec | None
|
A function |
None
|
capacity
|
int
|
The largest number of pairs of every member. |
1
|
phase
|
str | None
|
The phase of the step the pairing runs in, before the rules of the phase that read it. |
None
|
label
|
str
|
The name of the pairs. |
'match'
|
Examples:
>>> from skcomplex.core.laws import MatchLaw
>>> MatchLaw('buyers', 'sellers', label='trades').check().capacity
1
Source code in src/skcomplex/core/laws/_match.py
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | |
get_pairs(left, right, rng)
Return the pairs of the agents of both sides by the pairing.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
left
|
Sequence[AgentViewProtocol]
|
The agents of the first side. |
required |
right
|
Sequence[AgentViewProtocol]
|
The agents of the second side, the same sequence for pairs within one group. |
required |
rng
|
Generator
|
The random generator. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
pairs |
list[tuple[object, object]]
|
The pairs of agents, the first of every pair from the first side. |
Raises:
| Type | Description |
|---|---|
ValidationError
|
A selection of partners names a state the agents do not have. |
Source code in src/skcomplex/core/laws/_match.py
253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 | |
iterate_pairs(left, right, rng, feasible)
Yield the pairs of a selection of partners one at a time, so a caller settles each before the next one.
The agents act in random order, since the first to act take what the feasibility reads.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
left
|
Sequence[AgentViewProtocol]
|
The agents of the first side. |
required |
right
|
Sequence[AgentViewProtocol]
|
The agents of the second side. |
required |
rng
|
Generator
|
The random generator. |
required |
feasible
|
Feasibility
|
The function |
required |
Returns:
| Name | Type | Description |
|---|---|---|
pairs |
Iterator[tuple[AgentViewProtocol, AgentViewProtocol]]
|
The pairs of agents, the first of every pair from the first side. |
Raises:
| Type | Description |
|---|---|
ValidationError
|
The pairing is not a selection of partners, or it names a state the agents do not have. |
Source code in src/skcomplex/core/laws/_match.py
286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 | |
NoiseLaw(target, value, order=None, *, convention='ito', process=None, conserved=False, label='')
Bases: BaseLaw
Amplitude of a Wiener process that drives the highest time derivative of a state.
Without a process, every component of the target and every member of a group gets its own independent Wiener
process. Laws of one component, or of one member, that name the same local process share its increment. Laws that
name a process of a WienerProcessSpec through a role share it across components and members.
A conserved noise on a state of a field on a lattice adds div(value eta) instead, the finite-difference divergence
of a random flux with one Wiener process per link between neighbouring sites, so the total of the field changes
only by its rate laws.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
target
|
Target
|
The symbol of a scalar state, or the column of symbols of a vector state. |
required |
value
|
object
|
A symbolic expression, a |
required |
order
|
int | None
|
The order of the derivative the noise drives, checked against the state's order, or |
None
|
convention
|
str
|
The stochastic calculus of the law, |
'ito'
|
process
|
Process
|
|
None
|
conserved
|
bool
|
Whether the noise is the divergence of a random flux on the links of the lattice of a field. |
False
|
label
|
str
|
The name of the law, or the empty string for a law without one. |
''
|
Examples:
>>> from sage.all__sagemath_symbolics import var
>>> from skcomplex.core.laws import NoiseLaw
>>> x = var('x')
>>> NoiseLaw(x, 0.2 * x, process='shared').check().prepare().run({'x': 10.0}).value_
2.0
Source code in src/skcomplex/core/laws/_noise.py
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | |
RateLaw(target, value, order=None, *, cross_section=None, label='')
Bases: BaseLaw
Contribution to the highest time derivative of a state, the first for states of order 1.
Rates on the same state add up, so a system with only rate laws is a system of ordinary differential equations. On
a state of order k, a rate contributes to the k-th derivative, so independent mechanisms superpose.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
target
|
Target | Matrix
|
The symbol of a scalar state, the column of symbols of a vector state, or the matrix of a tensor state. |
required |
value
|
object
|
A symbolic expression, a matrix of the shape of a tensor state, a |
required |
order
|
int | None
|
The order of the derivative the rate gives, checked against the state's order, or |
None
|
cross_section
|
Callable[..., object] | None
|
The function |
None
|
label
|
str
|
The name of the law, or the empty string for a law without one. |
''
|
Examples:
>>> from sage.all__sagemath_symbolics import var
>>> from skcomplex.core.laws import RateLaw
>>> n = var('n')
>>> RateLaw(n, 2 * n).check().prepare().run({'n': 3.0}).value_
6.0
Source code in src/skcomplex/core/laws/_rate.py
48 49 50 51 52 53 54 55 56 57 58 59 60 61 | |
RuleLaw(function, phase=None, *, members=None, label='')
Bases: BaseLaw
Behaviour written as code, run once per step for every member of an agent group, or once per step for a model.
An element whose laws include rules is an agent, alone or in a group. A rule of an element receives the agent and
the model, function(agent, model). A rule of an interaction receives the model alone, function(model), unless it
names the role whose members run it: every member of the groups of that role then runs it in its own activation,
after the rules of its element and the member rules of the interactions before it, as function(agent, model) with
the model view of the interaction. A system with rules is agent-based and needs discrete time.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
function
|
Callable[..., object]
|
The function that runs the rule. |
required |
phase
|
str | None
|
The name of the phase of the step the rule runs in, or |
None
|
members
|
str | None
|
The role of the interaction whose members run the rule, or |
None
|
label
|
str
|
The name of the law, or the empty string for a law without one. |
''
|
Examples:
>>> from skcomplex.core.laws import RuleLaw
>>> moved = []
>>> RuleLaw(lambda agent, model: moved.append(agent)).check().prepare().run(('walker', None)).value_
>>> moved
['walker']
Source code in src/skcomplex/core/laws/_rule.py
44 45 46 47 48 49 50 51 52 53 54 55 | |
SampleLaw(objective, move, sampler=None, *, label='')
Bases: BaseLaw
Monte Carlo sweep that samples states by moves accepted from the change of an objective, one per unit of time.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
objective
|
ObjectiveSpec
|
The local objective of a site and its neighbourhood. |
required |
move
|
MoveSpec
|
The move proposed at a site. |
required |
sampler
|
SamplerSpec | None
|
The acceptance of moves, with its intensity and schedule, or |
None
|
label
|
str
|
The name of the law, or the empty string for a law without one. |
''
|
Examples:
>>> from sage.all__sagemath_symbolics import var
>>> from skcomplex.core.laws import SampleLaw
>>> from skcomplex.core.spaces import VonNeumannNeighborhood
>>> from skcomplex.specs import ObjectiveSpec, MoveSpec, SamplerSpec
>>> spin = var('spin')
>>> law = SampleLaw(ObjectiveSpec(-spin, VonNeumannNeighborhood()), MoveSpec(spin), SamplerSpec('glauber', 2.0))
>>> law.check().prepare().targets_
(spin,)
Source code in src/skcomplex/core/laws/_sample.py
40 41 42 43 44 45 46 47 48 49 50 51 | |
Sink(label='environment')
Environment a transfer releases a quantity to, outside the system, such as a drain or the atmosphere.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The name of the environment in transaction-flow matrices. |
'environment'
|
Examples:
>>> from skcomplex.core.laws import Sink
>>> Sink('drain').label
'drain'
Source code in src/skcomplex/core/laws/_transfer.py
46 47 | |
Source(label='environment')
Environment a transfer draws a quantity from, outside the system, such as a bank that creates money.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The name of the environment in transaction-flow matrices. |
'environment'
|
Examples:
>>> from skcomplex.core.laws import Source
>>> Source().label
'environment'
Source code in src/skcomplex/core/laws/_transfer.py
29 30 | |
TransferLaw(source, sink, amount, rate=None, *, label='', owner='')
Bases: BaseLaw
Movement of an amount of a quantity from a source holder to a sink holder, in continuous or discrete time.
A transfer is one outflow of its source and one inflow of its sink. Its amount is a rate in a system of rate laws,
the amount moved per step in a system of update laws, and the size of every jump when a rate is given. The
trajectory records the amount at every frame under <path>.<label>, the path of the part that declares the
transfer, or owner when given. One holder may be a state of a group read by shift_member at a member offset, so
every member transfers with the member that many places along the group order. Past the ends of a fixed boundary
no member is there, and the transfer moves nothing.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
source
|
Expression | Source
|
The symbol of the state the quantity leaves, the symbol read at a member offset, or |
required |
sink
|
Expression | Sink
|
The symbol of the state the quantity enters, the symbol read at a member offset, or |
required |
amount
|
object
|
The symbolic amount, a rate, a per-step amount, or a jump size. |
required |
rate
|
object
|
The propensity of a jump that moves |
None
|
label
|
str
|
The name of the flow, unique among the flows reported under one part, or the empty string for
|
''
|
owner
|
str
|
The path of the part the flow is reported under, relative to the system of the part that declares the transfer, such as the element an interaction moves a quantity within, or the empty string for the part that declares it. |
''
|
Examples:
>>> from sage.all__sagemath_symbolics import var
>>> from skcomplex.core.laws import Source, TransferLaw
>>> level = var('level')
>>> TransferLaw(Source(), level, 5, label='faucet').check().prepare().targets_
(level,)
Source code in src/skcomplex/core/laws/_transfer.py
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 | |
TransitionLaw(target, matrix, *, label='')
Bases: BaseLaw
Step of a discrete-time Markov chain, a state over a finite alphabet drawn from a row of a transition matrix.
The state's current value selects the row, and the next value is drawn from it. The state takes a categorical
domain or the integers from 0 to n - 1. A transition is a kind of update, so it combines with update laws.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
target
|
Expression
|
The symbol of a scalar state. |
required |
matrix
|
Sequence[Sequence[object]] | Callable[..., object] | CallSpec
|
The square transition matrix, whose entry |
required |
label
|
str
|
The name of the law, or the empty string for a law without one. |
''
|
Examples:
>>> from sage.all__sagemath_symbolics import var
>>> from skcomplex.core.laws import TransitionLaw
>>> x, q = var('x'), var('q')
>>> TransitionLaw(x, [[q, 1 - q], [0.4, 0.6]]).check().prepare().run({'q': 0.1}).value_[0]
[0.1, 0.9]
Source code in src/skcomplex/core/laws/_transition.py
42 43 44 45 46 47 48 49 50 51 | |
UpdateLaw(target, value, *, label='', increment=False, source=None, order=None, phase=None)
Bases: BaseLaw
Next value of a state after one discrete time step.
A state takes one update law, unless each of its update laws declares how it combines with the others. An
increment law gives the state plus a change, and a law with a source changes only a state that holds the source
value and keeps every other value. Several such laws of one state combine in one step by adding their changes,
x + sum_k (f_k - x), all computed from the states at the start of the step, so increments add and moves from
distinct source values compose. Two laws with the same source, or a law that declares neither, are an error.
With an order, the members of a group update one after the other, in increasing order of the value of order at
the start of the step, ties in the order of the members, and each member reads the values the members before it
set. Without one, every member updates at once from the states at the start of the step.
With a phase, the law runs in that phase of the step, which a PhasesScheduleSpec of the discrete time orders.
The phases run one after the other, each reading the states the phases before it set, and the laws of one phase
update at once. A law without a phase runs in the default phase, first unless the schedule places it.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
target
|
Target | TopologyRequestSpec
|
The symbol of a scalar state, the column of symbols of a vector state, or a |
required |
value
|
object
|
A symbolic expression, a |
required |
label
|
str
|
The name of the law, or the empty string for a law without one. |
''
|
increment
|
bool
|
Whether the value is the state plus a change that adds to the changes of the other update laws of the state. |
False
|
source
|
float | None
|
The value the law moves the state from, keeping every other value, or |
None
|
order
|
object
|
A symbolic expression of the states, parameters, and draws of a member, whose values order the members
that update one after the other, or |
None
|
phase
|
str | None
|
The name of the phase of the step the law runs in, or |
None
|
Raises:
| Type | Description |
|---|---|
ValidationError
|
The value is a NumPy array, or an increment law has a source. |
Examples:
>>> from sage.all__sagemath_symbolics import var
>>> from skcomplex.core.laws import UpdateLaw
>>> x = var('x')
>>> UpdateLaw(x, 4 * x * (1 - x)).check().prepare().run({'x': 0.5}).value_
1.0
>>> UpdateLaw(x, x + 1, increment=True).check().increment
True
>>> UpdateLaw(x, x + 1, phase='imitate').check().phase
'imitate'
Source code in src/skcomplex/core/laws/_update.py
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 | |