To answer the question as asked, we modify the code as follows:
replacementRule = Plus[
Dot[FRONT__, AA__, BACK__]
, Dot[FRONT__, BB__, BACK__]
] :> Dot[FRONT, Plus[Dot[AA], Dot[BB]], BACK]}]
w.a.b.r + w.c.d.r /. replacementRule
First, we have changed -> (Rule) to :> (RuleDelayed) so that when the expression is re-written, it will write it using the sub-expressions that match FRONT, AA, etc. instead of merely putting in the symbols FRONT, AA, etc.
Second, as the OP noted, AA__ matches a Sequence; in this case AA__ matches Sequence[a, b]. The re-write will not "remember" that a and b are Dotted, so we have to add this in by hand by wrapping AA with Dot.
As to the question that the OP posed in the comments: the OP wants to also re-write more complicated expressions. For instance, write w.g.a.b.r + w.g.c.d.r as w.g.(a.b + c.d).r. With the code as above, we get
w.g.a.b.r + w.g.c.d.r /. replacementRule
(* w.(g.a.b + g.c.d).r *)
The reason is that by default, the pattern matching algorithm matches the longest expression starting from the end of the list. To see what I mean, note that
{a, b, c, d} /. {x__, y__} :> {f[x], g[y]}
results in
{f[a], g[b, c, d]}
The patterns x__ and y__ both stand for sequence of one or more expressions, but since the pattern matching tries to match the longest matching expressions starting from the end of the list, y__ gets matched to Sequence[b, c, d], leaving x__ to match a.
In the OP's example, BACK__ matches only r because it has to match the same sequence of expressions in both expressions that are added together. However, since AA__ and BB__ can be different, the pattern matching eats up as many expressions to the left of r as it can, and this includes the g, leaving FRONT__ to match w.
To fix the problem, we force the pattern-matching to match FRONT__ to the longest sequence of expressions by adding wrapping it in Longest. Since FRONT__ is the same in both expressions that are added together, it will match the longest sub-expression that is the same. Thus, we modify replacementRule as
replacementRule = Plus[
Dot[Longest[FRONT__], AA__, BACK__]
, Dot[FRONT__, BB__, BACK__]
] :> Dot[FRONT, Plus[Dot[AA], Dot[BB]], BACK]}]
in which case
w.g.a.b.r + w.g.c.d.r /. replacementRule
yields
(* w.g.(a.b + c.d).r *)
Note that we don't need to modify the pattern as written to rewrite w.g.a.b.f.r + w.g.c.d.f.r as w.g.(a.b + c.d).f.r since, again, the pattern-matching matches the longest expression it can starting from the end of the list.
:>in place of->and changePlus[AA,BB]toPlus[Dot[AA], Dot[BB]]. (You saw thatAAis matchingSequence[a, b], so you've got to wrap it inDot; otherwise,Plus[AA, BB]isPlus[a, b, c, d].) – march Jul 27 '15 at 17:18w.g.a.b.r+w.g.c.d.rI want to getw.g.(a.b+c.d).r, but instead I getw.(g.a.b+g.c.d).r. How do I make sure that FRONT is the longest matching expression and not just the first term? – space_voyager Jul 27 '15 at 17:23FRONT__'s inLongest. That will force the pattern matching to find the longest sequence that matches. – march Jul 27 '15 at 17:25Dotthat I have seen in the past few days, in which one would expect Simplify to simplify the expression, but it does not. – bbgodfrey Jul 27 '15 at 18:17Dothelp page says thatDotremains unevaluated if one or more of its arguments is something other than aListorSparseArray. – march Jul 27 '15 at 18:22