Advertisement
eacousineau

Mathematica Common Subexpression Elimination Routine

Aug 22nd, 2012
990
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.21 KB | None | 0 0
  1. (*
  2. Original: Stonewall Ballard
  3. http://stoney.sb.org/wordpress/2009/06/converting-symbolic-mathematica-expressions-to-c-code/
  4. Modification: Eric Cousineau (eacousineau@gmail.com)
  5. . Reformatted code, placed it in a package
  6. . Fixed a small bug allowing it to return expressions with no subexpressions
  7. . Changed variable numbering to any number of digits
  8. . Fixed small bug in listSubExps[] handling if it returns no results from Scan[]
  9. *)
  10. BeginPackage["CommonSubexpressionElimination`"];
  11.  
  12. hoistCommonSubexpressions::usage = "Optimize expression by finding repeated subexpressions and extracting them into a set of rules.
  13. Returns { {main_expr}, {subexpr -> var, ...} }";
  14.  
  15. Begin["`Private`"];
  16.  
  17. listSubExps[exp_]:= Module[{res},
  18. Sort[
  19. res = Reap[
  20. Scan[
  21. If[!AtomQ[#], Sow[#]]&,
  22. exp, Infinity
  23. ]
  24. ];
  25. If[Length[res[[2]]] > 0, res[[2, 1]], {}],
  26. (*res[[2,1]],*)
  27. LeafCount[#1] < LeafCount[#2]&
  28. ]];
  29.  
  30. replaceRepeats[expr_]:=
  31. Module[{ceqns, eqns, rules},
  32. ceqns = Reap[
  33. Module[{vnum=0, modExpr=expr, subExprs=listSubExps[expr], subExpr, mapping},
  34. While[subExprs != {},
  35. subExpr = First[subExprs];
  36. subExprs = Rest[subExprs];
  37. (* If the expression appears more than once *)
  38. If[Count[subExprs, subExpr]>0,
  39. mapping = subExpr->Symbol["vv"<>IntegerString[vnum++,10]];
  40. Sow[mapping];
  41. modExpr=modExpr/.mapping;
  42. subExprs=DeleteCases[subExprs,subExpr]/.mapping
  43. ]
  44. ];
  45. modExpr
  46. ]
  47. ];
  48. eqns = ceqns[[1]];
  49. rules = ceqns[[2]];
  50. (* Change:
  51. Before, used Extract[temp, {{1}, {2, 1}}.
  52. If no expressions are found, it returns {}. If found, returns {{exprs...}}
  53. *)
  54. rules = If[Length[rules] > 0, rules[[1]], {}];
  55. Return[{eqns, rules}];
  56. ]
  57.  
  58. foldOneUseVariables[ceqns:{eqns_,rules_}]:=
  59. Module[{newRules,updates},
  60. {newRules, updates} = Reap[
  61. Select[rules,
  62. If[Count[ceqns, #[[2]], \[Infinity]]==2, Sow[#[[2]]->#[[1]]]; False, True]&
  63. ]
  64. ];
  65. {eqns,newRules}//.Flatten[updates]
  66. ]
  67.  
  68. renumberVariables[ceqns:{_,rules_}]:=
  69. Module[{vnum=0},
  70. ceqns /. Map[#[[2]]->Symbol["v"<>IntegerString[vnum++]]&,rules]
  71. ]
  72.  
  73. hoistCommonSubexpressions[expr_]:=
  74. renumberVariables[
  75. foldOneUseVariables[
  76. replaceRepeats[
  77. Together[expr]
  78. ]
  79. ]
  80. ]
  81.  
  82. End[];
  83. EndPackage[];
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement