Ejemplo n.º 1
0
    def _eval_(self, f, x):
        """
        EXAMPLES::

            sage: from sage.symbolic.integration.integral import indefinite_integral
            sage: indefinite_integral(exp(x), x) # indirect doctest
            e^x
            sage: indefinite_integral(exp(x), x^2)
            2*(x - 1)*e^x

        TESTS:

        Check that :trac:`28842` is fixed::

            sage: integrate(1/(x^4 + x^3 + 1), x)
            integrate(1/(x^4 + x^3 + 1), x)

        Check that :trac:`32002` is fixed::

            sage: result = integral(2*min_symbolic(x,2*x),x)
            ...
            sage: result
            -1/2*x^2*sgn(x) + 3/2*x^2
        """
        # Check for x
        if not is_SymbolicVariable(x):
            if len(x.variables()) == 1:
                nx = x.variables()[0]
                f = f * x.diff(nx)
                x = nx
            else:
                return None

        # we try all listed integration algorithms
        A = None
        for integrator in self.integrators:
            try:
                A = integrator(f, x)
            except (NotImplementedError, TypeError, AttributeError,
                    RuntimeError):
                pass
            except ValueError:
                # maxima is telling us something
                raise
            else:
                if not hasattr(A, 'operator'):
                    return A
                else:
                    uneval = integral(SR.wild(0), x, hold=True)
                    if not A.has(uneval):
                        return A
        return A
Ejemplo n.º 2
0
    def _eval_(self, f, x, a, b):
        """
        Return the results of symbolic evaluation of the integral.

        EXAMPLES::

            sage: from sage.symbolic.integration.integral import definite_integral
            sage: definite_integral(exp(x),x,0,1) # indirect doctest
            e - 1

        TESTS:

        Check that :trac:`32002` is fixed::

            sage: result = integral(2*min_symbolic(x,2*x),x,-1,1)
            ...
            sage: result
            -1
        """
        # Check for x
        if not is_SymbolicVariable(x):
            if len(x.variables()) == 1:
                nx = x.variables()[0]
                f = f * x.diff(nx)
                x = nx
            else:
                return None

        args = (f, x, a, b)

        # we try all listed integration algorithms
        A = None
        for integrator in self.integrators:
            try:
                A = integrator(*args)
            except (NotImplementedError, TypeError, AttributeError,
                    RuntimeError):
                pass
            except ValueError:
                # maxima is telling us something
                raise
            else:
                if not hasattr(A, 'operator'):
                    return A
                else:
                    uneval = integral(SR.wild(0), x, a, b, hold=True)
                    if not A.has(uneval):
                        return A
        return A
