# Computing the order of an ideal in a ray class group

Suppose $K$ is a number field, $\mathfrak{m}$ is a modulus of $K$, and $\mathfrak{a}$ is a given fractional ideal of $K$. SAGE can compute the ray class group $Cl_{\mathfrak{m}}(K)$. However, how can I find what element of the ray class group $\mathfrak{a}$ corresponds to? More specifically, I need to find the order of $\mathfrak{a}$ in $Cl_{\mathfrak{m}}$.

I can do this in MAGMA only when $\mathfrak{m}=(1)$, but does anyone know of a way to do this in SAGE?

edit retag close merge delete

Sort by » oldest newest most voted

Hi, for many computations in algebraic number theory SAGE uses PARI in the background. It seems to me that the relevant functionality for computing ray class groups (that is present in PARI) is not yet wrapped conveniently in SAGE.

There are two ways to proceed: You could use PARI/GP directly from the command line (the functions you're looking for are basically bnrinit to compute a representation of a ray class group as a product of cyclic groups and bnrisprincipal to compute the image of an ideal in this representation, from which you can get the order). Alternatively, you can use SAGE's GP-Interface to do the same from within SAGE, I'll demonstrate both ways.

First, an example in PARI/GP to demonstrate the basic computation (some output omitted, $\mathfrak m = (3)$ and $K$ has no real archimedean places):

? K = bnfinit(x^6 + 76*x^4 + 2*x^3 + 2029*x^2 - 158*x + 18955)
? bnfcertify(K)
%2 = 1
? Kr = bnrinit(K, [3, []], 1)
? Kr.clgp.cyc
%4 = [6, 6]     # => ray class group is C_6 x C_6
? J = idealhnf(Kr, 5, x^2 + 2*x + 23)
? bnrisprincipal(Kr,J)
%6 = [[4, 4]~, ...]  # image of J in ray class group


The following provides a quick and dirty hack to do basically the same from SAGE, using its PARI/GP Interface:

class RayClassGroup(AbelianGroup_class):
def __init__(self, number_field, mod_ideal = 1, mod_archimedean = None):
if mod_archimedean == None:
mod_archimedean =  * len(number_field.real_places())

bnf = gp(number_field.pari_bnf())
# Use PARI to compute ray class group
bnr = bnf.bnrinit([mod_ideal, mod_archimedean],1)
invariants = bnr         # bnr.clgp.cyc
invariants = [ ZZ(x) for x in invariants ]

AbelianGroup_class.__init__(self, len(invariants), invariants)
self.__number_field = number_field
self.__bnr = bnr

def __call__(self, *args, **kwargs):
return group.Group.__call__(self, *args, **kwargs)

def _element_constructor_(self, *args, **kwargs):
if isinstance(args, AbelianGroupElement):
return AbelianGroupElement(self, args)
else:
I = self.__number_field.ideal(*args, **kwargs)

# Use PARI to compute class of given ideal
g = self.__bnr.bnrisprincipal(I)
g = [ ZZ(x) for x in g ]
return AbelianGroupElement(self, g)


After running the above code (either in a notebook cell or the sage command-line, be careful to preserve the whitespace exactly as is), you can use the class like this:

K.<a> = NumberField(x^6 + 76*x^4 + 2*x^3 + 2029*x^2 - 158*x + 18955)
G = RayClassGroup(K, K.ideal(3), [])
J = K.ideal([5, a^2 + 2*a + 23])
G(J).order()


If you have real places, the infinite part is specified using 0's and 1's, e.g.

K.<a> = NumberField(x^6 - 3*x^5 - 3*x^4 + 10*x^3 + 3*x^2 - 6*x + 1)
G = RayClassGroup(K, K.ideal(1), [0,1,1,1,1,1])


gives trivial ray class group, while

K.<a> = NumberField(x^6 - 3*x^5 - 3*x^4 + 10*x^3 + 3*x^2 - 6*x + 1)
G = RayClassGroup(K, K.ideal(1), [1,1,1,1,1,1])


gives $C_2$. The order of ...

more

This detailed answer has been very useful, and I have plans to use it as the basis for a proper RayClassGroup class in Sage itself, after wrapping the pari bnrinit function to that there is no need to call gp. I would like to be able to credit the author -- daniels, who are you?

This code no longer works. See https://ask.sagemath.org/question/57338/computing-ray-class-numbers/ (this forum) .