예제 #1
0
def simplify_sqrt_real(expr):
    r"""
    Simplify sqrt in symbolic expressions in the real domain.
    
    EXAMPLES:
    
    Simplifications of basic expressions::
    
        sage: assume(x<0)      
        sage: simplify_sqrt_real( sqrt(x^2) )
        -x
        sage: simplify_sqrt_real( sqrt(x^2-2*x+1) )
        -x + 1
        sage: simplify_sqrt_real( sqrt(x^2) + sqrt(x^2-2*x+1) )
        -2*x + 1

    """
    from sage.symbolic.ring import SR
    from sage.calculus.calculus import maxima
    # 1/ Search for the sqrt's in expr
    sexpr = str(expr)
    if 'sqrt(' not in sexpr:  # no sqrt to simplify
        return expr
    pos_sqrts = []  # positions of the sqrt's in sexpr
    the_sqrts = []  # the sqrt sub-expressions in sexpr
    for pos in range(len(sexpr)):
        if sexpr[pos:pos + 5] == 'sqrt(':
            pos_sqrts.append(pos)
            parenth = 1
            scan = pos + 5
            while parenth != 0:
                if sexpr[scan] == '(': parenth += 1
                if sexpr[scan] == ')': parenth -= 1
                scan += 1
            the_sqrts.append(sexpr[pos:scan])
    # 2/ Simplifications of the sqrt's
    new_expr = ""  # will contain the result
    pos0 = 0
    for i, pos in enumerate(pos_sqrts):
        # radcan is called on each sqrt:
        x = SR(the_sqrts[i])
        simpl = SR(x._maxima_().radcan())
        # the absolute value of radcan's output is taken, the call to simplify()
        # taking into account possible assumptions regarding the sign of simpl:
        new_expr += sexpr[pos0:pos] + '(' + str(abs(simpl).simplify()) + ')'
        pos0 = pos + len(the_sqrts[i])
    new_expr += sexpr[pos0:]
    return SR(new_expr)
예제 #2
0
def simplify_sqrt_real(expr):
    r"""
    Simplify sqrt in symbolic expressions in the real domain.
    
    EXAMPLES:
    
    Simplifications of basic expressions::
    
        sage: assume(x<0)      
        sage: simplify_sqrt_real( sqrt(x^2) )
        -x
        sage: simplify_sqrt_real( sqrt(x^2-2*x+1) )
        -x + 1
        sage: simplify_sqrt_real( sqrt(x^2) + sqrt(x^2-2*x+1) )
        -2*x + 1

    """
    from sage.symbolic.ring import SR
    from sage.calculus.calculus import maxima
    # 1/ Search for the sqrt's in expr
    sexpr = str(expr)
    if 'sqrt(' not in sexpr:  # no sqrt to simplify
        return expr
    pos_sqrts = []   # positions of the sqrt's in sexpr
    the_sqrts = []   # the sqrt sub-expressions in sexpr
    for pos in range(len(sexpr)):
        if sexpr[pos:pos+5] == 'sqrt(':
            pos_sqrts.append(pos)
            parenth = 1
            scan = pos+5
            while parenth != 0:
                if sexpr[scan] == '(': parenth += 1
                if sexpr[scan] == ')': parenth -= 1
                scan += 1 
            the_sqrts.append( sexpr[pos:scan] )
    # 2/ Simplifications of the sqrt's
    new_expr = ""    # will contain the result
    pos0 = 0
    for i, pos in enumerate(pos_sqrts):
        # radcan is called on each sqrt:
        x = SR(the_sqrts[i])
        simpl = SR(x._maxima_().radcan())
        # the absolute value of radcan's output is taken, the call to simplify() 
        # taking into account possible assumptions regarding the sign of simpl:
        new_expr += sexpr[pos0:pos] + '(' + str(abs(simpl).simplify()) + ')'
        pos0 = pos + len(the_sqrts[i])
    new_expr += sexpr[pos0:]
    return SR(new_expr)
