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)
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])
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)
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)
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
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])
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_
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)
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)
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))
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)
def _eval_evalf(self, prec): z = self.args[0] nprec = prec_to_dps(prec) return polygamma(1, z).evalf(n=nprec)
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)
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_
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)
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)