diff --git a/Research/ConfluenceAndCausalInvariance/ConfluenceAndCausalInvariance.md b/Research/ConfluenceAndCausalInvariance/ConfluenceAndCausalInvariance.md
index 5d4bf2eb1..2a47c21bb 100644
--- a/Research/ConfluenceAndCausalInvariance/ConfluenceAndCausalInvariance.md
+++ b/Research/ConfluenceAndCausalInvariance/ConfluenceAndCausalInvariance.md
@@ -67,7 +67,12 @@ WolframModel[{{{1, 1, 2}} -> {{1, 1, 3}, {3, 3, 2}}, {{1, 2,
```
-->
-
+
On the other hand, *confluence* has to do with the symmetries between expressions' contents. It requires that particular
states from different branches are isomorphic as hypergraphs, regardless of the causal structures that lead to them:
@@ -125,7 +130,12 @@ Module[{leftBranch, rightBranch}, Graph[Join[
```
-->
-
+
## Confluence !=> Causal Invariance
@@ -144,7 +154,9 @@ In[] := ResourceFunction["MultiwaySystem"][
"WolframModel" -> {confluentRule}, {confluentInit}, 2, "StatesGraph", VertexSize -> 1]
```
-
+
However, this system is not causal invariant. We can generate two non-isomorphic causal graphs by using different event
ordering functions, which contradicts the definition above:
@@ -155,7 +167,9 @@ In[] := IsomorphicGraphQ @@ Echo @ (
"CausalGraph"] & /@ {"OldestEdge", "NewestEdge"})
```
-
+
```wl
Out[] = False
@@ -189,7 +203,9 @@ In[] := WolframModel[
"ExpressionsEventsGraph", VertexLabels -> Automatic]
```
-
+
These two events correspond to two different singleway evolutions terminating at states `{{1}, {1}}` and `{{1}, {2}}`,
respectively:
@@ -199,7 +215,12 @@ In[] := WolframModel[causalInvariantRule, causalInvariantInit, Infinity, "EventO
"ExpressionsEventsGraph", VertexLabels -> Placed[Automatic, After]] & /@ {"RuleOrdering", "ReverseRuleOrdering"}
```
-
+
These evolutions yield isomorphic causal graphs, which are composed of a single vertex with no edges, implying that this
system is causal invariant by definition:
@@ -210,7 +231,9 @@ In[] := IsomorphicGraphQ @@ Echo @ (
{"RuleOrdering", "ReverseRuleOrdering"})
```
-
+
```wl
Out[] = True
@@ -224,7 +247,9 @@ In[] := ResourceFunction["MultiwaySystem"][
"WolframModel" -> {causalInvariantRule}, {causalInvariantInit}, 2, "StatesGraph", VertexSize -> .7]
```
-
+
Therefore, causal invariance *does not imply* confluence.
diff --git a/Research/LocalMultiwaySystem/LocalMultiwaySystem.md b/Research/LocalMultiwaySystem/LocalMultiwaySystem.md
index 7d455a7b2..81b07c79a 100644
--- a/Research/LocalMultiwaySystem/LocalMultiwaySystem.md
+++ b/Research/LocalMultiwaySystem/LocalMultiwaySystem.md
@@ -49,7 +49,9 @@ Specifically, let's start with a rule that moves a "particle" (a unary expressio
In[] := RulePlot[WolframModel[{{1}, {1, 2}} -> {{1, 2}, {2}}]]
```
-
+
If we run this system on a path graph with 3 vertices, we get a very simple behavior:
@@ -59,7 +61,11 @@ In[] := ResourceFunction["MultiwaySystem"][
2}, {2, 3}}}, 3, "StatesGraph", VertexSize -> 1]
```
-
+
Now, what happens if we split the path in this graph into two different branches? In this case, the rules will lead to
nondeterministic behavior—multiple choices of substitutions are possible—so the system explores all possible
@@ -72,7 +78,11 @@ In[] := ResourceFunction["MultiwaySystem"][
GraphLayout -> "LayeredDigraphEmbedding"]
```
-
+
Now the states graph itself splits into two branches, mirroring precisely the input graph.
@@ -89,7 +99,12 @@ In[] := ResourceFunction["MultiwaySystem"][
VertexSize -> 1, GraphLayout -> "LayeredDigraphEmbedding"]
```
-
+
This is why our original graph uses branches of different lengths (`{{2, 3}}` and `{{2, 4}, {4, 5}}`).
@@ -108,7 +123,14 @@ In[] := ResourceFunction["MultiwaySystem"][
1}, {7, 2}}}]
```
-
+
Note that even at the first step, the system branches in two different states. However, there is no ambiguity. The two
events there occur at entirely different places in space. Note also that some events are duplicated. For example, the
@@ -140,7 +162,22 @@ In[] := ResourceFunction["MultiwaySystem"]["WolframModel" -> #1, {#2}, 2,
{{{{1, 2}} -> {{1, 2, 3}}}, {{1, 2}, {2, 3}}}}
```
-
+
## Local Multiway System
@@ -220,7 +257,9 @@ In[] := WolframModel[<|"PatternRules" -> {{{1, 2}} -> {{2, 3}},
VertexLabels -> Placed[Automatic, After]]
```
-
+
In this case we have two rules, `{{1, 2}} -> {{2, 3}}` and `{{1, 2}, {2, 3}} -> {{1, 2, 3}}`. Note that here `1`, `2`
and `3` are not patterns but labeled vertices. We have started with an initial condition, which is a single
@@ -252,7 +291,16 @@ In[] := WolframModel[<|"PatternRules" -> {{{1, 2}} -> {{2, 3}},
VertexLabels -> Placed[Automatic, Before]]
```
-
+
The match-all system will match branchlike events as well, as can be seen in the following example:
@@ -264,7 +312,11 @@ In[] := WolframModel[<|"PatternRules" -> {{{1, 2}} -> {{2, 3}},
VertexLabels -> Placed[Automatic, After]]
```
-
+
Note in the above there are two possibilities to match `{{1, 2}}`, which are incompatible according to the ordinary
[`WolframModel`](/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/WolframModelAndWolframModelEvolutionObject.md)
@@ -312,7 +364,20 @@ In[] := WolframModel[#1, #2, 2, "EventSelectionFunction" -> None][
FrameStyle -> LightGray] & /@ # &)
```
-
+
Note that the vertex `{2, 3}` in the first example has an out-degree of 2, which indicates the multiway branching. Also
note that the second example's events are entirely disconnected, as there are no causal connections between them. In
@@ -348,7 +413,13 @@ In[] := Framed[WolframModel[<|"PatternRules" -> #|>, {{1, 2}}, Infinity,
{{{1, 2}} -> {{2, 3}}, {{2, 3}} -> {{3, 4}}}}
```
-
+
In the first example, a single event produces two expressions, `{2, 3}` *and* `{3, 4}`. This corresponds to a spacelike
separation, as both of these expressions can appear simultaneously in a singleway system. In the second example, there
@@ -370,7 +441,13 @@ In[] := WolframModel[<|
VertexLabels -> Placed[Automatic, After]]
```
-
+
In this example, the expression `{1, 2}` first branches into two expressions `{2, 3}` and `{3, 4}`. They are then merged
by the third event, which creates two expressions, `{4, 5}` and `{5, 6}`. In that case, the final expressions `{4, 5}`
@@ -388,7 +465,14 @@ In[] := WolframModel[<|"PatternRules" -> {{{v, i}} -> {{v, 1}, {v, 2}},
VertexLabels -> Placed[Automatic, After]]
```
-
+
What is the separation between the expressions `{v, f, 1}` and `{v, f, 2}`? On one hand, they are spacelike separated,
because one of their common ancestors is the event
@@ -434,7 +518,9 @@ In[] := HypergraphPlot[{{a1}, {a1, a2}, {a2, a3}, {a3, m1}, {b1}, {b1,
b2}, {b2, m1}, {m1, m2}}, VertexLabels -> Automatic]
```
-
+
Instead of a mesh of redundant events that the global multiway system produced, we now only have two places where the
events merge:
@@ -448,7 +534,15 @@ In[] := WolframModel[{{1}, {1, 2}} -> {{1, 2}, {2}},
VertexLabels -> Automatic, ImageSize -> 400]
```
-
+
It is perhaps easier to see in a different layout:
@@ -462,7 +556,16 @@ In[] := WolframModel[{{1}, {1, 2}} -> {{1, 2}, {2}},
GraphLayout -> "SpringElectricalEmbedding", ImageSize -> 600]
```
-
+
If we look closely at the events near the merge points, we can see that some redundancy remains. However, it is no
longer due to the spacelike-separated events, but rather due to the "background" expressions being rewritten during
@@ -496,7 +599,14 @@ In[] := ResourceFunction["MultiwaySystem"][
EdgeStyle -> Automatic]
```
-
+
The current implementation of the local multiway system does not do that, however:
@@ -509,7 +619,17 @@ In[] := WolframModel[{{{1}} -> {{1, 2, 3}},
VertexLabels -> Automatic]
```
-
+
It would be interesting to introduce isomorphism testing to the local multiway system, as it will allow for a much
better understanding of how branches combine at the local level. This isomorphism testing can be done by starting with a
@@ -540,7 +660,15 @@ In[] := Graph[{{1} -> 1, {1} -> 2, 1 -> {1, 2, 3}, {1, 2, 3} -> 3,
"ExpressionVertexStyle"}, {_Integer, "EventVertexStyle"}})]
```
-
+
However, looking at even this simple example, we can determine that the algorithm described above is not quite right;
e.g., consider the last two expressions, `{1, 2, 3, 4}` and `{1, 3, 2, 4}`. On the one hand, if we start all the way