..nodoctest

Orders

x.__init__(...) initializes x; see help(type(x)) for signature

recip.orders.additive_gens_to_basis(gens, K)

Given generators of a lattice L in K, returns a basis of L.

recip.orders.are_nn_isogenous(Z1, Z2, n, F1, F2, transformation=False, double_check=False)

Given two CM period matrices with the same CM-type, returns True if and only if there is an (n,n)-isogeny between them. Assumes the orders Oi of Zi to satisfy Fi*OK subset Oi.

If double_check, also checks whether there is an isogeny the other way (which should be equivalent). Raises an error if there is an isogeny in only one direction.

EXAMPLES:

sage: from recip import *
sage: K = CM_Field([5,5,5])
sage: Phi = K.CM_types()[0]
sage: alpha = K.gen()
sage: orders = [K.order([1/2*alpha^3 + 1/2, 1/2*alpha^3 + 5/2*alpha^2 + 5/2*alpha, 5*alpha^2, alpha^3]), K.order([1, 2*alpha, 2*alpha^2, alpha^3]), K.order([3/2*alpha^3 + 1/2, 3/2*alpha^3 + 1/2*alpha^2 + 3/2*alpha, alpha^2, 3*alpha^3])]
sage: OK = K.maximal_order()

sage: O = orders[0]
sage: O.index_in(OK)
25
sage: s = superorders_stable_under_complex_conjugation(O)
sage: len(s)
3
sage: F = 5
sage: [ideal_contains(A.basis(), [F*b for b in OK.basis()]) for A in s]
[True, True, True]
sage: Zs = [period_matrices(A, F, Phi) for A in s] # long time, half a minute
sage: len(Zs[0]) == 1 and s[0] == OK # long time
True
sage: Zmax = Zs[0][0] # long time
sage: len(Zs[2]) == 0 and len(Zs[1]) == 1 # long time
True
sage: Zother = Zs[1][0] # long time
sage: are_nn_isogenous(Zmax, Zother, 5, 1, F, transformation=True) # long time
(True, 1/10*alpha^3 - 1/2)
sage: b, t = _ # long time
sage: ideal_index([b*t for b in Zmax.basis()], Zother.basis()) # long time
25
sage: cc = K.complex_conjugation() # long time
sage: Zother.xi()*t*cc(t)*5 == Zmax.xi() # long time
True

Some checks for the are_nn_isogenous function:

sage: are_nn_isogenous(Zmax, Zmax, 5, 5, 5, transformation=True) # long time
(True, -1/5*alpha^3 - 1/10*alpha^2 - 1/2*alpha - 1/2)
sage: are_nn_isogenous(Zmax, Zmax, 1, 1, 1, transformation=True) # long time
(True, 1)
sage: are_nn_isogenous(Zother, Zother, 1, F, F, transformation=True) # long time
(True, 1)
sage: are_nn_isogenous(Zmax, Zother, 3, 1, F) # long time
False
sage: are_nn_isogenous(Zmax, 7*Zmax, 7, 1, 7) # todo, multiplication of period matrices by integers is not implemented
True

Another example:

sage: O = orders[2]
sage: O.index_in(OK)
9
sage: s = superorders_stable_under_complex_conjugation(O)
sage: len(s)
2
sage: F = 3
sage: [ideal_contains(A.basis(), [F*b for b in OK.basis()]) for A in s]
[True, True]
sage: Zs = [period_matrices(A, F, Phi) for A in s]
sage: len(Zs[0]) == 1 and s[0] == OK
True
sage: Zmax = Zs[0][0]
sage: len(Zs[1]) == 2
True
sage: Zothers = Zs[1]
sage: are_nn_isogenous(Zmax, Zothers[0], 3, 1, F, transformation=True)
(True, 1)
sage: are_nn_isogenous(Zmax, Zothers[1], 3, 1, F, transformation=True)
(True, 1)

The 2-part will be dealt with for all fields together.

recip.orders.class_polynomials_order(O, F, Phi, prec, include_period_matrices=False)

Returns the class polynomials of an order in a cyclic quartic CM-field K.

TODO: more general fields, examples

recip.orders.ideal_contains(B, A)

Given bases of two lattices B and A in K, returns true if and only if the lattice B contains the lattice A.

recip.orders.ideal_divide(basis1, basis2, K)

Given bases of ideals A1 and A2, returns a basis of (A1 : A2) = {a in K : a*A2 subset A1}.

EXAMPLES:

sage: from recip import *
sage: K.<a> = QuadraticField(15)
sage: basis1 = [1, a]   # Maximal order OK
sage: basis2 = [2, 2*a] # 2OK
sage: basis3 = [1, 2*a] # Another order, O
sage: basis4 = [2, a]   # Fractional ideal. Note: 4*basis4 is an ideal of basis3.
sage: ideal_divide(basis1, basis2, K) # OK / 2OK = (1/2)OK
[1/2, 1/2*a]
sage: ideal_divide(basis1, basis3, K) # contains OK as OK*O = OK, and is contained in OK as it multiplies 1 into OK
[1, a]
sage: ideal_divide(basis2, basis3, K) # twice the above
[2, 2*a]
sage: ideal_divide(basis4, basis3, K) # ideal divided by its own order
[2, a]
sage: ideal_divide(basis4, basis4, K) # endomorphism ring of ideal 4
[1, 2*a]
recip.orders.ideal_index(B, A, check_included=True)

Given two ideals B and A, assuming B contains A, returns the index of A in B.

Here A and B are given by their bases, which are sequences of n elements of K, where n=[K:QQ] and A and B are lattices in K.

If check_included is False, then B does not have to contain A, and the output is the quotient of the indices in B+A.

recip.orders.ideal_inverse(basis, K, O=None)

Given a basis of an ideal A, returns a basis of (O : A) = {a in K : a*A subset O}.

If O is not specified, use ideal_order(basis, K).

EXAMPLES:

sage: from recip import *
sage: K.<a> = QuadraticField(15)
sage: basis1 = [1, a]   # Maximal order OK
sage: basis2 = [2, 2*a] # 2OK
sage: basis3 = [1, 2*a] # Another order, O
sage: basis4 = [2, a]   # Fractional ideal. Note: 2*basis4 is an ideal of basis3.
sage: ideal_inverse(basis1, K) # The order itself
[1, a]
sage: ideal_inverse(basis2, K) # (1/2)OK
[1/2, 1/2*a]
sage: ideal_inverse(basis3, K) # the order itself
[1, 2*a]
sage: basis5 = ideal_inverse(basis4, K); basis5 # happens to be self-inverse
[2, a]
sage: mult_ideals(basis4, basis5, K)
[1, 2*a]
sage: ideal_order(basis4, K).basis()
[1, 2*a]

sage: ideal_is_invertible(basis2, O = K.order(basis3))
False
sage: ideal_is_invertible(basis2, O = K.order(basis1))
True
sage: bases = [basis1, basis2, basis3, basis4]
sage: all([ideal_is_invertible(b) for b in bases]) # quadratic ring, hence all invertible for some ring
True

Special case of Exercise 2.20 of http://websites.math.leidenuniv.nl/algebra/ant.pdf

sage: from recip import *
sage: K.<a> = NumberField(x^3+x+1)
sage: A = K.order([1, a, a^2])
sage: p = 7
sage: R = K.order([1, p*a, p*a^2])
sage: I = additive_gens_to_basis([1, p*a, p*a^2, a, p*a^2, p*a^3], K); I
[1, a, 7*a^2]
sage: ideal_order(I, K) == R
True
sage: Isq = mult_ideals(I, I, K); Isq
[1, a, a^2]
sage: ideal_order(Isq, K) == A
True

The final part of the exercise is to show that the above implies that I is a proper, but non-invertible R-ideal. In particular, it is for all orders non-invertible. We compute the ``inverse’’ of this non-invertible ideal:

sage: Iinv = ideal_inverse(I, K); Iinv
[7, 7*a, 7*a^2]
sage: mult_ideals(I, Iinv, K)
[7, 7*a, 7*a^2]
sage: ideal_is_invertible(I)
False
sage: ideal_is_invertible(Isq, O=A)
True
sage: ideal_is_invertible(Isq, O=R)
False
sage: ideal_is_invertible(Isq)
True

Something from work with Sorina Ionica, Chloe Martindale and Damien Robert:

sage: from recip import *
sage: K = CM_Field([40, 20, 90])
sage: alpha = K.gen()
sage: I1 = [2*alpha^3 + 2, 220/3*alpha^3 + 2/3*alpha, 3*alpha^3 + 3*alpha^2,    111*alpha^3]
sage: xi1 = -1/5328*alpha^3 - 31/26640*alpha
sage: I2 = [28*alpha^3 + 2*alpha^2 + 10, 61/3*alpha^3 + 2*alpha^2 + 2/3*alpha,   15*alpha^3 + 6*alpha^2,   39*alpha^3]
sage: xi2 = -1/93600*alpha^3 + 1/9360*alpha
sage: I3 = [2*alpha^3 + 2, 4/3*alpha^3 + 2*alpha^2 + 2/3*alpha, 6*alpha^2, 3*alpha^3]
sage: xi3 = 1/1440*alpha^3 + 7/720*alpha

sage: O = ideal_order(I1, K)
sage: O == ideal_order(I2, K)
True
sage: O == ideal_order(I3, K)
True
sage: O.index_in(K.maximal_order())
27

sage: I1inv = ideal_inverse(I1, K)
sage: P1 = mult_ideals(I1, I1inv, K); P1
[3, 2*alpha^3 + alpha, 3*alpha^2, 3*alpha^3]
sage: O1 = ideal_order(P1, K); O1 == O
False
sage: O1.index_in(K.maximal_order())
1

sage: I2inv = ideal_inverse(I2, K)
sage: P2 = mult_ideals(I2, I2inv, K); P2
[3, 2*alpha^3 + alpha, 3*alpha^2, 3*alpha^3]
sage: O2 = ideal_order(P2, K)
sage: O2 == O1
True

sage: I3inv = ideal_inverse(I3, K)
sage: P3 = mult_ideals(I3, I3inv, K); P3
[3, 2*alpha^3 + alpha, 3*alpha^2, 3*alpha^3]
sage: O3 = ideal_order(P3, K)
sage: O3 == O1
True
recip.orders.ideal_is_invertible(basis, K=None, O=None)

Returns True if and only if the ZZ-lattice I spanned by basis is an invertible O-ideal.

If O is not specified, returns True if and only if there is an order O such that I is an invertible O-ideal. Equivalently, it then returns True if and only if it is an invertible ideal of its endomorphism order.

See ideal_inverse() for examples.

recip.orders.ideal_order(basis, K)

Given a basis of an ideal, returns the endomorphism ring inside K of this ideal, as an order.

EXAMPLES:

sage: from recip import *
sage: K.<a> = QuadraticField(15)
sage: basis1 = [1, a]   # Maximal order OK
sage: basis2 = [2, 2*a] # 2OK
sage: basis3 = [1, 2*a] # Another order, O
sage: basis4 = [2, a]   # Fractional ideal. Note: 4*basis4 is an ideal of basis3.
sage: O1 = ideal_order(basis1, K); O1
Order in Number Field in a with defining polynomial x^2 - 15
sage: O1.basis()
[1, a]

sage: ideal_order(basis2, K) == O1
True

sage: O3 = ideal_order(basis3, K)
sage: O3.basis()
[1, 2*a]
sage: O1 == O3
False

sage: ideal_order(basis4, K) == O3
True

sage: is_ideal(O3, basis3)
True
sage: is_ideal(O1, basis3)
False
sage: is_ideal(O1, basis1)
True
sage: is_ideal(O3, basis1)
True
recip.orders.ideals_equal(A, B, K=None)

Given bases of two lattices A and B in K, returns true if and only if the lattices are equal.

recip.orders.intersect_ideals(basis1, basis2, K)

Given bases of lattices in K, returns a basis of their intersection.

EXAMPLES:

sage: from recip import *
sage: K.<a> = QuadraticField(15)
sage: basis1 = [1, a]   # Maximal order OK
sage: basis2 = [2, 2*a] # 2OK
sage: basis3 = [1, 2*a] # Another order, O
sage: basis4 = [2, a]   # Fractional ideal. Note: 4*basis4 is an ideal of basis3.
sage: intersect_ideals(basis1, basis2, K) # ideal2 intersected with an ambient ring, hence unchanged
[2, 2*a]
sage: intersect_ideals(basis1, basis3, K) # Two orders intersected, hence the smallest is obtained
[1, 2*a]
sage: intersect_ideals(basis2, basis3, K) # ideal2 intersected with an ambient ring, hence unchanged
[2, 2*a]
sage: intersect_ideals(basis4, basis3, K) # intersection
[2, 2*a]
sage: intersect_ideals(basis4, basis4, K) # intersection with itself
[2, a]
recip.orders.is_ideal(O, B)

Given a basis B of a lattice L in a field K, and an order O in K, return True if and only if \(O L \subset L\).

recip.orders.is_trivial_in_shimura_group(A, alpha, O, cc=None)

Given an integral ideal A of the maximal order O_K of O coprime to F = [O_K : O] and given an element alpha of O with A*Abar = alpha*O_K, returns True if and only if there exists mu in K^* with mu*mubar = alpha and mu*O coprime to F*O as ideals of O and mu*O_K = A.

cc is complex conjugation (if not given, assumes K is a CM-field object).

Assumes K is a non-biquadratic quartic CM-field (TODO: does not warn for biquadratic fields).

Assumes O is stable under complex conjugation.

EXAMPLES:

We first create a suitable order, and standard things like reflex fields etcetera:

sage: from recip import *
sage: P.<x> = QQ[]
sage: CM_Field(x^4+2*x^3+16*x^2+15*x+19).minimal_DAB()
[149, 13, 5]
sage: K = CM_Field([149,13,5])
sage: Phi = K.CM_types()[0]
sage: Psi = Phi.reflex()
sage: Kr = Phi.reflex_field()
sage: [alpha1,alpha2]=(x^4+2*x^3+16*x^2+15*x+19).roots(K, multiplicities=False)
sage: cc = K.complex_conjugation()
sage: cc(alpha1) == alpha2
True
sage: O = K.order(alpha1)
sage: alpha2 in O
True
sage: OK = K.maximal_order()
sage: O.index_in(OK)
7

Now let’s compute lots of ideal classes to try:

sage: ideal_classes = [c.ideal() for c in Kr.class_group()]
sage: idealstar = Kr.ideal(7).idealstar(flag=2).list()
sage: ray_classes = [a*b for a in idealstar for b in ideal_classes]
sage: len(ray_classes)
2304
sage: type_norms = [(Psi.type_norm(I), I.norm()) for I in ray_classes] # long time, 20 seconds

Here we test the current function:

sage: all([is_trivial_in_shimura_group(A, alpha, OK) for (A, alpha) in type_norms]) # long time, 30 seconds
  ***   Warning: precision too low for generators, not given.
  ...
  ***   Warning: precision too low for generators, not given.
True
sage: len([A for (A, alpha) in type_norms if is_trivial_in_shimura_group(A, alpha, O)]) # long time, 25 seconds
384
sage: 2304/384
6

1/6 of ideals maps to a principal ideal, so the image has order 6.

recip.orders.minimal_F(O)

Given an order O in a number field K, returns the smallest integer F such that F*O_K subset O.

recip.orders.mult_ideals(basis1, basis2, K)

Given bases of lattices in K, returns a basis of their product.

EXAMPLES:

sage: from recip import *
sage: K.<a> = QuadraticField(15)
sage: basis1 = [1, a]   # Maximal order OK
sage: basis2 = [2, 2*a] # 2OK
sage: basis3 = [1, 2*a] # Another order, O
sage: basis4 = [2, a]   # Fractional ideal. Note: 4*basis4 is an ideal of basis3.
sage: mult_ideals(basis1, basis2, K) # basis2 multiplied by its endomorphism ring, hence unchanged
[2, 2*a]
sage: mult_ideals(basis1, basis3, K) # Two orders multiplied, hence the largest is obtained
[1, a]
sage: mult_ideals(basis2, basis3, K) # Twice the above
[2, 2*a]
sage: mult_ideals(basis4, basis3, K) # basis4 multiplied by its endomorphism ring, hence unchanged
[2, a]
sage: mult_ideals(basis4, basis4, K) # the square of basis4, generated by 4, 2a and a^2 = 15.
[1, 2*a]
recip.orders.period_matrices(O, F, Phi=None, reduced=True)

Returns all isomorphism classes of principally polarized abelian surfaces with CM by O of type Phi. Here F is such that F*OK is contained in O.

If Phi is None, use all CM-types and gives all elements up to complex conjugation of the CM type.

EXAMPLES:

Here is a bug, some numbers are close to zero and apparently CLF’s > 0 is not to be trusted.:

sage: from recip import *
sage: K = CM_Field([1837, 81, 1181])
sage: Phi = K.CM_types()[0]
sage: len(period_matrices(K.maximal_order(), 1, Phi)) # long time, half a minute
66
recip.orders.polarized_ideal_classes(O, F)

On input an order O of a quartic CM-field, returns all principally polarized ideal classes up to

  • changing (aaa, xi) into (aaa, -xi),
  • changing (aaa, xi) into (x*aaa, xi/x/xbar) for x in K.

In the primitive quartic case, this is either the empty set or half of a torsor for the group CCC(O) in the article of Bisson and Streng. (Half of, because only one of (aaa, xi) and (aaa, -xi) is given.) If O is the maximal order of a primtive quartic CM-field, then the output is non-empty.

INPUT:

  • \(O\) – order in a quartic \(CM_Field\) object
  • \(F\) – positive integer such that F*OK is contained in O (not checked)

EXAMPLES:

sage: from recip import *
sage: K = CM_Field([5,5,5])
sage: Phi = K.CM_types()[0]
sage: alpha = K.gen()
sage: O = K.order([1/2*alpha^3 + 1/2, 1/2*alpha^3 + 5/2*alpha^2 + 5/2*alpha, 5*alpha^2, alpha^3])
sage: OK = K.maximal_order()
sage: O.index_in(OK)
25
sage: s = superorders_stable_under_complex_conjugation(O)
sage: len(s)
3
sage: F = 5
sage: [ideal_contains(A.basis(), [F*b for b in OK.basis()]) for A in s]
[True, True, True]
sage: polarized_ideal_classes(s[0], 1)
[([1/2*alpha^3 + 1/2, 1/2*alpha^3 + 1/2*alpha^2 + 1/2*alpha, alpha^2, alpha^3],
  1/5*alpha),
 ([1/2*alpha^3 + 1/2, 1/2*alpha^3 + 1/2*alpha^2 + 1/2*alpha, alpha^2, alpha^3],
  -1/5*alpha^3 - 3/5*alpha)]
sage: polarized_ideal_classes(s[0], 5) == _ # long time
True
sage: polarized_ideal_classes(s[1], 5) # long time
[([1/2*alpha^3 + 1/2, 1/2*alpha^3 + 1/2*alpha^2 + 5/2*alpha, alpha^2, alpha^3],
  2/25*alpha^3 + 1/5*alpha),
 ([1/2*alpha^3 + 1/2, 1/2*alpha^3 + 1/2*alpha^2 + 5/2*alpha, alpha^2, alpha^3],
  1/25*alpha^3 + 1/5*alpha)]
sage: polarized_ideal_classes(s[2], 5) # long time
[]
recip.orders.proper_ideal_classes(O, F)

Input: O an order, F non-zero in ZZ and a multiple of the conductor.

Output: representatives of all classes of proper ideals of O modulo principal ideals.

