# How to use "Cases" for isolating terms of a sum in a nice way?

I'd like to isolate some terms with specific patterns within a sum that I called chunk.

chunk=-4*A[β, b]*dg[-α, η]*dg[-η, -β]*epsilong[-γ, -δ, -ϵ, -ζ]*CD[δ][A[γ, -a]]*CD[ζ][A[ϵ, -b]] -4*pertvf[α, a]*pertvf[β, b]*epsilong[-β, -γ, -δ, -ϵ]*CD[γ][A[-α, -b]]*CD[ϵ][A[δ, -a]] +2*A[β, -a]*A[γ, b]*dg[ζ, -α]*epsilong[-δ, -ϵ, -ζ, -η]*CD[-γ][dg[η, -β]]*CD[ϵ][A[δ, -b]] -4*epsilong[-α, -γ, -δ, -ϵ]*pertvf[β, b]*CD[δ][A[γ, -b]]*CD[ϵ][pertvf[-β, -a]] +A[β, -a]*A[γ, b]*A[δ, -b]*epsilong[-δ, -ϵ, -ζ, -η]*CD[-γ][dg[ϵ, -α]]*CD[η][dg[ζ, -β]] -4*A[β, b]*epsilong[-α, -γ, -δ, -ϵ]*CD[-β][pertvf[γ, -a]]*CD[ϵ][pertvf[δ, -b]] +2*A[β, b]*dg[-δ, -α]*epsilong[-β, -γ, -ϵ, -ζ]*CD[δ][A[γ, -a]]*CD[ζ][A[ϵ, -b]] -2*epsilong[-α, -γ, -δ, -ϵ]*pertvf[β, b]*CD[γ][A[-β, -a]]*CD[ϵ][A[δ, -b]] +A[β, -a]*A[γ, b]*epsilong[-γ, -δ, -ϵ, -ζ]*CD[-α][A[δ, -b]]*CD[ζ][dg[ϵ, -β]] -2*A[β, b]*epsilong[-α, -γ, -δ, -ϵ]*CD[-β][A[γ, -a]]*CD[ϵ][pertvf[δ, -b]] +8*dg[ζ, -α]*epsilong[-γ, -δ, -ϵ, -ζ]*pertvf[β, b]*CD[γ][A[-β, -a]]*CD[ϵ][A[δ, -b]] +4*A[β, b]*dg[-ϵ, -α]*epsilong[-β, -γ, -δ, -ζ]*CD[δ][A[γ, -a]]*CD[ζ][pertvf[ϵ, -b]] -2*A[β, b]*epsilong[-γ, -δ, -ϵ, -ζ]*pertvf[γ, -a]*CD[-β][dg[ζ, -α]]*CD[ϵ][A[δ, -b]] -2*A[β, -a]*A[γ, b]*epsilong[-β, -δ, -ϵ, -ζ]*CD[-γ][dg[ζ, -α]]*CD[ϵ][pertvf[δ, -b]] The terms have to be isolated in 4 different groups according to the following requirements:

1) They have exactly two dg[__,__]

2) They have exactly two pertvf[__,__]

3) They have exactly one dg[__,__] and one pertvf[__,__]

4) They have exactly one dg[__,__] or one pertvf[__,__]

In each case, it doesn't matter if they're inside the CD[__][__] functions or not.

I think 'Cases' is the best function to do this but I'll have to ask you, guys, for more suggestions or examples to gain more intuition about this commands. Until now, I've just found the following two commands to get the job partially done:

(chunk // Cases[#, dg[__,__]___] & // Apply[Plus, #] &)
(chunk // Cases[#, pertvf[__,__]___] & // Apply[Plus, #] &) The first one isolates all kind of terms with at least one dg[__,__] outside CD[__][__]. (It needs improvement to take into account thee cases where dg[__,__] is inside but, also, distinguish those cases where there are more than one dg[__,__]). The second one does the same for pertvf[__,__].

So far, I've been using: https://reference.wolfram.com/language/guide/Patterns.html

and this post: how to extract some terms out from an expression

I'm not able to incorporate the 4 requirements yet. What do you suggest, how could I do that?

I would not use Cases for this procedure.

chunk2 = List @@ chunk;
chunk3 = List @@@ chunk2 /. CD[_][x_] :> x;
chunk4 = Tally /@ Map[Head, chunk3, {2}];

group1 = Pick[chunk2, (MemberQ[#, {dg, 2}] &) /@ chunk4];
group2 = Pick[chunk2, (MemberQ[#, {pertvf, 2}] &) /@ chunk4];
group3 = Pick[chunk2, (MemberQ[#, {dg, 1}] && MemberQ[#, {pertvf, 1}] &) /@ chunk4];
group4 = Pick[chunk2, (MemberQ[#, {dg, 1}] || MemberQ[#, {pertvf, 1}] &) /@ chunk4];


I would also not use Cases. What about a bit old fashioned solution by marking the terms you are interested in explicitly, e.g., via

temp = chunk/.{dg[a__,b__]:>dgmarker * dg[a,b],pertvf[a__,b__]:>pertvfmarker * pervf[a,b]}


I assume that CD represents a covariant derivative, so you probably already know how to inform Mathematica that all *markers are constants and should be dragged out outside CD. Then you can simply get your chunks 3 and 4 by

temp2 = Coefficient[temp, dgmarker,1];
chunk3 = Coefficient[temp2, partvfmarker,1]
chunk4 = Coefficient[temp2, partvfmarker,0]


Alternatively you could use CoefficientList[temp,{dgmarker, pertvfmarker}] (however, then you need to decipher which output is which chunk) or CoefficientList[temp2,pertvfmarker] (here the output is rather obvious) to get all the chunks in one List at once.

• I like the idea, I believe it is the most suitable one because of its simplicity - that'll help later when dealing with larger sums. Thanks! Dec 6 '18 at 18:48
• Just let me add, for completeness, that (DefConstantSymbol) does the task you mentioned and informs Mathematica that all *markers are constants and should be dragged out outside CD. Dec 6 '18 at 18:55

If you do want to use Cases. This does the trick (without polluting the global context).

Plus @@ Cases[
chunk,
(dg[a__] | CD[_][ dg[a__]]) ( dg[b__] | CD[_][ dg[b__]]) _?(FreeQ[dg])
] (* case 1 *)
Plus @@ Cases[
chunk,
(pertvf[a__] | CD[_][ pertvf[a__]]) (pertvf[b__] | CD[_][ pertvf[b__]]) _?(FreeQ[pertvf])
] (* case 2 *)
Plus @@ Cases[
chunk,
( dg[a__] | CD[_][ dg[a__]]) (pertvf[b__] | CD[_][ pertvf[b__]])_?(FreeQ[pertvf | dg])
] (* case 3 *)
Plus @@ Cases[
chunk,
( dg[a__] | CD[_][ dg[a__]] | pertvf[b__] | CD[_][ pertvf[b__]]) _?(FreeQ[pertvf | dg])
] (* case 4 *)