A Class of Models with the Potential to Represent Fundamental Physics
  1. Introduction
  2. Basic Form of Models
  3. Typical Behaviors
  4. Limiting Behavior and Emergent Geometry
  5. The Updating Process for String Substitution Systems
  6. The Updating Process in Our Models
  7. Equivalence and Computation in Our Models
  8. Potential Relation to Physics
  9. Additional Material
  10. References
  11. Index

7.1 Correspondence with Other Systems

Our goal with the models introduced here is to have systems that are intrinsically as structureless as possible, and are therefore in a sense as flexible and general as possible. And one way to see how successful we have been is to look at what is involved in reproducing other systems using our models.

As a first example, consider the case of string substitution systems (e.g [1:3.5]). An obvious way to represent a string is to use a sequence of relations to set up what amounts to a linked list. The “payload” at each node of the linked list is an element of the string. If one has two kinds of string elements A and B, these can for example be represented respectively by 3-ary and 4-ary relations. Thus, for example, the string ABBAB could be (where the Bs can be identified from the “inner self-loops” in their 4-ary relations):

CloudGet["https://wolfr.am/KVyKN5CW"] ;StringToWMSet["ABBAB"]
CloudGet["https://wolfr.am/KVyKN5CW"] ;ResourceFunction["WolframModelPlot"][StringToWMSet["ABBAB"], VertexLabels -> Automatic]

Note that the labels of the elements and the order of relations are not significant, so equivalent forms are