예제 #3
0
파일: utilities.py 프로젝트: drupel/sage
def simplify_sqrt_real(expr):
    r"""
    Simplify ``sqrt`` in symbolic expressions in the real domain.

    EXAMPLES:

    Simplifications of basic expressions::

        sage: from sage.manifolds.utilities import simplify_sqrt_real
        sage: simplify_sqrt_real( sqrt(x^2) )
        abs(x)
        sage: assume(x<0)
        sage: simplify_sqrt_real( sqrt(x^2) )
        -x
        sage: simplify_sqrt_real( sqrt(x^2-2*x+1) )
        -x + 1
        sage: simplify_sqrt_real( sqrt(x^2) + sqrt(x^2-2*x+1) )
        -2*x + 1

    This improves over Sage's
    :meth:`~sage.symbolic.expression.Expression.canonicalize_radical`,
    which yields incorrect results when ``x < 0``::

        sage: forget()  # removes the assumption x<0
        sage: sqrt(x^2).canonicalize_radical()
        x
        sage: assume(x<0)
        sage: sqrt(x^2).canonicalize_radical() # wrong output
        x
        sage: sqrt(x^2-2*x+1).canonicalize_radical() # wrong output
        x - 1
        sage: ( sqrt(x^2) + sqrt(x^2-2*x+1) ).canonicalize_radical() # wrong output
        2*x - 1

    Simplification of nested ``sqrt``'s::

        sage: forget()  # removes the assumption x<0
        sage: simplify_sqrt_real( sqrt(1 + sqrt(x^2)) )
        sqrt(abs(x) + 1)
        sage: assume(x<0)
        sage: simplify_sqrt_real( sqrt(1 + sqrt(x^2)) )
        sqrt(-x + 1)
        sage: simplify_sqrt_real( sqrt(x^2 + sqrt(4*x^2) + 1) )
        -x + 1

    Again, :meth:`~sage.symbolic.expression.Expression.canonicalize_radical`
    fails on the last one::

        sage: (sqrt(x^2 + sqrt(4*x^2) + 1)).canonicalize_radical()  # wrong output
        x + 1

    """
    from sage.symbolic.ring import SR
    from sage.functions.other import sqrt
    # 1/ Search for the sqrt's in expr
    sexpr = str(expr)
    if 'sqrt(' not in sexpr:  # no sqrt to simplify
        return expr
    if 'D[' in sexpr:
        return expr    #!# the code below is not capable of simplifying
                       # expressions with symbolic derivatives denoted by Pynac
                       # symbols of the type D[0]
    # Lists to store the positions of all the top-level sqrt's in sexpr:
    pos_sqrts = []  # position of first character, i.e. 's' of 'sqrt(...)'
    pos_after = []  # position of character immediatelty after 'sqrt(...)'
    the_sqrts = []  # the sqrt sub-expressions in sexpr, i.e. 'sqrt(...)'
    pos_max = len(sexpr) - 6
    pos = 0
    while pos < pos_max:
        if sexpr[pos:pos+5] == 'sqrt(':
            pos_sqrts.append(pos)
            parenth = 1
            scan = pos+5
            while parenth != 0:
                if sexpr[scan] == '(': parenth += 1
                if sexpr[scan] == ')': parenth -= 1
                scan += 1
            the_sqrts.append( sexpr[pos:scan] )
            pos_after.append(scan)
            pos = scan
        else:
            pos += 1
    # 2/ Search for sub-sqrt's:
    for i in range(len(the_sqrts)):
        argum = the_sqrts[i][5:-1]  # the sqrt argument
        if 'sqrt(' in argum:
            simpl = simplify_sqrt_real(SR(argum))
            the_sqrts[i] = 'sqrt(' + str(simpl) + ')'
    # 3/ Simplifications of the sqrt's
    new_expr = ""    # will contain the result
    pos0 = 0
    for i, pos in enumerate(pos_sqrts):
        # radcan is called on each sqrt:
        x = SR(the_sqrts[i])
        argum = x.operands()[0] # the argument of sqrt
        den = argum.denominator()
        if not (den == 1):  # the argument of sqrt is a fraction
            # NB: after #19312 (integrated in Sage 6.10.beta7), the above
            # cannot be written as
            #    if den != 1!:
            num = argum.numerator()
            if num < 0 or den < 0:
                x = sqrt(-num) / sqrt(-den)  # new equivalent expression for x
        simpl = SR(x._maxima_().radcan())
        if str(simpl)[:5] == 'sqrt(' or str(simpl)[:7] == '1/sqrt(':
            # no further simplification seems possible:
            ssimpl = str(simpl)
        else:
            # the absolute value of radcan's output is taken, the call to
            # simplify() taking into account possible assumptions regarding the
            # sign of simpl:
            ssimpl = str(abs(simpl).simplify())
        # search for abs(1/sqrt(...)) term to simplify it into 1/sqrt(...):
        pstart = ssimpl.find('abs(1/sqrt(')
        if pstart != -1:
            ssimpl = ssimpl[:pstart] + ssimpl[pstart+3:] # getting rid of 'abs'
        new_expr += sexpr[pos0:pos] + '(' + ssimpl + ')'
        pos0 = pos_after[i]
    new_expr += sexpr[pos0:]
    return SR(new_expr)
