Ejemplo n.º 1
0
    def _eval_evalf(self, prec=15, **options):
        """Evaluate the coordinates of the point.

        This method will, where possible, create and return a new Point
        where the coordinates are evaluated as floating point numbers to
        the precision indicated (default=15).

        Parameters
        ==========

        prec : int

        Returns
        =======

        point : Point

        Examples
        ========

        >>> from sympy import Point, Rational
        >>> p1 = Point(Rational(1, 2), Rational(3, 2))
        >>> p1
        Point2D(1/2, 3/2)
        >>> p1.evalf()
        Point2D(0.5, 1.5)

        """
        dps = prec_to_dps(prec)
        coords = [x.evalf(n=dps, **options) for x in self.args]
        return Point(*coords, evaluate=False)
Ejemplo n.º 2
0
 def _eval_evalf(self, prec):
     try:
         _roots = self.poly.nroots(n=prec_to_dps(prec))
     except (DomainError, PolynomialError):
         return self
     else:
         return Add(*[self.fun(r) for r in _roots])
Ejemplo n.º 3
0
 def _eval_evalf(self, prec):
     try:
         _roots = self.poly.nroots(n=prec_to_dps(prec))
     except (DomainError, PolynomialError):
         return self
     else:
         return Add(*[self.fun(r) for r in _roots])
Ejemplo n.º 4
0
 def _eval_evalf(self, prec):
     if not self.args:
         return self
     new_args = []
     dps = prec_to_dps(prec)
     for mat, frame in self.args:
         new_args.append([mat.evalf(n=dps), frame])
     return Vector(new_args)
Ejemplo n.º 5
0
 def _eval_evalf(self, prec):
     if not self.args:
         return self
     new_args = []
     dps = prec_to_dps(prec)
     for inlist in self.args:
         new_inlist = list(inlist)
         new_inlist[0] = inlist[0].evalf(n=dps)
         new_args.append(tuple(new_inlist))
     return Dyadic(new_args)
Ejemplo n.º 6
0
def _eigenvals_eigenvects_mpmath(M):
    norm2 = lambda v: mp.sqrt(sum(i**2 for i in v))

    v1 = None
    prec = max([x._prec for x in M.atoms(Float)])
    eps = 2**-prec

    while prec < DEFAULT_MAXPREC:
        with workprec(prec):
            A = mp.matrix(M.evalf(n=prec_to_dps(prec)))
            E, ER = mp.eig(A)
            v2 = norm2([i for e in E for i in (mp.re(e), mp.im(e))])
            if v1 is not None and mp.fabs(v1 - v2) < eps:
                return E, ER
            v1 = v2
        prec *= 2

    # we get here because the next step would have taken us
    # past MAXPREC or because we never took a step; in case
    # of the latter, we refuse to send back a solution since
    # it would not have been verified; we also resist taking
    # a small step to arrive exactly at MAXPREC since then
    # the two calculations might be artificially close.
    raise PrecisionExhausted
Ejemplo n.º 7
0
    def _eval_evalf(self, prec):
        """Returns the floating point approximations (decimal numbers) of the quaternion.

        Returns
        =======

        Quaternion
            Floating point approximations of quaternion(self)

        Examples
        ========

        >>> from sympy import Quaternion
        >>> from sympy import sqrt
        >>> q = Quaternion(1/sqrt(1), 1/sqrt(2), 1/sqrt(3), 1/sqrt(4))
        >>> q.evalf()
        1.00000000000000
        + 0.707106781186547*i
        + 0.577350269189626*j
        + 0.500000000000000*k

        """
        nprec = prec_to_dps(prec)
        return Quaternion(*[arg.evalf(n=nprec) for arg in self.args])
