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 <[email protected]> wrote:
>> Thanks.
>>
>> On May 25, 9:02 pm, "Aaron S. Meurer" <[email protected]> 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" <[email protected]> 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
>>>>>> <[email protected]>
>>
>>
> >
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"sympy" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [email protected]
For more options, visit this group at http://groups.google.com/group/sympy?hl=en
-~----------~----~----~----~------~----~------~--~---