How to get FullSimplify to fully simplify my expression with custom complexity function? - Mathematica Stack Exchange most recent 30 from mathematica.stackexchange.com 2019-08-24T07:55:20Z https://mathematica.stackexchange.com/feeds/question/5403 http://www.creativecommons.org/licenses/by-sa/3.0/rdf https://mathematica.stackexchange.com/q/5403 12 How to get FullSimplify to fully simplify my expression with custom complexity function? celtschk https://mathematica.stackexchange.com/users/129 2012-05-10T06:55:56Z 2012-07-08T21:19:07Z <p>To simplify based on the visual complexity of an expression (i.e. the complexity of the function as displayed in the notebook instead of the internal form, which in some cases may be substantially different), I've defined the following complexity function:</p> <pre><code>VisualComplexity:=(Count[ToBoxes[#], Except[" "|"("|")", _String], Infinity]&amp;) </code></pre> <p>This works well on some simple examples, however not on the following:</p> <pre><code>FullSimplify[(-1+a)(-1+b) + Abs[c]^2 - Abs[d]^2, ComplexityFunction-&gt;VisualComplexity] (* ==&gt; 1 - a - b + a*b + Abs[c]^2 - Abs[d]^2 *) </code></pre> <p>What I had expected (and desired) would have been <code>(1-a)(1-b) + Abs[c]^2 - Abs[d]^2</code>. Note that with the built-in complexity function, it converts <code>(1-a)(1-b)</code> to <code>(-1+a)(-1+b)</code> in that context, so transforming between those two forms is definitely in the capabilities of <code>FullSimplify</code>.</p> <p>Now my first thought was that maybe that's really less complex according to my complexity function (which would have meant tweaking that function). However, it turned out that the desired form indeed <em>is</em> computed to be less complex:</p> <pre><code>VisualComplexity /@ {1 - a - b + a*b + Abs[c]^2 - Abs[d]^2, (1-a)(1-b) + Abs[c]^2 - Abs[d]^2} (* ==&gt; {20, 18} *) </code></pre> <p>Therefore my question is: How do I get FullSimplify to generate the simpler form?</p> https://mathematica.stackexchange.com/questions/5403/-/8080#8080 6 Answer by Simon Woods for How to get FullSimplify to fully simplify my expression with custom complexity function? Simon Woods https://mathematica.stackexchange.com/users/862 2012-07-08T21:19:07Z 2012-07-08T21:19:07Z <p>We can confirm that the desired form never gets tried, by viewing the expressions sent to the ComplexityFunction with <code>Sow</code> and <code>Reap</code>:</p> <pre><code>vc := (Count[ToBoxes[Sow@#], Except[" " | "(" | ")", _String], Infinity]) &amp; Union@Reap[FullSimplify[(-1 + a) (-1 + b), ComplexityFunction -&gt; vc]][[2, 1]] (* {-1 + a, -1 + b, (-1 + a) (-1 + b), 1 - a + (-1 + a) b, 1 - a - b + a b} *) </code></pre> <p>Therefore it seems that it will be essential to add to <code>TransformationFunctions</code>. First I tried generalising from the specific case given in your comment:</p> <pre><code>tf = {Automatic, # /. (x_ + a__) (y_ + b__) :&gt; (-x - a) (-y - b) &amp;}; SetOptions[FullSimplify, ComplexityFunction -&gt; vc, TransformationFunctions -&gt; tf]; FullSimplify[expr] (* (1 - a) (1 - b) *) </code></pre> <p>Unfortunately this fails in certain cases, because <code>ReplaceAll</code> makes the first replacement it finds, which might happen to be one that doesn't decrease the complexity measure:</p> <pre><code>(* this doesn't work *) FullSimplify[(a - b) (-1 + c) (-1 + d)] (* (a - b) (-1 + c) (-1 + d) *) (* but this does *) FullSimplify[(-1 + c) (-1 + d) (e-f)] (* (1 - c) (1 - d) (e - f) *) </code></pre> <p>Since it is problematic to find the correct pairs of terms to negate, my next approach was to convert <em>all</em> forms like <code>(-1+a)</code> into <code>-(1-a)</code>, but in such a way that the complexity function would ignore the overall multiplier of -1 (and therefore prefer the latter form).</p> <pre><code>tf = {Automatic, \$minusone (-#) &amp;}; vc := (Count[ToBoxes[#], Except["\$minusone" | " " | "(" | ")", _String], Infinity]) &amp; \$minusone /: \$minusone^2 = 1; \$minusone /: x_ + \$minusone = x - 1; specialSimplify[x_] := FullSimplify[x, ComplexityFunction -&gt; vc, TransformationFunctions -&gt; tf] /. \$minusone -&gt; -1 </code></pre> <p><code>specialSimplify</code> tries negating expressions and tests whether this decreases their complexity measure. The overall sign of the expression is kept correct by the symbol <code>\$minusone</code> which is ignored by the complexity function. <code>\$minusone</code> squared is converted to 1, and <code>\$minusone</code> when it appears as part of a sum is converted back to -1. Any residual <code>\$minusone</code> at the end of the simplification is converted back to -1.</p> <p>This seems to well enough on toy examples, though I haven't tested it thoroughly. Note that in the last example <code>specialSimplify</code> prefers to have an overall minus sign than an expression like <code>(-a+b)</code></p> <pre><code>specialSimplify[(-1 + a) (-1 + b)] (* (1 - a) (1 - b) *) specialSimplify[(a - b) (-1 + c) (-1 + d)] (* (a - b) (1 - c) (1 - d) *) specialSimplify[(b - a) (-1 + c) (-1 + d)] (* -(a - b) (1 - c) (1 - d) *) </code></pre>