Ejemplo n.º 8
0
def hypsum(expr, n, start, prec):
    """
    Sum a rapidly convergent infinite hypergeometric series with
    given general term, e.g. e = hypsum(1/factorial(n), n). The
    quotient between successive terms must be a quotient of integer
    polynomials.
    """
    from sympy import Float, hypersimp, lambdify

    if prec == float('inf'):
        raise NotImplementedError('does not support inf prec')

    if start:
        expr = expr.subs(n, n + start)
    hs = hypersimp(expr, n)
    if hs is None:
        raise NotImplementedError("a hypergeometric series is required")
    num, den = hs.as_numer_denom()

    func1 = lambdify(n, num)
    func2 = lambdify(n, den)

    h, g, p = check_convergence(num, den, n)

    if h < 0:
        raise ValueError("Sum diverges like (n!)^%i" % (-h))

    term = expr.subs(n, 0)
    if not term.is_Rational:
        raise NotImplementedError(
            "Non rational term functionality is not implemented.")

    # Direct summation if geometric or faster
    if h > 0 or (h == 0 and abs(g) > 1):
        term = (MPZ(term.p) << prec) // term.q
        s = term
        k = 1
        while abs(term) > 5:
            term *= MPZ(func1(k - 1))
            term //= MPZ(func2(k - 1))
            s += term
            k += 1
        return from_man_exp(s, -prec)
    else:
        alt = g < 0
        if abs(g) < 1:
            raise ValueError("Sum diverges like (%i)^n" % abs(1 / g))
        if p < 1 or (p == 1 and not alt):
            raise ValueError("Sum diverges like n^%i" % (-p))
        # We have polynomial convergence: use Richardson extrapolation
        vold = None
        ndig = prec_to_dps(prec)
        while True:
            # Need to use at least quad precision because a lot of cancellation
            # might occur in the extrapolation process; we check the answer to
            # make sure that the desired precision has been reached, too.
            prec2 = 4 * prec
            term0 = (MPZ(term.p) << prec2) // term.q

            def summand(k, _term=[term0]):
                if k:
                    k = int(k)
                    _term[0] *= MPZ(func1(k - 1))
                    _term[0] //= MPZ(func2(k - 1))
                return make_mpf(from_man_exp(_term[0], -prec2))

            with workprec(prec):
                v = nsum(summand, [0, mpmath_inf], method='richardson')
            vf = Float(v, ndig)
            if vold is not None and vold == vf:
                break
            prec += prec  # double precision each time
            vold = vf

        return v._mpf_
