49

Here is the example:

Simplify[x + y, x + y == a]
Simplify[x + y, x + y == 5]

Mathematica 9 output:

x+y
5

I expect the complexity of a to be lower than complexity of Plus[x,y], and the result of the first line should be a.

Even if I specify ComplexityFunction explicitly:

Simplify[x + y, x + y == a, ComplexityFunction -> LeafCount]

I still get x+y as a result. It's however obvious that LeafCount[x+y] is greater than LeafCount[a].

Why does Simplify ignore x+y==a but uses x+y==5? How can I define the former assumption in a right way?

xzczd
  • 65,995
  • 9
  • 163
  • 468
Nick Stranniy
  • 1,233
  • 9
  • 15
  • 2
    It is interesting that Simplify[x y, x y == a] returns a. – whuber Jan 17 '13 at 01:48
  • As does Simplify[x^2+y^2,x^2+y^2==a], and Simplify[x+y,x+y==Cos[a]] returns Cos[a] – Cassini Jan 17 '13 at 02:03
  • ... and, Simplify[x + y, x + y == Unevaluated[a]] gives a...? – kglr Jan 17 '13 at 02:09
  • Simplify[x+y, x+y == boo[]] also gives boo[]. Strange. – Szabolcs Jan 17 '13 at 02:15
  • 5
    It's something I've seen posted before, but can't find. It has to do with the fact that Simplify seems to have a preference for alphabetical order in sums. So you can get the expected result by replacing a with any symbol that lexically comes after x and y. For example, use Simplify[x + y, x + y == xPlusY] or just Simplify[x + y,x + y==z]. It probably tries substitutions not in all permutations but only in alphabetical order when sums are involved. – Jens Jan 17 '13 at 07:21
  • Related questions: http://mathematica.stackexchange.com/questions/4575, http://mathematica.stackexchange.com/questions/4522. – whuber Jan 17 '13 at 16:04
  • @Jens Your observation looks too important not to put it in an answer even if it is not a full answer. – Szabolcs Jan 17 '13 at 16:46
  • A similar issue was discussed in this question: mathematica.stackexchange.com/questions/11111 – Nick Stranniy Jan 20 '13 at 01:39

2 Answers2

43

We can see from the examples in the comments to the question that Simplify (and FullSimplify which builds on it) doesn't try all permutations of substitutions. That's probably justified in general to keep the computational effort from exploding, but in your example it leads to the quirky behavior that the variable names affect the result of the simplification.

For example, you get

Clear[a, z];
Simplify[x + y, x + y == a]

(* ==> x + y *)

Simplify[x + y, x + y == z]

(* ==> z *)

The only difference is that the last assumption uses a variable name that comes lexically after the names which you would like to replace.

I think the reason for this is that Mathematica tries substitutions in sums only in a specific sequence dictated by the alphabetical order of the variables it encounters.

My heuristic conclusion from this would be that assumptions in which you would like variables to be substituted by new names should have the new names chosen such that they come lexically after the "old" names.

If this doesn't work for you, the best alternative would be to do the elimination explicitly using Eliminate.

Jens
  • 97,245
  • 7
  • 213
  • 499
23

Here's a little tool from Adam Strzebonski that deals with the issue that Jens describes.

VOISimplify[vars_, expr_, assum_: True] := 
 Module[{perm, ee, best}, perm = Permutations[vars];
  ee = (FullSimplify @@ ({expr, assum} /. Thread[vars -> #])) & /@ perm;
  best = Sort[Transpose[{LeafCount /@ ee, ee, perm}]][[1]];
  best[[2]] /. Thread[best[[3]] -> vars]]

Now:

VOISimplify[{a, x, y}, x + y, x + y == a]
a
Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371