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.