Function Resource

Function Repository Resource:

TraceCausalGraph

Source Notebook

Build a causal graph from a trace

Contributed by: Nik Murzin

ResourceFunction["TraceCausalGraph"][expr]

evaluate an expression and return a causal graph of its trace.

ResourceFunction["TraceCausalGraph"][expr,n]

trace only up-to n steps of evaluation.

ResourceFunction["TraceCausalGraph"][expr,n,patt]

prune trace by a specifying a pattern of expressions to include.

ResourceFunction["TraceCausalGraph"][expr, ,"CausalGraph"]

same as above.

ResourceFunction["TraceCausalGraph"][expr, ,"Path"]

return a corresponding path as an interspersed list of HoldComplete expressions and positions.

ResourceFunction["TraceCausalGraph"][expr,,"PathGraph"]

return a corresponding path as a PathGraph.

ResourceFunction["TraceCausalGraph"][expr,,"PathEventsGraph"]

intersperse a path graph with corresponding event vertices.

ResourceFunction["TraceCausalGraph"][expr,,"PathCausalGraph"]

add causal dependency edges to the "PathEventsGraph".

Tracing functions with Flat, Orderless, OneIdentity attributes and other things that lead to non-standard evaluation (like Sequence) is not properly supported.
TraceCausalGraph takes the following options:
"IncludeInitialEvent"Falsewhether to include an additional event that produces original expression
"ShowIndices"Falseshow event indices
"ShowEventOrder"Falseshow evaluation order with a path between events
"ShowPositions"Falseshow event position with negative position indicating internal evaluations
"ShowExpressions"Trueshow complete or partial expressions
"PruneIdentities"Trueprune events that evaluate expression to itself
"PruneSidePaths"Falseprune expressions that do not correspond to any part of original expression
"PruneTerminatedEvaluation"Trueprune expression with TerminatedEvaluation
"EventStyleOptions" Style options for an event
"EventColumnOptions" Column options for before/after part of an event
"EventFrameOptions" Framed options for an event
"SideEventFrameOptions" Framed options for side events
“StateStyleOptions” Style options for a state
“StateFrameOptions” Framed options for a state

Examples

Basic Examples (5) 

Make a causal graph from a standard evaluation of an expression:

In[1]:=
ResourceFunction[
CloudObject[
  "https://www.wolframcloud.com/obj/nikm/DeployedResources/Function/TraceCausalGraph"]][(1 + (2 + 3)) + (4*5)]
Out[1]=

Make a path consisting of intermediate expressions together with subexpression positions being evaluated:

In[2]:=
ResourceFunction[
CloudObject[
  "https://www.wolframcloud.com/obj/nikm/DeployedResources/Function/TraceCausalGraph"]][(1 + (2 + 3)) + (4*5), "Path"]
Out[2]=

Make a path graph of expressions in a trace:

In[3]:=
ResourceFunction[
CloudObject[
  "https://www.wolframcloud.com/obj/nikm/DeployedResources/Function/TraceCausalGraph"]][(1 + (2 + 3)) + (4*5), "PathGraph"]
Out[3]=

Make a path with interspersed events between expressions:

In[4]:=
ResourceFunction[
CloudObject[
  "https://www.wolframcloud.com/obj/nikm/DeployedResources/Function/TraceCausalGraph"]][(1 + (2 + 3)) + (4*5), "PathEventsGraph"]
Out[4]=

Add dependency edges between events:

In[5]:=
ResourceFunction[
CloudObject[
  "https://www.wolframcloud.com/obj/nikm/DeployedResources/Function/TraceCausalGraph"]][(1 + (2 + 3)) + (4*5), "PathCausalGraph"]
Out[5]=

Trace a more complicated expression:

In[6]:=
ClearAll[fib]
fib[n_] := fib[n - 1] + fib[n - 2]
fib[0 | 1] = 1;

ResourceFunction[
CloudObject[
  "https://www.wolframcloud.com/obj/nikm/DeployedResources/Function/TraceCausalGraph"]][fib[3]]
Out[7]=

Tracing internal functions would result in side-events (indicated by a dashed boundary):

In[8]:=
ResourceFunction[
CloudObject[
  "https://www.wolframcloud.com/obj/nikm/DeployedResources/Function/TraceCausalGraph"]][FoldList[Plus, 0, {1, 2, 3}]]
Out[8]=
In[9]:=
ResourceFunction[
CloudObject[
  "https://www.wolframcloud.com/obj/nikm/DeployedResources/Function/TraceCausalGraph"]][Table[i^2 + i, {i, 2}], GraphLayout -> {"LayeredDigraphEmbedding", "Orientation" -> Left}]
Out[9]=

Include an additional event that all events causally depend on:

In[10]:=
ResourceFunction[
CloudObject[
  "https://www.wolframcloud.com/obj/nikm/DeployedResources/Function/TraceCausalGraph"]][2*3 + 4*5 + 6*7, "IncludeInitialEvent" -> True]
Out[10]=

Show indices of events in evaluation order:

In[11]:=
ResourceFunction[
CloudObject[
  "https://www.wolframcloud.com/obj/nikm/DeployedResources/Function/TraceCausalGraph"]][1 + (2 + (3 + 4)), "ShowIndices" -> True]
Out[11]=

Indicate an actual order of events during evaluation:

In[12]:=
ResourceFunction[
CloudObject[
  "https://www.wolframcloud.com/obj/nikm/DeployedResources/Function/TraceCausalGraph"]][(1 + 2) + (3 + 4)^5, "ShowEventOrder" -> True]
Out[12]=

Show positions of subexpression being evaluated:

In[13]:=
ResourceFunction[
CloudObject[
  "https://www.wolframcloud.com/obj/nikm/DeployedResources/Function/TraceCausalGraph"]][1 + (2 + (3 + 4)), "ShowPositions" -> True]
Out[13]=

With side-events having decreasing negative part numbers:

In[14]:=
ResourceFunction[
CloudObject[
  "https://www.wolframcloud.com/obj/nikm/DeployedResources/Function/TraceCausalGraph"]][Nest[f, 1, 3], "ShowPositions" -> True]
Out[14]=

Instead of the whole expression show only subexpressions under evaluation:

In[15]:=
ResourceFunction[
CloudObject[
  "https://www.wolframcloud.com/obj/nikm/DeployedResources/Function/TraceCausalGraph"]][1 + (2 + (3 + 4)), "ShowExpressions" -> False]
Out[15]=

Trivial identity events are pruned by default:

In[16]:=
ResourceFunction[
CloudObject[
  "https://www.wolframcloud.com/obj/nikm/DeployedResources/Function/TraceCausalGraph"]][1 + (2 + 3), "PruneIdentities" -> False]
Out[16]=

Prune side-paths from a trace PathGraph and corresponding events:

In[17]:=
f[n_ /; n > 1] := f[n - 1]
In[18]:=
ResourceFunction[
CloudObject[
  "https://www.wolframcloud.com/obj/nikm/DeployedResources/Function/TraceCausalGraph"]][f[3], "PruneSidePaths" -> False]
Out[18]=
In[19]:=
ResourceFunction[
CloudObject[
  "https://www.wolframcloud.com/obj/nikm/DeployedResources/Function/TraceCausalGraph"]][f[3], "PathGraph", "PruneSidePaths" -> True]
Out[19]=
In[20]:=
ResourceFunction[
CloudObject[
  "https://www.wolframcloud.com/obj/nikm/DeployedResources/Function/TraceCausalGraph"]][f[3], "PruneSidePaths" -> True]
Out[20]=

Terminating after non-terminal amount of steps results in TerminatedEvaluation inside of the last event:

In[21]:=
GraphicsRow[Table[ResourceFunction[
CloudObject[
    "https://www.wolframcloud.com/obj/nikm/DeployedResources/Function/TraceCausalGraph"]][(1 + 2)^3, n, "PruneTerminatedEvaluation" -> False, PlotLabel -> Row[{n, If[n == 1, "step", "steps"]}, " "], GraphLayout -> "SpiralEmbedding"], {n, 4, 12, 2}], Frame -> All]
Out[21]=

Non-standard evaluation, like flattening of Flat subexpressions results in incorrect reconstruction of intermediate expressions:

In[22]:=
ClearAll[f]
SetAttributes[f, Flat]
f[x, a] := f[a, x]
ResourceFunction[
CloudObject[
  "https://www.wolframcloud.com/obj/nikm/DeployedResources/Function/TraceCausalGraph"]][f[x, a, a], "PathGraph"]
Out[23]=

Trace a Fibonacci function with memoization:

In[24]:=
ClearAll[f]
f[0] = f[1] = 1; f[n_] := f[n] = f[n - 1] + f[n - 2]
In[25]:=
ResourceFunction[
CloudObject[
  "https://www.wolframcloud.com/obj/nikm/DeployedResources/Function/TraceCausalGraph"]][f[8], "CausalGraphStructure", GraphLayout -> "LayeredDigraphEmbedding"]
Out[25]=

Make a causal graph of a nested recursive function:

In[26]:=
Clear[f]
f[n_] := f[n - f[n - 3]] + f[n - 2]
f[n_ /; n < 1] = 1;
In[27]:=
ResourceFunction[
CloudObject[
  "https://www.wolframcloud.com/obj/nikm/DeployedResources/Function/TraceCausalGraph"]][f[5], "CausalGraphStructure"]
Out[27]=
In[28]:=
ResourceFunction[
CloudObject[
  "https://www.wolframcloud.com/obj/nikm/DeployedResources/Function/TraceCausalGraph"]][f[5], "CausalGraphStructure", GraphLayout -> "LayeredDigraphEmbedding", AspectRatio -> 2]
Out[28]=

Divide-and-conquer factorial:

In[29]:=
f[l_List] := Times @@ f /@ TakeDrop[l, Quotient[Length[l], 2]]
f[{x_}] := x
In[30]:=
ResourceFunction[
CloudObject[
  "https://www.wolframcloud.com/obj/nikm/DeployedResources/Function/TraceCausalGraph"]][f[Range[10]], "CausalGraphStructure"]
Out[30]=

Trace itself:

In[31]:=
ResourceFunction[
CloudObject[
  "https://www.wolframcloud.com/obj/nikm/DeployedResources/Function/TraceCausalGraph"]][ResourceFunction[
CloudObject[
   "https://www.wolframcloud.com/obj/nikm/DeployedResources/Function/TraceCausalGraph"]][(1 + (2 + 3)) + (4*5)], 6, "PathCausalGraph"]
Out[31]=