def __cmp__(self, other): r""" Comparison (using the complex embedding). TESTS:: sage: UCF = UniversalCyclotomicField() sage: l = [UCF.gen(3), UCF.gen(3)+1, UCF.gen(5), UCF.gen(5,2), ....: UCF.gen(4), 2*UCF.gen(4), UCF.gen(5)-22/3] sage: lQQbar = map(QQbar,l) sage: lQQbar.sort() sage: l.sort() sage: lQQbar == map(QQbar,l) True sage: for i in range(len(l)): ....: assert l[i] >= l[i] and l[i] <= l[i] ....: for j in range(i): ....: assert l[i] > l[j] and l[j] < l[i] """ if self._obj == other._obj: return 0 else: from sage.rings.qqbar import QQbar return cmp(QQbar(self), QQbar(other))
def _call_(self, x): r""" TESTS:: sage: UCF = UniversalCyclotomicField() sage: UCFtoQQbar = UCF.coerce_embedding() sage: UCFtoQQbar(UCF.gen(3)) # indirect doctest -0.500000000000000? + 0.866025403784439?*I """ obj = x._obj QQbar = self.codomain() if obj.IsRat(): return QQbar(obj.sage()) k = obj.Conductor().sage() coeffs = obj.CoeffsCyc(k).sage() zeta = QQbar.zeta(k) return QQbar(sum(coeffs[a] * zeta**a for a in range(1, k)))
def sqrt(self): """ Return a square root of ``self`` as an algebraic number. EXAMPLES:: sage: f = E(33) sage: f.sqrt() 0.9954719225730846? + 0.0950560433041827?*I sage: f.sqrt()**2 == f True """ return QQbar(self).sqrt()
def _algebraic_(self, R): r""" TESTS:: sage: UCF = UniversalCyclotomicField() sage: AA(UCF.gen(5) + UCF.gen(5,4)) 0.618033988749895? sage: AA(UCF.gen(5)) Traceback (most recent call last): ... ValueError: Cannot coerce algebraic number with non-zero imaginary part to algebraic real """ return R(QQbar(self))
def _mpfr_(self, R): r""" TESTS:: sage: RR(E(7) + E(7,6)) 1.24697960371747 sage: 2*cos(2*pi/7).n() 1.24697960371747 """ if not self.is_real(): raise TypeError("self is not real") from sage.rings.qqbar import QQbar, AA return AA(QQbar(self))._mpfr_(R)
def generalized_series_term_valuation(z, i, j, iota=None): r""" Given z, i, j, return the valuation of the term x^(z+i) log(x)^j """ try: z = QQbar(z) except ValueError: # FIXME: It would be great if we could show the warning once per # relevant field warn( "Choosing an arbitrary complex embedding for {}.\n" "To avoid it, extend the coefficients of the base ring.".format( z.parent()), RuntimeWarning) z = z.parent().embeddings(QQbar)[0](z) if iota is None: iota = generalized_series_default_iota return ZZ(z + i - iota(z, j))
def closed_form(self, n='n'): r""" Return a symbolic expression in ``n``, which equals the n-th term of the sequence. It is a well-known property of C-finite sequences ``a_n`` that they have a closed form of the type: .. MATH:: a_n = \sum_{i=1}^d c_i(n) \cdot r_i^n, where ``r_i`` are the roots of the characteristic equation and ``c_i(n)`` is a polynomial (whose degree equals the multiplicity of ``r_i`` minus one). This is a natural generalization of Binet's formula for Fibonacci numbers. See, for instance, [KP2011, Theorem 4.1]. Note that if the o.g.f. has a polynomial part, that is, if the numerator degree is not strictly less than the denominator degree, then this closed form holds only when ``n`` exceeds the degree of that polynomial part. In that case, the returned expression will differ from the sequence for small ``n``. EXAMPLES:: sage: CFiniteSequence(1/(1-x)).closed_form() 1 sage: CFiniteSequence(x^2/(1-x)).closed_form() 1 sage: CFiniteSequence(1/(1-x^2)).closed_form() 1/2*(-1)^n + 1/2 sage: CFiniteSequence(1/(1+x^3)).closed_form() 1/3*(-1)^n + 1/3*(1/2*I*sqrt(3) + 1/2)^n + 1/3*(-1/2*I*sqrt(3) + 1/2)^n sage: CFiniteSequence(1/(1-x)/(1-2*x)/(1-3*x)).closed_form() 9/2*3^n - 4*2^n + 1/2 Binet's formula for the Fibonacci numbers:: sage: CFiniteSequence(x/(1-x-x^2)).closed_form() sqrt(1/5)*(1/2*sqrt(5) + 1/2)^n - sqrt(1/5)*(-1/2*sqrt(5) + 1/2)^n sage: [_.subs(n=k).full_simplify() for k in range(6)] [0, 1, 1, 2, 3, 5] sage: CFiniteSequence((4*x+3)/(1-2*x-5*x^2)).closed_form() 1/2*(sqrt(6) + 1)^n*(7*sqrt(1/6) + 3) - 1/2*(-sqrt(6) + 1)^n*(7*sqrt(1/6) - 3) Examples with multiple roots:: sage: CFiniteSequence(x*(x^2+4*x+1)/(1-x)^5).closed_form() 1/4*n^4 + 1/2*n^3 + 1/4*n^2 sage: CFiniteSequence((1+2*x-x^2)/(1-x)^4/(1+x)^2).closed_form() 1/12*n^3 - 1/8*(-1)^n*(n + 1) + 3/4*n^2 + 43/24*n + 9/8 sage: CFiniteSequence(1/(1-x)^3/(1-2*x)^4).closed_form() 4/3*(n^3 - 3*n^2 + 20*n - 36)*2^n + 1/2*n^2 + 19/2*n + 49 sage: CFiniteSequence((x/(1-x-x^2))^2).closed_form() 1/5*(n - sqrt(1/5))*(1/2*sqrt(5) + 1/2)^n + 1/5*(n + sqrt(1/5))*(-1/2*sqrt(5) + 1/2)^n """ from sage.arith.all import binomial from sage.rings.qqbar import QQbar from sage.symbolic.ring import SR n = SR(n) expr = SR.zero() R = FractionField(PolynomialRing(QQbar, self.parent().variable_name())) ogf = R(self.ogf()) __, parts = ogf.partial_fraction_decomposition(decompose_powers=False) for part in parts: denom = part.denominator().factor() denom_base, denom_exp = denom[0] # denominator is of the form (x+b)^{m+1} m = denom_exp - 1 b = denom_base.constant_coefficient() # check that the partial fraction decomposition was indeed done correctly # (that is, there is only one factor, of degree 1, and monic) assert len(denom) == 1 and len(denom_base.list( )) == 2 and denom_base[1] == 1 and denom.unit() == 1 r = SR((-1 / b).radical_expression()) c = SR.zero() for k, a in enumerate(part.numerator()): a = -QQbar(a) if k % 2 else QQbar(a) bino = binomial(n + m - k, m) c += bino * SR((a * b**(k - m - 1)).radical_expression()) expr += c.expand() * r**n return expr
def lie_algebra_isomorphism_classes(F, dim): r""" Return a list of isomorphism classes of Lie algebras. INPUT: - ``F`` -- the base field of the Lie algebras - ``dim`` -- the dimension of Lie algebras to list The full listing is implemented for the fields of rationals ``QQ`` and algebraic numbers ``QQbar`` up to dimension 6. For dimension 7, the returned list is incomplete due to existence of one parameter families of Lie algebras, but contains at least one representative from each family. """ if F not in [QQ, QQbar]: return NotImplemented if dim == 1: return [L1_1(F)] if dim == 2: return [L2_1(F)] if dim == 3: return [L3_1(F), L3_2(F)] if dim == 4: return [L4_1(F), L4_2(F), L4_3(F)] if dim == 5: return [L5_1(F), L5_2(F), L5_3(F), L5_4(F), L5_5(F), L5_6(F), L5_7(F), L5_8(F), L5_9(F)] if dim == 6: l = [L6_1(F), L6_2(F), L6_3(F), L6_4(F), L6_5(F), L6_6(F), L6_7(F), L6_8(F), L6_9(F), L6_10(F), L6_11(F), L6_12(F), L6_13(F), L6_14(F), L6_15(F), L6_16(F), L6_17(F), L6_18(F), L6_19(F, -1)] if F == QQ: l += [L6_19(F, 1)] l += [L6_20(F), L6_21(F, -1)] if F == QQ: l += [L6_21(F, 1)] l += [L6_22(F, 0), L6_22(F, 1)] if F == QQ: l += [L6_22(F, -1)] l += [L6_23(F)] l += [L6_24(F, 0), L6_24(F, 1)] if F == QQ: l += [L6_24(F, -1)] l += [L6_25(F), L6_26(F), L6_27(F), L6_28(F)] return l if dim == 7: if F == QQ: return NotImplemented i = QQbar.gens()[0] l = [L37A(F), L37B(F), L37C(F), L37D(F)] l += [L357A(F), L357B(F), L357C(F)] l += [L27A(F), L27B(F)] l += [L257A(F), L257B(F), L257C(F), L257D(F), L257E(F), L257F(F), L257G(F), L257H(F), L257I(F), L257J(F), L257K(F), L257L(F)] l += [L247A(F), L247B(F), L247C(F), L247D(F), L247E(F), L247F(F), L247G(F), L247H(F), L247I(F), L247J(F), L247K(F), L247L(F), L247M(F), L247N(F), L247O(F), L247P(F), L247Q(F), L247R(F)] l += [L2457A(F), L2457B(F), L2457C(F), L2457D(F), L2457E(F), L2457F(F), L2457G(F), L2457H(F), L2457I(F), L2457J(F), L2457K(F), L2457L(F), L2457M(F)] l += [L2357A(F), L2357B(F), L2357C(F), L2357D(F)] l += [L23457A(F), L23457B(F), L23457C(F), L23457D(F), L23457E(F), L23457F(F), L23457G(F)] l += [L17(F)] l += [L157(F)] # 147 has a family # 147C = 147E(0) = 147E(1) = 247P l += [L147A(F), L147B(F), L147D(F)] l += [L147E(F, 2)] # singular value 147E(2)=147E(1/2)=147E(-1) # complex singular value same as 1/2-sqrt(3)/2*i l += [L147E(F, QQbar(1) / 2 + QQbar(sqrt(3)) / 2 * i)] # non-singular value # 147E(3)=147E(1/3)=147E(2/3)=147E(3/2)= 147E(-1/2)=147E(-2) l += [L147E(F, 3)] # non-singular value # 147E(5)=147E(1/5)=147E(4/5)=147E(5/4)= 147E(-1/4)=147E(-4) l += [L147E(F, 5)] l += [L1457A(F), L1457B(F)] l += [L137A(F), L137B(F), L137C(F), L137D(F)] # 1357 has a family l += [L1357A(F), L1357B(F), L1357C(F), L1357D(F), L1357E(F), L1357F(F), L1357G(F), L1357H(F), L1357I(F), L1357J(F), L1357K(F), L1357L(F)] # 1357M(a)=1357M(a') iff a=a' # 1357M(0)=2357B l += [L1357M(F, 1)] # singular value l += [L1357M(F, 2)] # singular value l += [L1357M(F, -1)] # singular value # l += [L1357M(F, QQbar(1) / 2)] # singular value, same as 1357K l += [L1357M(F, -QQbar(1) / 3)] # singular value # complex singular value l += [L1357M(F, QQbar(1) / 2 - QQbar(sqrt(3)) / 2 * i)] # complex singular value l += [L1357M(F, QQbar(1) / 2 + QQbar(sqrt(3)) / 2 * i)] l += [L1357M(F, 3)] # non singular value l += [L1357M(F, 5)] # non singular value # 1357N(a)=1357N(a') iff a=a' l += [L1357N(F, 0)] # singular value l += [L1357N(F, 1)] # singular value l += [L1357N(F, 3)] # non singular value l += [L1357N(F, 5)] # non singular value l += [L1357O(F), L1357P(F), L1357Q(F), L1357R(F)] # 1357S(a)=1357S(a') iff a*a'=1 # 1357S(1)=2357D l += [L1357S(F, 0)] # singular value l += [L1357S(F, QQbar(1) / 2)] # singular value l += [L1357S(F, -1)] # singular value # complex singular value l += [L1357S(F, QQbar(1) / 2 - QQbar(sqrt(3)) / 2 * i)] # complex singular value l += [L1357S(F, QQbar(1) / 2 + QQbar(sqrt(3)) / 2 * i)] l += [L1357S(F, 3)] # non singular value l += [L1357S(F, 5)] # non singular value # 13457 # 13457H in Seeley is not a Lie algebra l += [L13457A(F), L13457B(F), L13457C(F), L13457D(F), L13457E(F), L13457F(F), L13457G(F), L13457I(F)] # 12457 has a family l += [L12457A(F), L12457B(F), L12457C(F), L12457D(F), L12457E(F), L12457F(F), L12457G(F), L12457H(F), L12457I(F), L12457J(F), L12457K(F), L12457L(F), L12457M(F)] # 12457N(a)=12457N(a') iff a=a' or a=-a' # l += [L12457N(F, 0)] # singular value, same as 12457M l += [L12457N(F, 1)] # non singular value l += [L12457N(F, 3)] # non singular value l += [L12457N(F, 5)] # non singular value l += [L12357A(F), L12357B(F), L12357C(F)] # 123457 has a family l += [L123457A(F), L123457B(F), L123457C(F), L123457D(F), L123457E(F), L123457F(F), L123457G(F), L123457H(F)] # 123457I(a)=123457I(a') iff a=a' l += [L123457I(F, 0)] # non singular value #l += [L123457I(F, 1)] # singular value, same as 123457G l += [L123457I(F, 2)] # singular value l += [L123457I(F, 3)] # singular value l += [L123457I(F, -1)] # singular value # complex singular value l += [L123457I(F, QQbar(1) / 2 - QQbar(sqrt(3)) / 2 * i)] # complex singular value l += [L123457I(F, QQbar(1) / 2 + QQbar(sqrt(3)) / 2 * i)] return l return NotImplemented
def sqrt(self, extend=True, all=False): """ Return a square root of ``self``. With default options, the output is an element of the universal cyclotomic field when this element is expressed via a single root of unity (including rational numbers). Otherwise, return an algebraic number. INPUT: - ``extend`` -- bool (default: ``True``); if ``True``, might return a square root in the algebraic closure of the rationals. If false, return a square root in the universal cyclotomic field or raises an error. - ``all`` -- bool (default: ``False``); if ``True``, return a list of all square roots. EXAMPLES:: sage: UCF = UniversalCyclotomicField() sage: UCF(3).sqrt() E(12)^7 - E(12)^11 sage: (UCF(3).sqrt())**2 3 sage: r = UCF(-1400 / 143).sqrt() sage: r**2 -1400/143 sage: E(33).sqrt() -E(33)^17 sage: E(33).sqrt() ** 2 E(33) sage: (3 * E(5)).sqrt() -E(60)^11 + E(60)^31 sage: (3 * E(5)).sqrt() ** 2 3*E(5) Setting ``all=True`` you obtain the two square roots in a list:: sage: UCF(3).sqrt(all=True) [E(12)^7 - E(12)^11, -E(12)^7 + E(12)^11] sage: (1 + UCF.zeta(5)).sqrt(all=True) [1.209762576525833? + 0.3930756888787117?*I, -1.209762576525833? - 0.3930756888787117?*I] In the following situation, Sage is not (yet) able to compute a square root within the universal cyclotomic field:: sage: (E(5) + E(5, 2)).sqrt() 0.7476743906106103? + 1.029085513635746?*I sage: (E(5) + E(5, 2)).sqrt(extend=False) Traceback (most recent call last): ... NotImplementedError: sqrt() not fully implemented for elements of Universal Cyclotomic Field """ if all: s = self.sqrt(all=False) return [s, -s] UCF = self.parent() # rational case if self._obj.IsRat(): D = self._obj.sage() if self._obj.IsInt(): return UCF_sqrt_int(D, UCF) else: return UCF_sqrt_int(D.numerator(), UCF) / \ UCF_sqrt_int(D.denominator(), UCF) # root of unity k = self._obj.Conductor() coeffs = self._obj.CoeffsCyc(k).sage() if sum(bool(x) for x in coeffs) == 1: for i, x in enumerate(coeffs): if x: break return UCF(x).sqrt() * UCF.zeta(2 * k, i) # no method to construct square roots yet... if extend: return QQbar(self).sqrt() else: raise NotImplementedError( "sqrt() not fully implemented for elements of Universal Cyclotomic Field" )