Ticket #6111: trac6111-reviewer-cwitty.patch

File trac6111-reviewer-cwitty.patch, 17.2 KB (added by cwitty, 10 years ago)
  • sage/symbolic/benchmark.py

    # HG changeset patch
    # User Carl Witty <cwitty@newtonlabs.com>
    # Date 1243191638 25200
    # Node ID df6569aa17054d6a2df0231c8ab9f4f171f539b3
    # Parent  c9e8cd4071ea2c6a9d798969aee539f1eb1ef78b
    Fix a few typos and bugs in the new symbolics.
    
    diff -r c9e8cd4071ea -r df6569aa1705 sage/symbolic/benchmark.py
    a b  
    44Tests that will take a long time if something is wrong, but be very
    55quick otherwise.  See http://wiki.sagemath.org/symbench.  The
    66parameters chosen below are such that with pynac most of these take
    7 well less than a second, but would not even feasible using Sage's
     7well less than a second, but would not even be feasible using Sage's
    88Maxima-based symbolics.
    99
    1010Problem R1::
  • sage/symbolic/callable.py

    diff -r c9e8cd4071ea -r df6569aa1705 sage/symbolic/callable.py
    a b  
    4242#########################################################################################
    4343def is_CallableSymbolicExpressionRing(x):
    4444    """
    45     Return True if x is a callable symbolic expression.
     45    Return True if x is a callable symbolic expression ring.
    4646   
    4747    INPUT:
    4848   
  • sage/symbolic/constants.py

    diff -r c9e8cd4071ea -r df6569aa1705 sage/symbolic/constants.py
    a b  
    471471    def _singular_(self, singular):
    472472        """
    473473        Returns the constant as a string in Singular. Since Singular
    474         does not have floating point numbers, we simply return the
    475         constant as a string.
     474        does not always support floating point numbers, we simply
     475        return the constant as a string.  (Singular allows floating point
     476        numbers if the current ring has floating point coefficients,
     477        but not otherwise.)
    476478
    477479        EXAMPLES::
    478480
     
    825827            sage: loads(dumps(golden_ratio))
    826828            golden_ratio
    827829        """
    828         conversions = dict(mathematica='N[(1+Sqrt[5])/2]', gp='(1+sqrt(5))/2',
     830        conversions = dict(mathematica='(1+Sqrt[5])/2', gp='(1+sqrt(5))/2',
    829831                           maple='(1+sqrt(5))/2', maxima='(1+sqrt(5))/2',
    830832                           pari='(1+sqrt(5))/2', octave='(1+sqrt(5))/2',
    831833                           kash='(1+Sqrt(5))/2')
     
    937939            sage: loads(dumps(log2))
    938940            log2
    939941        """
    940         conversions = dict(mathematica='N[Log[2]]', kash='Log(2)',
     942        conversions = dict(mathematica='Log[2]', kash='Log(2)',
    941943                           maple='log(2)', maxima='log(2)', gp='log(2)',
    942944                           pari='log(2)', octave='log(2)')
    943945        Constant.__init__(self, name, conversions=conversions,
  • sage/symbolic/expression_conversions.py

    diff -r c9e8cd4071ea -r df6569aa1705 sage/symbolic/expression_conversions.py
    a b  
    33
    44This module provides routines for converting new symbolic expressions
    55to other types.  Primarily, it provides a class :class:`Converter`
    6 which will walk to expression tree and make calls to methods
     6which will walk the expression tree and make calls to methods
    77overridden by subclasses.
    88"""
    99###############################################################################
     
    2424GaussianField = I.pyobject().parent()
    2525
    2626class FakeExpression(object):
     27    r"""
     28    Pynac represents `x/y` as `xy^{-1}`.  Often, tree-walkers would prefer
     29    to see divisions instead of multiplications and negative exponents.
     30    To allow for this (since Pynac internally doesn't have division at all),
     31    there is a possibility to pass use_fake_div=True; this will rewrite
     32    an Expression into a mixture of Expression and FakeExpression nodes,
     33    where the FakeExpression nodes are used to represent divisions.
     34    These nodes are intended to act sufficiently like Expression nodes
     35    that tree-walkers won't care about the difference.
     36    """
     37
    2738    def __init__(self, operands, operator):
    2839        """
    2940        EXAMPLES::
     
    173184            ...
    174185            NotImplementedError: derivative
    175186
    176         We can set a default value for by setting the ``ex`` attribute::
     187        We can set a default value for the argument by setting
     188        the ``ex`` attribute::
    177189       
    178190            sage: c.ex = SR(2)
    179191            sage: c()
     
    14281440class SubstituteFunction(Converter):
    14291441    def __init__(self, ex, original, new):
    14301442        """
    1431         A class that walks the tree and replaces on occurrence of a
     1443        A class that walks the tree and replaces occurrences of a
    14321444        function with another.
    14331445
    14341446        EXAMPLES::
  • sage/symbolic/function.pyx

    diff -r c9e8cd4071ea -r df6569aa1705 sage/symbolic/function.pyx
    a b  
    814814                   
    815815    def __call__(self, x, hold=False):
    816816        """
    817         Evaluates this function at *x*.  First, it checks to see if *x*
    818         is a float in which case it calls :meth:`_approx_`.  Next,
    819         it checks to see if *x* has an attribute with the same name
    820         as.  If both of those fail, then it returns the symbolic version
    821         provided by :class:`SFunction`.
     817        Evaluates this function at *x*.  First, it checks to see if
     818        *x* is a float in which case it calls :meth:`_approx_`.  Next,
     819        it checks to see if *x* has an attribute with the same name as
     820        this function.  If both of those fail, then it returns the
     821        symbolic version provided by :class:`SFunction`.
    822822
    823823        EXAMPLES::
    824824       
  • sage/symbolic/pynac.pyx

    diff -r c9e8cd4071ea -r df6569aa1705 sage/symbolic/pynac.pyx
    a b  
    4848
    4949cdef public object ex_to_pyExpression(GEx juice):
    5050    """
    51     Convert given GiNaC::ex object to a python Expression class.
     51    Convert given GiNaC::ex object to a python Expression instance.
    5252
    5353    Used to pass parameters to custom power and series functions.
    5454    """
     
    8989    Converts a std::multiset<unsigned> to a PyTuple.
    9090   
    9191    Used to pass a list of parameter numbers with respect to which a function
    92     is differentiaed to the printing functions py_print_fderivative and
     92    is differentiated to the printing functions py_print_fderivative and
    9393    py_latex_fderivative.
    9494    """
    9595    cdef GParamSetIter itr = s.begin()
     
    290290
    291291        sage: from sage.symbolic.pynac import py_print_function_pystring
    292292        sage: from sage.symbolic.function import function, get_sfunction_from_serial, get_ginac_serial
    293         sage: var('x,y,z',ns=1)
    294          (x, y, z)
     293        sage: var('x,y,z')
     294        (x, y, z)
    295295        sage: foo = function('foo', 2)
    296296        sage: for i in range(get_ginac_serial(), get_ginac_serial()+50):
    297297        ...     if get_sfunction_from_serial(i) == foo: break
     
    352352
    353353        sage: from sage.symbolic.pynac import py_latex_function_pystring
    354354        sage: from sage.symbolic.function import function, get_sfunction_from_serial, get_ginac_serial
    355         sage: var('x,y,z',ns=1)
    356          (x, y, z)
     355        sage: var('x,y,z')
     356        (x, y, z)
    357357        sage: foo = function('foo', 2)
    358358        sage: for i in range(get_ginac_serial(), get_ginac_serial()+50):
    359359        ...     if get_sfunction_from_serial(i) == foo: break
     
    11781178        return x.zeta()
    11791179    except AttributeError:
    11801180        pass
    1181     # zeta() evaluates it's argument before calling this, so we should never
     1181    # zeta() evaluates its argument before calling this, so we should never
    11821182    # end up here. Precision is not a problem here, since zeta() passes that
    11831183    # on when it calls evalf() on the argument.
    11841184    raise RuntimeError, "py_zeta() received non evaluated argument"
     
    12131213        return x.exp()
    12141214    except AttributeError:
    12151215        pass
    1216     # exp() evaluates it's argument before calling this, so we should never
     1216    # exp() evaluates its argument before calling this, so we should never
    12171217    # end up here. Precision is not a problem here, since exp() passes that
    12181218    # on when it calls evalf() on the argument.
    12191219    raise RuntimeError, "py_exp() received non evaluated argument"
     
    12481248        return x.log()
    12491249    except AttributeError:
    12501250        pass
    1251     # log() evaluates it's argument before calling this, so we should never
     1251    # log() evaluates its argument before calling this, so we should never
    12521252    # end up here. Precision is not a problem here, since log() passes that
    12531253    # on when it calls evalf() on the argument.
    12541254    raise RuntimeError, "py_log() received non evaluated argument"
  • sage/symbolic/random_tests.py

    diff -r c9e8cd4071ea -r df6569aa1705 sage/symbolic/random_tests.py
    a b  
    66import sage.symbolic.pynac
    77from sage.symbolic.constants import *
    88
     9# For creating simple expressions
     10
    911fast_binary = [(0.4, operator.add), (0.1, operator.sub), (0.5, operator.mul)]
    1012fast_unary = [(0.8, operator.neg), (0.2, operator.abs)]
    1113fast_nodes = [(0.9, fast_binary, 2), (0.1, fast_unary, 1)]
    1214
     15# For creating expressions with the full power of Pynac's simple expression
     16# subset (with no quantifiers/operators; that is, no derivatives, integrals,
     17# etc.)
     18
    1319full_binary = [(0.3, operator.add), (0.1, operator.sub), (0.3, operator.mul), (0.2, operator.div), (0.1, operator.pow)]
    1420full_unary = [(0.8, operator.neg), (0.2, operator.inv)]
    1521full_functions = [(1.0, f, f.number_of_arguments()) for f in sage.symbolic.pynac.symbol_table['functions'].values() if f.number_of_arguments() > 0 and 'elliptic' not in str(f) and 'dickman_rho' not in str(f)]
     
    1723full_internal = [(0.6, full_binary, 2), (0.2, full_unary, 1), (0.2, full_functions)]
    1824
    1925def normalize_prob_list(pl, extra=()):
     26    r"""
     27    INPUT:
     28
     29    - ``pl`` - A list of tuples, where the first element of each tuple is
     30      a floating-point number (representing a relative probability).  The
     31      second element of each tuple may be a list or any other kind of object.
     32
     33    - ``extra`` - A tuple which is to be appended to every tuple in ``pl``.
     34
     35    This function takes such a list of tuples (a "probability list") and
     36    normalizes the probabilities so that they sum to one.  If any of the
     37    values are lists, then those lists are first normalized; then
     38    the probabilities in the list are multiplied by the main probability
     39    and the sublist is merged with the main list.
     40
     41    For example, suppose we want to select between group A and group B with
     42    50% probability each.  Then within group A, we select A1 or A2 with 50%
     43    probability each (so the overall probability of selecting A1 is 25%);
     44    and within group B, we select B1, B2, or B3 with probabilities in
     45    a 1:2:2 ratio.
     46
     47    EXAMPLES::
     48
     49        sage: from sage.symbolic.random_tests import *
     50        sage: A = [(0.5, 'A1'), (0.5, 'A2')]
     51        sage: B = [(1, 'B1'), (2, 'B2'), (2, 'B3')]
     52        sage: top = [(50, A, 'Group A'), (50, B, 'Group B')]
     53        sage: normalize_prob_list(top)
     54        [(0.250000000000000, 'A1', 'Group A'), (0.250000000000000, 'A2', 'Group A'), (0.10000000000000001, 'B1', 'Group B'), (0.20000000000000001, 'B2', 'Group B'), (0.20000000000000001, 'B3', 'Group B')]
     55    """
    2056    if len(pl) == 0:
    2157        return pl
    2258    result = []
     
    3773    return result
    3874
    3975def choose_from_prob_list(lst):
     76    r"""
     77    INPUT:
     78
     79    - ``lst`` - A list of tuples, where the first element of each tuple
     80      is a nonnegative float (a probability), and the probabilities sum
     81      to one.
     82
     83    OUTPUT:
     84
     85    A tuple randomly selected from the list according to the given
     86    probabilities.
     87
     88    EXAMPLES::
     89
     90        sage: from sage.symbolic.random_tests import *
     91        sage: v = [(0.1, False), (0.9, True)]
     92        sage: choose_from_prob_list(v)
     93        (0.900000000000000, True)
     94        sage: true_count = 0
     95        sage: for _ in range(10000):
     96        ...       if choose_from_prob_list(v)[1]:
     97        ...           true_count += 1
     98        sage: true_count
     99        9033
     100        sage: true_count - (10000 * 9/10)
     101        33
     102    """
    40103    r = random()
    41104    for i in range(len(lst)-1):
    42105        if r < lst[i][0]:
     
    46109
    47110def random_integer_vector(n, length):
    48111    r"""
     112    Give a random list of length *length*, consisting of nonnegative
     113    integers that sum to *n*.
     114
    49115    This is an approximation to IntegerVectors(n, length).random_element().
    50116    That gives values uniformly at random, but might be slow; this
    51     routine is not uniform, but should always be fast.
     117    routine is not uniform, but should always be fast. 
     118
     119    (This routine is uniform if *length* is 1 or 2; for longer vectors,
     120    we prefer approximately balanced vectors, where all the values
     121    are around `n/{length}`.)
     122
     123    EXAMPLES::
     124
     125        sage: from sage.symbolic.random_tests import *
     126        sage: random_integer_vector(100, 2)
     127        [11, 89]
     128        sage: random_integer_vector(100, 2)
     129        [51, 49]
     130        sage: random_integer_vector(100, 2)
     131        [4, 96]
     132        sage: random_integer_vector(10000, 20)
     133        [332, 529, 185, 738, 82, 964, 596, 892, 732, 134, 834, 765, 398, 608, 358, 300, 652, 249, 586, 66]
    52134    """
    53135    if length == 0:
    54136        return []
     
    62144        return [v] + random_integer_vector(n-v, length-1)
    63145
    64146def random_expr_helper(n_nodes, internal, leaves, verbose):
     147    r"""
     148    Produce a random symbolic expression of size *n_nodes* (or slightly
     149    larger).  Internal nodes are selected from the *internal* probability
     150    list; leaves are selected from *leaves*.  If *verbose* is True,
     151    then a message is printed before creating an internal node.
     152
     153    EXAMPLES::
     154
     155        sage: from sage.symbolic.random_tests import *
     156        sage: random_expr_helper(9, [(0.5, operator.add, 2), (0.5, operator.neg, 1)], [(0.5, 1), (0.5, x)], True)
     157        About to apply <built-in function add> to [1, x]
     158        About to apply <built-in function add> to [x, x + 1]
     159        About to apply <built-in function neg> to [1]
     160        About to apply <built-in function neg> to [-1]
     161        About to apply <built-in function neg> to [1]
     162        About to apply <built-in function add> to [2*x + 1, -1]
     163        2*x
     164    """
    65165    if n_nodes == 1:
    66166        return choose_from_prob_list(leaves)[1]
    67167    else:
     
    77177            print "About to apply %r to %r" % (r[1], children)
    78178        return r[1](*children)
    79179
    80 def random_expr(size, nvars=1, nconsts=None, var_frac=0.5, internal=full_internal, nullary=full_nullary, nullary_frac=0.2, const_generator=QQ.random_element, verbose=False):
     180def random_expr(size, nvars=1, ncoeffs=None, var_frac=0.5, internal=full_internal, nullary=full_nullary, nullary_frac=0.2, coeff_generator=QQ.random_element, verbose=False):
     181    r"""
     182    Produce a random symbolic expression of the given size.  By
     183    default, the expression involves (at most) one variable, an arbitrary
     184    number of coefficients, and all of the symbolic functions and constants
     185    (from the probability lists full_internal and full_nullary).  It is
     186    possible to adjust the ratio of leaves between symbolic constants,
     187    variables, and coefficients (var_frac gives the fraction of variables,
     188    and nullary_frac the fraction of symbolic constants; the remaining
     189    leaves are coefficients).
     190
     191    The actual mix of symbolic constants and internal nodes can be modified
     192    by specifying different probability lists.
     193
     194    To use a different type for coefficients, you can specify
     195    coeff_generator, which should be a function that will return
     196    a random coefficient every time it is called.
     197
     198    This function will often raise an error because it tries to create
     199    an erroneous expression (such as a division by zero).
     200
     201    EXAMPLES::
     202
     203        sage: from sage.symbolic.random_tests import *
     204        sage: random_expr(50, nvars=3, coeff_generator=CDF.random_element)
     205        sinh(arcsech(-coth(v2)/csc(-(0.615863165633 + 0.879368031485*I)*v1^2*v3) - gamma(pi) + csch(-(0.708874026302 - 0.954135400334*I)*v3)))^coth(-cosh(-arcsinh((0.0574954975369 - 0.917809644424*I)*(v2^2 - 0.723896589334 - 0.799038508886*I)*v1))/(-(1.04308121136 - 1.20890075541*I)*v2 - (1.45598591076 + 0.129560576376*I)*e))
     206        sage: random_expr(5, verbose=True)
     207        About to apply exp to [pi]
     208        About to apply <built-in function mul> to [e^pi, 1]
     209        About to apply cosh to [e^pi]
     210        cosh(e^pi)
     211    """
    81212    vars = [(1.0, sage.calculus.calculus.var('v%d' % (n+1))) for n in range(nvars)]
    82     if nconsts is None:
    83         nconsts = size
    84     consts = [(1.0, const_generator()) for _ in range(nconsts)]
    85     leaves = [(var_frac, vars), (1.0 - var_frac - nullary_frac, consts), (nullary_frac, nullary)]
     213    if ncoeffs is None:
     214        ncoeffs = size
     215    coeffs = [(1.0, coeff_generator()) for _ in range(ncoeffs)]
     216    leaves = [(var_frac, vars), (1.0 - var_frac - nullary_frac, coeffs), (nullary_frac, nullary)]
    86217    leaves = normalize_prob_list(leaves)
    87218
    88219    internal = normalize_prob_list(internal)