# Simple problem with pattern matching in Mathematica

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

-
Just so I understand your problem: you want all instances of Subtract[a b something, c d something] to be replaced by e*something, or do you need something more general? In any event, there is the built-in function Factor[] which might be apropos... – J. M. Aug 5 '11 at 5:28
I'm hoping that dealing with the minus sign issue will solve my more general problem. The real problem I'm trying to solve is more complicated, or rather there are more terms, but I think I've distilled the problem down to the source of my difficulty. I've tried Factor[], among other things, but so far I haven't been able to construct a replacement rule that works consistently. – Keith Aug 5 '11 at 5:44
Sorry, I'm still trying to figure out how to take expressions from Mathematica and paste them here in a sensible way. – Keith Aug 5 '11 at 6:39
"I'm still trying to figure out how to take expressions from Mathematica and paste them here in a sensible way." - apply InputForm[] to whatever output Mathematica spits back. – J. M. Aug 5 '11 at 6:46
I'd still love to have an answer to the original question if anyone is interested. – Keith Aug 9 '11 at 1:23

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]]
]

-

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.

-
Unfortunately both of your rules produce unexpected results when the coefficient is negative. Naming the first subRuleMW1 I get c*d - a*b /. subRuleMW1 produces e. For the second, subRuleMW2 I get c*d - a*b /. subRuleMW2 produces e. – Keith Aug 20 '11 at 6:29
@Keith I do not understand what you are trying to accomplish. I am sorry if that resulted in giving you bad code. If looking at the FullForm of your expressions does not allow you to construct working rules yourself, please post a series of examples of input and desired output, and I will try again. – Mr.Wizard Aug 20 '11 at 6:38
I was not aware of RepeatedNull, +1. – rcollyer Sep 29 '11 at 14:58

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.

-
If anyone is interested in the Coefficient[] based solution to the problem posed in the comments above, I'll be happy to post that as well. – Keith Aug 9 '11 at 23:14
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. – Keith Aug 10 '11 at 2:16