(a+b+c).match(a+w) ==> {w: b+c}
(a+b).match(w+a) ==> {w: b}
x.match(Add(w, evaluate=False)) ==> {w: x}
These rules are also available in Wolfram Mathematica.
There are some results which come out as an attempt to apply some kind of equation solving:
In [20]: (x*y).match(x/w)
Out[20]:
⎧ 1⎫
⎨w: ─⎬
⎩ y⎭
I would expect this result by calling:
In [29]: solve(Eq(x*y, x/w), w)
Out[29]:
⎡1⎤
⎢─⎥
⎣y⎦
I was wondering, what are the pattern matching rules for this awareness? This goes beyond the three rules I pointed out hereabove. Technically, mathematical-aware patterns may yield infinite results as long as they are combined with equation solvers.
Wolfram Mathematica seems not to have any solver-awareness, that is, the previous pattern does not match:
In[12]:= (x y) /. x/w_ -> {w}
Out[12]= x y
It would be useful to keep SymPy's pattern matching rules as close as possible to those of Mathematica. I suggest to remove redundant results relying on solvers, or maybe add a parameter to the matcher to turn it off. What do you think?
These 5 properties should be the extensions over a structural matcher introduced by SymPy's matcher.
In examples:
class Basic(object):
...
is_Associative = False # Basic(1, 2) != Basic(1, Basic(2))
is_one_param_identity = False # Basic(1) != 1
def get_permutation_iter(self):
def f():
yield self.args
return f
inverse_matcher = None
class Mul(Expr):
...
is_Associative = True
is_one_param_identity = True # Mul(x) == x
def get_permutation_iter(self):
def f():
... iter through all possible permutations such that
... the non-commutative parts do not commute
return f
inverse_match = "x -> Pow(x, -1)"
In this way, the information about how a specific type behaves under pattern matching can be easily customized. The generator of allowed permutations would thus be useful in cases where the commutation properties are complicated, for example when they are specified by a generic element of the symmetric group for the object instance.
Anyways, I would consider this task as low priority. Better first concentrate on import the RUBI ruleset into SymPy.
In [2]: x = symbols('x', real=False)
In [3]: w = Wild('w', real=True)
In [4]: x.match(w)
Out[4]: {w_: x}
Am 03.09.2014 um 02:07 schrieb Richard Fateman:
> Sure. Unlikely to be easy to do by simply hacking on trees. Here's a
> classic pattern:
>
> a*x^2+b*x+c. a,b,c are pattern variables. x, in this context, is a
> symbolic constant.
> You might like to also impose a,b,c free of x, and a is non-zero, to
> complete the pattern "quadratic in x"
>
> match this against the expression
>
> (45*x+10)^2/5 +q*x+pi
>
> Yes this can be done, but can you do it by placing attributes on + and *?
Easily, actually.
Just store the entire pattern, including preconditions, in the attribute
of the top-level node (+ in this case).
Actually Python makes this relatively easy since reifying functions is
fussless and reifying expressions as lambdas is lightweight (can't beat
Haskell or Lisp in that area, of course).
This would probably also make it easier to check for pattern overlap.
> I suppose there is also the question of whether you want this to match or
> not.
That's a strategy question: Which of multiple applicable rules do we
want to apply?
RUBI requires that at most one rule be applicable at a time (i.e. no
pattern overlap), so strategy is encoded in the preconditions of the
rules and it's a non-issue.