Skip to content

Commit

Permalink
Merge pull request #22 from rhennigan/feature/named-rule-sets
Browse files Browse the repository at this point in the history
Named Rule Sets
  • Loading branch information
rhennigan committed Jan 20, 2023
2 parents 7903fd3 + 9ea5388 commit 9e368fe
Show file tree
Hide file tree
Showing 33 changed files with 4,273 additions and 2,222 deletions.
66 changes: 66 additions & 0 deletions Data/RuleSets/ArgumentProperties.wl
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
(* ::**************************************************************************************************************:: *)
(* ::Section::Closed:: *)
(*Package Header*)

(* :!CodeAnalysis::BeginBlock:: *)
(* :!CodeAnalysis::Disable::TopLevelAssociation:: *)
(* :!CodeAnalysis::Disable::BadSymbol::SymbolQ:: *)

BeginPackage[ "Wolfram`CodeEquivalenceUtilities`" ];
Begin[ "`Private`" ];

(* ::**************************************************************************************************************:: *)
(* ::Section::Closed:: *)
(*Default Values*)
SetRuleDefaults @ <|
"Usage" -> { "EquivalenceTesting" }
|>;

(* ::**************************************************************************************************************:: *)
(* ::Section::Closed:: *)
(*Definitions*)
$orderlessLevel2Symbols = Blend | Length | Max | Mean | Min | RandomChoice | RandomSample | Sort | Total;
$orderlessLevel2AnyArgSymbols = Complement | Intersection | Union | Graph;
$flatLevel2Symbols = Min | Max;

(* ::**************************************************************************************************************:: *)
(* ::Section::Closed:: *)
(*Rules*)
<|
"Description" -> "Sort list arguments of functions that are not order-dependent",
"Symbols" :> { Sort, OrderedQ },
"Rule" ->
(f: $orderlessLevel2Symbols)[ l: { a___ }, b___ ] /; ! OrderedQ @ HoldComplete @ a :>
With[ { sorted = Sort @ TempHold @ a }, f[ { sorted }, b ] /; True ]
|>

(**********************************************************************************************************************)
<|
"Description" -> "Sort list arguments of functions that are not order-dependent",
"Symbols" :> { Sort, OrderedQ },
"Rule" ->
(f: $orderlessLevel2AnyArgSymbols)[ a___, l: { b___ }, c___ ] /; ! OrderedQ @ HoldComplete @ b :>
With[ { sorted = Sort @ TempHold @ b }, f[ a, { sorted }, c ] /; True ]
|>

(**********************************************************************************************************************)
<|
"Description" -> "Flatten arguments of functions that are not sensitive to nesting",
"Rule" ->
f: $flatLevel2Symbols[ a_ ] /; ! UFlatQ @ a :> \
With[ { flat = HFlatten[ f, HoldApply ] }, flat /; True ]
|>

(**********************************************************************************************************************)
<|
"Description" -> "Flatten arguments of functions that are not sensitive to nesting",
"Rule" -> (f: $flatLevel2Symbols)[ { a___ } ] :> f @ a
|>

(* ::**************************************************************************************************************:: *)
(* ::Section::Closed:: *)
(*Package Footer*)
End[ ];
EndPackage[ ];

(* :!CodeAnalysis::EndBlock:: *)
160 changes: 160 additions & 0 deletions Data/RuleSets/Arithmetic.wl
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
(* ::**************************************************************************************************************:: *)
(* ::Section::Closed:: *)
(*Package Header*)

(* :!CodeAnalysis::BeginBlock:: *)
(* :!CodeAnalysis::Disable::TopLevelAssociation:: *)
(* :!CodeAnalysis::Disable::BadSymbol::SymbolQ:: *)

BeginPackage[ "Wolfram`CodeEquivalenceUtilities`" ];
Begin[ "`Private`" ];

(* ::**************************************************************************************************************:: *)
(* ::Section::Closed:: *)
(*Default Values*)
SetRuleDefaults @ <|
"Description" -> "Transform using basic arithmetic rules",
"Usage" -> { "EquivalenceTesting" }
|>;

(* ::**************************************************************************************************************:: *)
(* ::Section::Closed:: *)
(*Rules*)

(**********************************************************************************************************************)
<|
"Name" -> "EvaluateArithmetic",
"Description" -> "Evaluate simple arithmetic expressions",
"Usage" -> { "EquivalenceTesting", "Simplification", "Optimization", "CodeStyle" },
"Symbols" :> { NumericQ, RuleCondition },
"Rule" :>
x_? HoldNumericQ /; SafeEvaluatedQ @ x === False && FreeQ[ HoldComplete @ x, $UnsafeSymbolPattern ] :>
RuleCondition @ x
|>

(**********************************************************************************************************************)
<|
"Name" -> "Arithmetic-enBgfX",
"Description" -> "Rewrite Total using Plus",
"Usage" -> { "EquivalenceTesting" },
"Symbols" :> { Total, Plus },
"Rule" :> Total[ list_ ] :> Plus @@ list
|>

