Wolfram/CodeEquivalenceUtilities

Utilities for testing code equivalence

Contributed By: Richard Hennigan

CodeEquivalenceUtilities is a collection of Wolfram Language functions that can be used to test if different pieces of code are equivalent without the need for evaluation.

This allows comparison of unevaluated expressions that may have non-deterministic outputs (e.g. random values, dates, etc).

This Paclet represents the underlying technology that powers several automated code grading systems, such as the online exercises for EIWL and Wolfram Challenges.

Installation Instructions

To install this paclet in your Wolfram Language environment, evaluate this code:
PacletInstall[ResourceObject["Wolfram/CodeEquivalenceUtilities"]]

Paclet Guide

Examples

Basic Examples (2) 

Check if two expressions are equivalent:

In[1]:=
InterpretationBox[FrameBox[TagBox[TooltipBox[PaneBox[GridBox[List[List[GraphicsBox[List[Thickness[0.006082377284997087`], StyleBox[List[FilledCurveBox[List[List[List[0, 2, 0], List[0, 1, 0], List[0, 1, 0]], List[List[0, 2, 0], List[0, 1, 0], List[0, 1, 0]], List[List[0, 2, 0], List[0, 1, 0], List[0, 1, 0]]], List[List[List[2.78206`, 85.44900000000004`], List[79.17353999999999`, 41.67850000000004`], List[79.17353999999999`, 1.6779000000000508`], List[2.78206`, 45.44840000000002`]], List[List[127.7826`, 115.44898000000003`], List[127.7826`, 26.449000000000012`], List[161.7832`, 47.44780000000006`], List[161.7832`, 135.44923000000003`]], List[List[5.78267`, 141.44910000000004`], List[40.783`, 121.44819000000003`], List[117.7831`, 165.44919000000004`], List[81.37629999999999`, 187.24592000000004`]]]]], List[FaceForm[RGBColor[0.9843139999999999`, 0.662745`, 0.25098000000000004`, 1.`]]], Rule[StripOnInput, False]], StyleBox[List[FilledCurveBox[List[List[List[0, 2, 0], List[0, 1, 0], List[0, 1, 0]], List[List[0, 2, 0], List[0, 1, 0], List[0, 1, 0]], List[List[0, 2, 0], List[0, 1, 0], List[0, 1, 0]]], List[List[List[79.20467000000001`, 90.91309000000003`], List[79.20546`, 48.911800000000056`], List[43.782610000000005`, 69.44830000000003`], List[43.782610000000005`, 111.44764000000002`]], List[List[82.77993`, 137.44809000000004`], List[48.77938`, 117.44782000000004`], List[82.77993`, 97.44923000000004`], List[117.7808`, 117.44782000000004`]], List[List[86.41823000000001`, 90.97696000000002`], List[86.45015000000001`, 48.71930000000003`], List[121.7829`, 70.44880000000003`], List[121.7829`, 112.44819000000003`]]]]], List[FaceForm[RGBColor[0.46274499999999996`, 0.066667`, 0.07451`, 1.`]]], Rule[StripOnInput, False]], StyleBox[List[FilledCurveBox[List[List[List[0, 2, 0], List[0, 1, 0], List[0, 1, 0]], List[List[0, 2, 0], List[0, 1, 0], List[0, 1, 0]], List[List[0, 2, 0], List[0, 1, 0], List[0, 1, 0]]], List[List[List[158.7825`, 141.44910000000004`], List[123.7817`, 121.44886000000004`], List[89.78278999999999`, 141.44910000000004`], List[123.7817`, 161.44770000000003`]], List[List[2.7817600000000002`, 92.44794000000003`], List[37.782610000000005`, 72.44770000000003`], List[37.782610000000005`, 114.44870000000003`], List[2.7817600000000002`, 134.44898000000003`]], List[List[86.45015000000001`, 1.7736000000000445`], List[121.78269999999999`, 23.44920000000002`], List[121.78269999999999`, 63.33730000000003`], List[86.45015000000001`, 41.66350000000003`]]]]], List[FaceForm[RGBColor[1.`, 0.41568600000000006`, 0.054902000000000006`, 1.`]]], Rule[StripOnInput, False]]], List[Rule[BaselinePosition, Scaled[0.15`]], Rule[ImageSize, 10], Rule[ImageSize, List[30, Automatic]]]], StyleBox[RowBox[List["CodeEquivalentQ", " "]], Rule[ShowAutoStyles, False], Rule[ShowStringCharacters, False], Rule[FontSize, Times[0.9`, Inherited]], Rule[FontColor, GrayLevel[0.1`]]]]], Rule[GridBoxSpacings, List[Rule["Columns", List[List[0.25`]]]]]], Rule[Alignment, List[Left, Baseline]], Rule[BaselinePosition, Baseline], Rule[FrameMargins, List[List[3, 0], List[0, 0]]], Rule[BaseStyle, List[Rule[LineSpacing, List[0, 0]], Rule[LineBreakWithin, False]]]], RowBox[List["PacletSymbol", "[", RowBox[List["\"Wolfram/CodeEquivalenceUtilities\"", ",", "\"CodeEquivalentQ\""]], "]"]], Rule[TooltipStyle, List[Rule[ShowAutoStyles, True], Rule[ShowStringCharacters, True]]]], Function[Annotation[Slot[1], Style[Defer[PacletSymbol["Wolfram/CodeEquivalenceUtilities", "CodeEquivalentQ"]], Rule[ShowStringCharacters, True]], "Tooltip"]]], Rule[Background, RGBColor[0.968`, 0.976`, 0.984`]], Rule[BaselinePosition, Baseline], Rule[DefaultBaseStyle, List[]], Rule[FrameMargins, List[List[0, 0], List[1, 1]]], Rule[FrameStyle, RGBColor[0.831`, 0.847`, 0.85`]], Rule[RoundingRadius, 4]], PacletSymbol["Wolfram/CodeEquivalenceUtilities", "CodeEquivalentQ"], Rule[Selectable, False], Rule[SelectWithContents, True], Rule[BoxID, "PacletSymbolBox"]][RandomInteger /@ Range[5], Array[RandomInteger, 5]]
Out[1]=

View the canonical representations of expressions:

In[2]:=
InterpretationBox[FrameBox[TagBox[TooltipBox[PaneBox[GridBox[List[List[GraphicsBox[List[Thickness[0.006082377284997087`], StyleBox[List[FilledCurveBox[List[List[List[0, 2, 0], List[0, 1, 0], List[0, 1, 0]], List[List[0, 2, 0], List[0, 1, 0], List[0, 1, 0]], List[List[0, 2, 0], List[0, 1, 0], List[0, 1, 0]]], List[List[List[2.78206`, 85.44900000000004`], List[79.17353999999999`, 41.67850000000004`], List[79.17353999999999`, 1.6779000000000508`], List[2.78206`, 45.44840000000002`]], List[List[127.7826`, 115.44898000000003`], List[127.7826`, 26.449000000000012`], List[161.7832`, 47.44780000000006`], List[161.7832`, 135.44923000000003`]], List[List[5.78267`, 141.44910000000004`], List[40.783`, 121.44819000000003`], List[117.7831`, 165.44919000000004`], List[81.37629999999999`, 187.24592000000004`]]]]], List[FaceForm[RGBColor[0.9843139999999999`, 0.662745`, 0.25098000000000004`, 1.`]]], Rule[StripOnInput, False]], StyleBox[List[FilledCurveBox[List[List[List[0, 2, 0], List[0, 1, 0], List[0, 1, 0]], List[List[0, 2, 0], List[0, 1, 0], List[0, 1, 0]], List[List[0, 2, 0], List[0, 1, 0], List[0, 1, 0]]], List[List[List[79.20467000000001`, 90.91309000000003`], List[79.20546`, 48.911800000000056`], List[43.782610000000005`, 69.44830000000003`], List[43.782610000000005`, 111.44764000000002`]], List[List[82.77993`, 137.44809000000004`], List[48.77938`, 117.44782000000004`], List[82.77993`, 97.44923000000004`], List[117.7808`, 117.44782000000004`]], List[List[86.41823000000001`, 90.97696000000002`], List[86.45015000000001`, 48.71930000000003`], List[121.7829`, 70.44880000000003`], List[121.7829`, 112.44819000000003`]]]]], List[FaceForm[RGBColor[0.46274499999999996`, 0.066667`, 0.07451`, 1.`]]], Rule[StripOnInput, False]], StyleBox[List[FilledCurveBox[List[List[List[0, 2, 0], List[0, 1, 0], List[0, 1, 0]], List[List[0, 2, 0], List[0, 1, 0], List[0, 1, 0]], List[List[0, 2, 0], List[0, 1, 0], List[0, 1, 0]]], List[List[List[158.7825`, 141.44910000000004`], List[123.7817`, 121.44886000000004`], List[89.78278999999999`, 141.44910000000004`], List[123.7817`, 161.44770000000003`]], List[List[2.7817600000000002`, 92.44794000000003`], List[37.782610000000005`, 72.44770000000003`], List[37.782610000000005`, 114.44870000000003`], List[2.7817600000000002`, 134.44898000000003`]], List[List[86.45015000000001`, 1.7736000000000445`], List[121.78269999999999`, 23.44920000000002`], List[121.78269999999999`, 63.33730000000003`], List[86.45015000000001`, 41.66350000000003`]]]]], List[FaceForm[RGBColor[1.`, 0.41568600000000006`, 0.054902000000000006`, 1.`]]], Rule[StripOnInput, False]]], List[Rule[BaselinePosition, Scaled[0.15`]], Rule[ImageSize, 10], Rule[ImageSize, List[30, Automatic]]]], StyleBox[RowBox[List["MakeCanonicalForm", " "]], Rule[ShowAutoStyles, False], Rule[ShowStringCharacters, False], Rule[FontSize, Times[0.9`, Inherited]], Rule[FontColor, GrayLevel[0.1`]]]]], Rule[GridBoxSpacings, List[Rule["Columns", List[List[0.25`]]]]]], Rule[Alignment, List[Left, Baseline]], Rule[BaselinePosition, Baseline], Rule[FrameMargins, List[List[3, 0], List[0, 0]]], Rule[BaseStyle, List[Rule[LineSpacing, List[0, 0]], Rule[LineBreakWithin, False]]]], RowBox[List["PacletSymbol", "[", RowBox[List["\"Wolfram/CodeEquivalenceUtilities\"", ",", "\"MakeCanonicalForm\""]], "]"]], Rule[TooltipStyle, List[Rule[ShowAutoStyles, True], Rule[ShowStringCharacters, True]]]], Function[Annotation[Slot[1], Style[Defer[PacletSymbol["Wolfram/CodeEquivalenceUtilities", "MakeCanonicalForm"]], Rule[ShowStringCharacters, True]], "Tooltip"]]], Rule[Background, RGBColor[0.968`, 0.976`, 0.984`]], Rule[BaselinePosition, Baseline], Rule[DefaultBaseStyle, List[]], Rule[FrameMargins, List[List[0, 0], List[1, 1]]], Rule[FrameStyle, RGBColor[0.831`, 0.847`, 0.85`]], Rule[RoundingRadius, 4]], PacletSymbol["Wolfram/CodeEquivalenceUtilities", "MakeCanonicalForm"], Rule[Selectable, False], Rule[SelectWithContents, True], Rule[BoxID, "PacletSymbolBox"]][RandomInteger /@ Range[5]]
Out[2]=
In[3]:=
InterpretationBox[FrameBox[TagBox[TooltipBox[PaneBox[GridBox[List[List[GraphicsBox[List[Thickness[0.006082377284997087`], StyleBox[List[FilledCurveBox[List[List[List[0, 2, 0], List[0, 1, 0], List[0, 1, 0]], List[List[0, 2, 0], List[0, 1, 0], List[0, 1, 0]], List[List[0, 2, 0], List[0, 1, 0], List[0, 1, 0]]], List[List[List[2.78206`, 85.44900000000004`], List[79.17353999999999`, 41.67850000000004`], List[79.17353999999999`, 1.6779000000000508`], List[2.78206`, 45.44840000000002`]], List[List[127.7826`, 115.44898000000003`], List[127.7826`, 26.449000000000012`], List[161.7832`, 47.44780000000006`], List[161.7832`, 135.44923000000003`]], List[List[5.78267`, 141.44910000000004`], List[40.783`, 121.44819000000003`], List[117.7831`, 165.44919000000004`], List[81.37629999999999`, 187.24592000000004`]]]]], List[FaceForm[RGBColor[0.9843139999999999`, 0.662745`, 0.25098000000000004`, 1.`]]], Rule[StripOnInput, False]], StyleBox[List[FilledCurveBox[List[List[List[0, 2, 0], List[0, 1, 0], List[0, 1, 0]], List[List[0, 2, 0], List[0, 1, 0], List[0, 1, 0]], List[List[0, 2, 0], List[0, 1, 0], List[0, 1, 0]]], List[List[List[79.20467000000001`, 90.91309000000003`], List[79.20546`, 48.911800000000056`], List[43.782610000000005`, 69.44830000000003`], List[43.782610000000005`, 111.44764000000002`]], List[List[82.77993`, 137.44809000000004`], List[48.77938`, 117.44782000000004`], List[82.77993`, 97.44923000000004`], List[117.7808`, 117.44782000000004`]], List[List[86.41823000000001`, 90.97696000000002`], List[86.45015000000001`, 48.71930000000003`], List[121.7829`, 70.44880000000003`], List[121.7829`, 112.44819000000003`]]]]], List[FaceForm[RGBColor[0.46274499999999996`, 0.066667`, 0.07451`, 1.`]]], Rule[StripOnInput, False]], StyleBox[List[FilledCurveBox[List[List[List[0, 2, 0], List[0, 1, 0], List[0, 1, 0]], List[List[0, 2, 0], List[0, 1, 0], List[0, 1, 0]], List[List[0, 2, 0], List[0, 1, 0], List[0, 1, 0]]], List[List[List[158.7825`, 141.44910000000004`], List[123.7817`, 121.44886000000004`], List[89.78278999999999`, 141.44910000000004`], List[123.7817`, 161.44770000000003`]], List[List[2.7817600000000002`, 92.44794000000003`], List[37.782610000000005`, 72.44770000000003`], List[37.782610000000005`, 114.44870000000003`], List[2.7817600000000002`, 134.44898000000003`]], List[List[86.45015000000001`, 1.7736000000000445`], List[121.78269999999999`, 23.44920000000002`], List[121.78269999999999`, 63.33730000000003`], List[86.45015000000001`, 41.66350000000003`]]]]], List[FaceForm[RGBColor[1.`, 0.41568600000000006`, 0.054902000000000006`, 1.`]]], Rule[StripOnInput, False]]], List[Rule[BaselinePosition, Scaled[0.15`]], Rule[ImageSize, 10], Rule[ImageSize, List[30, Automatic]]]], StyleBox[RowBox[List["MakeCanonicalForm", " "]], Rule[ShowAutoStyles, False], Rule[ShowStringCharacters, False], Rule[FontSize, Times[0.9`, Inherited]], Rule[FontColor, GrayLevel[0.1`]]]]], Rule[GridBoxSpacings, List[Rule["Columns", List[List[0.25`]]]]]], Rule[Alignment, List[Left, Baseline]], Rule[BaselinePosition, Baseline], Rule[FrameMargins, List[List[3, 0], List[0, 0]]], Rule[BaseStyle, List[Rule[LineSpacing, List[0, 0]], Rule[LineBreakWithin, False]]]], RowBox[List["PacletSymbol", "[", RowBox[List["\"Wolfram/CodeEquivalenceUtilities\"", ",", "\"MakeCanonicalForm\""]], "]"]], Rule[TooltipStyle, List[Rule[ShowAutoStyles, True], Rule[ShowStringCharacters, True]]]], Function[Annotation[Slot[1], Style[Defer[PacletSymbol["Wolfram/CodeEquivalenceUtilities", "MakeCanonicalForm"]], Rule[ShowStringCharacters, True]], "Tooltip"]]], Rule[Background, RGBColor[0.968`, 0.976`, 0.984`]], Rule[BaselinePosition, Baseline], Rule[DefaultBaseStyle, List[]], Rule[FrameMargins, List[List[0, 0], List[1, 1]]], Rule[FrameStyle, RGBColor[0.831`, 0.847`, 0.85`]], Rule[RoundingRadius, 4]], PacletSymbol["Wolfram/CodeEquivalenceUtilities", "MakeCanonicalForm"], Rule[Selectable, False], Rule[SelectWithContents, True], Rule[BoxID, "PacletSymbolBox"]][Array[RandomInteger, 5]]
Out[3]=

These are directly comparable:

In[4]:=
% === %%
Out[4]=

Scope (3) 

Get additional information about the equivalence test:

In[5]:=
InterpretationBox[FrameBox[TagBox[TooltipBox[PaneBox[GridBox[List[List[GraphicsBox[List[Thickness[0.006082377284997087`], StyleBox[List[FilledCurveBox[List[List[List[0, 2, 0], List[0, 1, 0], List[0, 1, 0]], List[List[0, 2, 0], List[0, 1, 0], List[0, 1, 0]], List[List[0, 2, 0], List[0, 1, 0], List[0, 1, 0]]], List[List[List[2.78206`, 85.44900000000004`], List[79.17353999999999`, 41.67850000000004`], List[79.17353999999999`, 1.6779000000000508`], List[2.78206`, 45.44840000000002`]], List[List[127.7826`, 115.44898000000003`], List[127.7826`, 26.449000000000012`], List[161.7832`, 47.44780000000006`], List[161.7832`, 135.44923000000003`]], List[List[5.78267`, 141.44910000000004`], List[40.783`, 121.44819000000003`], List[117.7831`, 165.44919000000004`], List[81.37629999999999`, 187.24592000000004`]]]]], List[FaceForm[RGBColor[0.9843139999999999`, 0.662745`, 0.25098000000000004`, 1.`]]], Rule[StripOnInput, False]], StyleBox[List[FilledCurveBox[List[List[List[0, 2, 0], List[0, 1, 0], List[0, 1, 0]], List[List[0, 2, 0], List[0, 1, 0], List[0, 1, 0]], List[List[0, 2, 0], List[0, 1, 0], List[0, 1, 0]]], List[List[List[79.20467000000001`, 90.91309000000003`], List[79.20546`, 48.911800000000056`], List[43.782610000000005`, 69.44830000000003`], List[43.782610000000005`, 111.44764000000002`]], List[List[82.77993`, 137.44809000000004`], List[48.77938`, 117.44782000000004`], List[82.77993`, 97.44923000000004`], List[117.7808`, 117.44782000000004`]], List[List[86.41823000000001`, 90.97696000000002`], List[86.45015000000001`, 48.71930000000003`], List[121.7829`, 70.44880000000003`], List[121.7829`, 112.44819000000003`]]]]], List[FaceForm[RGBColor[0.46274499999999996`, 0.066667`, 0.07451`, 1.`]]], Rule[StripOnInput, False]], StyleBox[List[FilledCurveBox[List[List[List[0, 2, 0], List[0, 1, 0], List[0, 1, 0]], List[List[0, 2, 0], List[0, 1, 0], List[0, 1, 0]], List[List[0, 2, 0], List[0, 1, 0], List[0, 1, 0]]], List[List[List[158.7825`, 141.44910000000004`], List[123.7817`, 121.44886000000004`], List[89.78278999999999`, 141.44910000000004`], List[123.7817`, 161.44770000000003`]], List[List[2.7817600000000002`, 92.44794000000003`], List[37.782610000000005`, 72.44770000000003`], List[37.782610000000005`, 114.44870000000003`], List[2.7817600000000002`, 134.44898000000003`]], List[List[86.45015000000001`, 1.7736000000000445`], List[121.78269999999999`, 23.44920000000002`], List[121.78269999999999`, 63.33730000000003`], List[86.45015000000001`, 41.66350000000003`]]]]], List[FaceForm[RGBColor[1.`, 0.41568600000000006`, 0.054902000000000006`, 1.`]]], Rule[StripOnInput, False]]], List[Rule[BaselinePosition, Scaled[0.15`]], Rule[ImageSize, 10], Rule[ImageSize, List[30, Automatic]]]], StyleBox[RowBox[List["EquivalenceTestData", " "]], Rule[ShowAutoStyles, False], Rule[ShowStringCharacters, False], Rule[FontSize, Times[0.9`, Inherited]], Rule[FontColor, GrayLevel[0.1`]]]]], Rule[GridBoxSpacings, List[Rule["Columns", List[List[0.25`]]]]]], Rule[Alignment, List[Left, Baseline]], Rule[BaselinePosition, Baseline], Rule[FrameMargins, List[List[3, 0], List[0, 0]]], Rule[BaseStyle, List[Rule[LineSpacing, List[0, 0]], Rule[LineBreakWithin, False]]]], RowBox[List["PacletSymbol", "[", RowBox[List["\"Wolfram/CodeEquivalenceUtilities\"", ",", "\"EquivalenceTestData\""]], "]"]], Rule[TooltipStyle, List[Rule[ShowAutoStyles, True], Rule[ShowStringCharacters, True]]]], Function[Annotation[Slot[1], Style[Defer[PacletSymbol["Wolfram/CodeEquivalenceUtilities", "EquivalenceTestData"]], Rule[ShowStringCharacters, True]], "Tooltip"]]], Rule[Background, RGBColor[0.968`, 0.976`, 0.984`]], Rule[BaselinePosition, Baseline], Rule[DefaultBaseStyle, List[]], Rule[FrameMargins, List[List[0, 0], List[1, 1]]], Rule[FrameStyle, RGBColor[0.831`, 0.847`, 0.85`]], Rule[RoundingRadius, 4]], PacletSymbol["Wolfram/CodeEquivalenceUtilities", "EquivalenceTestData"], Rule[Selectable, False], Rule[SelectWithContents, True], Rule[BoxID, "PacletSymbolBox"]][
 First[Rest[Range /@ Range[2^100]]],
 Part[Table[Table[j, {j, i}], {i, 2^100}], 2]
 ]
