## Best approach for 'manual' common subexpression elimination

2

I have working code, but am looking for ways to make it more elegant.

I have a fairly large expression with plenty of repetition and structure. A shortened toy example is

expr = (a/(a + b))^4.5  + (b/(a + b))^3.5 +
(a/(a + b))^1.5 + Cosh[a + b]  +
Log[a/(a + b)] + Log[b/(a + b)]


I have prepared a set of rules that simplifies the expression, for example like this:

rules = {
a + b -> sum,
a/sum -> g,
b/sum -> h}


In my actual code I use pattern matching, and also create unique symbols for all the matches, see below for an example.

 Derivative[l_List, i_][δ][xv, ρ] :>
Symbol[StringJoin["$δd", StringJoin[ToString /@ l], "x", ToString[i]]]  The simplified expression, and the actual set of replacements is provided by the following function: replaceone[expr_, rule_] := Block[{newtemps, unique}, unique = Union@Cases[expr, rule[[1]], Infinity]; newtemps = Thread[(unique /. rule) -> unique]; Sow[newtemps]; expr /. rule ] {newekspr, temps} = Reap[Fold[replaceone, expr, rules]] temps = Association[temps]  I can then prepare a function for efficient evaluation of the expression, like this, with a nested Block. exprfun[av_, bv_] := Block[{a = av, b = bv}, Block[Evaluate[Keys[temps]], KeyValueMap[Set, temps]; newekspr]]  I can Compile this function, although I suspect that the result is that the entire expression is expanded and simplified again. Compile[{a, b}, Evaluate[exprfun[a, b]]]  Is this the best way of doing this? Can I write a higher order function that takes my original expression, and a rules set, simplifies it and provides a optimised, and possibly compiled function? What is the benefit of a nested With, and LetL, that I have seen elsewhere, compared with this approach? And LetL is defined as? – Daniel Lichtblau – 2016-03-10T15:50:10.680 1Next time, when using a function obtained from another post on this site, please link to the original post. – J. M.'s ennui – 2016-03-10T16:32:42.390 @J.M. Yes, of course. Thanks for correcting. – Åsmund Hj – 2016-03-10T18:51:28.433 2 Have you tried ExperimentalOptimizeExpression on your expression? A few refs: (25136), (31614), (32097), (58985) – Michael E2 – 2016-03-13T17:07:19.610 @MichaelE2 My first attempts on ExperimentalOptimizeExpressionfailed, but I tried it again on a smaller problem, and now it works. Don't know why. Still, it seems a bit inelegant to let the expression explode in complexity, for then to leave toOptimizeExpression to clean up afterwards. My expression, with an original leafcount of around 150 000 is now calculated in 13 ns, compared to 28ms before compilation. Still, I would really like to use the manual rules as well, as these intermediary results are interesting by their own as well. – Åsmund Hj – 2016-03-13T17:37:16.363 Perhaps a small point, but rules contains typos. nvec/Total[nvec], {i, nc}] and $[Delta]d. – bbgodfrey – 2016-03-14T06:07:13.870

@bbgodfrey Thanks. I fixed the first one, but cannot find the second. – Åsmund Hj – 2016-03-14T06:47:25.840

I should have been more explicit. $[Delta]d should have been $\[Delta]d. Also, a comma was needed between the two rules involving Derivative. I fixed both and also cleaned the format a bit. Please verify that I did not introduce other issues. By the way, nc needs a value. – bbgodfrey – 2016-03-14T14:01:15.307