(**********************************************************************************************************************)
<|
"Name" -> "Arithmetic-deiVLm",
"Description" -> "Transform using basic arithmetic rules",
"Usage" -> { "EquivalenceTesting", "Simplification", "Optimization" },
"Symbols" :> { Plus },
"Rule" :> Verbatim[ Plus ][ ] :> 0
|>

(**********************************************************************************************************************)
<|
"Name" -> "Arithmetic-cJntVW",
"Description" -> "Transform using basic arithmetic rules",
"Usage" -> { "EquivalenceTesting", "Simplification", "Optimization" },
"Symbols" :> { Times },
"Rule" :> Verbatim[ Times ][ ] :> 1
|>

(**********************************************************************************************************************)
<|
"Name" -> "Arithmetic-bjzLyg",
"Description" -> "Transform using basic arithmetic rules",
"Usage" -> { "EquivalenceTesting", "Simplification", "Optimization" },
"Symbols" :> { Power },
"Rule" :> Power[ x_ ] :> x
|>

(**********************************************************************************************************************)
<|
"Name" -> "Arithmetic-3okbs",
"Description" -> "Transform using basic arithmetic rules",
"Usage" -> { "EquivalenceTesting", "Simplification", "Optimization" },
"Symbols" :> { Power },
"Rule" :> Except[ 0 | 0.0 ] ^ 0 :> 1
|>

(**********************************************************************************************************************)
<|
"Name" -> "Arithmetic-cBfVay",
"Description" -> "Transform using basic arithmetic rules",
"Usage" -> { "EquivalenceTesting", "Simplification", "Optimization" },
"Symbols" :> { Power },
"Rule" :> Except[ 0 | 0.0 ] ^ 0.0 :> 1.0
|>

(**********************************************************************************************************************)
<|
"Name" -> "Arithmetic-extZL7",
"Description" -> "Transform using basic arithmetic rules",
"Usage" -> { "EquivalenceTesting", "Simplification", "Optimization" },
"Symbols" :> { Power },
"Rule" :> (o: 1 | 1.0)^(-1 | -1.0) :> o
|>

(**********************************************************************************************************************)
<|
"Name" -> "Arithmetic-b02jrr",
"Description" -> "Transform using basic arithmetic rules",
"Usage" -> { "EquivalenceTesting", "Simplification", "Optimization" },
"Symbols" :> { Times },
"Rule" :> Verbatim[ Times ][ a___, 1, b___ ] :> a * b
|>

(**********************************************************************************************************************)
<|
"Name" -> "Arithmetic-ZbgcH",
"Description" -> "Transform using basic arithmetic rules",
"Usage" -> { "EquivalenceTesting", "Simplification", "Optimization" },
"Symbols" :> { Plus },
"Rule" :> Verbatim[ Plus ][ a___, 0, b___ ] :> a + b
|>

(**********************************************************************************************************************)
<|
"Name" -> "Arithmetic-dZBNGC",
"Description" -> "Transform using basic arithmetic rules",
"Usage" -> { "EquivalenceTesting", "Simplification", "Optimization" },
"Symbols" :> { Times, Real },
"Rule" :> Verbatim[ Times ][ OrderlessPatternSequence[ 1.0, _? RealTypeQ, a___ ] ] :> Times @ a
|>

(**********************************************************************************************************************)
<|
"Name" -> "Arithmetic-1r2rh",
"Description" -> "Transform using basic arithmetic rules",
"Usage" -> { "EquivalenceTesting", "Simplification", "Optimization" },
"Symbols" :> { Plus, Real },
"Rule" :> Verbatim[ Plus ][ OrderlessPatternSequence[ 0.0, _? RealTypeQ, a___ ] ] :> Plus @ a
|>

(**********************************************************************************************************************)
<|
"Name" -> "Arithmetic-ewmXga",
"Description" -> "Transform using basic arithmetic rules",
"Usage" -> { "EquivalenceTesting", "Simplification", "Optimization" },
"Symbols" :> { Times, Infinity, DirectedInfinity },
"Rule" :> Verbatim[ Times ][ -1, DirectedInfinity[ 1 ] ] :> DirectedInfinity[ -1 ]
|>

(**********************************************************************************************************************)
<|
"Name" -> "Arithmetic-JHpgn",
"Description" -> "Distribute Times over Plus",
"Usage" -> { "EquivalenceTesting" },
"Symbols" :> { Times, Plus },
"Rule" :>
Verbatim[ Times ][ x_, Verbatim[ Plus ][ a___ ] ] :>
With[ { dist = Replace[ TempHold @ Plus @ a, e_ :> x * e, { 2 } ] }, dist /; True ]
|>

(* ::**************************************************************************************************************:: *)
(* ::Section::Closed:: *)
(*Package Footer*)
End[ ];
EndPackage[ ];

(* :!CodeAnalysis::EndBlock:: *)
115 changes: 115 additions & 0 deletions Data/RuleSets/Attributes.wl
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
(* ::**************************************************************************************************************:: *)
(* ::Section::Closed:: *)
(*Package Header*)

