-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

I like the proposed plan.

I also agree with Nick on derivative() vs diff(), but since the plan
says that both will be around, I can probably live with that.


Best,
Alex




Nick Alexander wrote:
| As the author of the one of the patches, possibly soon to be
| obsolete, I like this proposal.
|
| The one thing I don't like is the name.  I prefer nouns, as in
| A.derivative().  A.diff() is short for A.differentiate(), which
| sounds like an in place procedure to me.
|
| Standardizing on an abbreviation is madness!  My preferred examples
| are characteristic polynomials and coefficients of polynomials.  If I
| want a characteristic polynomial, I look for that, not 'charpoly'.
| Also, in many places A.coefficients() or A.coefficient_list() is
| abbreviated A.coeffs().  It makes it harder to search.
|
| If I know what I want (a derivative!) that's what I will look for.
| Not a diff.
|
| Nick
|
| PS.  IIRC, the patch in trac would optimize only the case derivative
| (x, 3).
|
| On 24-Feb-08, at 6:37 AM, David Harvey wrote:
|
|> After hearing some ideas on IRC regarding the derivatives mess, in
|> this email I propose a plan. It's rough around the edges. Comments
|> welcome.
|>
|>
|> CURRENT SITUATION
|>
|> There are currently at least 18 different functions for
|> differentiation in Sage, attached to polynomials, power series,
|> symbolics, and other things. (See my previous email for a complete
|> list.)
|>
|> There are about 4 "diff", 12 "derivative", one "differentiate", and
|> sometimes (but not always) these names are aliases to each other.
|>
|> I count six different call signatures (all "derivative"s replaced by
|> "diff" in the following list):
|>
|> def diff(self): mainly for univariate polynomial and power series
|> types.
|>
|> def diff(self, verbose=None): only in the sage.functions.elementary
|> module. All doctests are switched off on this file. The documentation
|> says that this function *integrates* things! The verbose flag seems
|> to be something passed to maxima.
|>
|> def diff(self, *args): only in calculus.calculus.SymbolicExpression.
|> This is the most powerful version, and is the closest to what I want
|> to eventually support everywhere.
|>
|> def diff(f, *args, **kwds): only in calculus.functional. This is a
|> global, and just dispatches to the diff method on f.
|>
|> def diff(self, variable, have_ring=False): in the libsingular
|> multivariate polynomial code, and also mysteriously crops up in
|> polynomial_modn_dense_ntl.pyx. The parameter "have_ring" seems to be
|> ignored everywhere, and somewhere claims that it is needed for
|> "compatibility reasons". But I can't figure out what this means.
|>
|> def diff(self, var='x', n=1): only in
|> interfaces.maxima.MaximaElement. It means differentiate n times with
|> respect to x. Note that the variable is supplied as a *string*. We
|> might want to leave this one out of the discussion; I guess here the
|> diff function is supposed to conform to maxima semantics (about which
|> I know nothing) rather than fit into the sage object model.
|>
|> There are three open tickets on this issue:
|>
|> http://trac.sagemath.org/sage_trac/ticket/756 (patch is problematic)
|> http://trac.sagemath.org/sage_trac/ticket/753 (not much interesting
|> here)
|> http://trac.sagemath.org/sage_trac/ticket/1578 (there's a patch here,
|> might need to get superseded, sorry Nick)
|>
|> There are two separate issues here: function naming, and function
|> signatures. The former is much simpler, so I'll discuss that first.
|>
|>
|> FUNCTION NAMING
|>
|> I propose that we deprecate "differentiate".
|>
|> I propose that we use "diff" as the basic name, and have "derivative"
|> as an alias for any object supporting "diff".
|>
|> I propose that there be a lower-level function "_diff" with a simpler
|> signature, see below.
|>
|>
|> FUNCTION SIGNATURES
|>
|> Here is an approximation to what I would like to see.
|>
|> Any object F supporting differentiation should have a function
|> "_diff" (def or cpdef) taking at least one argument var=None. It can
|> have additional arguments, but these must be optional. For example:
|>     def _diff(self, var=None)
|>     def _diff(self, var=None, have_ring=False)
|>     def _diff(self, var=None, verbose=False)
|>
|> If var is supplied, it should be a variable object (for example, a
|> symbolic variable, or a generator of a polynomial ring). It need not
|> lie in the parent of F. Examples:
|>
|> * If F is in S[x] for some ring S, and you call F._diff(x), you get
|> what you expect.
|> * If F is in S[x] for some ring S, and you call F._diff(y), then
|> G._diff(y) gets called for each coefficient of F.
|> * If F is in the symbolic ring, then var can be any symbolic variable.
|>
|> If var is None, the object makes a decision about the default
|> variable and uses that. For example:
|>
|> * a univariate polynomial or power series will differentiate w.r.t.
|> the generator.
|> * a symbolic expression containing precisely one variable will use
|> that variable.
|> * a multivariate polynomial will raise an exception.
|> * a symbolic expression containing more than one variable will raise
|> an exception.
|>
|> Now we come to the "diff" method. It must have an "*args"-style
|> argument, which must be interpreted according to the following list
|> of examples (which is almost clear enough to serve as a
|> specification :-)):
|>
|>     F.diff(): equivalent to F._diff(None)
|>     F.diff(2): equivalent to F._diff(None)._diff(None)
|>     F.diff(x): equivalent to F._diff(x)
|>     F.diff(x, 3): equivalent to F._diff(x)._diff(x)._diff(x)
|>     F.diff(x, y): equivalent to F._diff(x)._diff(y)
|>     F.diff(x, 3, y, 2, z): equivalent to F._diff(x)._diff(x)._diff
|> (x)._diff(y)._diff(y)._diff(z)
|>     F.diff(2, x): equivalent to F._diff(None)._diff(None)._diff(x)
|> [this one currently causes an infinite loop for symbolic objects!]
|>     F.diff([x, y, z]): equivalent to F._diff(x)._diff(y)._diff(z)
|>     F.diff((x, y, z)): equivalent to F._diff(x)._diff(y)._diff(z)
|>
|> For the list and tuple versions, it must be the only parameter, and
|> repetition counts are not allowed.
|>
|> When I say "equivalent" in the above descriptions, I don't mean it
|> literally has to call _diff that way, I just mean the behaviour
|> should be equivalent.
|>
|> Discussion on IRC concluded that partial derivatives need not
|> commute, so we always have to do the derivatives in the order
|> specified. (Of course implementations are free to use commutativity
|> if they know about it, but the general case shouldn't assume it.)
|>
|> To avoid code duplication, there will be two global helper functions.
|>
|> The first one is
|>     def diff_parse(args)
|> which takes a list/tuple like [2, x, 3, y] and converts it to a list/
|> tuple like [None, None, x, x, x, y].
|>
|> The second one is
|>     def multi_diff(F, args):
|>        for arg in args:
|>           F = F._diff(arg)
|>        return F
|>
|> Therefore it will always be possible to implement diff via just:
|>     def diff(self, *args):
|>        return multi_diff(self, diff_parse(args))
|> as long as _diff has been implemented (which it should have been!)
|>
|> Of course you can put in a more efficient implementation if you want,
|> for example for univariate polynomials it might be:
|>     def diff(self, *args):
|>        if not args:
|>           return self._diff()
|>        return multi_diff(self, diff_parse(args))
|>
|> And of course a caller is always free to directly call _diff instead
|> of diff, if they know exactly what they want.
|>
|> NOTE: conspicuously absent is the **kwds parameter in the above spec.
|> I don't know quite how to do this in an efficient way. I'm worried
|> the overhead will kill us in the last example. Any thoughts about
|> this are welcome.
|>
|> david
|>
|>
|>
|
| |
|


- --
Alexandru Ghitza
Assistant Professor
Department of Mathematics
Colby College
Waterville, ME 04901
http://bayes.colby.edu/~ghitza/
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.7 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iD8DBQFHwciodZTaNFFPILgRAmaVAJ9vm+1F0wp7a6wLOJBy+J84qbmD6QCfYPxI
NoCxrnZ9hsyeObmsgLlingE=
=u4/l
-----END PGP SIGNATURE-----

--~--~---------~--~----~------------~-------~--~----~
To post to this group, send email to sage-devel@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at http://groups.google.com/group/sage-devel
URLs: http://www.sagemath.org
-~----------~----~----~----~------~----~------~--~---

Reply via email to