1
$\begingroup$

I'm having trouble setting a pattern for simplifying a complex expression. I've distilled the question down to the simplest case where Mathematica seems to fail.

I set up a simple rule based on a pattern:

simpRule = a b v___ - c d v___ -> e v 

which works on the direct case

a b - c d /. simpRule e 

but fails if I simply add a minus sign.

-a b + c d /. simpRule -a b + c d 

How do I go about writing a more robust rule? Or perhaps there's a better way to go about performing simplifications of this sort?

Thanks, Keith

  • 1
    I'd still love to have an answer to the original question if anyone is interested.2011-08-09

3 Answers 3

2

Eventually I posted the same question on MathGroup and received an answer which I think is superior to the one I posted before. I thought I should add it here.

As before, this is not strictly a replacement rule, instead it uses Mathematica's PolynomialReduce[], but it seems to be quite robust and if people come across this question they should be aware of this solution.

simpMeth[expr_] := Module[{pExpr},   pExpr = PolynomialReduce[expr, a b - c d, {b, d}];   pExpr[[1, 1]] e + pExpr[[2]]  ] 
1

You need to be aware of the FullForm of the expressions you are working with to correctly use replacement rules. Consider the FullForm of the two expressions you use ReplaceAll (/.) on:

 a b - c d // FullForm -a b + c d // FullForm 
(* Out *) Plus[Times[a, b], Times[-1, c, d]]
(* Out *) Plus[Times[-1, a, b], Times[c, d]]

From this you can see how the negation is internally represented as multiplication by -1, and therefore, why your rule matches differently. One way to allow for the alternative pattern is this:

rule = (-1 a b v___ | a b v___) + (-1 c d v___ | c d v___) -> e v; 

This makes use of Alternatives.

Another, somewhat more opaque way is:

rule = (-1 ...) a b v___ + (-1 ...) c d v___ -> e v; 

Which makes use of RepeatedNull.

  • 0
    I was not aware of `RepeatedNull`, +1.2011-09-29
0

Here's the best solution I've come up with so far. (Yes, I'm answering my own question, but I thought it would be nice to have some resolution to this question.)

simp[expr_] := Module[{fab,fcd,fabmcd,f0},   {fab,fcd} = {Coefficient[expr, a b], Coefficient[expr, c d]};   fabmcd = (1/2)(fab - fcd);   f0 = Simplify[expr - fabmcd (a b - c d)];   f0 + fabmcd e ] 

Here's how it works:

simp[a b - c d] produces e,

simp[-a b + c d] produces -e and

simp[a b - c d + c] produces e + c.

My original intention was to make a more robust pattern rule, however I haven't figured out how to do that. Instead the solution I'm presenting here is based on using Mathematica's Coefficient[] function. In my experience, Coefficient[] and CoefficientList[] can be used to do quite sophisticated expression rearrangement. None the less, someday I'd like figure how to do sophisticated pattern matching.

  • 0
    I don't have sufficient reputation to vote up anybody's comments, however I would like to give some credit to Andrew. In one of his comments above he outlines a technique where a single term is used to identify the coefficient on an a1 term. It was this approach that got me thinking, and ultimately led to the answer I've posted.2011-08-10