Ticket #6949: trac_6949-symbolic_min_max.take2.patch

File trac_6949-symbolic_min_max.take2.patch, 8.5 KB (added by burcin, 12 years ago)

add evalf methods, put common eval and call methods to base class

  • sage/functions/all.py

    # HG changeset patch
    # User Burcin Erocal <burcin@erocal.org>
    # Date 1270567369 -7200
    # Node ID bf38fa34dc71e7914dd899f0e739ed6a67aabeaf
    # Parent  3c2477b86e7e89405c92c8133f0fe5e7d6a88cb5
    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 MinMax_base(BuiltinFunction):
     16    def eval_helper(self, this_f, builtin_f, initial_val, args):
     17        """
     18        EXAMPLES::
     19
     20            sage: max_symbolic(3,5,x) # indirect doctest
     21            max(x, 5)
     22            sage: min_symbolic(3,5,x)
     23            min(x, 3)
     24        """
     25        if len(args) == 0:
     26            raise ValueError("number of arguments must be > 0")
     27
     28        # __call__ ensures that if args is a singleton, the element is iterable
     29        arg_is_iter = False
     30        if len(args) == 1:
     31            arg_is_iter = True
     32            args = args[0]
     33
     34        symb_args = []
     35        res = initial_val
     36        num_non_symbolic_args = 0
     37        for x in args:
     38            if isinstance(x, Expression):
     39                symb_args.append(x)
     40            else:
     41                num_non_symbolic_args += 1
     42                res = builtin_f(res, x)
     43
     44        # if no symbolic arguments, return the result
     45        if len(symb_args) == 0:
     46            return res
     47
     48        # if all arguments were symbolic return
     49        if num_non_symbolic_args <= 1 and not arg_is_iter:
     50            return None
     51
     52        symb_args.append(res)
     53        return this_f(*symb_args)
     54
     55    def __call__(self, *args, **kwds):
     56        """
     57        EXAMPLES::
     58
     59            sage: max_symbolic(3,5,x)
     60            max(x, 5)
     61            sage: max_symbolic(3,5,x, hold=True)
     62            max(3, 5, x)
     63            sage: max_symbolic([3,5,x])
     64            max(x, 5)
     65
     66        ::
     67
     68            sage: min_symbolic(3,5,x)
     69            min(x, 3)
     70            sage: min_symbolic(3,5,x, hold=True)
     71            min(3, 5, x)
     72            sage: min_symbolic([3,5,x])
     73            min(x, 3)
     74        """
     75        if len(args) == 1:
     76            try:
     77                args=(SR._force_pyobject(iter(args[0])),)
     78            except TypeError:
     79                return args
     80
     81        return BuiltinFunction.__call__(self, *args, **kwds)
     82
     83class MaxSymbolic(MinMax_base):
     84    def __init__(self):
     85        r"""
     86        Symbolic `max` function.
     87
     88        The Python builtin `max` function doesn't work as expected when symbolic
     89        expressions are given as arguments. This function delays evaluation
     90        until all symbolic arguments are substituted with values.
     91
     92        EXAMPLES::
     93
     94            sage: max_symbolic(3, x)
     95            max(3, x)
     96            sage: max_symbolic(3, x).subs(x=5)
     97            5
     98            sage: max_symbolic(3, 5, x)
     99            max(x, 5)
     100            sage: max_symbolic([3,5,x])
     101            max(x, 5)
     102
     103        TESTS::
     104
     105            sage: loads(dumps(max_symbolic(x,5)))
     106            max(x, 5)
     107            sage: latex(max_symbolic(x,5))
     108            \max\left(x, 5\right)
     109        """
     110        BuiltinFunction.__init__(self, 'max', nargs=0, latex_name="\max")
     111
     112    def _eval_(self, *args):
     113        """
     114        EXAMPLES::
     115
     116            sage: t = max_symbolic(x, 5); t
     117            max(x, 5)
     118            sage: t.subs(x=3) # indirect doctest
     119            5
     120            sage: max_symbolic(5,3)
     121            5
     122            sage: u = max_symbolic(*(range(10)+[x])); u
     123            max(x, 9)
     124            sage: u.subs(x=-1)
     125            9
     126            sage: u.subs(x=10)
     127            10
     128            sage: max_symbolic([0,x])
     129            max(x, 0)
     130
     131        TESTS::
     132
     133            sage: max_symbolic()
     134            Traceback (most recent call last):
     135            ...
     136            ValueError: number of arguments must be > 0
     137        """
     138        return self.eval_helper(max_symbolic, builtin_max, None, args)
     139
     140    def _evalf_(self, *args, **kwds):
     141        """
     142        EXAMPLES::
     143
     144            sage: t = max_symbolic(sin(x), cos(x))
     145            sage: t.subs(x=1).n(200)
     146            0.84147098480789650665250232163029899962256306079837106567275
     147            sage: var('y')
     148            y
     149            sage: t = max_symbolic(sin(x), cos(x), y)
     150            sage: u = t.subs(x=1); u
     151            max(sin(1), cos(1), y)
     152            sage: u.n()
     153            Traceback (most recent call last):
     154            ...
     155            TypeError: cannot evaluate symbolic expression numerically
     156        """
     157        return max_symbolic(args)
     158
     159max_symbolic = MaxSymbolic()
     160
     161
     162class MinSymbolic(MinMax_base):
     163    def __init__(self):
     164        r"""
     165        Symbolic `min` function.
     166
     167        The Python builtin `min` function doesn't work as expected when symbolic
     168        expressions are given as arguments. This function delays evaluation
     169        until all symbolic arguments are substituted with values.
     170
     171        EXAMPLES::
     172
     173            sage: min_symbolic(3, x)
     174            min(3, x)
     175            sage: min_symbolic(3, x).subs(x=5)
     176            3
     177            sage: min_symbolic(3, 5, x)
     178            min(x, 3)
     179            sage: min_symbolic([3,5,x])
     180            min(x, 3)
     181
     182        TESTS::
     183
     184            sage: loads(dumps(min_symbolic(x,5)))
     185            min(x, 5)
     186            sage: latex(min_symbolic(x,5))
     187            \min\left(x, 5\right)
     188        """
     189        BuiltinFunction.__init__(self, 'min', nargs=0, latex_name="\min")
     190
     191    def _eval_(self, *args):
     192        """
     193        EXAMPLES::
     194
     195            sage: t = min_symbolic(x, 5); t
     196            min(x, 5)
     197            sage: t.subs(x=3) # indirect doctest
     198            3
     199            sage: min_symbolic(5,3)
     200            3
     201            sage: u = min_symbolic(*(range(10)+[x])); u
     202            min(x, 0)
     203            sage: u.subs(x=-1)
     204            -1
     205            sage: u.subs(x=10)
     206            0
     207            sage: min_symbolic([3,x])
     208            min(x, 3)
     209
     210        TESTS::
     211
     212            sage: min_symbolic()
     213            Traceback (most recent call last):
     214            ...
     215            ValueError: number of arguments must be > 0
     216        """
     217        return self.eval_helper(min_symbolic, builtin_min, float('inf'), args)
     218
     219    def _evalf_(self, *args, **kwds):
     220        """
     221        EXAMPLES::
     222
     223            sage: t = min_symbolic(sin(x), cos(x))
     224            sage: t.subs(x=1).n(200)
     225            0.54030230586813971740093660744297660373231042061792222767010
     226            sage: var('y')
     227            y
     228            sage: t = min_symbolic(sin(x), cos(x), y)
     229            sage: u = t.subs(x=1); u
     230            min(sin(1), cos(1), y)
     231            sage: u.n()
     232            Traceback (most recent call last):
     233            ...
     234            TypeError: cannot evaluate symbolic expression numerically
     235        """
     236        return min_symbolic(args)
     237
     238min_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.