I frequently use Mathematica to rearrange or solve symbolic equations to use in C++ programs. While Mathematica is quite powerful for that, it has no facility to hoist common subexpressions into variables.

After spending some time manually rearranging a closed-form solution to a system of equations, it seemed worthwhile to find a way to hoist common subexpressions into variables. I didn’t find anything useful via Google, as the results were swamped by references to the common compiler “common subexpression elimination” optimization. It looked like it would require data-flow analysis to do this, which would be tedious to write and debug.

Some thought and experimentation suggested that it wouldn’t be all that hard to do a decent job using a straight-forward pattern matching and replacement (especially since I didn’t care how fast this ran), so I created this Mathematica 7 notebook to do just that. The code turned out to be concise, which means “unreadable” in Mathematica. I try to stick to functional style where I can, which is nice mental exercise, but can be hard to read. In the main function, I opted for iteration rather than a purely functional recursion just because it seemed clearer.

It’s always interesting to work on a problem like this in Mathematica. The language is very expressive, but often fails at the “Principle of Least Surprise“. In this case, I kept being tripped up by Mathematica matching non-existant arithmetic functions (Plus, Times, etc.) everywhere in an expression, in an overly-helpful attempt to match arithmetic patterns regardless of commutative or associative expression rearrangements. For future reference, it turns out that using HoldPattern will prevent that behavior.

I created a web page from the Mathematica notebook, but there doesn’t appear to be any way to do that and produce text, rather than pictures of the code. Oh well. Here it is anyway. If you want to see this notebook properly and don’t have Mathematica 7, you can use the free Mathematica Player.