# Pattern for a vector space basis expansion

I'd like a pattern which matches an expansion of a vector in a given basis, so mathematically any expression of the form $\mathbf{v} = \sum_{i = 1}^n v_n \mathbf{a}_n$. The basis is defined by a specific head, call this a, and the indices are any arbitrary argument of a, so the pattern for a basis vector $\mathbf{a}_n$ is a[__]. Then I can make up a pattern for a coefficient times this, $v_n \mathbf{a}_n$, as _. a[__]. I have two questions:

1) How can I make sure that the _. part doesn't have any a in it? I suspect this is with FreeQ but I'm a bit lost how to combine this with _..

2) How can I now have a sum of any number of such terms > 1? To me this could be Plus[(_. a[__])..], but when I run MatchQ[ f a[1] + g a[2], Plus[(_. a[__])..]] it evaluates to False

To give a couple of examples, let's call the pattern that I'm looking for p. (Note that my candidate p is Plus[(_. a[__])..], and I don't understand why this doesn't work). Then I'd like the following expressions to evaluate to True;

MatchQ[f a[1] + g a[2], p]
MatchQ[f a[1] + g a[2] + a[15], p]
MatchQ[Sum[v[i] a[i], {i,100}], p]
MatchQ[a[1,2,3], p]
MatchQ[a[1], p]
MatchQ[f a[anythinginhere], p]


And some examples which don't match my pattern might be

MatchQ[f a, p]
MatchQ[a a[1], p]
MatchQ[Sum[v[i] a[i], {i,100}] + 5, p]

• Would this work for you? x = f a[1] + g a[2]; Cases[x, factor_ a[_] -> factor] – yarchik Apr 25 '18 at 13:56
• Can you please include an example and the expected output? Thanks! – AccidentalFourierTransform Apr 25 '18 at 14:39
• @Yarchik, I think what you're saying is something like what I want, but I need a pattern to define a function call by, so I want to return True/False with MatchQ, and not return a list of the coefficients. @AccidentalFourierTransform I have tried to clarify. – Joe Apr 25 '18 at 19:27

You can use:

ClearAll[fun]
fun[Optional[_?(FreeQ[a])] __a] := True
fun[x_Plus] := fun /@ And @@ x
fun[_] := False

fun[f a[1] + g a[2]]               (* True *)
fun[f a[1] + g a[2] + a[15]]       (* True *)
fun[Sum[v[i] a[i], {i, 100}]]      (* True *)
fun[a[1, 2, 3]]                    (* True *)
fun[a[1]]                          (* True *)
fun[f a[anythinginhere]]           (* True *)
fun[f a]                           (* False *)
fun[a a[1]]                        (* False *)
fun[Sum[v[i] a[i], {i, 100}] + 5]  (* False *)


as expected.

If you want to use MatchQ, then the pattern is p = _?fun (e.g., MatchQ[a a[1], _?fun], which yields False).

OP asked for a more compact pattern that doesn't require an auxiliary function fun. A possibility is

p = (HoldPattern[+#] | #) &[(Optional[_?(FreeQ[a])] __a) ..];


so that, for example, MatchQ[f a[1] + g a[2], p] yields True, as required. We mention that this pattern is less clear and much less efficient than the solution above. I personally wouldn't use it, but to each their own.

• OK thankyou, I like this and it does solve my problem. Is it possible to do it with a shorter syntax that doesn't involve defining a separate function? And do you know why my Plus[(_. a[__])..] doesn't work? – Joe Apr 25 '18 at 20:08
• @Joe I don't think the code can get much shorter than this. There are several cases that have to be checked separately. Also, . is Dot, which is not the same thing as multiplication Times. – AccidentalFourierTransform Apr 25 '18 at 20:20
• @Joe You have to replace Dot for Times, and you have to hold the pattern (for otherwise Plus[X] evaluates to X directly). I have updated the answer with the solution, but it is inefficient, so my recommendation is to use the first option, with fun. – AccidentalFourierTransform Apr 25 '18 at 20:40
• Ahhh thank you, so Plus gets evaluated and HoldPattern was what I was missing. . is Dot, and _. is Optional[Blank[]], reference.wolfram.com/language/tutorial/… gives a nice description of some usage cases. It removes the need for the different cases, but I can't work out how to combine it with ?FreeQ[a]. Maybe I just didn't try very hard. – Joe Apr 25 '18 at 21:08
• So HoldPattern[Plus[_. a[__] ..]] is nearly what I wanted, but it's just missing the FreeQ bit. I tried to put the condition on _. via (x : _.) /; FreeQ[x, a], but this pulls up an error message about bad optional argument for some reason which I don't understand – Joe Apr 25 '18 at 21:18