Re: [sympy] Conditional substitution

2022-01-06 Thread David Bailey

On 06/01/2022 22:19, Oscar Benjamin wrote:

On Thu, 6 Jan 2022 at 21:23, David Bailey  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 sympy+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/sympy/e3ad99be-a44e-2c7c-43ee-fd4c78d81705%40dbailey.co.uk.


Re: [sympy] Conditional substitution

2022-01-06 Thread Oscar Benjamin
On Thu, 6 Jan 2022 at 21:23, David Bailey  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.


Re: [sympy] Conditional substitution

2022-01-06 Thread David Bailey

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.

--
Oscar

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!.


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 sympy+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/sympy/82e8af14-7131-4ff2-c804-4eae83818c04%40dbailey.co.uk.


Re: [sympy] Conditional substitution

2022-01-06 Thread Oscar Benjamin
On Thu, 6 Jan 2022 at 14:41, David Bailey  wrote:
>
> Dear group,
>
> A substitution like this is easy to make with SymPy:
>
> (a*x**2+b*x+c).subs(x,y)
>
> However, how can I make a conditional substitution, such as:
>
> a) One that would replace even powers of x only.
>
> b) One which would replace even powers of x by y**(n/2) resulting in
> a*y**7+b*x+c? I.e. one where parts of the object being replaced would be
> available to form part of the result - thus x**14 would contribute '7'
> to the resultant expression.

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.

--
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/CAHVvXxTz4FdkMPYqWH631zVjPjMLqa3Wy57TF87b510%3DztxtLA%40mail.gmail.com.


[sympy] Conditional substitution

2022-01-06 Thread David Bailey

Dear group,

A substitution like this is easy to make with SymPy:

(a*x**2+b*x+c).subs(x,y)

However, how can I make a conditional substitution, such as:

a) One that would replace even powers of x only.

b) One which would replace even powers of x by y**(n/2) resulting in 
a*y**7+b*x+c? I.e. one where parts of the object being replaced would be 
available to form part of the result - thus x**14 would contribute '7' 
to the resultant expression.


Thanks in anticipation!

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 sympy+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/sympy/f4c4ab4c-d84f-cd9b-1e6d-0e0260804c1d%40dbailey.co.uk.


Re: [sympy] Conditional substitution and on the fly dictionary creation

2013-04-27 Thread Aaron Meurer
It should work with a custom dictionary. At the very least, it will
work with any iterator or (old, new) pairs.

You could also make f symbolic and unevaluated by default, then call
doit after the substitution. It won't be 100% efficient if the same f
will appear more than once, though.

Aaron Meurer

On Apr 27, 2013, at 10:51 AM, Alan Bromborsky  wrote:

> On 04/27/2013 12:40 PM, Alan Bromborsky wrote:
>> consider the sympy expressions -
>>
>> a = a_1*e_1+...+a_n*e_n
>>
>> b = b_1*e_1+...+b_n*e_n
>>
>> where the a_i's and the b_i's are commutative sympy expressions and the
>> e_i's are non-commutative symbols and you have a dictionary
>>
>> mul_dict = {e_i*e_j: f(e_i,e_j)}
>>
>> if mul_dict is fully populated then
>>
>> a*b = (a*b).subs(mul_dict)
>>
>> However many of the entries in the dictionary will never be used since most 
>> of
>> the a_i's and b_i's will be zero, but you don't know which ones ahead of the 
>> multiplication.
>>
>> Likewise the function  f(e_i,e_j) is know but time consuming to evaluate.
>>
>> Is there a way to do a subsitution in a sympy expression where if e_i*e_j is 
>> a key subs will use
>> the dictionary, but is e_i*e_j is not a key f(e_i,e_j) will be evaluated, 
>> added to the dictionary, and
>> the substitution performed?
> I guess the real question is is there a way of use a custom dictionary class 
> Mydict(dict) with the sympy
> subs operation?
>
> --
> 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 post to this group, send email to sympy@googlegroups.com.
> Visit this group at http://groups.google.com/group/sympy?hl=en-US.
> For more options, visit https://groups.google.com/groups/opt_out.
>
>

-- 
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 post to this group, send email to sympy@googlegroups.com.
Visit this group at http://groups.google.com/group/sympy?hl=en-US.
For more options, visit https://groups.google.com/groups/opt_out.




Re: [sympy] Conditional substitution and on the fly dictionary creation

2013-04-27 Thread Alan Bromborsky

On 04/27/2013 12:40 PM, Alan Bromborsky wrote:

consider the sympy expressions -

a = a_1*e_1+...+a_n*e_n

b = b_1*e_1+...+b_n*e_n

where the a_i's and the b_i's are commutative sympy expressions and the
e_i's are non-commutative symbols and you have a dictionary

mul_dict = {e_i*e_j: f(e_i,e_j)}

if mul_dict is fully populated then

a*b = (a*b).subs(mul_dict)

However many of the entries in the dictionary will never be used since 
most of
the a_i's and b_i's will be zero, but you don't know which ones ahead 
of the multiplication.


Likewise the function  f(e_i,e_j) is know but time consuming to evaluate.

Is there a way to do a subsitution in a sympy expression where if 
e_i*e_j is a key subs will use
the dictionary, but is e_i*e_j is not a key f(e_i,e_j) will be 
evaluated, added to the dictionary, and

the substitution performed?




I guess the real question is is there a way of use a custom dictionary 
class Mydict(dict) with the sympy

subs operation?

--
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 post to this group, send email to sympy@googlegroups.com.
Visit this group at http://groups.google.com/group/sympy?hl=en-US.
For more options, visit https://groups.google.com/groups/opt_out.




[sympy] Conditional substitution and on the fly dictionary creation

2013-04-27 Thread Alan Bromborsky

consider the sympy expressions -

a = a_1*e_1+...+a_n*e_n

b = b_1*e_1+...+b_n*e_n

where the a_i's and the b_i's are commutative sympy expressions and the
e_i's are non-commutative symbols and you have a dictionary

mul_dict = {e_i*e_j: f(e_i,e_j)}

if mul_dict is fully populated then

a*b = (a*b).subs(mul_dict)

However many of the entries in the dictionary will never be used since 
most of
the a_i's and b_i's will be zero, but you don't know which ones ahead of 
the multiplication.


Likewise the function  f(e_i,e_j) is know but time consuming to evaluate.

Is there a way to do a subsitution in a sympy expression where if 
e_i*e_j is a key subs will use
the dictionary, but is e_i*e_j is not a key f(e_i,e_j) will be 
evaluated, added to the dictionary, and

the substitution performed?




--
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 post to this group, send email to sympy@googlegroups.com.
Visit this group at http://groups.google.com/group/sympy?hl=en-US.
For more options, visit https://groups.google.com/groups/opt_out.