From 626bd92663549989d8bb766b91aa1a8b2025c738 Mon Sep 17 00:00:00 2001 From: Tommy Hofmann Date: Thu, 2 May 2024 19:50:36 +0200 Subject: [PATCH] fix: extend abelian_extension for number fields - allow to provide conductors - fix handling of implicit maximal order --- src/FieldFactory/ab_exts.jl | 43 +++++++++++++++++++------- src/FieldFactory/conductors_generic.jl | 12 +++++-- test/RCF/rcf.jl | 21 +++++++++++++ 3 files changed, 62 insertions(+), 14 deletions(-) diff --git a/src/FieldFactory/ab_exts.jl b/src/FieldFactory/ab_exts.jl index 16403ec000..05b68aed0e 100644 --- a/src/FieldFactory/ab_exts.jl +++ b/src/FieldFactory/ab_exts.jl @@ -236,13 +236,15 @@ function abelian_extensions(K::AbsSimpleNumField, gtype::Vector{Int}, absolutely_distinct::Bool = false, ramified_at_inf_plc::Tuple{Bool, Vector{<: InfPlc}} = (false, InfPlc{AbsSimpleNumField, AbsSimpleNumFieldEmbedding}[]), only_tame::Bool = false, - signatures::Vector{Tuple{Int, Int}} = Tuple{Int, Int}[]) + signatures::Vector{Tuple{Int, Int}} = Tuple{Int, Int}[], + conductors = nothing) if length(signatures) == 0 return _abelian_extensions(K, gtype, absolute_discriminant_bound, absolutely_distinct = absolutely_distinct, ramified_at_inf_plc = ramified_at_inf_plc, - only_tame = only_tame) + only_tame = only_tame, + conductors = conductors) else if ramified_at_inf_plc[1] error("Cannot specify ramified place and target signatures simultaneously") @@ -270,7 +272,8 @@ function abelian_extensions(K::AbsSimpleNumField, gtype::Vector{Int}, more_fields = _abelian_extensions(K, gtype, absolute_discriminant_bound, absolutely_distinct = absolutely_distinct, ramified_at_inf_plc = (true, rlp_ramify), - only_tame = only_tame) + only_tame = only_tame, + conductors = conductors) for L in more_fields @assert signature(L) == (R, S) end @@ -285,19 +288,39 @@ function _abelian_extensions(K::AbsSimpleNumField, gtype::Vector{Int}, absolute_discriminant_bound::ZZRingElem; absolutely_distinct::Bool = false, ramified_at_inf_plc::Tuple{Bool, Vector{<: InfPlc}} = (false, InfPlc[]), - only_tame::Bool = false) + only_tame::Bool = false, + conductors = nothing) - OK = maximal_order(K) + # quick check + OK = lll(maximal_order(K)) gtype = map(Int, snf(abelian_group(gtype))[1].snf) n = prod(gtype) - inf_plc = InfPlc[] - fields = ClassField{MapRayClassGrp, FinGenAbGroupHom}[] bound = div(absolute_discriminant_bound, abs(discriminant(OK))^n) if iszero(bound) return fields end + # TODO: better preprocessing of custom conductors + # what to allow? lists of ideals, lists of factorizations, ... + # + # #Getting conductors first, because we also extrat the maximal order + if conductors === nothing + @vprintln :AbExt 1 "Computing conductors" + l_conductors = conductors_generic(K, gtype, absolute_discriminant_bound, only_tame = only_tame) + else + @vprintln :AbExt 1 "Conductors provided" + if conductors isa Vector{<:Dict} + l_conductors = conductors + else + @assert conductors isa Vector{ideal_type(OK)} + l_conductors = [factor(I) for I in conductors] + end + if !isempty(first(l_conductors)) + OK = order(first(keys(first(l_conductors)))) + end + end + inf_plc = real_places(K) if ramified_at_inf_plc[1] inf_plc = ramified_at_inf_plc[2] @@ -313,8 +336,7 @@ function _abelian_extensions(K::AbsSimpleNumField, gtype::Vector{Int}, cgrp = !is_coprime(n, order(Cl)) allow_cache!(mCl) - #Getting conductors - l_conductors = conductors_generic(K, gtype, absolute_discriminant_bound, only_tame = only_tame) + if absolutely_distinct l_conductors = _sieve_conjugates(auts, l_conductors) end @@ -326,7 +348,7 @@ function _abelian_extensions(K::AbsSimpleNumField, gtype::Vector{Int}, #Now, the big loop for (i, k) in enumerate(l_conductors) if i % 10000 == 0 - @vprintln :AbExt 1 "Left: $(length(l_conductors) - i)" + @vprintln :AbExt 1 "Conductors left: $(length(l_conductors) - i) (fields found: $(length(fields)))" end r, mr = ray_class_group_quo(OK, k, inf_plc, ctx) if !has_quotient(r, gtype) @@ -368,7 +390,6 @@ function _abelian_extensions(K::AbsSimpleNumField, gtype::Vector{Int}, end end if cC[1] == mr.defining_modulus[1] && norm(discriminant(C)) <= bound - @vprintln :AbExt 1 "New Field" push!(new_fields, C) end end diff --git a/src/FieldFactory/conductors_generic.jl b/src/FieldFactory/conductors_generic.jl index 39ddfcff21..fa4dc89e10 100644 --- a/src/FieldFactory/conductors_generic.jl +++ b/src/FieldFactory/conductors_generic.jl @@ -579,12 +579,15 @@ end function conductors_generic(K::AbsSimpleNumField, gtype::Vector{Int}, absolute_bound::ZZRingElem; only_tame::Bool = false) + return conductors_generic(lll(maximal_order(K)), gtype, absolute_bound; only_tame = only_tame) +end + +function conductors_generic(OK::AbsSimpleNumFieldOrder, gtype::Vector{Int}, absolute_bound::ZZRingElem; only_tame::Bool = false) #I am assuming that gtype is in "SNF" - conds_tame = conductors_generic_tame(K, gtype, absolute_bound) + conds_tame = conductors_generic_tame(OK, gtype, absolute_bound) if only_tame return Dict{AbsNumFieldOrderIdeal{AbsSimpleNumField, AbsSimpleNumFieldElem}, Int}[(x[1], Dict{AbsNumFieldOrderIdeal{AbsSimpleNumField, AbsSimpleNumFieldElem}, Int}()) for x in conds_tame] end - OK = maximal_order(K) wild = collect(keys(factor(gtype[end]).fac)) n = prod(gtype) bound = div(absolute_bound, abs(discriminant(OK))^n) @@ -670,7 +673,10 @@ function conductors_generic(K::AbsSimpleNumField, gtype::Vector{Int}, absolute_b end function conductors_generic_tame(K::AbsSimpleNumField, gtype::Vector{Int}, absolute_bound::ZZRingElem) - OK = maximal_order(K) + return conductors_generic_tame(lll(maximal_order(K), gtype, absolute_bound)) +end + +function conductors_generic_tame(OK::AbsSimpleNumFieldOrder, gtype::Vector{Int}, absolute_bound::ZZRingElem) n = prod(gtype) wild = collect(keys(factor(n).fac)) pmin = Int(minimum(wild)) diff --git a/test/RCF/rcf.jl b/test/RCF/rcf.jl index 347ee1e730..8a79d8112f 100644 --- a/test/RCF/rcf.jl +++ b/test/RCF/rcf.jl @@ -348,3 +348,24 @@ end l = abelian_extensions([2], collect(1:10^3)) @test length(l) == 607 end + +let + Qx, x = QQ["x"] + K, a = rationals_as_number_field() + all_fields = abelian_extensions(K, [2], ZZRingElem(10)^3, absolutely_distinct = true) + OK = maximal_order(K) + lp = prime_ideals_up_to(OK, 10^3) + prime_cond = abelian_extensions(K, [2], ZZRingElem(10)^3, absolutely_distinct = true, conductors = lp) + @test length(prime_cond) == count(is_prime.(first.(conductor.(all_fields)))) + + # with target signatures + K, a = number_field(x^3 - x^2 - 2*x + 1, cached = false) + l = abelian_extensions(K, [2, 2], ZZRingElem(10)^12) + conds = Hecke.conductors_generic(K, [2, 2], ZZ(10)^12) + l = abelian_extensions(K, [2, 2], ZZRingElem(10)^12) + ll = abelian_extensions(K, [2, 2], ZZRingElem(10)^12, conductors = conds) + @test length(l) == length(ll) + l1 = abelian_extensions(K, [2, 2], ZZRingElem(10)^12, signatures = [(4, 4)]) + ll1 = abelian_extensions(K, [2, 2], ZZRingElem(10)^12, signatures = [(4, 4)], conductors = conds) + @test length(l1) == length(ll1) +end