Dear All,
I was hoping to use SymPy patterns to perform a transformation equivalent to this Mathematica code:
f[a + 2*b + c] /. f[x_] -> g[x]
g[a + 2 b + c]
I.e. I wanted to replace calls to the (undefined) function f with calls to the function g with the same arguments.
I tried the following, with f and g set up as undefined functions:
patt=Wild("p1")
f(a+2*b+c).subs(f(patt),g(patt))
f(a + 2*b + c)
Is there a way to do 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+un...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/sympy/87d22d50-3fd2-101e-7dc2-ad90843b06ca%40dbailey.co.uk.
Hello David,in Sympy there are three substitution methods:1. subs: it is the most generic.2. xreplace: it only replace the exact expression you provide.3. replace: this is the most powerful, as it allows for "pattern matching operations".
In your case, I would do something like this:
f, g = symbols("f, g", cls=Function)
a, b, c = symbols("a:c")
expr = f(a + 2 * b + c)
expr.replace(f, g)
Thanks for that quick response! Unfortunately I don't think your solution really generalises. I mean suppose I wanted to replace
f(anything) by g(5*anything**2)
(again that would be easy in Mathematica - the transformation
would be f[x_] -> g[5*x^2] )
I mean, clearly those patterns are there to solve problems like that, and I can't figure out how to use them effectively.
David
Thanks Oscar,
Wow - that is ingenious, and it will take me a while to think out how much of Mathematica's pattern functionality can be achieved this way.
However, I am curious, What are the patterns produced by the Wild function actually used for - or are these an attempt to reproduce Mathematica's pattern matching functionality (which is really neat) that is yet to be finished?
David
Hi David (CCing the list),
Yes, I know - I need to remember to press"Reply List" rather than "Reply" in Thunderbird!
I haven't used Mathematica's pattern functionality myself so I'm interested to hear how it compares.
Sure - to use your example:
Out[2]= Cos[b + a x]
p1_ matches anything and p1_. also matches nothing by default in
the context of multiplication (i.e. 1). Since p2_. is used in the
context of addition, it matches zero by default. On the RHS there
are referred to as p1 and p2 (which implies some rather
complicated scoping rules that only apply within the replacement
operation.
Here I make use of both the defaults (p1=1 and p2=0)
In[5]:= Sin[x] /. Sin[x*p1_. + p2_.] -> Cos[x*p1 + p2]unwanted
Out[5]= Cos[x]
These replacements do not have to be at the top level:
In[6]:= Exp[Sin[a*x + b]] /. Sin[x*p1_ + p2_.] -> Cos[x*p1 +
p2]
Out[6]= E^Cos[b + a x]
There is also a variant of ->, :> which suppressed certain possible evaluations, but My Mathematica is fairly rusty.
Of course every Mathematica operator - such as '->' and '/.'
has a long form which avoids remembering all the various operator
precedences.
The sheer compactness of these replacements makes replacement
operations very popular for algebraic manipulations.
Because you do actually extract the values taken on by the patterns in those examples, I rather wonder if something more like Mathematica replacements could be constructed out of what is already available in SymPy?
David
The main difference as far as I tell compared to replace is the need to create the Wild symbols explicitly. Maybe we could add a bunch of those to sympy.abc with names like p1_ and p2_ (are those names standardised?).
Those examples are a revelation! I think they should be added to the documentation of replace and Wild(). I must admit I thought I'd tried something like that with replace, but without success - maybe I hit a bug?
Of course I realise that SymPy can't start defining operators
like /. -> etc. In any case, one irritation with Mathematica,
is that there are just too many operator precedences to remember!
The only thing that is standard about the names is the _ on the end, the rest of the name is chosen by the user, if you named the pattern variables with a trailing _ in abc , then I think it would be really friendly - I mean I think a CAS needs to be easy to use.
Given that functionality, the pattern matching looks pretty good. One other thing is that Mathematica also has a way to define a pattern that only matches if a predicate returns True when applied to it, for example:
p1_?Even
There are also some more obscure things that can be done with
Mathematica patterns, but probably these are of lesser importance.
Also patterns are used in some other contexts, for example a user
defined function is written with pattern variables as arguments.
This allows for overloaded functions.
It sounds as if the real thing that needs doing is documenting these features!
I haven't used this at all myself but you might be interested by mathics: http://mathics.github.io/ "" Mathics is a free, general-purpose online computer algebra system featuring Mathematica-compatible syntax and functions. It is backed by highly extensible Python code, relying on SymPy for most mathematical tasks. """
I did consider this, but it became clear that it isn't being actively supported. For example, it required a specific (out of date) version of Python. I'd certainly not get anything like the support that your group offer! Besides, by now, I have got somewhat under the hood of SymPy.
David
If we had Wilds in abc then they wouldn't have those kinds of exclusion patterns.
True, but this is analogous to the fact that 'f' is defined as an ordinary symbol in abc, even though you may want to redefine it as a function symbol. Defining things in abc doesn't in any way stop people redefining them - it just provides for the most typical situations - which helps to get people started.
Thanks for the help today - you have just disentangled a number of issues for me!
David