On 06/01/2022 22:19, Oscar Benjamin wrote:
On Thu, 6 Jan 2022 at 21:23, David Bailey <[email protected]> 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

Thanks again, Oscar for that second helping of insight into how to use Wild!

If only you could be cloned about 6 times, a couple of your copies could create some SymPy documentation that would sparkle with gems like this.

David

--
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 [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/sympy/e3ad99be-a44e-2c7c-43ee-fd4c78d81705%40dbailey.co.uk.

Reply via email to