Out[5]=

View the sequence of transformations used to convert an expression to its canonical form:

In[6]:=
InterpretationBox[FrameBox[TagBox[TooltipBox[PaneBox[GridBox[List[List[GraphicsBox[List[Thickness[0.006082377284997087`], StyleBox[List[FilledCurveBox[List[List[List[0, 2, 0], List[0, 1, 0], List[0, 1, 0]], List[List[0, 2, 0], List[0, 1, 0], List[0, 1, 0]], List[List[0, 2, 0], List[0, 1, 0], List[0, 1, 0]]], List[List[List[2.78206`, 85.44900000000004`], List[79.17353999999999`, 41.67850000000004`], List[79.17353999999999`, 1.6779000000000508`], List[2.78206`, 45.44840000000002`]], List[List[127.7826`, 115.44898000000003`], List[127.7826`, 26.449000000000012`], List[161.7832`, 47.44780000000006`], List[161.7832`, 135.44923000000003`]], List[List[5.78267`, 141.44910000000004`], List[40.783`, 121.44819000000003`], List[117.7831`, 165.44919000000004`], List[81.37629999999999`, 187.24592000000004`]]]]], List[FaceForm[RGBColor[0.9843139999999999`, 0.662745`, 0.25098000000000004`, 1.`]]], Rule[StripOnInput, False]], StyleBox[List[FilledCurveBox[List[List[List[0, 2, 0], List[0, 1, 0], List[0, 1, 0]], List[List[0, 2, 0], List[0, 1, 0], List[0, 1, 0]], List[List[0, 2, 0], List[0, 1, 0], List[0, 1, 0]]], List[List[List[79.20467000000001`, 90.91309000000003`], List[79.20546`, 48.911800000000056`], List[43.782610000000005`, 69.44830000000003`], List[43.782610000000005`, 111.44764000000002`]], List[List[82.77993`, 137.44809000000004`], List[48.77938`, 117.44782000000004`], List[82.77993`, 97.44923000000004`], List[117.7808`, 117.44782000000004`]], List[List[86.41823000000001`, 90.97696000000002`], List[86.45015000000001`, 48.71930000000003`], List[121.7829`, 70.44880000000003`], List[121.7829`, 112.44819000000003`]]]]], List[FaceForm[RGBColor[0.46274499999999996`, 0.066667`, 0.07451`, 1.`]]], Rule[StripOnInput, False]], StyleBox[List[FilledCurveBox[List[List[List[0, 2, 0], List[0, 1, 0], List[0, 1, 0]], List[List[0, 2, 0], List[0, 1, 0], List[0, 1, 0]], List[List[0, 2, 0], List[0, 1, 0], List[0, 1, 0]]], List[List[List[158.7825`, 141.44910000000004`], List[123.7817`, 121.44886000000004`], List[89.78278999999999`, 141.44910000000004`], List[123.7817`, 161.44770000000003`]], List[List[2.7817600000000002`, 92.44794000000003`], List[37.782610000000005`, 72.44770000000003`], List[37.782610000000005`, 114.44870000000003`], List[2.7817600000000002`, 134.44898000000003`]], List[List[86.45015000000001`, 1.7736000000000445`], List[121.78269999999999`, 23.44920000000002`], List[121.78269999999999`, 63.33730000000003`], List[86.45015000000001`, 41.66350000000003`]]]]], List[FaceForm[RGBColor[1.`, 0.41568600000000006`, 0.054902000000000006`, 1.`]]], Rule[StripOnInput, False]]], List[Rule[BaselinePosition, Scaled[0.15`]], Rule[ImageSize, 10], Rule[ImageSize, List[30, Automatic]]]], StyleBox[RowBox[List["MakeCanonicalForm", " "]], Rule[ShowAutoStyles, False], Rule[ShowStringCharacters, False], Rule[FontSize, Times[0.9`, Inherited]], Rule[FontColor, GrayLevel[0.1`]]]]], Rule[GridBoxSpacings, List[Rule["Columns", List[List[0.25`]]]]]], Rule[Alignment, List[Left, Baseline]], Rule[BaselinePosition, Baseline], Rule[FrameMargins, List[List[3, 0], List[0, 0]]], Rule[BaseStyle, List[Rule[LineSpacing, List[0, 0]], Rule[LineBreakWithin, False]]]], RowBox[List["PacletSymbol", "[", RowBox[List["\"Wolfram/CodeEquivalenceUtilities\"", ",", "\"MakeCanonicalForm\""]], "]"]], Rule[TooltipStyle, List[Rule[ShowAutoStyles, True], Rule[ShowStringCharacters, True]]]], Function[Annotation[Slot[1], Style[Defer[PacletSymbol["Wolfram/CodeEquivalenceUtilities", "MakeCanonicalForm"]], Rule[ShowStringCharacters, True]], "Tooltip"]]], Rule[Background, RGBColor[0.968`, 0.976`, 0.984`]], Rule[BaselinePosition, Baseline], Rule[DefaultBaseStyle, List[]], Rule[FrameMargins, List[List[0, 0], List[1, 1]]], Rule[FrameStyle, RGBColor[0.831`, 0.847`, 0.85`]], Rule[RoundingRadius, 4]], PacletSymbol["Wolfram/CodeEquivalenceUtilities", "MakeCanonicalForm"], Rule[Selectable, False], Rule[SelectWithContents, True], Rule[BoxID, "PacletSymbolBox"]][Array[RandomInteger, 5], "Trace" -> True] // Column
Out[6]=

Convert a canonical representation to a normal expression:

In[7]:=
InterpretationBox[FrameBox[TagBox[TooltipBox[PaneBox[GridBox[List[List[GraphicsBox[List[Thickness[0.006082377284997087`], StyleBox[List[FilledCurveBox[List[List[List[0, 2, 0], List[0, 1, 0], List[0, 1, 0]], List[List[0, 2, 0], List[0, 1, 0], List[0, 1, 0]], List[List[0, 2, 0], List[0, 1, 0], List[0, 1, 0]]], List[List[List[2.78206`, 85.44900000000004`], List[79.17353999999999`, 41.67850000000004`], List[79.17353999999999`, 1.6779000000000508`], List[2.78206`, 45.44840000000002`]], List[List[127.7826`, 115.44898000000003`], List[127.7826`, 26.449000000000012`], List[161.7832`, 47.44780000000006`], List[161.7832`, 135.44923000000003`]], List[List[5.78267`, 141.44910000000004`], List[40.783`, 121.44819000000003`], List[117.7831`, 165.44919000000004`], List[81.37629999999999`, 187.24592000000004`]]]]], List[FaceForm[RGBColor[0.9843139999999999`, 0.662745`, 0.25098000000000004`, 1.`]]], Rule[StripOnInput, False]], StyleBox[List[FilledCurveBox[List[List[List[0, 2, 0], List[0, 1, 0], List[0, 1, 0]], List[List[0, 2, 0], List[0, 1, 0], List[0, 1, 0]], List[List[0, 2, 0], List[0, 1, 0], List[0, 1, 0]]], List[List[List[79.20467000000001`, 90.91309000000003`], List[79.20546`, 48.911800000000056`], List[43.782610000000005`, 69.44830000000003`], List[43.782610000000005`, 111.44764000000002`]], List[List[82.77993`, 137.44809000000004`], List[48.77938`, 117.44782000000004`], List[82.77993`, 97.44923000000004`], List[117.7808`, 117.44782000000004`]], List[List[86.41823000000001`, 90.97696000000002`], List[86.45015000000001`, 48.71930000000003`], List[121.7829`, 70.44880000000003`], List[121.7829`, 112.44819000000003`]]]]], List[FaceForm[RGBColor[0.46274499999999996`, 0.066667`, 0.07451`, 1.`]]], Rule[StripOnInput, False]], StyleBox[List[FilledCurveBox[List[List[List[0, 2, 0], List[0, 1, 0], List[0, 1, 0]], List[List[0, 2, 0], List[0, 1, 0], List[0, 1, 0]], List[List[0, 2, 0], List[0, 1, 0], List[0, 1, 0]]], List[List[List[158.7825`, 141.44910000000004`], List[123.7817`, 121.44886000000004`], List[89.78278999999999`, 141.44910000000004`], List[123.7817`, 161.44770000000003`]], List[List[2.7817600000000002`, 92.44794000000003`], List[37.782610000000005`, 72.44770000000003`], List[37.782610000000005`, 114.44870000000003`], List[2.7817600000000002`, 134.44898000000003`]], List[List[86.45015000000001`, 1.7736000000000445`], List[121.78269999999999`, 23.44920000000002`], List[121.78269999999999`, 63.33730000000003`], List[86.45015000000001`, 41.66350000000003`]]]]], List[FaceForm[RGBColor[1.`, 0.41568600000000006`, 0.054902000000000006`, 1.`]]], Rule[StripOnInput, False]]], List[Rule[BaselinePosition, Scaled[0.15`]], Rule[ImageSize, 10], Rule[ImageSize, List[30, Automatic]]]], StyleBox[RowBox[List["MakeCanonicalForm", " "]], Rule[ShowAutoStyles, False], Rule[ShowStringCharacters, False], Rule[FontSize, Times[0.9`, Inherited]], Rule[FontColor, GrayLevel[0.1`]]]]], Rule[GridBoxSpacings, List[Rule["Columns", List[List[0.25`]]]]]], Rule[Alignment, List[Left, Baseline]], Rule[BaselinePosition, Baseline], Rule[FrameMargins, List[List[3, 0], List[0, 0]]], Rule[BaseStyle, List[Rule[LineSpacing, List[0, 0]], Rule[LineBreakWithin, False]]]], RowBox[List["PacletSymbol", "[", RowBox[List["\"Wolfram/CodeEquivalenceUtilities\"", ",", "\"MakeCanonicalForm\""]], "]"]], Rule[TooltipStyle, List[Rule[ShowAutoStyles, True], Rule[ShowStringCharacters, True]]]], Function[Annotation[Slot[1], Style[Defer[PacletSymbol["Wolfram/CodeEquivalenceUtilities", "MakeCanonicalForm"]], Rule[ShowStringCharacters, True]], "Tooltip"]]], Rule[Background, RGBColor[0.968`, 0.976`, 0.984`]], Rule[BaselinePosition, Baseline], Rule[DefaultBaseStyle, List[]], Rule[FrameMargins, List[List[0, 0], List[1, 1]]], Rule[FrameStyle, RGBColor[0.831`, 0.847`, 0.85`]], Rule[RoundingRadius, 4]], PacletSymbol["Wolfram/CodeEquivalenceUtilities", "MakeCanonicalForm"], Rule[Selectable, False], Rule[SelectWithContents, True], Rule[BoxID, "PacletSymbolBox"]][Array[RandomInteger, 5]]
Out[7]=
In[8]:=
InterpretationBox[FrameBox[TagBox[TooltipBox[PaneBox[GridBox[List[List[GraphicsBox[List[Thickness[0.006082377284997087`], StyleBox[List[FilledCurveBox[List[List[List[0, 2, 0], List[0, 1, 0], List[0, 1, 0]], List[List[0, 2, 0], List[0, 1, 0], List[0, 1, 0]], List[List[0, 2, 0], List[0, 1, 0], List[0, 1, 0]]], List[List[List[2.78206`, 85.44900000000004`], List[79.17353999999999`, 41.67850000000004`], List[79.17353999999999`, 1.6779000000000508`], List[2.78206`, 45.44840000000002`]], List[List[127.7826`, 115.44898000000003`], List[127.7826`, 26.449000000000012`], List[161.7832`, 47.44780000000006`], List[161.7832`, 135.44923000000003`]], List[List[5.78267`, 141.44910000000004`], List[40.783`, 121.44819000000003`], List[117.7831`, 165.44919000000004`], List[81.37629999999999`, 187.24592000000004`]]]]], List[FaceForm[RGBColor[0.9843139999999999`, 0.662745`, 0.25098000000000004`, 1.`]]], Rule[StripOnInput, False]], StyleBox[List[FilledCurveBox[List[List[List[0, 2, 0], List[0, 1, 0], List[0, 1, 0]], List[List[0, 2, 0], List[0, 1, 0], List[0, 1, 0]], List[List[0, 2, 0], List[0, 1, 0], List[0, 1, 0]]], List[List[List[79.20467000000001`, 90.91309000000003`], List[79.20546`, 48.911800000000056`], List[43.782610000000005`, 69.44830000000003`], List[43.782610000000005`, 111.44764000000002`]], List[List[82.77993`, 137.44809000000004`], List[48.77938`, 117.44782000000004`], List[82.77993`, 97.44923000000004`], List[117.7808`, 117.44782000000004`]], List[List[86.41823000000001`, 90.97696000000002`], List[86.45015000000001`, 48.71930000000003`], List[121.7829`, 70.44880000000003`], List[121.7829`, 112.44819000000003`]]]]], List[FaceForm[RGBColor[0.46274499999999996`, 0.066667`, 0.07451`, 1.`]]], Rule[StripOnInput, False]], StyleBox[List[FilledCurveBox[List[List[List[0, 2, 0], List[0, 1, 0], List[0, 1, 0]], List[List[0, 2, 0], List[0, 1, 0], List[0, 1, 0]], List[List[0, 2, 0], List[0, 1, 0], List[0, 1, 0]]], List[List[List[158.7825`, 141.44910000000004`], List[123.7817`, 121.44886000000004`], List[89.78278999999999`, 141.44910000000004`], List[123.7817`, 161.44770000000003`]], List[List[2.7817600000000002`, 92.44794000000003`], List[37.782610000000005`, 72.44770000000003`], List[37.782610000000005`, 114.44870000000003`], List[2.7817600000000002`, 134.44898000000003`]], List[List[86.45015000000001`, 1.7736000000000445`], List[121.78269999999999`, 23.44920000000002`], List[121.78269999999999`, 63.33730000000003`], List[86.45015000000001`, 41.66350000000003`]]]]], List[FaceForm[RGBColor[1.`, 0.41568600000000006`, 0.054902000000000006`, 1.`]]], Rule[StripOnInput, False]]], List[Rule[BaselinePosition, Scaled[0.15`]], Rule[ImageSize, 10], Rule[ImageSize, List[30, Automatic]]]], StyleBox[RowBox[List["FromCanonicalForm", " "]], Rule[ShowAutoStyles, False], Rule[ShowStringCharacters, False], Rule[FontSize, Times[0.9`, Inherited]], Rule[FontColor, GrayLevel[0.1`]]]]], Rule[GridBoxSpacings, List[Rule["Columns", List[List[0.25`]]]]]], Rule[Alignment, List[Left, Baseline]], Rule[BaselinePosition, Baseline], Rule[FrameMargins, List[List[3, 0], List[0, 0]]], Rule[BaseStyle, List[Rule[LineSpacing, List[0, 0]], Rule[LineBreakWithin, False]]]], RowBox[List["PacletSymbol", "[", RowBox[List["\"Wolfram/CodeEquivalenceUtilities\"", ",", "\"FromCanonicalForm\""]], "]"]], Rule[TooltipStyle, List[Rule[ShowAutoStyles, True], Rule[ShowStringCharacters, True]]]], Function[Annotation[Slot[1], Style[Defer[PacletSymbol["Wolfram/CodeEquivalenceUtilities", "FromCanonicalForm"]], Rule[ShowStringCharacters, True]], "Tooltip"]]], Rule[Background, RGBColor[0.968`, 0.976`, 0.984`]], Rule[BaselinePosition, Baseline], Rule[DefaultBaseStyle, List[]], Rule[FrameMargins, List[List[0, 0], List[1, 1]]], Rule[FrameStyle, RGBColor[0.831`, 0.847`, 0.85`]], Rule[RoundingRadius, 4]], PacletSymbol["Wolfram/CodeEquivalenceUtilities", "FromCanonicalForm"], Rule[Selectable, False], Rule[SelectWithContents, True], Rule[BoxID, "PacletSymbolBox"]][%]
Out[8]=

Evaluate:

In[9]:=
ReleaseHold[%]
Out[9]=

Neat Examples (6) 

Here is a list of expressions, some of which are equivalent to others:

In[10]:=
expressions = {
   HoldForm[Table[i, {i, 5}, {j, i + 2}]],
   HoldForm[Array[Range, 5, 3]],
   HoldForm[Table[ConstantArray[i, i + 2], {i, 5}]],
   HoldForm[First[Rest[Range /@ Range[10]]]],
   HoldForm[Range /@ Range[3, 7]],
   HoldForm[Part[Table[Table[j, {j, i}], {i, 10}], 2]]
   };

Find the sequence of transformations for each expression:

In[11]:=
Short[traces = Most@InterpretationBox[FrameBox[TagBox[TooltipBox[PaneBox[GridBox[List[List[GraphicsBox[List[Thickness[0.006082377284997087`], StyleBox[List[FilledCurveBox[List[List[List[0, 2, 0], List[0, 1, 0], List[0, 1, 0]], List[List[0, 2, 0], List[0, 1, 0], List[0, 1, 0]], List[List[0, 2, 0], List[0, 1, 0], List[0, 1, 0]]], List[List[List[2.78206`, 85.44900000000004`], List[79.17353999999999`, 41.67850000000004`], List[79.17353999999999`, 1.6779000000000508`], List[2.78206`, 45.44840000000002`]], List[List[127.7826`, 115.44898000000003`], List[127.7826`, 26.449000000000012`], List[161.7832`, 47.44780000000006`], List[161.7832`, 135.44923000000003`]], List[List[5.78267`, 141.44910000000004`], List[40.783`, 121.44819000000003`], List[117.7831`, 165.44919000000004`], List[81.37629999999999`, 187.24592000000004`]]]]], List[FaceForm[RGBColor[0.9843139999999999`, 0.662745`, 0.25098000000000004`, 1.`]]], Rule[StripOnInput, False]], StyleBox[List[FilledCurveBox[List[List[List[0, 2, 0], List[0, 1, 0], List[0, 1, 0]], List[List[0, 2, 0], List[0, 1, 0], List[0, 1, 0]], List[List[0, 2, 0], List[0, 1, 0], List[0, 1, 0]]], List[List[List[79.20467000000001`, 90.91309000000003`], List[79.20546`, 48.911800000000056`], List[43.782610000000005`, 69.44830000000003`], List[43.782610000000005`, 111.44764000000002`]], List[List[82.77993`, 137.44809000000004`], List[48.77938`, 117.44782000000004`], List[82.77993`, 97.44923000000004`], List[117.7808`, 117.44782000000004`]], List[List[86.41823000000001`, 90.97696000000002`], List[86.45015000000001`, 48.71930000000003`], List[121.7829`, 70.44880000000003`], List[121.7829`, 112.44819000000003`]]]]], List[FaceForm[RGBColor[0.46274499999999996`, 0.066667`, 0.07451`, 1.`]]], Rule[StripOnInput, False]], StyleBox[List[FilledCurveBox[List[List[List[0, 2, 0], List[0, 1, 0], List[0, 1, 0]], List[List[0, 2, 0], List[0, 1, 0], List[0, 1, 0]], List[List[0, 2, 0], List[0, 1, 0], List[0, 1, 0]]], List[List[List[158.7825`, 141.44910000000004`], List[123.7817`, 121.44886000000004`], List[89.78278999999999`, 141.44910000000004`], List[123.7817`, 161.44770000000003`]], List[List[2.7817600000000002`, 92.44794000000003`], List[37.782610000000005`, 72.44770000000003`], List[37.782610000000005`, 114.44870000000003`], List[2.7817600000000002`, 134.44898000000003`]], List[List[86.45015000000001`, 1.7736000000000445`], List[121.78269999999999`, 23.44920000000002`], List[121.78269999999999`, 63.33730000000003`], List[86.45015000000001`, 41.66350000000003`]]]]], List[FaceForm[RGBColor[1.`, 0.41568600000000006`, 0.054902000000000006`, 1.`]]], Rule[StripOnInput, False]]], List[Rule[BaselinePosition, Scaled[0.15`]], Rule[ImageSize, 10], Rule[ImageSize, List[30, Automatic]]]], StyleBox[RowBox[List["ToCanonicalForm", " "]], Rule[ShowAutoStyles, False], Rule[ShowStringCharacters, False], Rule[FontSize, Times[0.9`, Inherited]], Rule[FontColor, GrayLevel[0.1`]]]]], Rule[GridBoxSpacings, List[Rule["Columns", List[List[0.25`]]]]]], Rule[Alignment, List[Left, Baseline]], Rule[BaselinePosition, Baseline], Rule[FrameMargins, List[List[3, 0], List[0, 0]]], Rule[BaseStyle, List[Rule[LineSpacing, List[0, 0]], Rule[LineBreakWithin, False]]]], RowBox[List["PacletSymbol", "[", RowBox[List["\"Wolfram/CodeEquivalenceUtilities\"", ",", "\"ToCanonicalForm\""]], "]"]], Rule[TooltipStyle, List[Rule[ShowAutoStyles, True], Rule[ShowStringCharacters, True]]]], Function[Annotation[Slot[1], Style[Defer[PacletSymbol["Wolfram/CodeEquivalenceUtilities", "ToCanonicalForm"]], Rule[ShowStringCharacters, True]], "Tooltip"]]], Rule[Background, RGBColor[0.968`, 0.976`, 0.984`]], Rule[BaselinePosition, Baseline], Rule[DefaultBaseStyle, List[]], Rule[FrameMargins, List[List[0, 0], List[1, 1]]], Rule[FrameStyle, RGBColor[0.831`, 0.847`, 0.85`]], Rule[RoundingRadius, 4]], PacletSymbol["Wolfram/CodeEquivalenceUtilities", "ToCanonicalForm"], Rule[Selectable, False], Rule[SelectWithContents, True], Rule[BoxID, "PacletSymbolBox"]][#, "Trace" -> True] & /@ expressions]
Out[11]=

Generate a graph for each sequence:

In[12]:=
paths = Graph[DirectedEdge @@@ Partition[#, 2, 1]] & /@ traces
Out[12]=

Combine the graphs:

In[13]:=
graph = Graph[GraphUnion @@ paths, Sequence[
   VertexLabels -> Placed["Name", Tooltip], GraphLayout -> "LayeredDigraphEmbedding"]];

Equivalent expressions converge to the same connected component:

In[14]:=
HighlightGraph[graph, paths]
Out[14]=

Group the expressions into their corresponding equivalence class:

In[15]:=
grouped = GroupBy[expressions, InterpretationBox[FrameBox[TagBox[TooltipBox[PaneBox[GridBox[List[List[GraphicsBox[List[Thickness[0.006082377284997087`], StyleBox[List[FilledCurveBox[List[List[List[0, 2, 0], List[0, 1, 0], List[0, 1, 0]], List[List[0, 2, 0], List[0, 1, 0], List[0, 1, 0]], List[List[0, 2, 0], List[0, 1, 0], List[0, 1, 0]]], List[List[List[2.78206`, 85.44900000000004`], List[79.17353999999999`, 41.67850000000004`], List[79.17353999999999`, 1.6779000000000508`], List[2.78206`, 45.44840000000002`]], List[List[127.7826`, 115.44898000000003`], List[127.7826`, 26.449000000000012`], List[161.7832`, 47.44780000000006`], List[161.7832`, 135.44923000000003`]], List[List[5.78267`, 141.44910000000004`], List[40.783`, 121.44819000000003`], List[117.7831`, 165.44919000000004`], List[81.37629999999999`, 187.24592000000004`]]]]], List[FaceForm[RGBColor[0.9843139999999999`, 0.662745`, 0.25098000000000004`, 1.`]]], Rule[StripOnInput, False]], StyleBox[List[FilledCurveBox[List[List[List[0, 2, 0], List[0, 1, 0], List[0, 1, 0]], List[List[0, 2, 0], List[0, 1, 0], List[0, 1, 0]], List[List[0, 2, 0], List[0, 1, 0], List[0, 1, 0]]], List[List[List[79.20467000000001`, 90.91309000000003`], List[79.20546`, 48.911800000000056`], List[43.782610000000005`, 69.44830000000003`], List[43.782610000000005`, 111.44764000000002`]], List[List[82.77993`, 137.44809000000004`], List[48.77938`, 117.44782000000004`], List[82.77993`, 97.44923000000004`], List[117.7808`, 117.44782000000004`]], List[List[86.41823000000001`, 90.97696000000002`], List[86.45015000000001`, 48.71930000000003`], List[121.7829`, 70.44880000000003`], List[121.7829`, 112.44819000000003`]]]]], List[FaceForm[RGBColor[0.46274499999999996`, 0.066667`, 0.07451`, 1.`]]], Rule[StripOnInput, False]], StyleBox[List[FilledCurveBox[List[List[List[0, 2, 0], List[0, 1, 0], List[0, 1, 0]], List[List[0, 2, 0], List[0, 1, 0], List[0, 1, 0]], List[List[0, 2, 0], List[0, 1, 0], List[0, 1, 0]]], List[List[List[158.7825`, 141.44910000000004`], List[123.7817`, 121.44886000000004`], List[89.78278999999999`, 141.44910000000004`], List[123.7817`, 161.44770000000003`]], List[List[2.7817600000000002`, 92.44794000000003`], List[37.782610000000005`, 72.44770000000003`], List[37.782610000000005`, 114.44870000000003`], List[2.7817600000000002`, 134.44898000000003`]], List[List[86.45015000000001`, 1.7736000000000445`], List[121.78269999999999`, 23.44920000000002`], List[121.78269999999999`, 63.33730000000003`], List[86.45015000000001`, 41.66350000000003`]]]]], List[FaceForm[RGBColor[1.`, 0.41568600000000006`, 0.054902000000000006`, 1.`]]], Rule[StripOnInput, False]]], List[Rule[BaselinePosition, Scaled[0.15`]], Rule[ImageSize, 10], Rule[ImageSize, List[30, Automatic]]]], StyleBox[RowBox[List["ToCanonicalForm", " "]], Rule[ShowAutoStyles, False], Rule[ShowStringCharacters, False], Rule[FontSize, Times[0.9`, Inherited]], Rule[FontColor, GrayLevel[0.1`]]]]], Rule[GridBoxSpacings, List[Rule["Columns", List[List[0.25`]]]]]], Rule[Alignment, List[Left, Baseline]], Rule[BaselinePosition, Baseline], Rule[FrameMargins, List[List[3, 0], List[0, 0]]], Rule[BaseStyle, List[Rule[LineSpacing, List[0, 0]], Rule[LineBreakWithin, False]]]], RowBox[List["PacletSymbol", "[", RowBox[List["\"Wolfram/CodeEquivalenceUtilities\"", ",", "\"ToCanonicalForm\""]], "]"]], Rule[TooltipStyle, List[Rule[ShowAutoStyles, True], Rule[ShowStringCharacters, True]]]], Function[Annotation[Slot[1], Style[Defer[PacletSymbol["Wolfram/CodeEquivalenceUtilities", "ToCanonicalForm"]], Rule[ShowStringCharacters, True]], "Tooltip"]]], Rule[Background, RGBColor[0.968`, 0.976`, 0.984`]], Rule[BaselinePosition, Baseline], Rule[DefaultBaseStyle, List[]], Rule[FrameMargins, List[List[0, 0], List[1, 1]]], Rule[FrameStyle, RGBColor[0.831`, 0.847`, 0.85`]], Rule[RoundingRadius, 4]], PacletSymbol["Wolfram/CodeEquivalenceUtilities", "ToCanonicalForm"], Rule[Selectable, False], Rule[SelectWithContents, True], Rule[BoxID, "PacletSymbolBox"]]]
Out[15]=
In[16]:=
TableForm[KeyValueMap[Reverse@*List, grouped]]
Out[16]=

Disclosures

License Information

MIT License

Resource History

Paclet Source

Source Metadata

See Also