Imagine that at some step in the evolution of a rule one reverses a single relation. What effect will it have? Here is an example for the rule {{x,y},{x,z}}{{x,z},{x,w},{y,w},{z,w}}. The first row is the original evolution; the second is the evolution after reversing the relation:
init = ResourceFunction[
"WolframModel"][{{x, y}, {x, z}} -> {{x, z}, {x, w}, {y, w}, {z,
w}}, {{0, 0}, {0, 0}}, 5, "FinalState"];
evol = ResourceFunction[
"WolframModel"][{{x, y}, {x, z}} -> {{x, z}, {x, w}, {y, w}, {z,
w}}, init, 4]["StatesPlotsList", ImageSize -> 120]
initp = {{0, 9}, {4, 10}, {0, 2}, {0, 12}, {5, 12}, {2, 12}, {3, 7}, \
{3, 13}, {6, 13}, {7, 13}, {2, 7}, {2, 14}, {6, 14}, {7, 14}, {1, 4}, \
{1, 15}, {6, 15}, {4, 15}, {0, 1}, {0, 16}, {7, 16}, {1, 16}, {4, 9}, \
{4, 17}, {8, 17}, {9, 17}, {1, 9}, {1, 18}, {18, 8}, {9, 18}, {2, \
10}, {2, 19}, {5, 19}, {10, 19}, {1, 11}, {1, 20}, {3, 20}, {11, 20}, \
{5, 11}, {5, 21}, {10, 21}, {11, 21}, {3, 11}, {3, 22}, {8, 22}, {11, \
22}}; evolp =
ResourceFunction[
"WolframModel"][{{x, y}, {x, z}} -> {{x, z}, {x, w}, {y, w}, {z,
w}}, initp, 4]["StatesPlotsList", ImageSize -> 120]
We can illustrate the effect by coloring edges in the first row of graphs that are different in the second one (taking account of graph isomorphism) [41]:
init = ResourceFunction[
"WolframModel"][{{x, y}, {x, z}} -> {{x, z}, {x, w}, {y, w}, {z,
w}}, {{0, 0}, {0, 0}}, 5, "FinalState"];
evol = ResourceFunction[
"WolframModel"][{{x, y}, {x, z}} -> {{x, z}, {x, w}, {y, w}, {z,
w}}, init, 4, "StatesList"];
initp = {{0, 9}, {4, 10}, {0, 2}, {0, 12}, {5, 12}, {2, 12}, {3,
7}, {3, 13}, {6, 13}, {7, 13}, {2, 7}, {2, 14}, {6, 14}, {7,
14}, {1, 4}, {1, 15}, {6, 15}, {4, 15}, {0, 1}, {0, 16}, {7,
16}, {1, 16}, {4, 9}, {4, 17}, {8, 17}, {9, 17}, {1, 9}, {1,
18}, {18, 8}, {9, 18}, {2, 10}, {2, 19}, {5, 19}, {10, 19}, {1,
11}, {1, 20}, {3, 20}, {11, 20}, {5, 11}, {5, 21}, {10, 21}, {11,
21}, {3, 11}, {3, 22}, {8, 22}, {11, 22}};
evolp = ResourceFunction[
"WolframModel"][{{x, y}, {x, z}} -> {{x, z}, {x, w}, {y, w}, {z,
w}}, initp, 4, "StatesList"];
MapThread[
ResourceFunction["WolframModelPlot"][#,
EdgeStyle -> <|Alternatives @@ #2 -> Directive[Thick, Red]|>,
ImageSize -> 120] &, {evol, MapThread[Complement, {evol, evolp}]}]
Visualizing the second and third graphs in 3D makes it more obvious that the changed edges are mostly connected:
init = ResourceFunction[
"WolframModel"][{{x, y}, {x, z}} -> {{x, z}, {x, w}, {y, w}, {
z, w}}, {{0, 0}, {0, 0}}, 5, "FinalState"];
evol = Map[Graph[
Apply[Rule, #, {1}], GraphLayout -> "SpringElectricalEmbedding",
ImageSize -> 120,
VertexStyle -> ResourceFunction["WolframPhysicsProjectStyleData"][
"SpatialGraph", "VertexStyle"],
EdgeStyle -> ResourceFunction["WolframPhysicsProjectStyleData"][
"SpatialGraph", "EdgeLineStyle"]]& ,
ResourceFunction[
"WolframModel"][{{x, y}, {x, z}} -> {{x, z}, {x, w}, {y, w}, {
z, w}}, init, 4, "StatesList"]];
initp = {{0, 9}, {4, 10}, {0, 2}, {0, 12}, {5, 12}, {2, 12}, {3, 7}, {
3, 13}, {6, 13}, {7, 13}, {2, 7}, {2, 14}, {6, 14}, {7, 14}, {1,
4}, {1, 15}, {6, 15}, {4, 15}, {0, 1}, {0, 16}, {7, 16}, {1, 16}, {
4, 9}, {4, 17}, {8, 17}, {9, 17}, {1, 9}, {1, 18}, {18, 8}, {9,
18}, {2, 10}, {2, 19}, {5, 19}, {10, 19}, {1, 11}, {1, 20}, {3,
20}, {11, 20}, {5, 11}, {5, 21}, {10, 21}, {11, 21}, {3, 11}, {3,
22}, {8, 22}, {11, 22}};
evolp = Map[Graph[
Apply[Rule, #, {1}], GraphLayout -> "SpringElectricalEmbedding",
ImageSize -> 120,
VertexStyle -> ResourceFunction["WolframPhysicsProjectStyleData"][
"SpatialGraph", "VertexStyle"],
EdgeStyle -> ResourceFunction["WolframPhysicsProjectStyleData"][
"SpatialGraph", "EdgeLineStyle"]]& ,
ResourceFunction[
"WolframModel"][{{x, y}, {x, z}} -> {{x, z}, {x, w}, {y, w}, {
z, w}}, initp, 4, "StatesList"]];
evold = MapThread[HighlightGraph[#,
Map[Style[#, Thick, Red]& , #2]]& , {evol,
Map[EdgeList,
MapThread[GraphDifference, {evol, evolp}]]}];
Graph3D[#, ImageSize -> 270,
BaseStyle -> {Graphics3DBoxOptions -> {Method -> {"ShrinkWrap" ->
True}}},
VertexStyle ->
ResourceFunction["WolframPhysicsProjectStyleData"][
"SpatialGraph3D", "VertexStyle"],
EdgeStyle ->
ResourceFunction["WolframPhysicsProjectStyleData"][
"SpatialGraph3D", "EdgeLineStyle"]] & /@ evold[[{2, 3}]]
It takes only a few steps before the effect of the change has spread to essentially all parts of the system. (In this particular case, with the updating order used, about 20% of edges are still unaffected after 5 steps, with the fraction slowly decreasing, even as the number of new edges increases.)
In rules with fairly simple behavior, it is common for changes to remain localized:
sinit = ResourceFunction[
"WolframModel"][{{x, y}} -> {{x, z}, {x, z}, {z, y}}, {{0, 0}}, 2,
"FinalState"];
sinitp = {{0, 2}, {0, 2}, {2, 1}, {0, 3}, {0, 3}, {1, 3}, {1, 4}, {1,
4}, {4, 0}};
sevol = Graph[Rule @@@ #, GraphLayout -> "SpringElectricalEmbedding",
VertexStyle ->
ResourceFunction["WolframPhysicsProjectStyleData"][
"SpatialGraph", "VertexStyle"],
EdgeStyle ->
ResourceFunction["WolframPhysicsProjectStyleData"][
"SpatialGraph", "EdgeLineStyle"] , ImageSize -> 120] & /@
ResourceFunction[
"WolframModel"][{{x, y}} -> {{x, z}, {x, z}, {z, y}}, sinit, 3,
"StatesList"];
sevolp = Graph[Rule @@@ #, GraphLayout -> "SpringElectricalEmbedding",
VertexStyle ->
ResourceFunction["WolframPhysicsProjectStyleData"][
"SpatialGraph", "VertexStyle"],
EdgeStyle ->
ResourceFunction["WolframPhysicsProjectStyleData"][
"SpatialGraph", "EdgeLineStyle"], ImageSize -> 120] & /@
ResourceFunction[
"WolframModel"][{{x, y}} -> {{x, z}, {x, z}, {z, y}}, sinitp, 3,
"StatesList"];
MapThread[
HighlightGraph[#, Style[#, Thick, Red] & /@ #2] &, {sevol,
EdgeList /@ MapThread[GraphDifference, {sevol, sevolp}]}]
However, when complex behavior occurs, changes tend to spread. This is analogous to what is seen, for example, in the much simpler case of class 2 versus class 3 cellular automata [31][1:6.3]:
With[{u = RandomInteger[1, 100]}, SeedRandom[24245];
ArrayPlot[
Sum[(2 + (-1)^i) CellularAutomaton[#, ReplacePart[u, 50 -> i],
50], {i, 0, 1}],
ColorRules -> {0 -> White, 4 -> Black, 1 -> Red, 3 -> Red},
ImageSize -> 150]] & /@ {78, 94, 22, 30}
Cellular automata are also known [31] to exhibit the important phenomenon of class 4 behavior—in which there is a discrete set of localized “particle-like” structures through which changes typically propagate:
SeedRandom[24246]; Table[
With[{u = RandomInteger[1, 400]},
ArrayPlot[
Sum[(2 + (-1)^i) CellularAutomaton[110, ReplacePart[u, 200 -> i],
300], {i, 0, 1}],
ColorRules -> {0 -> White, 4 -> Black, 1 -> Red, 3 -> Red},
ImageSize -> 280]], 2]
In cellular automata, there is a fixed lattice on which local rules operate, making it straightforward [1:6.3] to identify the region that can in principle be affected by a change in initial conditions. In the models here, however, everything is dynamic, and so even the question of what parts can in principle be affected by a change in initial conditions is nontrivial.
As we will discuss at length later, however, it is always possible to trace which updating events in a particular evolution depend on which others, and which relations are associated with these. The result will always be a superset of the actual effect of a change in the initial condition:
WolframModelCausalCones[function_, evolution_,
startGeneration_Integer, endGeneration_Integer,
eventChoiceFunction_ : RandomChoice] :=
Module[{startEvent, finalGenerationEvents, toHighlight,
positiveStartGeneration,
positiveEndGeneration}, {positiveStartGeneration,
positiveEndGeneration} =
If[# >= 0, #,
evolution["TotalGenerationsCount"] + # +
1] & /@ {startGeneration, endGeneration};
startEvent =
eventChoiceFunction[
First /@
Position[evolution["AllEventsGenerationsList"],
positiveStartGeneration]];
finalGenerationEvents =
Prepend[0]@Accumulate@evolution["GenerationEventsCountList"];
toHighlight =
First /@
Position[evolution["EdgeCreatorEventIndices"],
Alternatives @@
VertexOutComponent[evolution["CausalGraph"], startEvent]];
function[evolution["AllEventsEdgesList"][[#]],
evolution["AllEventsEdgesList"][[
Intersection[#, toHighlight]]]] & /@ (evolution[
"StateEdgeIndicesAfterEvent", #] &) /@
finalGenerationEvents[[
positiveStartGeneration + 1 ;; positiveEndGeneration + 1]]]
WolframModelCausalConeSlices[evolution_, startGeneration_Integer : -4,
endGeneration_Integer : -1, eventChoiceFunction_ : RandomChoice] :=
WolframModelCausalCones[
ResourceFunction["WolframModelPlot"][#1, GraphHighlight -> #2,
ImageSize -> 120, GraphHighlightStyle -> Directive[Red, Thick]] &,
evolution, startGeneration, endGeneration,
eventChoiceFunction]; SeedRandom[4247]; \
WolframModelCausalConeSlices[
ResourceFunction[
"WolframModel"][{{x, y}, {x, z}} -> {{x, z}, {x, w}, {y, w}, {z,
w}}, {{0, 0}, {0, 0}}, 9], -5, -1]
We discussed above the quantity Vr(X) obtained by “statically” looking at the number of nodes in a hypergraph reached by going graph distance r—in effect computing the volume of a ball of radius r in the hypergraph. By looking at the dependence of updating events in t successive steps of evolution, we can define another quantity Ct(X) which in effect measures the volume of a cone of dependencies in the evolution of the system.
Vr(X) is in a sense a quantity that is “applied” to the system from outside; Ct(X) is in a sense intrinsic. But as we will discuss later, Vr(X) is in some sense an approximation to Ct(X)—and particularly when we can reasonably consider the evolution of a model to have reached some kind of “equilibrium”, Vr(X) will provide a useful characterization of the “state” of a model.