Basic Examples (5)

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

({{"[◼]", "TraceCausalGraph" }})[(1+(2+3))+(4×5)]

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

({{"[◼]", "TraceCausalGraph" }})[(1+(2+3))+(4×5),"Path"]

Make a path graph of expressions in a trace:

({{"[◼]", "TraceCausalGraph" }})[(1+(2+3))+(4×5),"PathGraph"]

Make a path with interspersed events between expressions:

({{"[◼]", "TraceCausalGraph" }})[(1+(2+3))+(4×5),"PathEventsGraph"]

Add dependency edges between events:

({{"[◼]", "TraceCausalGraph" }})[(1+(2+3))+(4×5),"PathCausalGraph"]

Scope (2)

Trace a more complicated expression:

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

({{"[◼]", "TraceCausalGraph" }})[fib[3]]

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

({{"[◼]", "TraceCausalGraph" }})[FoldList[Plus,0,{1,2,3}]]

({{"[◼]", "TraceCausalGraph" }})[Table[i^2+i,{i,2}],GraphLayout->{"LayeredDigraphEmbedding","Orientation"->Left}]

Options (9)

IncludeInitialEvent (1)

Include an additional event that all events causally depend on:

({{"[◼]", "TraceCausalGraph" }})[2*3+4*5+6*7,"IncludeInitialEvent"->True]

ShowIndices (1)

Show indices of events in evaluation order:

({{"[◼]", "TraceCausalGraph" }})[1+(2+(3+4)),"ShowIndices"->True]

ShowEventOrder (1)

Indicate an actual order of events during evaluation:

({{"[◼]", "TraceCausalGraph" }})[(1+2)+(((3+4))^5),"ShowEventOrder"->True]

ShowPositions (2)

Show positions of subexpression being evaluated:

({{"[◼]", "TraceCausalGraph" }})[1+(2+(3+4)),"ShowPositions"->True]

With side-events having decreasing negative part numbers:

({{"[◼]", "TraceCausalGraph" }})[Nest[f,1,3],"ShowPositions"->True]

ShowExpressions (1)

Instead of the whole expression show only subexpressions under evaluation:

({{"[◼]", "TraceCausalGraph" }})[1+(2+(3+4)),"ShowExpressions"->False]

PruneIdentities (1)

Trivial identity events are pruned by default:

({{"[◼]", "TraceCausalGraph" }})[1+(2+3),"PruneIdentities"->False]

PruneSidePaths (1)

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

f[n_/;n>1]:=f[n-1]

({{"[◼]", "TraceCausalGraph" }})[f[3],"PruneSidePaths"->False]

({{"[◼]", "TraceCausalGraph" }})[f[3],"PathGraph","PruneSidePaths"->True]

({{"[◼]", "TraceCausalGraph" }})[f[3],"PruneSidePaths"->True]

PruneTerminatedEvaluation (1)

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

GraphicsRow[Table[({{"[◼]", "TraceCausalGraph" }})[(1+2)^3,n,"PruneTerminatedEvaluation"->False,PlotLabel->Row[{n,If[n==1,"step","steps"]}," "],GraphLayout->"SpiralEmbedding"],{n,4,12,2}],Frame->All]

Possible Issues (1)

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

ClearAll[f]
SetAttributes[f,Flat]
f[x,a]:=f[a,x]
({{"[◼]", "TraceCausalGraph" }})[f[x,a,a],"PathGraph"]

Neat Examples (4)

Trace a Fibonacci function with memoization:

ClearAll[f]
f[0]=f[1]=1; f[n_]:=f[n]=f[n-1]+f[n-2]

({{"[◼]", "TraceCausalGraph" }})[f[8],"CausalGraphStructure",GraphLayout->"LayeredDigraphEmbedding"]

Make a causal graph of a nested recursive function:

Clear[f]
f[n_]:=f[n-f[n-3]]+f[n-2]
f[n_/;n<1]=1;

({{"[◼]", "TraceCausalGraph" }})[f[5],"CausalGraphStructure"]

({{"[◼]", "TraceCausalGraph" }})[f[5],"CausalGraphStructure",GraphLayout->"LayeredDigraphEmbedding",AspectRatio->2]

Divide-and-conquer factorial:

f[l_List]:=Times@@f/@TakeDrop[l,Quotient[Length[l],2]]
f[{x_}]:=x

({{"[◼]", "TraceCausalGraph" }})[f[Range[10]],"CausalGraphStructure"]

Trace itself:

({{"[◼]", "TraceCausalGraph" }})[({{"[◼]", "TraceCausalGraph" }})[(1+(2+3))+(4×5)],6,"PathCausalGraph"]