Warning: not tested much except for primitive quartic CM-fields.

sage: from recip import * sage: K = CM_Field([5,5,5]) sage: Phi = K.CM_types()[0] sage: alpha = K.gen() sage: O = K.order([1/2*alpha^3 + 1/2, 1/2*alpha^3 + 5/2*alpha^2 + 5/2*alpha, 5*alpha^2, alpha^3]) sage: OK = K.maximal_order() sage: O.index_in(OK) 25 sage: s = superorders_stable_under_complex_conjugation(O) sage: len(s) 3 sage: F = 5 sage: [ideal_contains(A.basis(), [F*b for b in OK.basis()]) for A in s] [True, True, True] sage: proper_ideal_classes(s[0], 1) ([[1/2*alpha^3 + 1/2, 1/2*alpha^3 + 1/2*alpha^2 + 1/2*alpha, alpha^2, alpha^3]], [[1/2*alpha^3 + 1/2, 1/2*alpha^3 + 1/2*alpha^2 + 1/2*alpha, alpha^2, alpha^3]], [[1/2*alpha^3 + 1/2, 1/2*alpha^3 + 1/2*alpha^2 + 1/2*alpha, alpha^2, alpha^3]]) sage: proper_ideal_classes(s[0], 5) == _ # long time True sage: proper_ideal_classes(s[1], 5) # long time ([[1/2*alpha^3 + 1/2, 1/2*alpha^3 + 1/2*alpha^2 + 5/2*alpha, alpha^2, alpha^3]], [[1/2*alpha^3 + 1/2, 5/2*alpha^3 + 5/2*alpha^2 + 5/2*alpha, alpha^2, alpha^3]], [[1/2*alpha^3 + 1/2, 1/2*alpha^3 + 1/2*alpha^2 + 5/2*alpha, alpha^2, alpha^3]]) sage: proper_ideal_classes(s[2], 5) # long time ([[1/2*alpha^3 + 1/2, 1/2*alpha^3 + 1/2*alpha^2 + 1/2*alpha, 5*alpha^2, alpha^3], [1/2*alpha^3 + 1/2, 1/2*alpha^3 + 5/2*alpha^2 + 5/2*alpha, 5*alpha^2, alpha^3]], [[1/2*alpha^3 + 1/2, 1/2*alpha^3 + 1/2*alpha^2 + 1/2*alpha, 5*alpha^2, alpha^3], [1/2*alpha^3 + 1/2, 5/2*alpha^3 + 5/2*alpha^2 + 5/2*alpha, 5*alpha^2, alpha^3]], [[1/2*alpha^3 + 1/2, 1/2*alpha^3 + 5/2*alpha^2 + 5/2*alpha, 5*alpha^2, alpha^3]])
recip.orders.superorders(O)

Given an order O in a number field K, returns all orders in K containing O.

NOTE: this implementation is probably not optimal, as it uses all subgroups of OK/O and tests whether they yield rings.

EXAMPLES:

sage: from recip import *
sage: K = CM_Field([5,5,5])
sage: OK = K.maximal_order()
sage: O = K.order([5*b for b in OK.basis()])
sage: s = superorders(O)
sage: [A.index_in(OK) for A in s]
[1, 5, 25, 25, 25, 25, 25, 25, 125]
recip.orders.superorders_stable_under_complex_conjugation(O, c=None)

Given an order O in a number field K, and an automorphism c of K, returns all orders of K containing O and fixed under c.

If c is omitted and K has a method complex_conjugation, then use that for c.

EXAMPLES:

sage: from recip import *
sage: K = CM_Field([5,5,5])
sage: OK = K.maximal_order()
sage: O = K.order([5*b for b in OK.basis()])
sage: s = superorders_stable_under_complex_conjugation(O)
sage: [A.index_in(OK) for A in s]
[1, 5, 25, 25, 125]
recip.orders.trace_dual_complex_conjugate(A, cc=None)

Given a basis A of a lattice, returns the trace dual of cc(A). If cc is not specified and K has a complex_conjugation method, use that.