예제 #4
0
파일: utilities.py 프로젝트: shalec/sage
def simplify_sqrt_real(expr):
    r"""
    Simplify ``sqrt`` in symbolic expressions in the real domain.

    EXAMPLES:

    Simplifications of basic expressions::

        sage: from sage.manifolds.utilities import simplify_sqrt_real
        sage: simplify_sqrt_real( sqrt(x^2) )
        abs(x)
        sage: assume(x<0)
        sage: simplify_sqrt_real( sqrt(x^2) )
        -x
        sage: simplify_sqrt_real( sqrt(x^2-2*x+1) )
        -x + 1
        sage: simplify_sqrt_real( sqrt(x^2) + sqrt(x^2-2*x+1) )
        -2*x + 1

    This improves over Sage's
    :meth:`~sage.symbolic.expression.Expression.canonicalize_radical`,
    which yields incorrect results when ``x < 0``::

        sage: forget()  # removes the assumption x<0
        sage: sqrt(x^2).canonicalize_radical()
        x
        sage: assume(x<0)
        sage: sqrt(x^2).canonicalize_radical() # wrong output
        x
        sage: sqrt(x^2-2*x+1).canonicalize_radical() # wrong output
        x - 1
        sage: ( sqrt(x^2) + sqrt(x^2-2*x+1) ).canonicalize_radical() # wrong output
        2*x - 1

    Simplification of nested ``sqrt``'s::

        sage: forget()  # removes the assumption x<0
        sage: simplify_sqrt_real( sqrt(1 + sqrt(x^2)) )
        sqrt(abs(x) + 1)
        sage: assume(x<0)
        sage: simplify_sqrt_real( sqrt(1 + sqrt(x^2)) )
        sqrt(-x + 1)
        sage: simplify_sqrt_real( sqrt(x^2 + sqrt(4*x^2) + 1) )
        -x + 1

    Again, :meth:`~sage.symbolic.expression.Expression.canonicalize_radical`
    fails on the last one::

        sage: (sqrt(x^2 + sqrt(4*x^2) + 1)).canonicalize_radical()  # wrong output
        x + 1

    """
    from sage.symbolic.ring import SR
    from sage.functions.other import sqrt
    # 1/ Search for the sqrt's in expr
    sexpr = str(expr)
    if 'sqrt(' not in sexpr:  # no sqrt to simplify
        return expr
    if ('D[' in sexpr) or ('diff(' in sexpr):
        return expr  #!# the code below is not capable of simplifying
        # expressions with symbolic derivatives denoted
        # by Pynac symbols of the type D[0] or diff(...)
    # Lists to store the positions of all the top-level sqrt's in sexpr:
    pos_sqrts = []  # position of first character, i.e. 's' of 'sqrt(...)'
    pos_after = []  # position of character immediately after 'sqrt(...)'
    the_sqrts = []  # the sqrt sub-expressions in sexpr, i.e. 'sqrt(...)'
    pos_max = len(sexpr) - 6
    pos = 0
    while pos < pos_max:
        if sexpr[pos:pos + 5] == 'sqrt(':
            pos_sqrts.append(pos)
            parenth = 1
            scan = pos + 5
            while parenth != 0:
                if sexpr[scan] == '(': parenth += 1
                if sexpr[scan] == ')': parenth -= 1
                scan += 1
            the_sqrts.append(sexpr[pos:scan])
            pos_after.append(scan)
            pos = scan
        else:
            pos += 1
    # 2/ Search for sub-sqrt's:
    for i in range(len(the_sqrts)):
        argum = the_sqrts[i][5:-1]  # the sqrt argument
        if 'sqrt(' in argum:
            simpl = simplify_sqrt_real(SR(argum))
            the_sqrts[i] = 'sqrt(' + str(simpl) + ')'
    # 3/ Simplifications of the sqrt's
    new_expr = ""  # will contain the result
    pos0 = 0
    for i, pos in enumerate(pos_sqrts):
        # radcan is called on each sqrt:
        x = SR(the_sqrts[i])
        argum = x.operands()[0]  # the argument of sqrt
        den = argum.denominator()
        if not (den == 1):  # the argument of sqrt is a fraction
            # NB: after #19312 (integrated in Sage 6.10.beta7), the above
            # cannot be written as
            #    if den != 1!:
            num = argum.numerator()
            if num < 0 or den < 0:
                x = sqrt(-num) / sqrt(-den)  # new equivalent expression for x
        simpl = SR(x._maxima_().radcan())
        if str(simpl)[:5] == 'sqrt(' or str(simpl)[:7] == '1/sqrt(':
            # no further simplification seems possible:
            ssimpl = str(simpl)
        else:
            # the absolute value of radcan's output is taken, the call to
            # simplify() taking into account possible assumptions regarding the
            # sign of simpl:
            ssimpl = str(abs(simpl).simplify())
        # search for abs(1/sqrt(...)) term to simplify it into 1/sqrt(...):
        pstart = ssimpl.find('abs(1/sqrt(')
        if pstart != -1:
            ssimpl = ssimpl[:pstart] + ssimpl[pstart +
                                              3:]  # getting rid of 'abs'
        new_expr += sexpr[pos0:pos] + '(' + ssimpl + ')'
        pos0 = pos_after[i]
    new_expr += sexpr[pos0:]
    return SR(new_expr)
