I'd like to simplify a complex symbolic expression expr by substituting and listing subexpressions that appear more than once in expr – kind of like Matlab does.

I need to port the result to C code, so the motivation is avoiding unnecessary recomputation of subterms.

To illustrate the idea, let's pick a simple expression expr = Inverse[Array[a, {2,2}]]:

Actual output of MMA when executing Inverse[Array[a, {3,3}]]:

$$ \left( \begin{array}{cc} \frac{a(2,2)}{a(1,1) a(2,2)-a(1,2) a(2,1)} & -\frac{a(1,2)}{a(1,1) a(2,2)-a(1,2) a(2,1)} \\ -\frac{a(2,1)}{a(1,1) a(2,2)-a(1,2) a(2,1)} & \frac{a(1,1)}{a(1,1) a(2,2)-a(1,2) a(2,1)} \\ \end{array} \right) $$

By looking at the output of this simple expression, I can see that the denominator is exactly the same in all of the matrix's elements (the determinant of the matrix).

The desired output of MMA: $$ \left( \begin{array}{cc} \frac{a(2,2)}{S_1} & -\frac{a(1,2)}{S_1} \\ -\frac{a(2,1)}{S_1} & \frac{a(1,1)}{S_1} \\ \end{array} \right), $$


$$S_1 = a(1,1) a(2,2)-a(1,2) a(2,1)$$

  • $\begingroup$ Inverse[Array[a, {2, 2}]] /. {-a[1, 2] a[2, 1] + a[1, 1] a[2, 2] -> S1} $\endgroup$ – corey979 Sep 5 '17 at 15:20
  • 2
    $\begingroup$ Have a look at Experimental`OptimizeExpression[Inverse[Array[a, {2, 2}]]]. $\endgroup$ – J. M.'s torpor Sep 5 '17 at 15:22
  • $\begingroup$ @corey979 I forgot to mention that I don't know what subexpressions are duplicated in expr (in my case expr is composed of operations on 6x6 matrices). $\endgroup$ – sarasvati Sep 5 '17 at 15:38
  • $\begingroup$ @J.M. Thank you. This seems like what I had in mind. Please consider posting this as an answer – I'll accept it. P.S. Am I right that there's no documentation for Experimental`OptimizeExpression? $\endgroup$ – sarasvati Sep 5 '17 at 15:42

As I noted in my comment above, the undocumented (thus, caveat emptor as usual) method is to use Experimental`OptimizeExpression[]:

Experimental`OptimizeExpression[Inverse[Array[a, {2, 2}]]]
       Block[{Compile`$9, Compile`$10, Compile`$11, Compile`$12, Compile`$14,
              Compile`$15, Compile`$16, Compile`$17}, 
             Compile`$9 = a[2, 2]; Compile`$10 = a[1, 2]; Compile`$11 = a[2, 1]; 
             Compile`$12 = -Compile`$10 Compile`$11; Compile`$14 = a[1, 1]; 
             Compile`$15 = Compile`$14 Compile`$9; 
             Compile`$16 = Compile`$12 + Compile`$15; 
             Compile`$17 = 1/Compile`$16;
             {{Compile`$9 Compile`$17, -Compile`$10 Compile`$17},
              {-Compile`$11 Compile`$17, Compile`$14 Compile`$17}}]]

The output has a slightly messy appearance, but if you take a careful look at the output, you'll see that e.g. the common factor in the elements of the matrix inverse (i.e. the reciprocal of the determinant) has been separated out, in this case as Compile`$17.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.