Ejemplo n.º 9
0
def _jordan_form(M, calc_transform=True, *, chop=False):
    """Return $(P, J)$ where $J$ is a Jordan block
    matrix and $P$ is a matrix such that $M = P J P^{-1}$

    Parameters
    ==========

    calc_transform : bool
        If ``False``, then only $J$ is returned.

    chop : bool
        All matrices are converted to exact types when computing
        eigenvalues and eigenvectors.  As a result, there may be
        approximation errors.  If ``chop==True``, these errors
        will be truncated.

    Examples
    ========

    >>> from sympy.matrices import Matrix
    >>> M = Matrix([[ 6,  5, -2, -3], [-3, -1,  3,  3], [ 2,  1, -2, -3], [-1,  1,  5,  5]])
    >>> P, J = M.jordan_form()
    >>> J
    Matrix([
    [2, 1, 0, 0],
    [0, 2, 0, 0],
    [0, 0, 2, 1],
    [0, 0, 0, 2]])

    See Also
    ========

    jordan_block
    """

    if not M.is_square:
        raise NonSquareMatrixError("Only square matrices have Jordan forms")

    mat = M
    has_floats = M.has(Float)

    if has_floats:
        try:
            max_prec = max(term._prec for term in M.values()
                           if isinstance(term, Float))
        except ValueError:
            # if no term in the matrix is explicitly a Float calling max()
            # will throw a error so setting max_prec to default value of 53
            max_prec = 53

        # setting minimum max_dps to 15 to prevent loss of precision in
        # matrix containing non evaluated expressions
        max_dps = max(prec_to_dps(max_prec), 15)

    def restore_floats(*args):
        """If ``has_floats`` is `True`, cast all ``args`` as
        matrices of floats."""

        if has_floats:
            args = [m.evalf(n=max_dps, chop=chop) for m in args]
        if len(args) == 1:
            return args[0]

        return args

    # cache calculations for some speedup
    mat_cache = {}

    def eig_mat(val, pow):
        """Cache computations of ``(M - val*I)**pow`` for quick
        retrieval"""

        if (val, pow) in mat_cache:
            return mat_cache[(val, pow)]

        if (val, pow - 1) in mat_cache:
            mat_cache[(val, pow)] = mat_cache[(val, pow - 1)].multiply(
                mat_cache[(val, 1)], dotprodsimp=None)
        else:
            mat_cache[(val, pow)] = (mat - val * M.eye(M.rows)).pow(pow)

        return mat_cache[(val, pow)]

    # helper functions
    def nullity_chain(val, algebraic_multiplicity):
        """Calculate the sequence  [0, nullity(E), nullity(E**2), ...]
        until it is constant where ``E = M - val*I``"""

        # mat.rank() is faster than computing the null space,
        # so use the rank-nullity theorem
        cols = M.cols
        ret = [0]
        nullity = cols - eig_mat(val, 1).rank()
        i = 2

        while nullity != ret[-1]:
            ret.append(nullity)

            if nullity == algebraic_multiplicity:
                break

            nullity = cols - eig_mat(val, i).rank()
            i += 1

            # Due to issues like #7146 and #15872, SymPy sometimes
            # gives the wrong rank. In this case, raise an error
            # instead of returning an incorrect matrix
            if nullity < ret[-1] or nullity > algebraic_multiplicity:
                raise MatrixError("SymPy had encountered an inconsistent "
                                  "result while computing Jordan block: "
                                  "{}".format(M))

        return ret

    def blocks_from_nullity_chain(d):
        """Return a list of the size of each Jordan block.
        If d_n is the nullity of E**n, then the number
        of Jordan blocks of size n is

            2*d_n - d_(n-1) - d_(n+1)"""

        # d[0] is always the number of columns, so skip past it
        mid = [2 * d[n] - d[n - 1] - d[n + 1] for n in range(1, len(d) - 1)]
        # d is assumed to plateau with "d[ len(d) ] == d[-1]", so
        # 2*d_n - d_(n-1) - d_(n+1) == d_n - d_(n-1)
        end = [d[-1] - d[-2]] if len(d) > 1 else [d[0]]

        return mid + end

    def pick_vec(small_basis, big_basis):
        """Picks a vector from big_basis that isn't in
        the subspace spanned by small_basis"""

        if len(small_basis) == 0:
            return big_basis[0]

        for v in big_basis:
            _, pivots = M.hstack(*(small_basis +
                                   [v])).echelon_form(with_pivots=True)

            if pivots[-1] == len(small_basis):
                return v

    # roots doesn't like Floats, so replace them with Rationals
    if has_floats:
        mat = mat.applyfunc(lambda x: nsimplify(x, rational=True))

    # first calculate the jordan block structure
    eigs = mat.eigenvals()

    # Make sure that we have all roots in radical form
    for x in eigs:
        if x.has(CRootOf):
            raise MatrixError(
                "Jordan normal form is not implemented if the matrix have "
                "eigenvalues in CRootOf form")

    # most matrices have distinct eigenvalues
    # and so are diagonalizable.  In this case, don't
    # do extra work!
    if len(eigs.keys()) == mat.cols:
        blocks = list(sorted(eigs.keys(), key=default_sort_key))
        jordan_mat = mat.diag(*blocks)

        if not calc_transform:
            return restore_floats(jordan_mat)

        jordan_basis = [eig_mat(eig, 1).nullspace()[0] for eig in blocks]
        basis_mat = mat.hstack(*jordan_basis)

        return restore_floats(basis_mat, jordan_mat)

    block_structure = []

    for eig in sorted(eigs.keys(), key=default_sort_key):
        algebraic_multiplicity = eigs[eig]
        chain = nullity_chain(eig, algebraic_multiplicity)
        block_sizes = blocks_from_nullity_chain(chain)

        # if block_sizes =       = [a, b, c, ...], then the number of
        # Jordan blocks of size 1 is a, of size 2 is b, etc.
        # create an array that has (eig, block_size) with one
        # entry for each block
        size_nums = [(i + 1, num) for i, num in enumerate(block_sizes)]

        # we expect larger Jordan blocks to come earlier
        size_nums.reverse()

        block_structure.extend(
            (eig, size) for size, num in size_nums for _ in range(num))

    jordan_form_size = sum(size for eig, size in block_structure)

    if jordan_form_size != M.rows:
        raise MatrixError("SymPy had encountered an inconsistent result while "
                          "computing Jordan block. : {}".format(M))

    blocks = (mat.jordan_block(size=size, eigenvalue=eig)
              for eig, size in block_structure)
    jordan_mat = mat.diag(*blocks)

    if not calc_transform:
        return restore_floats(jordan_mat)

    # For each generalized eigenspace, calculate a basis.
    # We start by looking for a vector in null( (A - eig*I)**n )
    # which isn't in null( (A - eig*I)**(n-1) ) where n is
    # the size of the Jordan block
    #
    # Ideally we'd just loop through block_structure and
    # compute each generalized eigenspace.  However, this
    # causes a lot of unneeded computation.  Instead, we
    # go through the eigenvalues separately, since we know
    # their generalized eigenspaces must have bases that
    # are linearly independent.
    jordan_basis = []

    for eig in sorted(eigs.keys(), key=default_sort_key):
        eig_basis = []

        for block_eig, size in block_structure:
            if block_eig != eig:
                continue

            null_big = (eig_mat(eig, size)).nullspace()
            null_small = (eig_mat(eig, size - 1)).nullspace()

            # we want to pick something that is in the big basis
            # and not the small, but also something that is independent
            # of any other generalized eigenvectors from a different
            # generalized eigenspace sharing the same eigenvalue.
            vec = pick_vec(null_small + eig_basis, null_big)
            new_vecs = [
                eig_mat(eig, i).multiply(vec, dotprodsimp=None)
                for i in range(size)
            ]

            eig_basis.extend(new_vecs)
            jordan_basis.extend(reversed(new_vecs))

    basis_mat = mat.hstack(*jordan_basis)

    return restore_floats(basis_mat, jordan_mat)
