You need to give arguments to the function. Most things that I have tried in SymPy do not work with Functions unless they have arguments. If you don't want arguments, just use a Symbol. I don't think implied arguments (e.g., everything a function of t) has been implemented, though it has been suggested. >>> from sympy import * >>> a = Wild('a', exclude=[pi]) >>> b = Wild('b') >>> t = Symbol('t') >>> e = pi/S(2) + x(t) >>> e.match(a*pi + b) {a: 1/2, b: x(t)}
If you run into something for which that doesn't work, one trick that I have used is to substitute the function for a dummy variable, do whatever you want to do, and then substitute it back. use y = Symbol('y', dummy=True) #dummy takes care of the possibility that the expression will have y in it already. This also only works if you provide the arguments of the function, such as expr = expr.subs(f(x), y) <do something with expr> expr = expr,subs(y, f(x)) I have personally found this useful if I want to substitute something for x but not for x in f(x), or if I want to take the partial with respect to x or y and y == y(x) in the expression (I am working on ODEs and dsolve). Aaron Meurer On May 26, 2009, at 2:46 PM, Luke wrote: > > Aaron, > It seems like this only works for Symbol instances, not > FunctionClass instances, i.e: >>>> from sympy import * >>>> x = Function('x') >>>> a = Wild('a', exclude=[pi]) >>>> b = Wild('b') >>>> e = pi/S(2) + x >>>> e.match(a*pi + b) > Traceback (most recent call last): > File "<stdin>", line 1, in <module> > File "sympy/core/basic.py", line 1317, in match > return pattern.matches(self, {}) > File "sympy/core/operations.py", line 111, in _matches_commutative > if (not p in repl_dict) and (not p in expr): > File "sympy/core/basic.py", line 1046, in __contains__ > if what in x: > TypeError: argument of type 'FunctionClass' is not iterable >>>> a = WildFunction('a', exclude=[pi]) > Traceback (most recent call last): > File "<stdin>", line 1, in <module> > File "sympy/core/function.py", line 399, in __new__ > obj = Function.__new__(cls, name, **assumptions) > File "sympy/core/multidimensional.py", line 127, in wrapper > return f(*args, **kwargs) > File "sympy/core/cache.py", line 82, in wrapper > return func_cache_it_cache[k] > TypeError: unhashable type: 'list' >>>> a = WildFunction('a', exclude=pi) >>>> b = WildFunction('b') >>>> e.match(a*pi + b) > Traceback (most recent call last): > File "<stdin>", line 1, in <module> > File "sympy/core/basic.py", line 1317, in match > return pattern.matches(self, {}) > File "sympy/core/operations.py", line 111, in _matches_commutative > if (not p in repl_dict) and (not p in expr): > File "sympy/core/basic.py", line 1046, in __contains__ > if what in x: > TypeError: argument of type 'FunctionClass' is not iterable >>>> a = Wild('a', exclude=[pi]) >>>> e.match(a*pi + b) > Traceback (most recent call last): > File "<stdin>", line 1, in <module> > File "sympy/core/basic.py", line 1317, in match > return pattern.matches(self, {}) > File "sympy/core/operations.py", line 111, in _matches_commutative > if (not p in repl_dict) and (not p in expr): > File "sympy/core/basic.py", line 1046, in __contains__ > if what in x: > TypeError: argument of type 'FunctionClass' is not iterable >>>> > > > The reason I see this being a problem is that people might not always > be using Symbol instances, they may instead want to use a Function > that is implicitly dependent upon one or more other variables (case in > point, generalized coordinates in classical mechanics). > > Ondrej, I'm told you are the only one who understands .match(), can > you shed any light on this? Maybe we just need to extend .match() to > work with other things besides Symbol? > > ~Luke > > > On May 26, 9:33 am, Luke <hazelnu...@gmail.com> wrote: >> Thanks. >> >> On May 25, 9:02 pm, "Aaron S. Meurer" <asmeu...@gmail.com> wrote: >> >>> You need to use the exclude option I was telling you about. Do, >>> >>> a = Wild('a', exclude=[pi]) >>> and >>> >>> b = Wild('a', exclude=[pi]). >>> and you get >>> >>> e1.match(a*pi + b) >>> {a_: 1, b_: x} >>> >>> b = Wild('b', exclude=[pi]) >>> >>> e2.match(a*pi + b) >>> {b_: -x, a_: 1} >>> >>> e3.match(a*pi + b) >>> {b_: x, a_: -1} >>> >>> e4.match(a*pi + b) >>> {b_: -x, a_: -1} >> >>> just as you expected. >> >>> Aaron Meurer >>> On May 25, 2009, at 7:46 PM, Luke wrote: >> >>>> Aaron, >>>> Thanks for the clarification. I think I get the idea, but I'm >>>> having trouble matching expressions of the following form: >>>> a = Wild('a') >>>> b = Wild('b') >>>> x = Symbol('x') >>>> e1 = pi + x >>>> e2 = pi - x >>>> e3 = -pi + x >>>> e4 = -pi - x >> >>>> I would think that for e{1,2,3,4} that I could get the following >>>> behavior: >>>>>>> e1.match(a*pi + b) >>>> {a: 1, b: x} >>>>>>> e2.match(a*pi + b) >>>> {a: 1, b: -x} >>>>>>> e3.match(a*pi + b) >>>> {a: -1, b: x} >>>> e4.match(a*pi + b) >>>> {a: -1, b: -x} >> >>>> But instead, I get: >>>> In [61]: e1.match(a*pi + b) >>>> Out[61]: >>>> ⎧ x ⎫ >>>> ⎨a: ─, b: π⎬ >>>> ⎩ π ⎭ >> >>>> In [65]: e2.match(a*pi+b) >>>> Out[65]: {a: 1, b: -x} >> >>>> In [66]: e3.match(a*pi+b) >>>> Out[66]: >>>> ⎧ x ⎫ >>>> ⎨a: ─, b: -π⎬ >>>> ⎩ π ⎭ >> >>>> In [67]: e4.match(a*pi+b) >>>> Out[67]: {a: -1, b: -x} >> >>>> The results for e2 and e4 makes sense to me, but I don't understand >>>> the behavior for e1 and e3. Is there another simpler approach, >>>> or am >>>> I missing something fundamental here? >> >>>> Thanks, >>>> ~Luke >> >>>> On May 25, 4:07 pm, "Aaron S. Meurer" <asmeu...@gmail.com> wrote: >>>>> On May 25, 2009, at 11:56 AM, Luke wrote: >> >>>>>> Here is the link for the Maxima trigsimp() code. It was >>>>>> written in >>>>>> 1981, according to the comments!!! >>>>>> http://maxima.cvs.sourceforge.net/viewvc/maxima/maxima/share/trigonom >>>>>> ... >> >>>>>> I emailed the authors of the Fu et al. paper to see if they >>>>>> would be >>>>>> willing to share their implementation of the algorithm -- maybe >>>>>> we >>>>>> can >>>>>> save ourselves some work this way. >> >>>>>> I want to start coding for this, because much of the stuff I am >>>>>> doing >>>>>> in PyDy is heavy on kinematics and the expressions become >>>>>> excessively >>>>>> long unless intelligent trigsimplification is possible. Many >>>>>> of my >>>>>> unittests simply will not work because some results I know to be >>>>>> true >>>>>> cannot be achieved with the current state of trigsimp, so this >>>>>> has >>>>>> become a significant limitation for me. >> >>>>>> What should be the general framework for implementing the 'rules' >>>>>> that >>>>>> are laid out in the Fu paper? There are certainly other rules we >>>>>> could find, either on Wikipedia, Mathworld, or in a engineering/ >>>>>> mathematics reference manual. >> >>>>>> I have read over how trigsimp() and trigsimp_nonrecursive() are >>>>>> currently implemented, and I think I get the gyst of what the >>>>>> approach >>>>>> is. Can somebody explain what this is doing exactly: >>>>>> for pattern, simp in matchers: >>>>>> res = result.match(pattern) >>>>>> .... >> >>>>>> I'm not 100% clear on the use of the .match() method, does >>>>>> somebody >>>>>> have a quick example of use? >> >>>>> This should be res = ret.match(pattern). >> >>>>> match() takes a wildcard expression and matches it into a >>>>> dictionary. >>>>> In the code above, pattern is each of the items in the list >>>>> ((a*sin(b)**2, a - a*cos(b)**2),(a*tan(b)**2, a*(1/cos(b))**2 - >>>>> a), >>>>> (a*cot(b)**2, a*(1/sin(b))**2 - a)) (it runs a for loop). a, b >>>>> and c >>>>> are wild cards, to it will try to take the expression result and >>>>> find >>>>> what a, b, and c are equal to. >> >>>>> For example, consider the first one: a*sin(b)**2. If your ret == >>>>> 4*x*sin(x**2)**2, then running res = ret.match(a*sin(b)**2) will >>>>> return the dictionary {a: 4*x, b: x**2}. You can then access a >>>>> and b >>>>> from res[a] and res[b]. >> >>>>> You should also probably be aware of the exclude option on >>>>> Wild. If >>>>> you do a = Wild('a', exclude=[sin(x)]), then a will not match >>>>> anything >>>>> with sin(x) in it. Do help(x.matches) for another example. >> >>>>>> It seems like the flow of trigsimp (in the case of >>>>>> recursive==False >>>>>> and deep==False): >>>>>> 1) call trigsimp_nonrecursive(expr, deep==False), store the >>>>>> result in >>>>>> 'result' >>>>>> 2) do some final pattern matching on 'result', currently this >>>>>> will >>>>>> only simplify a*sin(b)**c/cos(b)**c --> a*tan(b)**c >> >>>>>> So, should all the rules in Fu et al. be implemented as a tuple >>>>>> of >>>>>> length 2 tuples, similar to the existing matchers tuple? >> >>>>>> I'm kind of thinking out loud right now and trying to figure >>>>>> out the >>>>>> next step to take.... >> >>>>>> ~Luke >> >>>>>> On May 21, 7:42 am, Akshay Srinivasan >>>>>> <akshaysriniva...@gmail.com> >> >> > > --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "sympy" group. To post to this group, send email to sympy@googlegroups.com To unsubscribe from this group, send email to sympy+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/sympy?hl=en -~----------~----~----~----~------~----~------~--~---