Ticket #6756: trac_6756-diff-derivative-sage.patch

File trac_6756-diff-derivative-sage.patch, 12.9 KB (added by gmhossain, 12 years ago)
  • sage/calculus/calculus.py

    # HG changeset patch
    # User Golam Mortuza Hossain <gmhossain@gmail.com>
    # Date 1250529412 10800
    # Node ID 3b717920f9365d5beef91827290913e275778b17
    # Parent  684eea91ff224e5bc6259ca19f1576c4c082b9d3
    Implement diff format symbolic derivative in Sage using pynac implementation
    
    diff -r 684eea91ff22 -r 3b717920f936 sage/calculus/calculus.py
    a b  
    13941394    """
    13951395    return _limit(args[0], var(repr(args[1])), SR(args[2]))
    13961396
    1397 def dummy_diff(*args):
    1398     """
    1399     This function is called when 'diff' appears in a Maxima string.
    1400 
    1401     EXAMPLES::
    1402 
    1403         sage: from sage.calculus.calculus import dummy_diff
    1404         sage: x,y = var('x,y')
    1405         sage: dummy_diff(sin(x*y), x, SR(2), y, SR(1))
    1406         -x*y^2*cos(x*y) - 2*y*sin(x*y)
    1407 
    1408     Here the function is used implicitly::
    1409 
    1410         sage: a = var('a')
    1411         sage: f = function('cr', a)
    1412         sage: g = f.diff(a); g
    1413         D[0](cr)(a)
    1414     """
    1415     f = args[0]
    1416     args = list(args[1:])
    1417     for i in range(1, len(args), 2):
    1418         args[i] = Integer(args[i])
    1419     return f.diff(*args)
    1420  
    14211397def dummy_integrate(*args):
    14221398    """
    14231399    This function is called to create formal wrappers of integrals that
     
    16641640     
    16651641    # have to do this here, otherwise maxima_tick catches it
    16661642    syms['limit'] = dummy_limit
    1667     syms['diff'] = dummy_diff
    16681643    syms['integrate'] = dummy_integrate
    16691644    syms['laplace'] = dummy_laplace
    16701645    syms['ilt'] = dummy_inverse_laplace
  • sage/symbolic/all.py

    diff -r 684eea91ff22 -r 3b717920f936 sage/symbolic/all.py
    a b  
    77
    88from sage.symbolic.relation import solve, solve_mod
    99from sage.symbolic.assumptions import assume, forget, assumptions
     10
     11from pynac import set_diff_derivative_level
     12from derivative import symbolic_diff
  • new file sage/symbolic/derivative.py

    diff -r 684eea91ff22 -r 3b717920f936 sage/symbolic/derivative.py
    - +  
     1"""
     2Symbolic Derivative
     3
     4
     5AUTHORS:
     6
     7- Golam Mortuza Hossain (2009-08-15): initial version
     8
     9"""
     10
     11##############################################################################
     12#
     13#       Copyright (C) 2009 Golam Mortuza Hossain <gmhossain@gmail.com>
     14#
     15#  Distributed under the terms of the GNU General Public License (GPL v2+)
     16#                  http://www.gnu.org/licenses/
     17#
     18##############################################################################
     19
     20from sage.symbolic.function import SFunction
     21
     22class SymbolicDiffDerivative(SFunction):
     23    r"""
     24    Returns ``diff`` format symbolic derivative of a function
     25    with respect to the given variables.
     26
     27
     28    You can use ``symbolic_diff`` through usual methods for computing
     29    derivatives as well as directly. See EXAMPLES for more details.
     30
     31    INPUT:
     32       
     33    -   To use ``symbolic_diff`` directly, its arguments should be
     34        provided in the format ``symbolic_diff(f(x), x, n)`` or
     35        ``symbolic_diff(f(x,y), x, n, y, m)`` where ``n`` and ``m`` denote
     36        the number of times derivative acts w.r.t.  ``x`` or ``y``.
     37        It allows ``n`` or ``m`` to be symbolic but cannot be omitted.
     38       
     39
     40    EXAMPLES:
     41
     42    To use diff format derivative you may need to set diff derivative
     43    evaluation level to ``1`` or higher ::
     44 
     45        sage: default_level=set_diff_derivative_level()
     46        sage: set_diff_derivative_level(1)
     47
     48    To use diff format derivative regular way ::
     49
     50        sage: f(x) = function('f', x)
     51        sage: f(x).diff(x)
     52        diff(f(x), x, 1)
     53        sage: diff(f(x), x, 1)
     54        diff(f(x), x, 1)
     55
     56
     57    Symbolic n-th derivative:
     58
     59    To work with symbolic n-th derivative, ``symbolic_diff`` needs
     60    to be called directly ::
     61
     62        sage: m,n=var('m,n')       
     63        sage: h = symbolic_diff(f(x), x, n); h
     64        diff(f(x), x, n)
     65
     66    Output expression can be further differentiated ::
     67
     68        sage: h.diff(x)
     69        diff(f(x), x, n + 1)
     70       
     71    Or integrated ::
     72
     73        sage: h.integral(x)
     74        diff(f(x), x, n - 1)
     75
     76    Further symbolic m-th derivative can be applied ::
     77
     78        sage: symbolic_diff(h, x, m)
     79        diff(f(x), x, m + n)
     80
     81    Some simplifications are carried out for symbolic n-th
     82    derivative ::
     83
     84        sage: g(x,y) = function('g',x,y)
     85        sage: symbolic_diff(2*f(x)*g(x,y), y, m)
     86        2*diff(g(x, y), y, m)*f(x)
     87
     88    If possible partial evaluations are carried out ::
     89
     90        sage: symbolic_diff(x^2 + 2*x*y, y, m, x, 1)
     91        2*x*diff(1, y, m) + 2*diff(y, y, m)
     92
     93    Given n can be ``0`` following is returned un-evaluated ::
     94
     95        sage: symbolic_diff(y, x, n)
     96        diff(y, x, n)
     97
     98
     99    Evaluation level:
     100
     101    Symbolic diff supports multiple evaluation level.
     102
     103    - Level ``0`` (no ``diff`` derivative but uses ``D`` format) ::
     104
     105        sage: set_diff_derivative_level(0)
     106        sage: f(x).diff(x)
     107        D[0](f)(x)
     108
     109    - Level ``1`` (without chain rule) ::
     110
     111        sage: set_diff_derivative_level(1)
     112        sage: f(x^2).diff(x)
     113        diff(f(x^2), x, 1)
     114
     115    - Level ``2`` (with chain rule)  ::
     116
     117        sage: set_diff_derivative_level(2)
     118        sage: f(x^2).diff(x)
     119        2*x*diff(f(x^2), x^2, 1)
     120
     121        sage: f(sin(x^2)).diff(x)
     122        2*x*cos(x^2)*diff(f(sin(x^2)), sin(x^2), 1)
     123
     124        sage: g(x,f(x)).diff(x)
     125        diff(f(x), x, 1)*diff(g(x, f(x)), f(x), 1) + diff(g(x, f(x)), x, 1)
     126
     127    - Calling ``symbolic_diff`` directly will NOT apply chain rule ::
     128
     129        sage: symbolic_diff(f(x^2), x, 1)
     130        diff(f(x^2), x, 1)
     131
     132    .. warning:: For a function with multiple arguments, while applying
     133        chain rule, arguments are assumed to be independent for the purpose
     134        of partial derivative.
     135
     136    - Thus, in level ``2``, following result is expected by current design ::
     137
     138        sage: g(x,x).diff(x)
     139        2*diff(g(x, x), x, 1)
     140
     141
     142    Explicit Evaluation:
     143
     144    Symbolic derivative can be explicitly evaluated by substituting
     145    the function ::
     146       
     147        sage: h = f(x).diff(x); h
     148        diff(f(x), x, 1)
     149        sage: h.subs(f(x)==x^4)
     150        4*x^3
     151
     152    Even for situation where chain rule has been applied and derivative
     153    is specified w.r.t. an expression ::
     154
     155        sage: h = f(x^2).diff(x); h
     156        2*x*diff(f(x^2), x^2, 1)
     157        sage: h.subs(f(x^2)==x^4)
     158        4*x^3
     159        sage: symbolic_diff(f(x)^2, f(x), 1)
     160        2*f(x)
     161        sage: symbolic_diff(x^2-2*x*y+y^2, x-y, 1)
     162        2*x - 2*y
     163
     164    However, for some situation explicit evaluation is not possible
     165    without knowing which variable combination is kept fixed ::
     166
     167        sage: symbolic_diff(x, x-y, 1)
     168        diff(x, x - y, 1)
     169
     170
     171    Symbolic n-th derivative can be evaluated similarly ::
     172
     173        sage: h = symbolic_diff(f(x), x, n); h
     174        diff(f(x), x, n)
     175        sage: h.subs(f(x)==x^4).subs(n==1)
     176        4*x^3
     177        sage: h.subs(n==0)
     178        f(x)
     179
     180
     181    Conversion to ``D`` format:
     182
     183    Symbolic ``diff`` format derivative can be easily converted to ``D``
     184    format derivative ::
     185
     186        sage: h = f(x).diff(x) + f(x^2).diff(x); h
     187        2*x*diff(f(x^2), x^2, 1) +  diff(f(x), x, 1)
     188
     189    To convert ``h`` first set diff derivative level to ``0`` then
     190    trigger a re-evaluation for example by doing a dummy substitution ::
     191
     192        sage: set_diff_derivative_level(0)
     193        sage: h.subs(x==y).subs(y==x)
     194        2*x*D[0](f)(x^2) +  D[0](f)(x)
     195
     196    Restore derivative level to Sage default::
     197
     198        sage: set_diff_derivative_level(default_level)
     199
     200
     201    NOTES:
     202
     203        This implementation of ``diff`` derivative is based on GiNaC/pynac.
     204
     205    """
     206    def __init__(self, *args, **kwds):
     207        r"""
     208        The diff format symbolic derivative
     209
     210        EXAMPLES::
     211
     212            sage: from sage.symbolic.pynac import set_diff_derivative_level
     213            sage: l=set_diff_derivative_level()
     214            sage: set_diff_derivative_level(1)
     215            sage: x,y=var('x,y')
     216            sage: f(x,y) = function('f',x,y)
     217            sage: f(x,y).diff(x,y)
     218            diff(f(x, y), x, 1, y, 1)
     219            sage: f(x,y).diff(x,2)
     220            diff(f(x, y), x, 2)
     221            sage: set_diff_derivative_level(l)
     222
     223        """
     224        # This method wraps the underlying diff implementation of pynac
     225        kwds['built_in_function'] = True
     226        kwds['ginac_name'] = "diff"
     227        kwds['nargs'] = 0
     228        kwds['print_latex_func'] = self._print_latex_
     229
     230        SFunction.__init__(self, "diff", *args, **kwds)
     231
     232    def _print_latex_(self, *args, **kwds):
     233        r"""
     234        Return LaTeX expression for diff format symbolic derivative.
     235       
     236        EXAMPLES::
     237       
     238            sage: from sage.symbolic.derivative import symbolic_diff
     239            sage: dlatex = symbolic_diff._print_latex_
     240            sage: x,y=var('x,y')
     241            sage: f(x) = function('f',x)
     242            sage: dlatex(f(x), x, 1)
     243            '{\\frac{d f\\left(x\\right)}{d x}}'
     244            sage: dlatex(f(x), x, 2)
     245            '{\\frac{d^{2} f\\left(x\\right)}{d {x}^{2}}}'
     246   
     247            sage: f(x,y) = function('f',x,y)
     248            sage: dlatex(f(x,y), x, 1)
     249            '{\\frac{\\partial}{\\partial x}f\\left(x, y\\right)}'
     250            sage: dlatex(f(x,y), x, 3)
     251            '{\\frac{\\partial^{3}}{\\partial {x}^{3}}f\\left(x, y\\right)}'
     252            sage: dlatex(f(x,y), x, 1, y, 1)
     253            '{\\frac{\\partial^{2}}{\\partial y\\partial x}f\\left(x, y\\right)}'
     254       
     255            sage: dlatex(f(x,y), x-y, 1)
     256            '{\\frac{\\partial}{\\partial \\left(x - y\\right)}f\\left(x, y\\right)}'
     257
     258        NOTES::
     259           
     260            This typesetting scheme closely follows old (maxima) typesetting scheme
     261
     262        """
     263        from sage.misc.latex import latex
     264        from sage.symbolic.ring import is_SymbolicVariable
     265        from sage.symbolic.pynac import set_diff_derivative_level
     266        n = len(args)
     267        f = args[0]
     268        # Check whether it should be partial derivative
     269        level = set_diff_derivative_level()
     270        f_nops = len(f.operands())
     271        if len(f.args()) == 1 and (f_nops == 1 or level == 1):
     272            d_latex = "d"
     273        else:
     274            d_latex = "\\partial"
     275        if not isinstance(f.operator(), SFunction):
     276            fstr = "\\left(" + latex(f) + "\\right)"
     277        else:
     278            fstr = latex(f)
     279        # Read the variables
     280        diffstr = ""; total = 0
     281        for i in range(1,n-1,2):
     282            x = args[i]    # variable
     283            j = args[i+1]  # no of times diff acts on f w.r.t. variable x
     284            total = total + j    # total no of times diff acts 
     285            if not is_SymbolicVariable(x) and not isinstance(x.operator(), SFunction):
     286                xstr = "\\left(" + latex(x) + "\\right)"
     287            else:
     288                xstr = latex(x)
     289            if j == 1:
     290                diffstr = "%s %s"%(d_latex, xstr) + diffstr 
     291            else:
     292                diffstr = "%s {%s}^{%s}"%(d_latex, xstr, latex(j)) + diffstr 
     293        # Return final expression
     294        if total == 1:
     295            numer_str = d_latex
     296        else:
     297            numer_str = "%s^{%s}"%(d_latex, latex(total))
     298
     299        if f_nops == 1 and d_latex == "d":
     300            return "{\\frac{%s %s}{%s}}"%(numer_str, fstr, diffstr)
     301        else:
     302            return "{\\frac{%s}{%s}%s}"%(numer_str, diffstr, fstr)
     303
     304symbolic_diff = SymbolicDiffDerivative()
  • sage/symbolic/pynac.pyx

    diff -r 684eea91ff22 -r 3b717920f936 sage/symbolic/pynac.pyx
    a b  
    146146    """
    147147    return py_get_ginac_serial()
    148148
     149# This variable tells pynac the level of diff derivative
     150cdef public int diff_derivative_level = 0
     151
     152def set_diff_derivative_level(int level=-1):
     153    """
     154    Set the evaluation level of diff format symbolic derivative. If
     155    no argument is given then it returns its current value.
     156
     157    INPUT:
     158   
     159    -  ``level`` - an integer value with following level of evaluation:
     160
     161        ``0`` - No diff derivative
     162        ``1`` - Diff derivative without chain rule (maxima-like)
     163        ``2`` - Diff derivative with chain rule
     164
     165    EXAMPLES::
     166
     167        sage: from sage.symbolic.pynac import set_diff_derivative_level
     168        sage: l=set_diff_derivative_level()
     169        sage: set_diff_derivative_level(1)
     170        sage: set_diff_derivative_level()
     171        1
     172        sage: set_diff_derivative_level(2)
     173        sage: set_diff_derivative_level()
     174        2
     175        sage: set_diff_derivative_level(l)
     176
     177    """
     178    global diff_derivative_level
     179    if level < 0:
     180        return diff_derivative_level
     181    diff_derivative_level = level
     182
    149183#################################################################
    150184# Printing helpers
    151185#################################################################