On Fri, Jun 6, 2008 at 7:50 PM, Rickard Armiento <[EMAIL PROTECTED]> wrote:
>
> Hi,
>
> I recently discovered sympy and really like the idea of a symbolic
> math engine in python. I'm trying to learn how to use it, but I am
> confusing myself with how to work with generic functions. Any help is
> much appreciated.
>
> Sorry for being so verbose, but I thought that it might be helpful to
> see the process that got me into my current state of confusion...
>
> Just as a first test, this of course worked nicely:
>
> In [1]:  sin(5*x).diff(x)
> Out[1]: 5*cos(5*x)
>
> So I was surprised that I couldn't do the same with a generic
> function:
>
> In [2]: f = Function("f")
> In [3]: f(5*x).diff(x)
> ** backtrace ending in core/function.py in __new__(cls, expr,
> *symbols, **assumptions)
> <type 'exceptions.TypeError'>: __new__() argument after * must be a
> sequence

I fixed this and sent patches for a review (see the sympy-patches
list), in the meantime you can play with it using my development repo:

$ hg clone http://hg.certik.cz/sympy-devel
$ cd sympy-devel
$ bin/isympy

In [1]: f(5*x).diff(x)
Out[1]:
   d
5*────(f(5*x))
  d5*x

In [2]: print f(5*x).diff(x)
5*D(f(5*x), 5*x)


We could probably improve the pretty printing in [1] to put () around the 5*x.

>
> After digging into the framework I think I understood that the
> 'problem' is that the generic function I get out of Function("f") is
> not 'prepared' to be derived. Or, if you will, not assumed to be
> analytical.
>
> So, based on the tutorial I instead created my own function like this:
> =======
> class myfunction(Function):
>    nargs = 1
>    def fdiff(self, argindex=1):
>        return Function("myfunctionPrime")(self.args[0])
> =======
>
> This works fine:
> In [6]: myfunction(5*x).diff(x)
> Out[6]: 5*myfunction_prime(5*x)
>
> But, of course I want my function to be indefinitely derivable so that
> I can, for example, work with series expansions. So I fiddled around
> trying to create a clever fdiff implementation that adds a 'Prime' to
> the previous name. But, when trying to solve my problems with that
> approach I realized that it seems stupid to go for a specific function
> definition like this, and what I *really* would want is to subclass
> Function to an AnalyticalFunction and use as a generic function
> factory for functions with the relevant property. That is, I would
> like it to work like this:
>
> In [1]: f = AnalyticalFunction("f")
> In [2]: f(5*x).diff(x)
> Out[2]: 5*fPrime(5*x)
>
> And:
>
> In [3]: f(x).series(x,0,3)
> Out[3]: f(0) + x*fPrime(0) + x**2/2*fPrimePrime(0)+O(x**3)

If my patches are accepted, you can now use:

In [7]: f(x).series(x, 0, 2, add_order=False)
Out[7]:
                   2                 3                     4
              2   d            3    d              4      d
             x *─────(f(x))   x *────────(f(x))   x *───────────(f(x))
  d             dx dx            dx dx dx            dx dx dx dx
x*──(f(x)) + ────────────── + ───────────────── + ──────────────────── + f(0)
  dx               2                  6                    24

In [8]: print f(x).series(x, 0, 2, add_order=False)
x*D(f(x), x) + (1/2)*x**2*D(f(x), x, x) + (1/6)*x**3*D(f(x), x, x, x)
+ (1/24)*x**4*D(f(x), x, x, x, x) + f(0)


I think this is a better approach (to use the Derivative class for
representing derivatives) than defining a new function for every
derivative.

What remains to be done is to improve the Derivative class to
represent the substitution, i.e. currently:

In [12]: Derivative(y*x**2, x)
Out[12]:
d ⎛   2⎞
──⎝y*x ⎠
dx

In [13]: Derivative(y*x**2, x).subs(y, 1)
Out[13]: 2*x

In [14]: Derivative(y*x**2, x).subs(x, 1)
Out[14]:
d ⎛   2⎞
──⎝y*x ⎠
dx

So the substitution works only if you are substituting for something
else than the differentiation variable --- if you substitute for "x",
which is needed in the taylor expansion, it returns itself for now, so
that the series works (but you need to append the add_order=False
parameter to it, otherwise the Order class fails to determine the
inclusion relations of things like Derivative(x**2, x) and x**3). When
we teach Derivative(x**2, x).subs(x, 0) to behave like a number, then
all should work as expected.

Any ideas? I think we just need another argument to be added to
Derivative --- the point of differentiation and that should be it.

>
> A first simple attempt was something along the lines of:
> =======
> class AnalyticFunction(Function):
>
>    def fdiff(self, argindex=1):
>        return AnalyticFunction(self.__class__.__name__+"Prime")
> (self.args[0])
> =======
>
> However, I just cannot get any subclass of Function to work as a
> general function factory! I always get something like this:
>
> In [1]: f = AnalyticalFunction("f")
> In [2]: f(1)
> ** backtrace ending in core/basic.py in __call__(self, *args,
> **removeme)
>  <type 'exceptions.NameError'>: global name 'Function' is not defined

It probably could be fixed, but as I said above, I think the way to go
is to fix the Derivative class.

Please let us know what you think and if you'd even like to help us
with it, it'd be awesome. :)

Ondrej

--~--~---------~--~----~------------~-------~--~----~
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 [EMAIL PROTECTED]
For more options, visit this group at http://groups.google.com/group/sympy?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to