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?
LetLis defined as? – Daniel Lichtblau Mar 10 '16 at 15:50Experimental`OptimizeExpressionon your expression? A few refs: (25136), (31614), (32097), (58985) – Michael E2 Mar 13 '16 at 17:07ExperimentalOptimizeExpressionfailed, 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 Mar 13 '16 at 17:37rulescontains typos.nvec/Total[nvec], {i, nc}]and$[Delta]d. – bbgodfrey Mar 14 '16 at 06:07$[Delta]dshould have been$\[Delta]d. Also, a comma was needed between the two rules involvingDerivative. I fixed both and also cleaned the format a bit. Please verify that I did not introduce other issues. By the way,ncneeds a value. – bbgodfrey Mar 14 '16 at 14:01