Ejemplo n.º 10
0
 def _eval_evalf(self, prec=15, **options):
     pt, r = self.args
     dps = prec_to_dps(prec)
     pt = pt.evalf(n=dps, **options)
     r = r.evalf(n=dps, **options)
     return self.func(pt, r, evaluate=False)
Ejemplo n.º 11
0
 def _eval_evalf(self, prec=15, **options):
     f, (t, a, b) = self.args
     dps = prec_to_dps(prec)
     f = tuple([i.evalf(n=dps, **options) for i in f])
     a, b = [i.evalf(n=dps, **options) for i in (a, b)]
     return self.func(f, (t, a, b))
Ejemplo n.º 12
0
 def _eval_evalf(self, prec, **kwargs):
     """Evaluate this complex root to the given precision."""
     # all kwargs are ignored
     return self.eval_rational(n=prec_to_dps(prec))._evalf(prec)
Ejemplo n.º 13
0
 def _eval_evalf(self, prec, **kwargs):
     """Evaluate this complex root to the given precision."""
     # all kwargs are ignored
     return self.eval_rational(n=prec_to_dps(prec))._evalf(prec)
Ejemplo n.º 14
0
 def _eval_evalf(self, prec):
     z = self.args[0]
     nprec = prec_to_dps(prec)
     return polygamma(1, z).evalf(n=nprec)
Ejemplo n.º 15
0
    def eval(cls, arg):
        from .complexes import im
        if arg.is_integer:
            return arg
        if isinstance(arg, cls):
            return arg
        if arg.is_imaginary or (I*arg).is_extended_real:
            i = im(arg)
            if not i.has(I):
                return cls(i)*I
            return cls(arg, evaluate=False)

        v = cls._eval_number(arg)
        if v is not None:
            return v

        # Integral, numerical, symbolic part
        ipart = npart = spart = Integer(0)

        # Extract integral (or complex integral) terms
        terms = Add.make_args(arg)

        for t in terms:
            if t.is_integer or (t.is_imaginary and im(t).is_integer):
                ipart += t
            elif t.free_symbols:
                spart += t
            else:
                npart += t

        if not (npart or spart):
            return ipart

        # Evaluate npart numerically if independent of spart
        if npart and (not spart or npart.is_extended_real and
                      (spart.is_imaginary or (I*spart).is_extended_real) or
                      npart.is_imaginary and spart.is_extended_real):
            npart_int = None
            try:
                from ...core.evalf import DEFAULT_MAXPREC as TARGET
                prec = 10
                r, i = Integer(0), Integer(0)
                npart_re, npart_im = npart.as_real_imag()
                while prec < TARGET:
                    dps = prec_to_dps(prec)
                    r, i = npart_re.evalf(dps), npart_im.evalf(dps)
                    if ((not r or int(2**prec*abs(r)) > 2**prec*abs(int(r))) and
                            (not i or int(2**prec*abs(i)) > 2**prec*abs(int(i)))):
                        npart_int = cls(r) + cls(i)*I
                        break
                    prec += 10
                else:
                    raise PrecisionExhausted
            except PrecisionExhausted:
                npart_int = cls(r) + cls(i)*I
                if not npart.equals(npart_int):
                    npart_int = None

            if npart_int is not None:
                ipart += npart_int
                npart = Integer(0)

        spart += npart
        if not spart:
            return ipart
        elif spart.is_imaginary or (I*spart).is_extended_real:
            return ipart + cls(im(spart), evaluate=False)*I
        else:
            return ipart + cls(spart, evaluate=False)
