The Wolfram Model is a rule-based computational framework in which a system is represented by a hypergraph that evolves through simple, local rewriting rules. Even with simple rules, the model can generate rich, emergent behavior and is used to explore complex systems.

This repository contains a full-featured Elixir implementation of the Wolfram Model, providing:

  • N-pattern hypergraph rewriting rules (any number of input hyperedges)
  • Configurable update orderings and parallel evolution
  • Causal networks tracking rule applications
  • Multiway DAG evolution exploring all possible paths
  • Emergent structure analysis including dimension estimation and conservation laws
  • SVG visualizations for hypergraphs, multiway DAGs, branchial graphs, and geodesic plots

Installation

def deps do
  [
    {:wolfram_model, "~> 1.3.0"}
  ]
end

Key Features

Evolution Rules

  • N-pattern matching — rules with any number of input hyperedges via recursive backtracking
  • Configurable update orderings: :first, :leftmost, :random
  • Parallel evolution via evolve_parallel/1 — applies all non-conflicting matches in one step
  • Fixpoint detection via fixpoint?/1 and evolve_until_fixpoint/3
  • Multiple built-in rule sets: basic_rules/0, :growth, :cellular_automaton, :spacetime
  • Classic Wolfram Physics Project benchmark rules via RuleSet.rule_set(:wolfram, key)
  • Standard rule notation parser/printer via WolframModel.Rule.parse/2 and WolframModel.Rule.to_string/1

Causal Networks

  • Tracks every rule application as an event with parent_ids for O(1) causal lookup
  • Builds causal relationships between events
  • Exports causal graph via export_event_graph/1 and causal_network_data/1
  • Computes spacelike foliations (layers of causally independent events) via foliations/1
  • Checks causal invariance (confluence) via causally_invariant?/2 — tests both overlapping pairs (Church-Rosser) and non-overlapping pairs (commutativity)

Multiway Evolution

  • Explores all possible rule applications
  • multiway_explore/2 — branching evolution tree
  • multiway_explore_dag/2 — proper DAG where converging branches share nodes
  • Builds the branchial graph of conflicting branches via branchial_graph/1

Emergent Structure Analysis

  • Measures complexity, growth rates, clustering
  • Estimates effective spatial dimension via hypergraph geodesic ball growth (Analytics.estimate_dimension/1)
  • Estimates Ricci scalar curvature from the next-order ball-growth correction (Analytics.estimate_ricci_scalar/1) — positive for sphere-like, negative for hyperbolic-like geometries
  • Detects conserved quantities (vertex count, edge count, total degree and their parities) via Analytics.detect_conserved_quantities/1
  • Uses an information-theoretic approach to measure spatial coherence (Correlation Length)
  • Analyzes diameter and connectivity patterns

Visualization

  • HypergraphSVG.to_svg/2 — force-directed layout of a hypergraph; binary edges as directed arrows, N-ary edges as translucent polygons
  • HypergraphSVG.evolution_to_svg/2 — horizontal strip of panels showing every generation
  • MultiwayGraphSVG.to_svg/2 — hierarchical DAG layout of multiway evolution; nodes labelled with vertex/edge counts
  • BranchialGraphSVG.to_svg/2 — circular layout of conflicting rule matches with rule-name legend
  • GeodesicPlotSVG.to_svg/2 — dual-panel chart: linear V(r) vs r and log-log with best-fit dimension slope
  • CausalGraphSVG.to_svg/1 — generation-layered causal event graph

Rule Analysis

  • RuleAnalysis.reversible?/1 — checks structural reversibility
  • RuleAnalysis.self_complementary?/1 — checks pattern/replacement symmetry
  • RuleAnalysis.introduces_new_vertices?/1 — detects vertex-generating rules
  • RuleAnalysis.hyperedge_delta/1 — net hyperedge count change per application
  • RuleAnalysis.arity/1 — hyperedge size signature of a rule
  • RuleAnalysis.canonical_form/1 — normalises variable names in first-appearance order
  • RuleAnalysis.equivalent?/2 — checks if two rules are isomorphic up to variable renaming

Example Usage

# Create a simple universe
universe = WolframModel.Example.simple_universe()

# Evolve it for 10 steps (default :first ordering)
evolved = WolframModel.evolve_steps(universe, 10)

# Use leftmost or random ordering
WolframModel.evolve_step(universe, ordering: :leftmost)
WolframModel.evolve_step(universe, ordering: :random)

