On Thu, 6 Jan 2022 at 21:23, David Bailey <d...@dbailey.co.uk> wrote:
>
> On 06/01/2022 16:41, Oscar Benjamin wrote:
> > You can use replace to make arbitrary conditions on substitution.
> > There are different syntaxes so here's how you do it using wild
> > pattern-matching:
> >
> > In [15]: expr = (a*x**14 + b*x + c)
> >
> > In [16]: expr
> > Out[16]:
> >     14
> > a⋅x   + b⋅x + c
> >
> > In [17]: w = Wild('w')
> >
> > In [18]: expr.replace(x**w, lambda w: y**(w/2) if w.is_even else x**w)
> > Out[18]:
> >     7
> > a⋅y  + b⋅x + c
> >
> > Here's how you do it with just functions:
> >
> > In [19]: query = lambda e: e.is_Pow and e.base == x and e.exp.is_even
> >
> > In [20]: replacer = lambda e: y**(e.exp/2)
> >
> > In [21]: expr.replace(query, replacer)
> > Out[21]:
> >     7
> > a⋅y  + b⋅x + c
> >
> > Since query and replacer can be completely arbitrary functions any
> > kind of replacement rule can be implemented in this way.
> >
> Thanks very much for that Oscar, your solution looks extremely useful
> and general. Somehow I hadn't realised the power of Wild(), although I
> knew Wild existed. The Wild/replace method looks most useful to me - I
> get easily lost in multiple lambda's!.

The lambdas can get confusing. The point to note though is that a
lambda function is just a shorthand for creating a Python function
e.g.

    f = lambda e: e.is_Pow

is equivalent to

    def f(e):
        return e.is_Pow

What that means is that in the functional form of replace you can pass
completely arbitrary functions for the query and the replacer. The
query function is given a subexpression as query(e) and returns True
or False to determine if a replacement should be made. If query(e)
returns True then replacer(e) generates the replacement expression so
if f and g are functions then

    expr.replace(f, g)

looks at all subexpressions e in expr and if f(e) is True then e is
replaced by g(e). That's about as general as you can get for
replacements. In the Wild form the query function is replaced by a
pattern so it looks more like pattern-matching. The pattern is easier
to read but pattern matching is strictly less powerful than being able
to use a completely arbitrary query function.

The pattern form is especially nice if you use a pattern for both
query and replacement e.g.:

In [1]: w = Wild('w')

In [2]: (sin(x)**2 + tan(x)).replace(sin(w), exp(w))
Out[2]:
 2⋅x
ℯ    + tan(x)

--
Oscar

-- 
You received this message because you are subscribed to the Google Groups 
"sympy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sympy+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/sympy/CAHVvXxQh9vxXyHBnB0-mPP8FRP13jK27ASkEkuwU-akBwZf2WA%40mail.gmail.com.

Reply via email to