Ticket #6949: trac_6949-symbolic_min_max.patch

File trac_6949-symbolic_min_max.patch, 8.3 KB (added by burcin, 12 years ago)
  • sage/functions/all.py

    # HG changeset patch
    # User Burcin Erocal <burcin@erocal.org>
    # Date 1270567369 -7200
    # Node ID ff7143c1f5c1bc5a8871c4731dcbacb71ed29d18
    # Parent  ed63459665a2d61c4b7d700c27acb5c8b05944ff
    trac 6949: Implement symbolic min and max functions.
    
    diff --git a/sage/functions/all.py b/sage/functions/all.py
    a b  
    6262
    6363from generalized import (dirac_delta, heaviside, unit_step, sgn,
    6464                         kronecker_delta)
     65
     66from min_max import max_symbolic, min_symbolic
  • new file sage/functions/min_max.py

    diff --git a/sage/functions/min_max.py b/sage/functions/min_max.py
    new file mode 100644
    - +  
     1###############################################################################
     2#   Sage: Open Source Mathematical Software
     3#       Copyright (C) 2010 Burcin Erocal <burcin@erocal.org>
     4#  Distributed under the terms of the GNU General Public License (GPL),
     5#  version 2 or any later version.  The full text of the GPL is available at:
     6#                  http://www.gnu.org/licenses/
     7###############################################################################
     8
     9from sage.symbolic.function import BuiltinFunction
     10from sage.symbolic.expression import Expression
     11from sage.symbolic.ring import SR
     12
     13from __builtin__ import max as builtin_max, min as builtin_min
     14
     15class MaxSymbolic(BuiltinFunction):
     16    def __init__(self):
     17        r"""
     18        Symbolic `max` function.
     19
     20        The Python builtin `max` function doesn't work as expected when symbolic
     21        expressions are given as arguments. This function delays evaluation
     22        until all symbolic arguments are substituted with values.
     23
     24        EXAMPLES::
     25
     26            sage: max_symbolic(3, x)
     27            max(3, x)
     28            sage: max_symbolic(3, x).subs(x=5)
     29            5
     30            sage: max_symbolic(3, 5, x)
     31            max(x, 5)
     32            sage: max_symbolic([3,5,x])
     33            max(x, 5)
     34
     35        TESTS::
     36
     37            sage: loads(dumps(max_symbolic(x,5)))
     38            max(x, 5)
     39            sage: latex(max_symbolic(x,5))
     40            \max\left(x, 5\right)
     41        """
     42        BuiltinFunction.__init__(self, 'max', nargs=0, latex_name="\max")
     43
     44    def _eval_(self, *args):
     45        """
     46        EXAMPLES::
     47
     48            sage: t = max_symbolic(x, 5); t
     49            max(x, 5)
     50            sage: t.subs(x=3) # indirect doctest
     51            5
     52            sage: max_symbolic(5,3)
     53            5
     54            sage: u = max_symbolic(*(range(10)+[x])); u
     55            max(x, 9)
     56            sage: u.subs(x=-1)
     57            9
     58            sage: u.subs(x=10)
     59            10
     60            sage: max_symbolic([0,x])
     61            max(x, 0)
     62
     63        TESTS::
     64
     65            sage: max_symbolic()
     66            Traceback (most recent call last):
     67            ...
     68            ValueError: number of arguments must be > 0
     69        """
     70        if len(args) == 0:
     71            raise ValueError("number of arguments must be > 0")
     72
     73        # __call__ ensures that if args is a singleton, the element is iterable
     74        arg_is_iter = False
     75        if len(args) == 1:
     76            arg_is_iter = True
     77            args = args[0]
     78
     79        symb_args = []
     80        res = None
     81        num_non_symbolic_args = 0
     82        for x in args:
     83            if isinstance(x, Expression):
     84                symb_args.append(x)
     85            else:
     86                num_non_symbolic_args += 1
     87                res = builtin_max(res, x)
     88
     89        # if no symbolic arguments, return the result
     90        if len(symb_args) == 0:
     91            return res
     92
     93        # if all arguments were symbolic return
     94        if num_non_symbolic_args <= 1 and not arg_is_iter:
     95            return None
     96
     97        symb_args.append(res)
     98        return max_symbolic(*symb_args)
     99
     100    def __call__(self, *args, **kwds):
     101        """
     102        EXAMPLES::
     103
     104            sage: max_symbolic(3,5,x)
     105            max(x, 5)
     106            sage: max_symbolic(3,5,x, hold=True)
     107            max(3, 5, x)
     108            sage: max_symbolic([3,5,x])
     109            max(x, 5)
     110        """
     111        if len(args) == 1:
     112            try:
     113                args=(SR._force_pyobject(iter(args[0])),)
     114            except TypeError:
     115                return args
     116
     117        return BuiltinFunction.__call__(self, *args, **kwds)
     118
     119max_symbolic = MaxSymbolic()
     120
     121
     122class MinSymbolic(BuiltinFunction):
     123    def __init__(self):
     124        r"""
     125        Symbolic `min` function.
     126
     127        The Python builtin `min` function doesn't work as expected when symbolic
     128        expressions are given as arguments. This function delays evaluation
     129        until all symbolic arguments are substituted with values.
     130
     131        EXAMPLES::
     132
     133            sage: min_symbolic(3, x)
     134            min(3, x)
     135            sage: min_symbolic(3, x).subs(x=5)
     136            3
     137            sage: min_symbolic(3, 5, x)
     138            min(x, 3)
     139            sage: min_symbolic([3,5,x])
     140            min(x, 3)
     141
     142        TESTS::
     143
     144            sage: loads(dumps(min_symbolic(x,5)))
     145            min(x, 5)
     146            sage: latex(min_symbolic(x,5))
     147            \min\left(x, 5\right)
     148        """
     149        BuiltinFunction.__init__(self, 'min', nargs=0, latex_name="\min")
     150
     151    def _eval_(self, *args):
     152        """
     153        EXAMPLES::
     154
     155            sage: t = min_symbolic(x, 5); t
     156            min(x, 5)
     157            sage: t.subs(x=3) # indirect doctest
     158            3
     159            sage: min_symbolic(5,3)
     160            3
     161            sage: u = min_symbolic(*(range(10)+[x])); u
     162            min(x, 0)
     163            sage: u.subs(x=-1)
     164            -1
     165            sage: u.subs(x=10)
     166            0
     167            sage: min_symbolic([3,x])
     168            min(x, 3)
     169
     170        TESTS::
     171
     172
     173            sage: min_symbolic()
     174            Traceback (most recent call last):
     175            ...
     176            ValueError: number of arguments must be > 0
     177        """
     178        if len(args) == 0:
     179            raise ValueError("number of arguments must be > 0")
     180
     181        # __call__ ensures that if args is a singleton, the element is iterable
     182        arg_is_iter = False
     183        if len(args) == 1:
     184            arg_is_iter = True
     185            args = args[0]
     186
     187        symb_args = []
     188        # set res to a value greater than anything
     189        res = float('inf')
     190        num_non_symbolic_args = 0
     191        for x in args:
     192            if isinstance(x, Expression):
     193                symb_args.append(x)
     194            else:
     195                num_non_symbolic_args += 1
     196                res = builtin_min(res, x)
     197
     198        # if no symbolic arguments, return the result
     199        if len(symb_args) == 0:
     200            return res
     201
     202        # if all arguments were symbolic return
     203        if num_non_symbolic_args <= 1 and not arg_is_iter:
     204            return None
     205
     206        symb_args.append(res)
     207        return min_symbolic(*symb_args)
     208
     209    def __call__(self, *args, **kwds):
     210        """
     211        EXAMPLES::
     212
     213            sage: min_symbolic(3,5,x)
     214            min(x, 3)
     215            sage: min_symbolic(3,5,x, hold=True)
     216            min(3, 5, x)
     217            sage: min_symbolic([3,5,x])
     218            min(x, 3)
     219        """
     220        if len(args) == 1:
     221            try:
     222                args=(SR._force_pyobject(iter(args[0])),)
     223            except TypeError:
     224                return args
     225
     226        return BuiltinFunction.__call__(self, *args, **kwds)
     227
     228min_symbolic = MinSymbolic()
  • sage/symbolic/ring.pyx

    diff --git a/sage/symbolic/ring.pyx b/sage/symbolic/ring.pyx
    a b  
    271271
    272272        return new_Expression_from_GEx(self, exp)
    273273
     274    def _force_pyobject(self, x):
     275        """
     276        Wrap the given Python object in a symbolic expression even if it
     277        cannot be coerced to the Symbolic Ring.
     278
     279        EXAMPLES::
     280
     281            sage: t = SR._force_pyobject([3,4,5]); t
     282            [3, 4, 5]
     283            sage: type(t)
     284            <type 'sage.symbolic.expression.Expression'>
     285        """
     286        cdef GEx exp
     287        GEx_construct_pyobject(exp, x)
     288        return new_Expression_from_GEx(self, exp)
     289
    274290    def wild(self, unsigned int n=0):
    275291        """
    276292        Return the n-th wild-card for pattern matching and substitution.
     
    441457            t0
    442458
    443459            sage: SR.symbol() # temporary variable
    444             symbol160
     460            symbol...
    445461        """
    446462        cdef GSymbol symb
    447463        cdef Expression e