def airy_bi(x): r""" The function `Ai(x)` and the related function `Bi(x)`, which is also called an *Airy function*, are solutions to the differential equation .. math:: y'' - xy = 0, known as the *Airy equation*. The initial conditions `Ai(0) = (\Gamma(2/3)3^{2/3})^{-1}`, `Ai'(0) = -(\Gamma(1/3)3^{1/3})^{-1}` define `Ai(x)`. The initial conditions `Bi(0) = 3^{1/2}Ai(0)`, `Bi'(0) = -3^{1/2}Ai'(0)` define `Bi(x)`. They are named after the British astronomer George Biddell Airy. They belong to the class of "Bessel functions of fractional order". EXAMPLES:: sage: airy_ai(1) # last few digits are random 0.135292416312881400 sage: airy_bi(1) # last few digits are random 1.20742359495287099 REFERENCE: - Abramowitz and Stegun: Handbook of Mathematical Functions, http://www.math.sfu.ca/~cbm/aands/ - http://en.wikipedia.org/wiki/Airy_function """ _init() return RDF(meval("airy_bi(%s)" % RDF(x)))
def _compute_power_series(self, n, abs_prec, cache_ring=None): """ Compute the power series giving Dickman's function on [n, n+1], by recursion in n. For internal use; self.power_series() is a wrapper around this intended for the user. INPUT: - ``n`` - the lower endpoint of the interval for which this power series holds - ``abs_prec`` - the absolute precision of the resulting power series - ``cache_ring`` - for internal use, caches the power series at this precision. EXAMPLES:: sage: f = dickman_rho.power_series(2, 20); f -9.9376e-8*x^11 + 3.7722e-7*x^10 - 1.4684e-6*x^9 + 5.8783e-6*x^8 - 0.000024259*x^7 + 0.00010341*x^6 - 0.00045583*x^5 + 0.0020773*x^4 - 0.0097336*x^3 + 0.045224*x^2 - 0.11891*x + 0.13032 """ if n <= 1: if n <= -1: return PolynomialRealDense(RealField(abs_prec)['x']) if n == 0: return PolynomialRealDense(RealField(abs_prec)['x'], [1]) elif n == 1: nterms = (RDF(abs_prec) * RDF(2).log() / RDF(3).log()).ceil() R = RealField(abs_prec) neg_three = ZZ(-3) coeffs = [1 - R(1.5).log() ] + [neg_three**-k / k for k in range(1, nterms)] f = PolynomialRealDense(R['x'], coeffs) if cache_ring is not None: self._f[n] = f.truncate_abs(f[0] >> ( cache_ring.prec() + 1)).change_ring(cache_ring) return f else: f = self._compute_power_series(n - 1, abs_prec, cache_ring) # integrand = f / (2n+1 + x) # We calculate this way because the most significant term is the constant term, # and so we want to push the error accumulation and remainder out to the least # significant terms. integrand = f.reverse().quo_rem( PolynomialRealDense(f.parent(), [1, 2 * n + 1]))[0].reverse() integrand = integrand.truncate_abs(RR(2)**-abs_prec) iintegrand = integrand.integral() ff = PolynomialRealDense(f.parent(), [f(1) + iintegrand(-1)]) - iintegrand i = 0 while abs(f[i]) < abs(f[i + 1]): i += 1 rel_prec = int(abs_prec + abs(RR(f[i])).log2()) if cache_ring is not None: self._f[n] = ff.truncate_abs( ff[0] >> (cache_ring.prec() + 1)).change_ring(cache_ring) return ff.change_ring(RealField(rel_prec))
def adjust_options(self): r""" Adjust plotting options. This function determines appropriate default values for those options, that were not specified by the user, based on the other options. See :class:`ToricPlotter` for a detailed example. OUTPUT: - none. TESTS:: sage: from sage.geometry.toric_plotter import ToricPlotter sage: tp = ToricPlotter(dict(), 2) sage: print tp.show_lattice None sage: tp.adjust_options() sage: print tp.show_lattice True """ # Unfortunately, some of the defaults are dimension specific for no # good reason but to remedy 2-d/3-d plotting inconsistencies in Sage. d = self.dimension if d <= 2: if self.point_size is None: self.point_size = 50 elif d == 3: if self.point_size is None: self.point_size = 10 if self.generator_thickness is None: self.generator_thickness = self.ray_thickness sd = self.__dict__ bounds = ["radius", "xmin", "xmax", "ymin", "ymax", "zmin", "zmax"] bounds = [abs(sd[bound]) for bound in bounds if sd[bound] is not None] r = RDF(max(bounds + [0.5]) if bounds else 2.5) self.radius = r round = self.mode == "round" for key in ["xmin", "ymin", "zmin"]: if round or sd[key] is None: sd[key] = -r if sd[key] > -0.5: sd[key] = -0.5 sd[key] = RDF(sd[key]) for key in ["xmax", "ymax", "zmax"]: if round or sd[key] is None: sd[key] = r if sd[key] < 0.5: sd[key] = 0.5 sd[key] = RDF(sd[key]) if self.show_lattice is None: self.show_lattice = (r <= 5) if d <= 2 else r <= 3
def _normal_pivot(self): """ Return the index of the largest entry of the normal vector. OUTPUT: An integer. The index of the largest entry. EXAMPLES:: sage: H.<x,y,z> = HyperplaneArrangements(QQ) sage: V = H.ambient_space() sage: (x + 3/2*y - 2*z)._normal_pivot() 2 sage: H.<x,y,z> = HyperplaneArrangements(GF(5)) sage: V = H.ambient_space() sage: (x + 3*y - 4*z)._normal_pivot() 1 """ try: values = [abs(x) for x in self.A()] except ArithmeticError: from sage.rings.all import RDF values = [abs(RDF(x)) for x in self.A()] max_pos = 0 max_value = values[max_pos] for i in range(1, len(values)): if values[i] > max_value: max_pos = i max_value = values[i] return max_pos
def __init__(self, projection_point): """ Create a stereographic projection function. INPUT: - ``projection_point`` -- a list of coordinates in the appropriate dimension, which is the point projected from. EXAMPLES:: sage: from sage.geometry.polyhedron.plot import ProjectionFuncStereographic sage: proj = ProjectionFuncStereographic([1.0,1.0]) sage: proj.__init__([1.0,1.0]) sage: proj.house [-0.7071067811... 0.7071067811...] [ 0.7071067811... 0.7071067811...] sage: TestSuite(proj).run(skip='_test_pickling') """ self.projection_point = vector(projection_point) self.dim = self.projection_point.degree() pproj = vector(RDF, self.projection_point) self.psize = norm(pproj) if (self.psize).is_zero(): raise ValueError, "projection direction must be a non-zero vector." v = vector(RDF, [0.0] * (self.dim - 1) + [self.psize]) - pproj polediff = matrix(RDF, v).transpose() denom = RDF((polediff.transpose() * polediff)[0][0]) if denom.is_zero(): self.house = identity_matrix(RDF, self.dim) else: self.house = identity_matrix(RDF,self.dim) \ - 2*polediff*polediff.transpose()/denom # Householder reflector
def orthonormal_1(dim_n=5): """ A matrix of rational approximations to orthonormal vectors to ``(1,...,1)``. INPUT: - ``dim_n`` - the dimension of the vectors OUTPUT: A matrix over ``QQ`` whose rows are close to an orthonormal basis to the subspace normal to ``(1,...,1)``. EXAMPLES:: sage: from sage.geometry.polyhedron.library import Polytopes sage: m = Polytopes.orthonormal_1(5) sage: m [ 70711/100000 -7071/10000 0 0 0] [ 1633/4000 1633/4000 -81649/100000 0 0] [ 7217/25000 7217/25000 7217/25000 -43301/50000 0] [ 22361/100000 22361/100000 22361/100000 22361/100000 -44721/50000] """ pb = [] for i in range(0, dim_n - 1): pb.append([1.0 / (i + 1)] * (i + 1) + [-1] + [0] * (dim_n - i - 2)) m = matrix(RDF, pb) new_m = [] for i in range(0, dim_n - 1): new_m.append( [RDF(100000 * q / norm(m[i])).ceil() / 100000 for q in m[i]]) return matrix(QQ, new_m)
def mrrw1_bound_asymp(delta,q): """ Computes the first asymptotic McEliese-Rumsey-Rodemich-Welsh bound for the information rate, provided `0 < \delta < 1-1/q`. EXAMPLES:: sage: mrrw1_bound_asymp(1/4,2) 0.354578902665 """ return RDF(entropy((q-1-delta*(q-2)-2*sqrt((q-1)*delta*(1-delta)))/q,q))
def elias_bound_asymp(delta, q): """ Computes the asymptotic Elias bound for the information rate, provided `0 < \delta < 1-1/q`. EXAMPLES:: sage: codes.bounds.elias_bound_asymp(1/4,2) 0.39912396330... """ r = 1 - 1 / q return RDF((1 - entropy(r - sqrt(r * (r - delta)), q)))
def mrrw1_bound_asymp(delta,q): """ The first asymptotic McEliese-Rumsey-Rodemich-Welsh bound. This only makes sense when `0 < \delta < 1-1/q`. EXAMPLES:: sage: codes.bounds.mrrw1_bound_asymp(1/4,2) # abs tol 4e-16 0.3545789026652697 """ return RDF(entropy((q-1-delta*(q-2)-2*sqrt((q-1)*delta*(1-delta)))/q,q))
def six_hundred_cell(self, exact=False): """ Return the standard 600-cell polytope. The 600-cell is a 4-dimensional regular polytope. In many ways this is an analogue of the icosahedron. .. WARNING:: The coordinates are not exact by default. The computation with exact coordinates takes a huge amount of time. INPUT: - ``exact`` - (boolean, default ``False``) if ``True`` use exact coordinates instead of floating point approximations EXAMPLES:: sage: p600 = polytopes.six_hundred_cell() sage: p600 A 4-dimensional polyhedron in RDF^4 defined as the convex hull of 120 vertices sage: p600.f_vector() (1, 120, 720, 1200, 600, 1) Computation with exact coordinates is currently too long to be useful:: sage: p600 = polytopes.six_hundred_cell(exact=True) # not tested - very long time sage: len(list(p600.bounded_edges())) # not tested - very long time 120 """ if exact: from sage.rings.number_field.number_field import QuadraticField K = QuadraticField(5, 'sqrt5') sqrt5 = K.gen() g = (1 + sqrt5) / 2 base_ring = K else: g = (1 + RDF(5).sqrt()) / 2 base_ring = RDF q12 = base_ring(1) / base_ring(2) z = base_ring.zero() verts = [[s1 * q12, s2 * q12, s3 * q12, s4 * q12] for s1, s2, s3, s4 in itertools.product([1, -1], repeat=4)] V = (base_ring)**4 verts.extend(V.basis()) verts.extend(-v for v in V.basis()) pts = [[s1 * q12, s2 * g / 2, s3 / (2 * g), z] for (s1, s2, s3) in itertools.product([1, -1], repeat=3)] for p in AlternatingGroup(4): verts.extend(p(x) for x in pts) return Polyhedron(vertices=verts, base_ring=base_ring)
def elias_bound_asymp(delta,q): """ The asymptotic Elias bound for the information rate. This only makes sense when `0 < \delta < 1-1/q`. EXAMPLES:: sage: codes.bounds.elias_bound_asymp(1/4,2) 0.39912396330... """ r = 1-1/q return RDF((1-entropy(r-sqrt(r*(r-delta)), q)))
def icosahedron(self, base_ring=QQ): """ Return an icosahedron with edge length 1. INPUT: - ``base_ring`` -- Either ``QQ`` or ``RDF``. OUTPUT: A Polyhedron object of a floating point or rational approximation to the regular 3d icosahedron. If ``base_ring=QQ``, a rational approximation is used and the points are not exactly the vertices of the icosahedron. The icosahedron's coordinates contain the golden ratio, so there is no exact representation possible. EXAMPLES:: sage: ico = polytopes.icosahedron() sage: sum(sum( ico.vertex_adjacency_matrix() ))/2 30 """ if base_ring == QQ: g = QQ(1618033) / 1000000 # Golden ratio approximation r12 = QQ(1) / 2 elif base_ring == RDF: g = RDF((1 + sqrt(5)) / 2) r12 = RDF(QQ(1) / 2) else: raise ValueError("field must be QQ or RDF.") verts = [i([0, r12, g / 2]) for i in AlternatingGroup(3)] verts = verts + [i([0, r12, -g / 2]) for i in AlternatingGroup(3)] verts = verts + [i([0, -r12, g / 2]) for i in AlternatingGroup(3)] verts = verts + [i([0, -r12, -g / 2]) for i in AlternatingGroup(3)] return Polyhedron(vertices=verts, base_ring=base_ring)
def hypergeometric_U(alpha, beta, x, algorithm="pari", prec=53): r""" Default is a wrap of PARI's hyperu(alpha,beta,x) function. Optionally, algorithm = "scipy" can be used. The confluent hypergeometric function `y = U(a,b,x)` is defined to be the solution to Kummer's differential equation .. math:: xy'' + (b-x)y' - ay = 0. This satisfies `U(a,b,x) \sim x^{-a}`, as `x\rightarrow \infty`, and is sometimes denoted ``x^{-a}2_F_0(a,1+a-b,-1/x)``. This is not the same as Kummer's `M`-hypergeometric function, denoted sometimes as ``_1F_1(alpha,beta,x)``, though it satisfies the same DE that `U` does. .. warning:: In the literature, both are called "Kummer confluent hypergeometric" functions. EXAMPLES:: sage: hypergeometric_U(1,1,1,"scipy") 0.596347362323... sage: hypergeometric_U(1,1,1) 0.59634736232319... sage: hypergeometric_U(1,1,1,"pari",70) 0.59634736232319407434... """ if algorithm == "scipy": if prec != 53: raise ValueError( "for the scipy algorithm the precision must be 53") import scipy.special return RDF(scipy.special.hyperu(float(alpha), float(beta), float(x))) elif algorithm == 'pari': from sage.libs.pari.all import pari R = RealField(prec) return R(pari(R(alpha)).hyperu(R(beta), R(x), precision=prec)) else: raise ValueError("unknown algorithm '%s'" % algorithm)
def regular_polygon(self, n, base_ring=QQ): """ Return a regular polygon with n vertices. Over the rational field the vertices may not be exact. INPUT: - ``n`` -- a positive integer, the number of vertices. - ``field`` -- either ``QQ`` or ``RDF``. EXAMPLES:: sage: octagon = polytopes.regular_polygon(8) sage: len(octagon.vertices()) 8 """ npi = 3.14159265359 verts = [] for i in range(n): t = 2 * npi * i / n verts.append([sin(t), cos(t)]) verts = [[base_ring(RDF(x)) for x in y] for y in verts] return Polyhedron(vertices=verts, base_ring=base_ring)
def _sage_(self): """ Convert self to a Sage object. EXAMPLES:: sage: a = axiom(1/2); a #optional - axiom 1 - 2 sage: a.sage() #optional - axiom 1/2 sage: _.parent() #optional - axiom Rational Field sage: gp(axiom(1/2)) #optional - axiom 1/2 sage: fricas(1/2).sage() #optional - fricas 1/2 DoubleFloat's in Axiom are converted to be in RDF in Sage. :: sage: axiom(2.0).as_type('DoubleFloat').sage() #optional - axiom 2.0 sage: _.parent() #optional - axiom Real Double Field sage: axiom(2.1234)._sage_() #optional - axiom 2.12340000000000 sage: _.parent() #optional - axiom Real Field with 53 bits of precision sage: a = RealField(100)(pi) sage: axiom(a)._sage_() #optional - axiom 3.1415926535897932384626433833 sage: _.parent() #optional - axiom Real Field with 100 bits of precision sage: axiom(a)._sage_() == a #optional - axiom True sage: axiom(2.0)._sage_() #optional - axiom 2.00000000000000 sage: _.parent() #optional - axiom Real Field with 53 bits of precision We can also convert Axiom's polynomials to Sage polynomials. sage: a = axiom(x^2 + 1) #optional - axiom sage: a.type() #optional - axiom Polynomial Integer sage: a.sage() #optional - axiom x^2 + 1 sage: _.parent() #optional - axiom Univariate Polynomial Ring in x over Integer Ring sage: axiom('x^2 + y^2 + 1/2').sage() #optional - axiom y^2 + x^2 + 1/2 sage: _.parent() #optional - axiom Multivariate Polynomial Ring in y, x over Rational Field """ P = self._check_valid() type = str(self.type()) if type in ["Type", "Domain"]: return self._sage_domain() if type == "Float": from sage.rings.all import RealField, ZZ prec = max(self.mantissa().length()._sage_(), 53) R = RealField(prec) x, e, b = self.unparsed_input_form().lstrip('float(').rstrip( ')').split(',') return R(ZZ(x) * ZZ(b)**ZZ(e)) elif type == "DoubleFloat": from sage.rings.all import RDF return RDF(repr(self)) elif type.startswith('Polynomial'): from sage.rings.all import PolynomialRing base_ring = P(type.lstrip('Polynomial '))._sage_domain() vars = str(self.variables())[1:-1] R = PolynomialRing(base_ring, vars) return R(self.unparsed_input_form()) #If all else fails, try using the unparsed input form try: import sage.misc.sage_eval return sage.misc.sage_eval.sage_eval(self.unparsed_input_form()) except: raise NotImplementedError