CloudGet["https://wolfr.am/KVyKN5CW"] ;CanonicalCollection[coll_List] := coll /. Thread[# -> Range[Length[#]]] &[Union[Flatten[coll]]] CanonicalCollection[StringToWMSet["ABBAB"]]

or, with our standard canonicalization:

CloudGet["https://wolfr.am/KVyKN5CW"] ;CanonicalCollection[coll_List] := coll /. Thread[# -> Range[Length[#]]] &[Union[Flatten[coll]]] ResourceFunction["FindCanonicalHypergraph"][ CanonicalCollection[StringToWMSet["ABBAB"]]]

A rule like

{"A" -> "BA", "B" -> "A"}

can then be translated to

CloudGet["https://wolfr.am/KVyKN5CW"] ;StringRuleToWMRule[{"A" -> "BA", "B" -> "A"}]

or:

CloudGet["https://wolfr.am/KVyKN5CW"] ;CanonicalRules[ lhs_ -> rhs_] := (lhs -> rhs) /. Thread[# -> Range[Length[#]]] &[ Union[Flatten[{lhs, rhs}]]] CanonicalRules[rules_List] := CanonicalRules /@ rules ResourceFunction["CanonicalWolframModelRule"][ CanonicalRules[ StringRuleToWMRule[{"A" -> "BA", "B" -> "A"}]], "Letter"]

Starting with A, the original rule gives:

SubstitutionSystem[{"A" -> "BA", "B" -> "A"}, "A", 6]

In terms of our translation, this is now:

CloudGet["https://wolfr.am/KVyKN5CW"] ;ResourceFunction["WolframModel"][ StringRuleToWMRule[{"A" -> "BA", "B" -> "A"}], StringToWMSet["A"], 6, "StatesPlotsList"]

The causal graph for the rule in effect shows the dependence of the string elements

CloudGet["https://wolfr.am/KVyKN5CW"] ;ResourceFunction["WolframModel"][ StringRuleToWMRule[{"A" -> "BA", "B" -> "A"}], StringToWMSet["A"], 6, "CausalGraph"]

corresponding to the evolution graph (see 5.1):

ResourceFunction["SubstitutionSystemPlot"][{"A" -> {"B"}, "B" -> {"A", "B"}}, {"A"}, 6]

We can also take our translation of the string substitution system, and use it in a multiway system:

CloudGet["https://wolfr.am/KVyKN5CW"] ;ResourceFunction["MultiwaySystem"][ "WolframModel" -> StringRuleToWMRule[{"A" -> "BA", "B" -> "A"}], {StringToWMSet[ "A"]}, 5, "StatesGraph", VertexSize -> 1]

The result is a direct translation of what we could get with the underlying string system:

ResourceFunction["MultiwaySystem"][{"A" -> "BA", "B" -> "A"}, "A", 5, "StatesGraph"]

Having seen how our models can reproduce string substitution systems, we consider next the slightly more complex case of reproducing Turing machines [93].

As an example, consider the simplest universal Turing machine [1:p709][94][95] [96], which has the 2-state 3-color rule:

RulePlot[TuringMachine[{596440, 2, 3}]]

Given a tape with the Turing machine head at a certain position

RulePlot[TuringMachine[{596440, 2, 3}], {{1, 4}, {0, 0, 0, 1, 2, 0, 0, 1, 0, 2, 0}}, 0, Mesh -> All, Frame -> None]

a possible encoding uses different-arity hyperedges to represent different values on the tape, and different states for the head, then attaches the head to a certain position on the tape, and uses special (in this case 6-ary) hyperedges to provide “extensible end caps” to the tape:

CloudGet["https://wolfr.am/KVCBnkcw"];ResourceFunction["WolframModelPlot"][ encodeTMState[{1, 4}, {0, 0, 0, 1, 2, 0, 0, 1, 0, 2, 0}], VertexCoordinates -> {1 -> {-12.62218727868862, 0.08961958377754731}, 2 -> {-11.600470452576143`, 0.20437494307342405`}, 3 -> {-10.457663437795505`, 0.34517176486828904`}, 4 -> {-9.22123276332042, 0.5441476966904967}, 5 -> {-7.917198587986488, 0.4707193395536903}, 6 -> {-6.633329003211881, 0.4245381542565931}, 7 -> {-5.370565902404637, 0.3862975127002847}, 8 -> {-4.138681304822544, 0.35176852124229313`}, 9 -> {-2.9529661975006136`, 0.3197747248943611}, 10 -> {-1.8364651707427124`, 0.29024121295138106`}, 11 -> {-0.8256748210271151, 0.2637904460782475}, "leftEnd" -> {-13.451054550991815`, 0.}, "rightEnd" -> {0., 0.24229725022320545`}, $head -> {-9.413370569641202, 1.2647990234280893`}}]

With this setup, the rule can be encoded as:

CloudGet["https://wolfr.am/KVCBnkcw"]; \ RulePlot[ResourceFunction["WolframModel"][#], "RulePartsAspectRatio" -> 1, ImageSize -> 132] & /@ encodeTMRule[{596440, 2, 3}, 0]

Starting from a representation of a blank tape, the first few steps of evolution are (note that the tape is extended as needed)

CloudGet["https://wolfr.am/KVCBnkcw"]; ResourceFunction["WolframModel"][encodeTMRule[{596440, 2, 3}, 0], encodeTMState[{1, 1}, {0}], 8, "StatesPlotsList"]

which corresponds to the first few steps of the Turing machine evolution:

CloudGet["https://wolfr.am/KVCBnkcw"]; \ RulePlot[ TuringMachine[{596440, 2, 3}], decodeTMEvolution[ ResourceFunction["WolframModel"][encodeTMRule[{596440, 2, 3}, 0], encodeTMState[{1, 1}, {0}], 40]], Mesh -> All, Frame -> None]

The causal graph for our model directly reflects the motion of the Turing machine head, as well as the causal connections generated by symbols “remembered” on the tape between head traversals:

CloudGet["https://wolfr.am/KVCBnkcw"]; ResourceFunction["WolframModel"][encodeTMRule[{596440, 2, 3}, 0], encodeTMState[{1, 1}, {0}], 50, "LayeredCausalGraph"]

Re-rendering this causal graph, we see that it begins to form a grid:

CloudGet["https://wolfr.am/KVCBnkcw"]; \ Graph[ResourceFunction["WolframModel"][ encodeTMRule[{596440, 2, 3}, 0], encodeTMState[{1, 1}, {0}], 40, "CausalGraph"], GraphLayout -> "SpringElectricalEmbedding"]

It is notable that even though in the underlying Turing machine only one action happens at each step, the causal graph still connects many events in parallel (cf. [1:p489]). After 1000 steps the graph has become a closer approximation to a flat 2D manifold, with the specific Turing machine evolution reflected in the detailed “knitting” of connections on its surface:

CloudGet["https://wolfr.am/KVCBnkcw"]; ResourceFunction["WolframModel"][encodeTMRule[{596440, 2, 3}, 0], encodeTMState[{1, 1}, {0}], 1000, "CausalGraph"]

The rule we have set up allows only one thread of history, so the multiway system is trivial:

CloudGet["https://wolfr.am/KVCBnkcw"]; ResourceFunction["MultiwaySystem"][ "WolframModel" -> encodeTMRule[{596440, 2, 3}, 0], {encodeTMState[{1, 1}, {0}]}, 5, "StatesGraph", VertexSize -> 1]

But with our model the underlying setup is general enough that it can handle not only ordinary deterministic Turing machines in which each possible case leads to a specific outcome, but also non-deterministic ones (as used in formulating NP problems) (e.g. [97]), in which there are multiple outcomes for some cases:

NKSSpecialFunctions`RulePlot`Dump`ValidTuringMachineRulesQ; PrependTo[ DownValues[ NKSSpecialFunctions`RulePlot`Dump`ValidTuringMachineRulesQ], HoldPattern[ NKSSpecialFunctions`RulePlot`Dump`ValidTuringMachineRulesQ[ args___]] :> True]; RulePlot[ TuringMachine[{{1, 2} -> {1, 1, -1}, {1, 1} -> {1, 2, -1}, {1, 0} -> {2, 1, 1}, {1, 0} -> {2, 1, -1}, {2, 2} -> {1, 0, 1}, {2, 1} -> {2, 2, 1}, {2, 0} -> {1, 2, -1}, {2, 0} -> {1, 2, 1}}]]

For a non-deterministic Turing machine, there can be multiple paths in the multiway system:

CloudGet["https://wolfr.am/KVCBnkcw"]; ResourceFunction["MultiwaySystem"][ "WolframModel" -> encodeTMRule[{{1, 2} -> {1, 1, -1}, {1, 1} -> {1, 2, -1}, {1, 0} -> {2, 1, 1}, {1, 0} -> {2, 1, -1}, {2, 2} -> {1, 0, 1}, {2, 1} -> {2, 2, 1}, {2, 0} -> {1, 2, -1}, {2, 0} -> {1, 2, 1}}, 0], {encodeTMState[{1, 1}, {0}]}, 6, "StatesGraph", VertexSize -> 1]

Continuing this, we see that the non-deterministic Turing machine shows a fairly complex pattern of branching and merging in the multiway system (this particular example is not causal invariant):

tmr = Join[{{1, 2} -> {1, 1, -1}, {1, 1} -> {1, 2, -1}, {2, 2} -> {1, 0, 1}, {2, 1} -> {2, 2, 1}}, #] & /@ Tuples[{{{1, 0} -> {2, 1, 1}, {1, 0} -> {2, 1, -1}}, {{2, 0} -> {1, 2, -1}, {2, 0} -> {1, 2, 1}}}]; LayeredGraphPlot[ VertexReplace[ NestGraph[ h /@ (Through[(TuringMachine /@ tmr)@First[#]]) &, {h[{1, {{}, 0}}]}, 14], h[{{a_, b_, _}, s_}] :> OutputForm[{{a, b}, s}]], AspectRatio -> 1/2, VertexStyle -> ResourceFunction["WolframPhysicsProjectStyleData"]["CausalGraph", "VertexStyle"], EdgeStyle -> ResourceFunction["WolframPhysicsProjectStyleData"]["CausalGraph", "EdgeStyle"]]

After a few more steps, and using a different rendering, the multiway system has the form:

tmr = Join[{{1, 2} -> {1, 1, -1}, {1, 1} -> {1, 2, -1}, {2, 2} -> {1, 0, 1}, {2, 1} -> {2, 2, 1}}, #] & /@ Tuples[{{{1, 0} -> {2, 1, 1}, {1, 0} -> {2, 1, -1}}, {{2, 0} -> {1, 2, -1}, {2, 0} -> {1, 2, 1}}}]; VertexReplace[ NestGraph[ h /@ (Through[(TuringMachine /@ tmr)@First[#]]) &, {h[{1, {{}, 0}}]}, 17, VertexStyle -> ResourceFunction["WolframPhysicsProjectStyleData"]["StatesGraph", "VertexStyle"], EdgeStyle -> ResourceFunction["WolframPhysicsProjectStyleData"]["StatesGraph", "EdgeStyle"]], h[{{a_, b_, _}, s_}] :> OutputForm[{{a, b}, s}]]

(Note that in actually using a non-deterministic Turing machine, say to solve an NP-complete problem, one needs to check the results on each branch of the multiway systemwith different search strategies corresponding to using different foliations in exploring the multiway system.)

As a final example, consider using our models to reproduce cellular automata. Our models are in a sense intended to be as flexible as possible, while cellular automata have a simple but rigid structure. In particular, a cellular automaton consists of a rigid array of cells, with specific, discrete values that are updated in parallel at each step. In our models, on the other hand, there is no intrinsic geometry, no built-in notion of “values”, and different updating events are treated as independent and “asynchronous”, subject only to the partial ordering imposed by causal relations.

In reproducing a Turing machine using our models, we already needed a definite tape that encodes values, but we only had to deal with one action happening at a time, so there was no issue of synchronization. For a cellular automaton, however, we have to arrange for synchronization of updates across all cells. But as we will see, even though our models ultimately work quite differently, there is no fundamental problem in doing this with the models.

For example, given the rule 30 cellular automaton

RulePlot[CellularAutomaton[30]]

we encode a state like

ArrayPlot[{{0, 0, 1, 0, 1, 0}}, Mesh -> All]

in the form

CloudGet["https://wolfr.am/KVFlzzoq"]; ResourceFunction["WolframModelPlot"][ encodeCAState[{0, 0, 1, 0, 1, 0}]]

where the 6-ary self-loops represent black cells. Note that there is a quite complex structure that in effect maintains the cellular automaton array, complete with “extensible end caps” that allow it to grow.

Given this structure, the rule corresponding to the rule 30 cellular automaton becomes

CloudGet["https://wolfr.am/KVFlzzoq"]; \ RulePlot[ResourceFunction["WolframModel"][#], "RulePartsAspectRatio" -> 1, ImageSize -> 132] & /@ encodeCARule[30, 0]

where the first two transformations relate to the end caps, and the remaining 8 actually implement the various cases of the cellular automata rule. Applying the rule for our model for a few steps to an initial condition consisting of a single black cell, we get:

CloudGet["https://wolfr.am/KVFlzzoq"]; ResourceFunction["WolframModel"][encodeCARule[30, 0], encodeCAState[{1}], 6, "StatesPlotsList"]

Each of these steps has information on certain cells in the cellular automaton at a certain step in the cellular automaton evolution. “Decoding” each of the steps in our model shown above, we get the following, in which the “front” of cellular automaton cells whose values are present at that step in our model are highlighted:

CloudGet["https://wolfr.am/KVFlzzoq"]; \ Table[ Pane[Show[ decodeCAEvolution[ ResourceFunction["WolframModel"][encodeCARule[30, 0], encodeCAState[{1}], t], {0 -> Lighter[Red, .9], 1 -> Darker[Red, .5]}], ImageSize -> (2 t + 1) 20], {Automatic, 4*20}, BaselinePosition -> Scaled[.8]], {t, 6}]

The particular foliation we have used to determine the steps in the evolution of our model corresponds to a particular foliation of the evolution of the cellular automaton:

CloudGet["https://wolfr.am/KXgcRNRJ"] ;\ ArrayPlot[CellularAutomaton[30, {{1}, 0}, 15], ColorRules -> {0 -> White, 1 -> Black}, Frame -> None, Epilog -> {Lighter[Red, .3], Thick, Table[Line[arrayPlotFoliationLine[k, 15]], {k, 1, 47, 3}]}]

The final “spacetime” cellular automaton pattern is the same, but the foliation defines a specific order for building it up. We can visualize the way the data flows in the computation by looking at the causal graph (with events forming cells with different colors indicated):

CloudGet["https://wolfr.am/LbiWCbfn"]; Show[caCausalGraph[30, 10, Automatic, Automatic, Epilog -> {Thick, Red, straightFoliationLines[{1/3, 0}, {0, 0}, (# &), {0, -1}]}], ImageSize -> 600]

Here is the foliation of the causal graph that corresponds to each step in a traditional synchronized parallel cellular automaton updating:

CloudGet["https://wolfr.am/LbiWCbfn"]; Show[caCausalGraph[30, 10, Automatic, Automatic, Epilog -> caFoliationLines[10]], ImageSize -> 600]