An event A causes an event B if there exists an expression (set element) created by A and destroyed by **
B**. If we then consider all such relationships between events, we create a "CausalGraph"
. In a causal graph,
vertices correspond to events, and edges correspond to the set elements (aka spatial edges).
To make it even more explicit, we have another property, "ExpressionsEventsGraph"
. In this graph, there are two
types of vertices corresponding to events and expressions, and edges correspond to a given expression being an input or
an output of a given event.
For example, if we consider our simple arithmetic model {a_, b_} :> a + b
starting from {3, 8, 8, 8, 2, 10, 0, 9, 7}
we get an expressions-events graph which quite clearly describes what's going on:
In[] := WolframModel[<|"PatternRules" -> {a_, b_} :> a + b|>,
{3, 8, 8, 8, 2, 10, 0, 9, 7}, Infinity]["ExpressionsEventsGraph",
VertexLabels -> Placed[Automatic, After]]
The causal graph is very similar, it just has the expression-vertices contracted:
In[] := WolframModel[<|"PatternRules" -> {a_, b_} :> a + b|>,
{3, 8, 8, 8, 2, 10, 0, 9, 7}, Infinity, "CausalGraph"]
Here is an example for a hypergraph model (admittedly considerably harder to understand). Multiedges correspond to situations where multiple set elements were both created and destroyed by the same pair of events:
In[] := WolframModel[{{1, 2, 3}, {4, 5, 6}, {1, 4}} ->
{{3, 7, 8}, {9, 2, 10}, {11, 12, 5}, {13, 14, 6}, {7, 12}, {11,
9}, {13, 10}, {14, 8}},
{{1, 1, 1}, {1, 1, 1}, {1, 1}, {1, 1}, {1, 1}}, 20, "CausalGraph"]
"LayeredCausalGraph"
generates the same graph but layers events generation-by-generation. For example, in our
arithmetic causal graph, note how it's arranged differently from an example above:
In[] := WolframModel[<|"PatternRules" -> {a_, b_} :> a + b|>,
{3, 8, 8, 8, 2, 10, 0, 9, 7}, Infinity, "LayeredCausalGraph"]
Note how slices through the expressions-events graph correspond to states returned by "StatesList"
. Pay
attention to intersections of the slices with edges as well, as they correspond to unused expressions from previous
generations that remain in the state:
In[] := With[{evolution =
WolframModel[<|"PatternRules" -> {a_, b_} :> a + b|>,
{3, 8, 8, 8, 2, 10, 0, 9, 7}, Infinity]},
evolution["ExpressionsEventsGraph",
VertexLabels -> Placed[Automatic, {After, Above}],
Epilog -> {Red, Dotted,
Table[Line[{{-10, k}, {10, k}}], {k, 0, 9, 2}]}]]
In[] := WolframModel[<|"PatternRules" -> {a_, b_} :> a + b|>,
{3, 8, 8, 8, 2, 10, 0, 9, 7}, Infinity, "StatesList"]
Out[] = {{3, 8, 8, 8, 2, 10, 0, 9, 7}, {7, 11, 16, 12, 9}, {9, 18, 28}, {28,
27}, {55}}
"ExpressionsEventsGraph"
is particularly useful for multiway systems, as it allows one to immediately see multiway
branching. For example, here the expression-vertex {2}
has the out-degree of 2, which indicates it was used in two
conflicting events, which indicates multiway branching:
In[] := WolframModel[{{1}, {1, 2}} -> {{2}}, {{1}, {1, 2}, {2, 3}, {2, 4}},
Infinity,
"EventSelectionFunction" -> None]["ExpressionsEventsGraph",
VertexLabels -> Placed[Automatic, After]]
"CausalGraph"
, "LayeredCausalGraph"
and "ExpressionsEventsGraph"
properties all
accept Graph
options, as was demonstrated above
with VertexLabels
. Some options have special behavior
for the Automatic
value,
i.e., VertexLabels -> Automatic
in "ExpressionsEventsGraph"
displays the contents of expressions, which are not the
vertex names in that graph (as there can be multiple expressions with the same contents). VertexLabels -> "Index"
, on
the other hand, displays the vertex indices of both expressions and events in the graph:
In[] := WolframModel[{{{x, y}, {x, z}} -> {{x, z}, {x, w}, {y, w}, {z, w}}},
{{0, 0}, {0, 0}}, 2]["ExpressionsEventsGraph", VertexLabels -> "Index"]