(* :!CodeAnalysis::BeginBlock:: *)
(* :!CodeAnalysis::Disable::TopLevelAssociation:: *)
(* :!CodeAnalysis::Disable::BadSymbol::SymbolQ:: *)

BeginPackage[ "Wolfram`CodeEquivalenceUtilities`" ];
Begin[ "`Private`" ];

(* ::**************************************************************************************************************:: *)
(* ::Section::Closed:: *)
(*Default Values*)
SetRuleDefaults @ <|
"Usage" -> { "EquivalenceTesting" },
"Symbols" :> { Attributes }
|>;

(* ::**************************************************************************************************************:: *)
(* ::Section::Closed:: *)
(*Rules*)

(**********************************************************************************************************************)
<|
"Description" -> "Flatten arguments of functions that have the Flat attribute",
"Usage" -> { Inherited, "Simplification", "Optimization" },
"Symbols" :> { Attributes, Flat },
"Rule" :>
(f_Symbol? SymbolQ)[ a1___, f_[ a2___ ], a3___ ] /; MemberQ[ Attributes @ f, Flat ] :>
f[ a1, a2, a3 ]
|>

(**********************************************************************************************************************)
<|
"Description" -> "Sort arguments of functions that have the Orderless attribute",
"Symbols" :> { Attributes, Orderless },
"Rule" :>
(f_Symbol? SymbolQ)[ a___ ] /; MemberQ[ Attributes @ f, Orderless ] && ! OrderedQ @ Unevaluated @ { a } :>
With[ { sorted = Sort @ TempHold @ a }, f @ sorted /; True ]
|>

(**********************************************************************************************************************)
<|
"Description" -> "Resolve single-argument forms of functions with the OneIdentity attribute",
"Symbols" :> { Attributes, OneIdentity },
"Rule" :>
(f_Symbol? SymbolQ)[ x: Except[ _Symbol? SymbolQ, _? UAtomQ ] ] /; MemberQ[ Attributes @ f, OneIdentity ] :>
x
|>

(**********************************************************************************************************************)
<|
(* TODO: this doesn't quite belong in attribute rules *)
"Description" -> "Resolve Apply when the specified function is not holding",
"Symbols" :> { Attributes, HoldFirst, HoldRest, HoldAll, HoldAllComplete, Apply },
"Rule" :>
(f_? SymbolQ) @@ { a___ } /; And[
NonHoldingQ @ f,
FreeQ[ Unevaluated @ { a }, s_? SymbolQ /; ! FreeQ[ UpValueSymbols @ s, Apply, { 1 } ], { 1 } ]
] :>
f @ a
|>

(**********************************************************************************************************************)
<|
"Description" -> "Remove order-modifying functions if the result is being passed to an Orderless function",
"Usage" -> { Inherited, "Simplification", "Optimization" },
"Symbols" :> { Attributes, HoldFirst, HoldRest, HoldAll, HoldAllComplete, Apply, Reverse },
"Rule" :>
(f_? OrderlessQ) @@ (Reverse)[ h_[ a___ ] ] /; NonHoldingQ @ f :>
f @@ h @ a
|>

(* TODO: combine with next rule *)

(**********************************************************************************************************************)
<|
"Description" -> "Remove order-modifying functions if the result is being passed to an Orderless function",
"Usage" -> { Inherited, "Simplification", "Optimization" },
"Symbols" :> { Attributes, HoldFirst, HoldRest, HoldAll, HoldAllComplete, Apply, Sort },
"Rule" :>
(f_? OrderlessQ) @@ (Sort)[ h_[ a___ ] ] /; NonHoldingQ @ f :>
f @@ h @ a
|>

(**********************************************************************************************************************)
<|
"Description" -> "Thread listable functions over equal-length tables",
"Usage" -> { Inherited, "Simplification", "Optimization" },
"Symbols" :> { Attributes, Listable, Table },
"Rule" :>
(f_? ListableQ)[ Table[ ei_, { i_, i1_, i2_, di_ } ], Table[ ej_, { j_, i1_, i2_, di_ } ] ] :>
With[ { ej2 = TempHold @ ej /. HoldPattern @ Verbatim @ j :> i },
Table[ f[ ei, ej2 ], { i, i1, i2, di } ] /; True
]
|>

(**********************************************************************************************************************)
<|
"Description" -> "Apply listable functions after taking parts of lists instead of before",
"Usage" -> { Inherited, "Optimization" },
"Symbols" :> { Attributes, Listable, Part, Span },
"Rule" :>
(f_? ListableQ)[ list_? ListTypeQ ][[ s_Span ]] :>
f @ list[[ s ]]
|>

(* ::**************************************************************************************************************:: *)
(* ::Section::Closed:: *)
(*Package Footer*)
End[ ];
EndPackage[ ];

(* :!CodeAnalysis::EndBlock:: *)
Loading

0 comments on commit 9e368fe

Please sign in to comment.