@@ -6,10 +6,12 @@ Supertype for cellular automata that retain an evolution history.
66abstract type AbstractCellularAutomaton end
77
88"""
9- next_state(rule, state; boundary=Periodic())
9+ next_state(rule, state; boundary=Periodic(), scheme=Synchronous(), rng=nothing )
1010
11- Apply one synchronous cellular-automaton transition without mutating `state`.
12- Rules may specialize this function to define differentiable transitions.
11+ Apply one cellular-automaton transition without mutating `state`. Rule subtypes
12+ define their transition by implementing
13+ `CellularAutomata.__step(rule, state, boundary)`; this wrapper then applies the
14+ selected update scheme.
1315
1416# Arguments
1517
@@ -20,6 +22,11 @@ Rules may specialize this function to define differentiable transitions.
2022
2123 - `boundary`: Boundary condition used outside the state array.
2224 Defaults to `Periodic()`.
25+ - `scheme`: Update scheme controlling which cells apply the transition.
26+ Defaults to `Synchronous()`; use `Stochastic(rate)` for a per-cell random mask.
27+ - `rng`: Random number generator used by stochastic schemes. It must be supplied
28+ explicitly with `Stochastic` and its state advances when the mask is drawn.
29+ It is not consulted by `Synchronous`.
2330
2431# Examples
2532
@@ -38,23 +45,33 @@ julia> next_state(DCA(30), [0, 0, 1, 0, 0])
3845function next_state (
3946 rule:: AbstractCellularAutomatonRule ,
4047 state;
41- boundary:: AbstractBoundaryCondition = Periodic ()
48+ boundary:: AbstractBoundaryCondition = Periodic (),
49+ scheme:: AbstractUpdateScheme = Synchronous (),
50+ rng:: Union{Nothing, AbstractRNG} = nothing
4251 )
4352 __validate_state (rule, state)
44- return __step (rule, state, boundary)
53+ __validate_scheme_rng (scheme, rng)
54+ new_state = __step (rule, state, boundary)
55+ return __apply_scheme (scheme, rng, state, new_state)
4556end
4657
4758@concrete struct __Transition
4859 rule
4960 boundary
61+ scheme
62+ rng
5063end
5164
5265function (transition:: __Transition )(state, _)
53- return next_state (transition. rule, state; boundary = transition. boundary)
66+ return next_state (
67+ transition. rule, state;
68+ boundary = transition. boundary, scheme = transition. scheme, rng = transition. rng
69+ )
5470end
5571
5672"""
57- rollout(rule, initial_state, steps; boundary=Periodic(), save=false)
73+ rollout(rule, initial_state, steps; boundary=Periodic(), scheme=Synchronous(),
74+ rng=nothing, save=false)
5875
5976Apply `steps` transitions of `rule` to `initial_state`. By default only the final
6077state is returned, which is the preferred path inside a loss function. With
@@ -70,6 +87,10 @@ on the last axis.
7087# Keyword arguments
7188
7289 - `boundary`: Boundary condition used by each transition. Defaults to `Periodic()`.
90+ - `scheme`: Update scheme applied at every step. Defaults to `Synchronous()`.
91+ - `rng`: Random number generator passed to every step. It must be supplied
92+ explicitly with `Stochastic`; the same object is reused and its state advances
93+ across steps. It is not consulted by `Synchronous`.
7394 - `save`: Retain the initial state and every subsequent state. Defaults to `false`.
7495
7596# Examples
@@ -96,11 +117,14 @@ function rollout(
96117 initial_state,
97118 steps:: Integer ;
98119 boundary:: AbstractBoundaryCondition = Periodic (),
120+ scheme:: AbstractUpdateScheme = Synchronous (),
121+ rng:: Union{Nothing, AbstractRNG} = nothing ,
99122 save:: Bool = false
100123 )
101124 steps >= 0 || throw (ArgumentError (" steps must be nonnegative" ))
102125 isempty (initial_state) && throw (ArgumentError (" initial_state cannot be empty" ))
103- transition = __Transition (rule, boundary)
126+ __validate_scheme_rng (scheme, rng)
127+ transition = __Transition (rule, boundary, scheme, rng)
104128 if save
105129 states = accumulate (transition, 1 : steps; init = initial_state)
106130 return stack (Iterators. flatten (((initial_state,), states)))
0 commit comments