Ejemplo n.º 3
0
def simplify_abs_trig(expr):
    r"""
    Simplify ``abs(sin(...))`` and ``abs(cos(...))`` in symbolic expressions.

    EXAMPLES::

        sage: M = Manifold(3, 'M', structure='topological')
        sage: X.<x,y,z> = M.chart(r'x y:(0,pi) z:(-pi/3,0)')
        sage: X.coord_range()
        x: (-oo, +oo); y: (0, pi); z: (-1/3*pi, 0)

    Since `x` spans all `\RR`, no simplification of ``abs(sin(x))``
    occurs, while ``abs(sin(y))`` and ``abs(sin(3*z))`` are correctly
    simplified, given that `y \in (0,\pi)` and `z \in (-\pi/3,0)`::

        sage: from sage.manifolds.utilities import simplify_abs_trig
        sage: simplify_abs_trig( abs(sin(x)) + abs(sin(y)) + abs(sin(3*z)) )
        abs(sin(x)) + sin(y) + sin(-3*z)

    Note that neither
    :meth:`~sage.symbolic.expression.Expression.simplify_trig` nor
    :meth:`~sage.symbolic.expression.Expression.simplify_full`
    works in this case::

        sage: s = abs(sin(x)) + abs(sin(y)) + abs(sin(3*z))
        sage: s.simplify_trig()
        abs(4*cos(-z)^2 - 1)*abs(sin(-z)) + abs(sin(x)) + abs(sin(y))
        sage: s.simplify_full()
        abs(4*cos(-z)^2 - 1)*abs(sin(-z)) + abs(sin(x)) + abs(sin(y))

    despite the following assumptions hold::

        sage: assumptions()
        [x is real, y is real, y > 0, y < pi, z is real, z > -1/3*pi, z < 0]

    Additional checks are::

        sage: simplify_abs_trig( abs(sin(y/2)) )  # shall simplify
        sin(1/2*y)
        sage: simplify_abs_trig( abs(sin(2*y)) )  # must not simplify
        abs(sin(2*y))
        sage: simplify_abs_trig( abs(sin(z/2)) )  # shall simplify
        sin(-1/2*z)
        sage: simplify_abs_trig( abs(sin(4*z)) )  # must not simplify
        abs(sin(-4*z))

    Simplification of ``abs(cos(...))``::

        sage: forget()
        sage: M = Manifold(3, 'M', structure='topological')
        sage: X.<x,y,z> = M.chart(r'x y:(0,pi/2) z:(pi/4,3*pi/4)')
        sage: X.coord_range()
        x: (-oo, +oo); y: (0, 1/2*pi); z: (1/4*pi, 3/4*pi)
        sage: simplify_abs_trig( abs(cos(x)) + abs(cos(y)) + abs(cos(2*z)) )
        abs(cos(x)) + cos(y) - cos(2*z)

    Additional tests::

        sage: simplify_abs_trig(abs(cos(y-pi/2)))  # shall simplify
        cos(-1/2*pi + y)
        sage: simplify_abs_trig(abs(cos(y+pi/2)))  # shall simplify
        -cos(1/2*pi + y)
        sage: simplify_abs_trig(abs(cos(y-pi)))  # shall simplify
        -cos(-pi + y)
        sage: simplify_abs_trig(abs(cos(2*y)))  # must not simplify
        abs(cos(2*y))
        sage: simplify_abs_trig(abs(cos(y/2)) * abs(sin(z)))  # shall simplify
        cos(1/2*y)*sin(z)

    TESTS:

    Simplification of expressions involving some symbolic derivatives::

        sage: f = function('f')
        sage: s = abs(cos(x)) + abs(cos(y))*diff(f(x),x) + abs(cos(2*z))
        sage: simplify_abs_trig(s)
        cos(y)*diff(f(x), x) + abs(cos(x)) - cos(2*z)
        sage: s = abs(sin(x))*diff(f(x),x).subs(x=y^2) + abs(cos(y))
        sage: simplify_abs_trig(s)
        abs(sin(x))*D[0](f)(y^2) + cos(y)
        sage: forget()  # for doctests below

    """
    w0 = SR.wild()
    if expr.has(abs_symbolic(sin(w0))) or expr.has(abs_symbolic(cos(w0))):
        return SimplifyAbsTrig(expr)()
    return expr
