Ask Your Question
1

polycyclic presentation

asked 2025-08-01 10:41:52 +0200

pierre.C gravatar image

I try to apply ideas from Sutherland's paper about volcanoes (Titles "Isogeny volcanoes" 2012) , in particular I want to obtain a polycyclic presentation of a class group ๐บ (of negative discriminant, viewed as a group of binary quadratic forms). I easily get a set ๐‘† of generators (of ๐บ) of prime norm and from those I want to implement the following in SageMath :

  1. Get a polycylic presentation of $G$ from $S$.
  2. Compute the discrete log of elements of ๐บ with respect to this polycyclic presentation.

Q/ Is there an efficient way to do this by using GAP pcgs inside SageMath ?

For now, here is what I do :

 # gens is a set of generators of the Class group I am interested in.
G = FreeGroup(len(gens))

relations_orders = [G([i+1]*(g.order())) for i,g in enumerate(gens)]
relations =[]

for i,g in enumerate(gens):
    nexts = gens[i+1:]
    for j,a in enumerate(nexts):
        try:
            d = discrete_log(g,a,operation="+")               #d*a - g =0
            relations.append( G([j+1+i+1]*d+[-i-1]) )
        except:
            pass

rels = relations+relations_orders

H = G/rels

Now, I would like to use gap.interact() in order to call Pcgs(H) in GAP and then recover it back in Sage.

edit retag flag offensive close merge delete

Comments

Please make your code self-contained by adding a definition of gens (any example will do).

rburing gravatar imagerburing ( 2025-08-02 12:59:03 +0200 )edit

1 Answer

Sort by ยป oldest newest most voted
0

answered 2025-08-02 16:28:18 +0200

pierre.C gravatar image

Actually I found it much more efficient to use a direct computation in the class group. All my attempts to interact with GAP were quite slow.

def get_bqf(D,p):
    d = fundamental_discriminant(D)
    v = isqrt(D//d)
    if v % p == 0:
        return None
    ks = kronecker_symbol(D,p)
    if ks == -1:
        return None
    c= floor(-D/(4*p))
    while True:
        c += 1
        b2 = D+4*p*c
        if isqrt(b2)**2 == b2:
            b = isqrt(b2)
            return  BinaryQF([p,b,c])
    return None

def get_prime_forms(D):
    P = Primes()
    p = 2
    B = isqrt(abs(D)/3)
    gens = []
    while p < B:
        bq = get_bqf(D,p)
        if  bq is not None :
            gens.append(bq)
        p = P.next(p)
    return gens

# p.16 of https://arxiv.org/pdf/0903.2785

def TableInsert(T,g):
    T.append(g.reduced_form())
    return None

def TableLookup(T,beta):
    b = beta.reduced_form()
    if b in T:
        return T.index(b)
    else:
        return None

def poly_rep(gens):
    G = (gens[0].form_class()).parent()
    n = len(gens)
    T = []
    r = []
    s = []
    TableInsert(T,G.zero().form())
    for i in range(1,n+1):
        beta = gens[i-1].reduced_form()
        ri = 1
        N = len(T)
        si = TableLookup(T,beta)
        while si == None:
            for j in range(N):
                TableInsert(T,beta*T[j])
            beta = beta*gens[i-1]
            si = TableLookup(T,beta)
            ri += 1
        r.append(ri)
        s.append(si)
    return T,r,s

D = -5291
gens = get_prime_forms(D)  
T,r,s=poly_rep(gens)

This does not include improvements from p.17 of Computing Hilbert Class Polynomials With Chinese Remainder Theorem from Andrew Sutherland.

edit flag offensive delete link more

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools

Stats

Asked: 2025-08-01 07:14:24 +0200

Seen: 7,161 times

Last updated: Aug 02