5

When I input this:

MatchQ[x*SF[a,b] + y*SF[c,d], Plus[Times[x,SF[a,b]],Times[y,SF[c,d]]]] 

I get "True" as expected. But If I change it to:

MatchQ[x*SF[a,b] + y*SF[c,d], Plus[Times[_,SF[_,_]],Times[_,SF[_,_]]]] 

Which ought to be more general, it returns false.

Why does this happen? I think it's evaluate the Plus, and return a pattern like Times[2,,SF[,_]]. But how do I make it stop doing that?

My goal is to Match the pattern for expressions like x*SF[a,b] + y*SF[c,d] + z*SF[e,f] ... So what do I have to do to fix this?

2 Answers2

9

You need to realize that pattern expressions evaluate just like any other in Mathematica. Let's look at how this plays out for each pattern you gave:

Plus[Times[x, SF[a, b]], Times[y, SF[c, d]]]

Plus[Times[_, SF[_, _]], Times[_, SF[_, _]]]
x SF[a, b] + y SF[c, d]

2 _ SF[_, _]

Clearly they are not equivalent. In this particular case you can use HoldPattern to prevent this unwanted "simplification" from taking place:

MatchQ[
  x*SF[a, b] + y*SF[c, d], 
  Plus[Times[_, SF[_, _]], Times[_, SF[_, _]]] // HoldPattern
]
True

Be aware that due to the Orderless attribute (and others) of Plus, Times, etc., you may still encounter unexpected behavior, e.g.:

Different behaviours of Default Argument

Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371
  • don't you think that the first argument to Times _ is to greedy and should be changed to a __ instead? – Stefan Jun 22 '13 at 20:59
  • @Stefan I suppose it depends on what you expect it to match but perhaps I don't understand your concern. – Mr.Wizard Jun 22 '13 at 21:01
  • if you use _, this is in that specific case the whole expression x,SF[a,b]],Times[y,SF[c,d], since _ is greedy like its regex equivalent *. If you use __ instead it is less greedy (like +?) and the expressions get evaluated correctly... – Stefan Jun 22 '13 at 21:04
  • @Stefan I'm afraid I don't understand. The parts I expect to correspond appear to, in e.g. Replace[ x*SF[a, b] + y*SF[c, d], q : Plus[r : Times[s : _, t : SF[_, _]], Times[_, SF[_, _]]] :> {q, r, s, t} ] -- is a part of this pattern (q, r, s, t) is not as you expect? – Mr.Wizard Jun 22 '13 at 21:14
  • @Mr.Wizard No. Your answer is brilliant, but what I tried to say (see my answer) is, if you change the pattern in Times from '_' to '__' it matches. Even with your Replacement code. – Stefan Jun 22 '13 at 21:16
  • @Anon You're welcome. Also take a look at the function Verbatim which while not applicable here (that I can see) is also important for making certain patterns work as desired. – Mr.Wizard Jun 22 '13 at 21:17
  • sorry the double underscore is hard to display in comments... – Stefan Jun 22 '13 at 21:20
  • @Stefan NFA - "National Fibromyalgia Association?" :o) It works because the named patterns prevent the automatic simplification that breaks the original code. (Wrap code in back-ticks in comments; double back-ticks of necessary.) – Mr.Wizard Jun 22 '13 at 21:21
  • :))...luv it!...the name patterns prevent....let me think about that for a while... – Stefan Jun 22 '13 at 21:27
0

I always struggle with the pattern matching rules as well.

The first thing that is suspicious to me is the greedy _ in your Times expression.

_, just like its regex counterpart *, is greedy and will match everything. But, if you change that one to __ (regex + or even better +?) your matching succeeds.

MatchQ[x*SF[a, b] + y*SF[c, d], Plus[Times[__, SF[_, _]], Times[_, SF[_, _]]]]

(* Out: True *)
MarcoB
  • 67,153
  • 18
  • 91
  • 189
Stefan
  • 5,347
  • 25
  • 32
  • the more i look at it, the more doubtful my answer seems to me...the best would be maybe to capture the groups if this really matches the expression at all.... – Stefan Jun 22 '13 at 21:13
  • 2
    I don't think the original issue has anything to do with greedy patterns but rather automatic "simplification", which you (partly) avoid here due to use of both _ and __ -- however, if you change both Times expressions to use __: Plus[Times[__, SF[_, _]], Times[__, SF[_, _]]] it will evaluate to 2 __ SF[_, _] – Mr.Wizard Jun 22 '13 at 21:19
  • @Mr.Wizard. Yes exactly. This is the point, where it gets weird to me. And that's why I expressed doubts about my answer...but it works; that you've to agree with. Even with your Replace expression above...I'm confused. – Stefan Jun 22 '13 at 21:24
  • I imagine we are talking past each other and I apologize for that. I'm merely trying to point out that the original pattern is analogous to Times["x", "other"] + Times["x", "other"] evaluating to 2 "other" "x" and your change is analogous to Times["y", "other"] + Times["x", "other"] remaining separate terms. ("other" "x" + "other" "y") – Mr.Wizard Jun 22 '13 at 21:27
  • 2
    @Mr.Wizard You don't have to apologise. It is the fault of the"National Fibromyalgia Association" and her little sister the "non deterministic finite automata". Puzzling creatures... :). Cheers. Always a pleasure to me. – Stefan Jun 22 '13 at 21:31