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

1 Answer 1

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$
6
  • $\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$
    – Jojo
    Apr 25, 2018 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$ Apr 25, 2018 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$ Apr 25, 2018 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$
    – Jojo
    Apr 25, 2018 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$
    – Jojo
    Apr 25, 2018 at 21:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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