2
$\begingroup$

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]
$\endgroup$
  • $\begingroup$ Would this work for you? x = f a[1] + g a[2]; Cases[x, factor_ a[_] -> factor] $\endgroup$ – yarchik Apr 25 '18 at 13:56
  • $\begingroup$ Can you please include an example and the expected output? Thanks! $\endgroup$ – AccidentalFourierTransform Apr 25 '18 at 14:39
  • $\begingroup$ @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. $\endgroup$ – Joe Apr 25 '18 at 19:27
4
$\begingroup$

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.

$\endgroup$
  • $\begingroup$ 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? $\endgroup$ – Joe Apr 25 '18 at 20:08
  • $\begingroup$ @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. $\endgroup$ – AccidentalFourierTransform Apr 25 '18 at 20:20
  • $\begingroup$ @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. $\endgroup$ – AccidentalFourierTransform Apr 25 '18 at 20:40
  • $\begingroup$ 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. $\endgroup$ – Joe Apr 25 '18 at 21:08
  • $\begingroup$ 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 $\endgroup$ – Joe Apr 25 '18 at 21:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.