예제 #5
0
def simplify_sqrt_real(expr):
    r"""
    Simplify sqrt in symbolic expressions in the real domain.

    EXAMPLES:

    Simplifications of basic expressions::

        sage: from sage.geometry.manifolds.utilities import simplify_sqrt_real
        sage: assume(x<0)
        sage: simplify_sqrt_real( sqrt(x^2) )
        -x
        sage: simplify_sqrt_real( sqrt(x^2-2*x+1) )
        -x + 1
        sage: simplify_sqrt_real( sqrt(x^2) + sqrt(x^2-2*x+1) )
        -2*x + 1

    This improves over Sage's
    :meth:`~sage.symbolic.expression.Expression.canonicalize_radical` which yields
    incorrect results when x<0::

        sage: sqrt(x^2).canonicalize_radical() # wrong output
        x
        sage: sqrt(x^2-2*x+1).canonicalize_radical() # wrong output
        x - 1
        sage: ( sqrt(x^2) + sqrt(x^2-2*x+1) ).canonicalize_radical() # wrong output
        2*x - 1

    """
    from sage.symbolic.ring import SR
    from sage.calculus.calculus import maxima
    from sage.functions.other import sqrt
    # 1/ Search for the sqrt's in expr
    sexpr = str(expr)
    if 'sqrt(' not in sexpr:  # no sqrt to simplify
        return expr
    if 'D[' in sexpr:
        return expr    #!# the code below is not capable of simplifying
                       # expressions with symbolic derivatives denoted by Pynac
                       # symbols of the type D[0]
    pos_sqrts = []   # positions of the sqrt's in sexpr
    the_sqrts = []   # the sqrt sub-expressions in sexpr
    for pos in range(len(sexpr)):
        if sexpr[pos:pos+5] == 'sqrt(':
            pos_sqrts.append(pos)
            parenth = 1
            scan = pos+5
            while parenth != 0:
                if sexpr[scan] == '(': parenth += 1
                if sexpr[scan] == ')': parenth -= 1
                scan += 1
            the_sqrts.append( sexpr[pos:scan] )
    # 2/ Simplifications of the sqrt's
    new_expr = ""    # will contain the result
    pos0 = 0
    for i, pos in enumerate(pos_sqrts):
        # radcan is called on each sqrt:
        x = SR(the_sqrts[i])
        argum = x.operands()[0] # the argument of sqrt
        den = argum.denominator()
        if den != 1:  # the argument of sqrt is a fraction
            num = argum.numerator()
            if num < 0 or den < 0:
                x = sqrt(-num) / sqrt(-den)  # new equivalent expression for x
        simpl = SR(x._maxima_().radcan())
        if str(simpl)[:5] != 'sqrt(':
            # the absolute value of radcan's output is taken, the call to simplify()
            # taking into account possible assumptions regarding the sign of simpl:
            ssimpl = str(abs(simpl).simplify())
        else:
            ssimpl = str(simpl)
        # search for abs(1/sqrt(...)) term to simplify it into 1/sqrt(...):
        pstart = ssimpl.find('abs(1/sqrt(')
        if pstart != -1:
            ssimpl = ssimpl[:pstart] + ssimpl[pstart+3:] # getting rid of 'abs'
        new_expr += sexpr[pos0:pos] + '(' + ssimpl + ')'
        pos0 = pos + len(the_sqrts[i])
    new_expr += sexpr[pos0:]
    return SR(new_expr)