Re: [sympy] Conditional substitution
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
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
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
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
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
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
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
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.