Ejemplo n.º 16
0
def hypsum(expr, n, start, prec):
    """
    Sum a rapidly convergent infinite hypergeometric series with
    given general term, e.g. e = hypsum(1/factorial(n), n). The
    quotient between successive terms must be a quotient of integer
    polynomials.
    """
    from sympy import Float, hypersimp, lambdify

    if prec == float('inf'):
        raise NotImplementedError('does not support inf prec')

    if start:
        expr = expr.subs(n, n + start)
    hs = hypersimp(expr, n)
    if hs is None:
        raise NotImplementedError("a hypergeometric series is required")
    num, den = hs.as_numer_denom()

    func1 = lambdify(n, num)
    func2 = lambdify(n, den)

    h, g, p = check_convergence(num, den, n)

    if h < 0:
        raise ValueError("Sum diverges like (n!)^%i" % (-h))

    term = expr.subs(n, 0)
    if not term.is_Rational:
        raise NotImplementedError("Non rational term functionality is not implemented.")

    # Direct summation if geometric or faster
    if h > 0 or (h == 0 and abs(g) > 1):
        term = (MPZ(term.p) << prec) // term.q
        s = term
        k = 1
        while abs(term) > 5:
            term *= MPZ(func1(k - 1))
            term //= MPZ(func2(k - 1))
            s += term
            k += 1
        return from_man_exp(s, -prec)
    else:
        alt = g < 0
        if abs(g) < 1:
            raise ValueError("Sum diverges like (%i)^n" % abs(1/g))
        if p < 1 or (p == 1 and not alt):
            raise ValueError("Sum diverges like n^%i" % (-p))
        # We have polynomial convergence: use Richardson extrapolation
        vold = None
        ndig = prec_to_dps(prec)
        while True:
            # Need to use at least quad precision because a lot of cancellation
            # might occur in the extrapolation process; we check the answer to
            # make sure that the desired precision has been reached, too.
            prec2 = 4*prec
            term0 = (MPZ(term.p) << prec2) // term.q

            def summand(k, _term=[term0]):
                if k:
                    k = int(k)
                    _term[0] *= MPZ(func1(k - 1))
                    _term[0] //= MPZ(func2(k - 1))
                return make_mpf(from_man_exp(_term[0], -prec2))

            with workprec(prec):
                v = nsum(summand, [0, mpmath_inf], method='richardson')
            vf = Float(v, ndig)
            if vold is not None and vold == vf:
                break
            prec += prec  # double precision each time
            vold = vf

        return v._mpf_
Ejemplo n.º 17
0
 def _eval_evalf(self, prec=15, **options):
     pt, tup = self.args
     dps = prec_to_dps(prec)
     pt = pt.evalf(n=dps, **options)
     tup = tuple([i.evalf(n=dps, **options) for i in tup])
     return self.func(pt, normal_vector=tup, evaluate=False)
Ejemplo n.º 18
0
    def eval(cls, arg, base=None):
        from .complexes import unpolarify

        if base is not None:
            if base == 1:
                if arg == 1:
                    return nan
                else:
                    return zoo
            try:
                # handle extraction of powers of the base now
                # or else expand_log in Mul would have to handle this
                n = multiplicity(base, arg)
                if n:
                    den = base**n
                    if den.is_Integer:
                        return n + log(arg // den) / log(base)
                    else:
                        return n + log(arg / den) / log(base)
            except ValueError:
                pass
            if base is not E:
                if arg.is_Float:
                    dps = prec_to_dps(arg._prec + 4)
                    return cls(arg) / cls(base).evalf(dps)
                else:
                    return cls(arg) / cls(base)
            else:
                return cls(arg)

        if arg.is_Number:
            if arg == 0:
                return zoo
            elif arg == 1:
                return Integer(0)
            elif arg in (oo, -oo):
                return oo
            elif arg.is_Rational:
                if arg.denominator != 1:
                    return cls(arg.numerator) - cls(arg.denominator)

        if arg.is_Exp and arg.exp.is_extended_real:
            return arg.exp
        elif isinstance(arg, exp_polar):
            return unpolarify(arg.exp)

        if arg.is_number:
            if arg.is_negative:
                return pi * I + cls(-arg)
            elif arg is zoo:
                return zoo
            elif arg is E:
                return Integer(1)

        # don't autoexpand Pow or Mul (see the issue sympy/sympy#3351):
        if not arg.is_Add:
            coeff = arg.as_coefficient(I)

            if coeff is not None:
                if coeff in (oo, -oo):
                    return oo
                elif coeff.is_Rational:
                    if coeff.is_nonnegative:
                        return +pi * I / 2 + cls(+coeff)
                    else:
                        return -pi * I / 2 + cls(-coeff)