9

How do I tell mathematica to do this replacement smartly? (or how do I get smarter at telling mathematica to do what i want)

expr = b + c d + ec + 2 a;
expr /. a + b :> 1

Out = 2 a + b + c d + ec

I expect the answer to be a + cd + ec + 1. And before someone suggests, I don't want to do a :> 1 - b, because for aesthetic purposes, I'd like to have both a and b in my equation as long as the a+b = 1 simplification cannot be made.


In addition, how do I get it to replace all instances of 1-b, -b+1 or -1+b, b-1 with a or -a respectively and vice versa?

Here's an example for this part:

expr = b + c (1 - a) + (-1 + b)(a - 1) + (1 -a -b) d + 2 a
  • 3
    `Replace` replaces subexpressions based on the structural equivalence (see `FullForm`), it doesn't perform any algebraic manipulations. You might try using `Reduce`, which is designed for these cases. I can't test it now though. – Norbert P. Jun 02 '11 at 04:53
  • 5
    Might want to look into PolynomialReduce if the expression will generally be a polynomial. – Daniel Lichtblau Jun 02 '11 at 10:31

2 Answers2

19

You can use a customised version of FullSimplify by supplying your own transformations to FullSimplify and let it figure out the details:

In[1]:= MySimplify[expr_,equivs_]:= FullSimplify[expr,
          TransformationFunctions ->
            Prepend[
              Function[x,x-#]&/@Flatten@Map[{#,-#}&,equivs/.Equal->Subtract],
              Automatic
            ]
        ]
In[2]:= MySimplify[2a+b+c*d+e*c, {a+b==1}]
Out[2]= a + c(d + e) + 1

equivs/.Equal->Subtract turns given equations into expressions equal to zero (e.g. a+b==1 -> a+b-1). Flatten@Map[{#,-#}&, ] then constructs also negated versions and flattens them into a single list. Function[x,x-#]& /@ turns the zero expressions into functions, which subtract the zero expressions (the #) from what is later given to them (x) by FullSimplify.

It may be necessary to specify your own ComplexityFunction for FullSimplify, too, if your idea of simple differs from FullSimplify's default ComplexityFunction (which is roughly equivalent to LeafCount), e.g.:

MySimplify[expr_, equivs_] := FullSimplify[expr,
  TransformationFunctions ->
    Prepend[
      Function[x,x-#]&/@Flatten@Map[{#,-#}&,equivs/.Equal->Subtract],
      Automatic
    ],
  ComplexityFunction -> (
    1000 LeafCount[#] + 
    Composition[
      Total,Flatten,Map[ArrayDepth[#]#&,#]&,CoefficientArrays
    ][#] &
  )
]

In your example case, the default ComplexityFunction works fine, though.

Thies Heidecke
  • 2,497
  • 1
  • 23
  • 25
  • wow thanks. It'll take me a little while before i fully understand that. –  Jun 02 '11 at 07:31
  • 1
    +1, for the construct `Function[x, x-#]&` alone. I was under the mistaken impression that wouldn't work, so it seems I need to re-evaluate some of my assumptions. – rcollyer Jun 02 '11 at 12:39
  • +1 for the Function and the clear explanation. Even with this, it took me a few minutes to fully grasp it. – Sjoerd C. de Vries Jun 03 '11 at 21:15
5

For the first case, you might consider:

expr = b + c d + ec + 2 a

PolynomialReduce[expr, {a + b - 1}, {b, a}][[2]]

For the second case, consider:

expr = b + c (1 - a) + (-1 + b) (a - 1) + (1 - a - b) d + 2 a;

PolynomialReduce[expr, {x + b - 1}][[2]]

(% /. x -> 1 - b) == expr // Simplify

and:

PolynomialReduce[expr, {a + b - 1}][[2]]

Simplify[% == expr /. a -> 1 - b]
Mr.Wizard
  • 24,179
  • 5
  • 44
  • 125