# Apply all non-conflicting matches in one parallel step
WolframModel.evolve_parallel(universe)

# Evolve until no rules apply (fixpoint)
final = WolframModel.evolve_until_fixpoint(universe)
WolframModel.fixpoint?(final)  # => true

# Analyze what emerged
WolframModel.print_stats(evolved)

# Explore multiway evolution as a tree...
multiway_tree = WolframModel.multiway_explore(universe, 3)

# ...or as a proper DAG where converging branches share nodes
dag = WolframModel.multiway_explore_dag(universe, 3)
# dag.nodes :: %{canonical_key => %WolframModel{}}
# dag.edges :: MapSet of {from_key, to_key}

# Analyze causality
causality = WolframModel.Analytics.analyze_causality(evolved)

# Compute spacelike foliations
layers = WolframModel.foliations(evolved)

# Explore the branchial graph of conflicting branches
bg = WolframModel.branchial_graph(universe)

# Check causal invariance (tests both overlapping and non-overlapping pairs)
WolframModel.causally_invariant?(universe)
WolframModel.causally_invariant?(universe, 3)  # depth-3 Church-Rosser check

# Estimate the emergent spatial dimension (uses hypergraph geodesics)
dim = WolframModel.Analytics.estimate_dimension(evolved.hypergraph)

# Estimate Ricci scalar curvature (positive → sphere-like, negative → hyperbolic)
r_scalar = WolframModel.Analytics.estimate_ricci_scalar(evolved.hypergraph)

# Detect conserved quantities across evolution history
conserved = WolframModel.Analytics.detect_conserved_quantities(evolved)
# => %{conserved: [:edge_count_parity, ...], vertex_count_history: [...], ...}

# Use classic Wolfram Physics Project benchmark rules
rules = WolframModel.RuleSet.rule_set(:wolfram, :rule_1)

# Parse rules from standard Wolfram notation
rule = WolframModel.Rule.parse("{{1,2},{1,3}} -> {{2,3},{1,4}}")
WolframModel.Rule.to_string(rule)
# => "{{1,2},{1,3}} -> {{2,3},{1,4}}"

# Inspect rule properties
alias WolframModel.RuleAnalysis
RuleAnalysis.reversible?(rule)
RuleAnalysis.introduces_new_vertices?(rule)
RuleAnalysis.hyperedge_delta(rule)
RuleAnalysis.canonical_form(rule)
RuleAnalysis.equivalent?(rule_a, rule_b)

# SVG visualizations
alias WolframModel.{HypergraphSVG, MultiwayGraphSVG, BranchialGraphSVG, GeodesicPlotSVG, CausalGraphSVG}

# Render the current hypergraph
evolved.hypergraph
|> HypergraphSVG.to_svg(title: "Step #{evolved.generation}")
|> then(&File.write!("hypergraph.svg", &1))

# Render the full evolution as a strip of panels
evolved
|> HypergraphSVG.evolution_to_svg(max_snapshots: 8, panel_size: 200)
|> then(&File.write!("evolution.svg", &1))

# Render the multiway DAG
dag = WolframModel.multiway_explore_dag(universe, 3)
dag
|> MultiwayGraphSVG.to_svg()
|> then(&File.write!("multiway.svg", &1))

# Render the branchial graph
WolframModel.branchial_graph(universe)
|> BranchialGraphSVG.to_svg(title: "Branchial graph")
|> then(&File.write!("branchial.svg", &1))

# Render the causal graph
evolved
|> WolframModel.causal_network_data()
|> CausalGraphSVG.to_svg()
|> then(&File.write!("causal.svg", &1))

# Render the geodesic ball growth plot with dimension estimate
evolved.hypergraph
|> GeodesicPlotSVG.to_svg(seeds: 5, title: "Geodesic dimension")
|> then(&File.write!("geodesic.svg", &1))

Interactive Livebook

For a step-by-step guided tour — including theory, worked examples, visualisations, and curvature analysis — open wolfram_model.livemd in Livebook:

livebook server wolfram_model.livemd

The notebook covers:

  1. Wolfram Physics background and core concepts
  2. Building and evolving universes
  3. Update orderings and parallel evolution
  4. Causal networks, foliations, and causal invariance
  5. Multiway evolution and branchial graphs
  6. Emergent spatial dimension and Ricci scalar curvature
  7. Classic Wolfram benchmark rules
  8. Rule analysis and conservation law detection

References