How to group certain symbolic expressions?

For example, I have the following expression :

A( 2 x1 + B(y1 + y2) + 2 x2 )


How do I make the output look like this (grouping (x1 + x2) and (y1 + y2) terms together) ?

2A (x1 + x2) + A B (y1 + y2)


I don't know why Simplify doesn't group (x1 + x2) together but just gives:

A (2 x1 + 2 x2 + B (y1 + y2))


I can use Collect to get (y1 + y2) after Simplify but how about (x1 + x2) ?

Remember this is just a simple example, I would have a much more complicated terms involving (x1 + x2) and (y1 + y2), so a method with no operation on the constants (2A and A B) would be great.

-

migrated from stackoverflow.comNov 16 '12 at 15:27

This question came from our site for professional and enthusiast programmers.

Perhaps replacing with dummies for simplification?

doThat[expr_, vars_List] :=
Expand[Simplify[
expr /. Flatten[
Solve[# == ToString@#, First@Variables@#] & /@ vars]],
Alternatives @@ ToString /@ vars] /.


So

doThat[c a (x1 + x2) + d a (x1 + x2) + a (y1 + y2), {x1 + x2,
y1 + y2}]


gives

a (c + d) (x1 + x2) + a (y1 + y2)

-
Thanks, this can take care of the minus sign if any. –  Fred G Dec 1 '12 at 6:21
@FredG haha. What about the edited code? –  Rojo Dec 1 '12 at 7:00

Maybe this will get you started :

expr = A*(2*x1 + B*(y1 + y2) + 2*x2) ;

rules = {c_ x1 + c_ x2 -> c (x1 + x2), d_ y1 + d_ y2 -> d (y1 + y2)} ;

(expr // Expand) //. rules

(* 2 A (x1 + x2) + A B (y1 + y2) *)

-
BTW, how do you make a pattern for {c_ x1 - c_ x2 -> c (x1 - x2)} ? It won't recognize the minus sign. –  Fred G Dec 1 '12 at 5:58
In the simple cases you don't need much; expr = c x1 - c x2; expr//Simplify will do. –  b.gatessucks Dec 1 '12 at 9:15
@FredG If you don't know the recommended way (as well as the most general) to solve the problem is based on this approach Collect[expr,var, h]. You can apply it for much more involved algebraic expressions not worrying to play around with rules or whatever else. Look at my answer carefully. –  Artes Dec 2 '12 at 2:52

One can apply a proper function as the third argument of Collect:

From documentation :

Collect[expr,var,h]  applies h to the expression that forms the coefficient of each term
obtained.


Here we can use B as var and Factor as h :

Collect[ A( 2x1 + B(y1 + y2) + 2x2), B, Factor]

2 A (x1 + x2) + A B (y1 + y2)


Instead of Factor one can use here Simplify or FullSimplify, and {B, A} instead of B. In full generality we cannot say what is the most appropriate function, it depends rather on a case-by-case basis. Sometimes one can get expected forms using only appropriate options in Simplify and FullSimplify like : ComplexityFunction, ExcludedForms, TransformationFunctions. More can be found in tutorials e.g. Simplification or Simplification Control in Algebraic Transformations

-

I do not know how to make it more directly, but you can hack it like this

expr = A ( 2x1 + B (y1 + y2) + 2x2);
Collect[ expr, B];
Plus @@ { Simplify[ %[[1]]] , %[[2]]}


which gives

(*  2 A ( x1 + x2) + A B ( y1 + y2)  *)


not too pretty. I am sure there is a better way.

-
Thanks for the answer but as stated above, I have much more complicated expressions than just that B. I can't Collect each then simplify again and look again to see what to Collect next... –  Fred G Nov 16 '12 at 1:07

Consider this as an additional rule-based approach:

 expr = A (2 x1 + B (y1 + y2) + 2 x2);
(expr /. {x1 -> X - x2, y1 -> Y - y2} // Simplify) /. {X -> (x1 + x2),
Y -> (y1 + y2)}


yielding the answer: A (2 (x1 + x2) + B (y1 + y2))

-