Ejemplo n.º 4
0
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
    :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()
        -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
        -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()
        x - 1

    TESTS:

    Simplification of expressions involving some symbolic derivatives::

        sage: f = function('f')
        sage: simplify_sqrt_real( diff(f(x), x)/sqrt(x^2-2*x+1) )  # x<0 => x-1<0
        -diff(f(x), x)/(x - 1)
        sage: g = function('g')
        sage: simplify_sqrt_real( sqrt(x^3*diff(f(g(x)), x)^2) )  # x<0
        (-x)^(3/2)*abs(D[0](f)(g(x)))*abs(diff(g(x), x))
        sage: forget()  # for doctests below

    """
    w0 = SR.wild()
    one_half = Rational((1, 2))
    if expr.has(w0**one_half) or expr.has(w0**(-one_half)):
        return SimplifySqrtReal(expr)()
    return expr
Ejemplo n.º 5
0
    def composition(self, ex, operator):
        r"""
        This is the only method of the base class
        :class:`~sage.symbolic.expression_conversions.ExpressionTreeWalker`
        that is reimplemented, since it manages the composition of
        ``abs`` with ``cos`` or ``sin``.

        INPUT:

        - ``ex`` -- a symbolic expression
        - ``operator`` -- an operator

        OUTPUT:

        - a symbolic expression, equivalent to ``ex`` with ``abs(cos(...))``
          and ``abs(sin(...))`` simplified, according to the range of their
          argument.

        EXAMPLES::

            sage: from sage.manifolds.utilities import SimplifyAbsTrig
            sage: assume(-pi/2 < x, x<0)
            sage: a = abs(sin(x))
            sage: s = SimplifyAbsTrig(a)
            sage: a.operator()
            abs
            sage: s.composition(a, a.operator())
            sin(-x)

        ::

            sage: a = exp(function('f')(x))  # no abs(sin_or_cos(...))
            sage: a.operator()
            exp
            sage: s.composition(a, a.operator())
            e^f(x)

        ::

            sage: forget()  # no longer any assumption on x
            sage: a = abs(cos(sin(x)))  # simplifiable since -1 <= sin(x) <= 1
            sage: s.composition(a, a.operator())
            cos(sin(x))
            sage: a = abs(sin(cos(x)))  # not simplifiable
            sage: s.composition(a, a.operator())
            abs(sin(cos(x)))

        """
        if operator is abs_symbolic:
            argum = ex.operands()[0]  # argument of abs
            if argum.operator() is sin:
                # Case of abs(sin(...))
                x = argum.operands()[0]  # argument of sin
                w0 = SR.wild()
                if x.has(abs_symbolic(sin(w0))) or x.has(abs_symbolic(
                        cos(w0))):
                    x = self(x)  # treatment of nested abs(sin_or_cos(...))
                # Simplifications for values of x in the range [-pi, 2*pi]:
                if x >= 0 and x <= pi:
                    ex = sin(x)
                elif (x > pi and x <= 2 * pi) or (x >= -pi and x < 0):
                    ex = -sin(x)
                return ex
            if argum.operator() is cos:
                # Case of abs(cos(...))
                x = argum.operands()[0]  # argument of cos
                w0 = SR.wild()
                if x.has(abs_symbolic(sin(w0))) or x.has(abs_symbolic(
                        cos(w0))):
                    x = self(x)  # treatment of nested abs(sin_or_cos(...))
                # Simplifications for values of x in the range [-pi, 2*pi]:
                if (x >= -pi / 2 and x <= pi / 2) or (x >= 3 * pi / 2
                                                      and x <= 2 * pi):
                    ex = cos(x)
                elif (x > pi / 2 and x <= 3 * pi / 2) or (x >= -pi
                                                          and x < -pi / 2):
                    ex = -cos(x)
                return ex
        # If no pattern is found, we default to ExpressionTreeWalker:
        return super(SimplifyAbsTrig, self).composition(ex, operator)
Ejemplo n.º 6
0
    def arithmetic(self, ex, operator):
        r"""
        This is the only method of the base class
        :class:`~sage.symbolic.expression_conversions.ExpressionTreeWalker`
        that is reimplemented, since square roots are considered as
        arithmetic operations with ``operator`` = ``pow`` and
        ``ex.operands()[1]`` = ``1/2`` or ``-1/2``.

        INPUT:

        - ``ex`` -- a symbolic expression
        - ``operator`` -- an arithmetic operator

        OUTPUT:

        - a symbolic expression, equivalent to ``ex`` with square roots
          simplified

        EXAMPLES::

            sage: from sage.manifolds.utilities import SimplifySqrtReal
            sage: a = sqrt(x^2+2*x+1)
            sage: s = SimplifySqrtReal(a)
            sage: a.operator()
            <built-in function pow>
            sage: s.arithmetic(a, a.operator())
            abs(x + 1)

        ::

            sage: a = x + 1  # no square root
            sage: s.arithmetic(a, a.operator())
            x + 1

        ::

            sage: a = x + 1 + sqrt(function('f')(x)^2)
            sage: s.arithmetic(a, a.operator())
            x + abs(f(x)) + 1

        """
        if operator is _pow:
            operands = ex.operands()
            power = operands[1]
            one_half = Rational((1, 2))
            minus_one_half = -one_half
            if (power == one_half) or (power == minus_one_half):
                # This is a square root or the inverse of a square root
                w0 = SR.wild(0)
                w1 = SR.wild(1)
                sqrt_pattern = w0**one_half
                inv_sqrt_pattern = w0**minus_one_half
                sqrt_ratio_pattern1 = w0**one_half * w1**minus_one_half
                sqrt_ratio_pattern2 = w0**minus_one_half * w1**one_half
                argum = operands[0]  # the argument of sqrt
                if argum.has(sqrt_pattern) or argum.has(inv_sqrt_pattern):
                    argum = self(argum)  # treatment of nested sqrt's
                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 test cannot be written as "if den != 1:"
                    num = argum.numerator()
                    if num < 0 or den < 0:
                        ex = sqrt(-num) / sqrt(-den)
                    else:
                        ex = sqrt(argum)
                else:
                    ex = sqrt(argum)
                simpl = SR(ex._maxima_().radcan())
                if (not simpl.match(sqrt_pattern)
                        and not simpl.match(inv_sqrt_pattern)
                        and not simpl.match(sqrt_ratio_pattern1)
                        and not simpl.match(sqrt_ratio_pattern2)):
                    # radcan transformed substantially the expression,
                    # possibly getting rid of some sqrt; in order to ensure a
                    # positive result, the absolute value of radcan's output
                    # is taken, the call to simplify() taking care of possible
                    # assumptions regarding signs of subexpression of simpl:
                    simpl = abs(simpl).simplify()
                if power == minus_one_half:
                    simpl = SR(1) / simpl
                return simpl
        # If operator is not a square root, we default to ExpressionTreeWalker:
        return super(SimplifySqrtReal, self).arithmetic(ex, operator)