Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GModule work from OSCAR Workshop #4095

Draft
wants to merge 7 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 28 additions & 19 deletions experimental/GModule/src/GModule.jl
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
isdefined(Oscar, :word) || function word end

include("Cohomology.jl")
include("Types.jl")
include("GaloisCohomology.jl")
include("GrpExt.jl")
include("Misc.jl")

module GModuleFromGap
using Oscar
using Hecke
import Hecke: data

#XXX: clash of names!
Expand Down Expand Up @@ -43,7 +43,7 @@ julia> C = gmodule(CyclotomicField, C);
julia> h = subfields(base_ring(C), degree = 2)[1][2];

julia> restriction_of_scalars(C, h)
G-module for G acting on vector space of dimension 4 over number field
(G-module for G acting on vector space of dimension 4 over number field, Map: C -> g-module for G acting on vector space of dimension 4 over number field)

julia> restriction_of_scalars(C, QQ)
G-module for G acting on vector space of dimension 8 over QQ
Expand All @@ -56,9 +56,15 @@ function restriction_of_scalars(M::GModule{<:Oscar.GAPGroup, <:AbstractAlgebra.F
@assert codomain(phi) == base_ring(M)
d = divexact(degree(codomain(phi)), degree(domain(phi)))
F = free_module(domain(phi), dim(M)*d)
_, _, rep = relative_field(phi)
_, coord, rep = relative_field(phi)

return GModule(F, group(M), [hom(F, F, hvcat(dim(M), [rep(x) for x in transpose(matrix(y))]...)) for y in M.ac])
D = GModule(F, group(M), [hom(F, F, hvcat(dim(M), [rep(x) for x in transpose(matrix(y))]...)) for y in M.ac])
#the blow-up function is not a "nice" module hom as tis is used
#to make from a K-Module to e.g. a QQ-module, so the map
#will be QQ-linear and we'd need to get QQ-gens from a K-module
#also: pre-image is not working (not implemented) (needs more info from
#relative_field)
return D, hom(M, D, MapFromFunc(M.M, D.M, x->D.M(vcat([coord(t) for t = x.v[1,:]]...))); check = false)
end

function restriction_of_scalars(C::GModule{<:Any, <:AbstractAlgebra.FPModule{AbsSimpleNumFieldElem}}, ::QQField)
Expand Down Expand Up @@ -313,7 +319,7 @@ function maximal_submodule_bases(M::GModule{<:Oscar.GAPGroup, <:AbstractAlgebra.
return res
end

function maximal_submodules(M::GModule{<:Oscar.GAPGroup, <:AbstractAlgebra.FPModule{<:FinFieldElem}})
function Oscar.maximal_submodules(M::GModule{<:Oscar.GAPGroup, <:AbstractAlgebra.FPModule{<:FinFieldElem}})
return [sub(M, s) for s = maximal_submodule_bases(M)]
end

Expand Down Expand Up @@ -496,7 +502,7 @@ function _minimize(V::GModule{<:Oscar.GAPGroup, <:AbstractAlgebra.FPModule{AbsSi
k char field
|
Q

So: V is given as G -> GL(n, K)
This is represented by
sigma: Gal(K/k)^2 -> K a 2-chain
Expand All @@ -520,7 +526,7 @@ function _minimize(V::GModule{<:Oscar.GAPGroup, <:AbstractAlgebra.FPModule{AbsSi
split by A in GL(n, K)
Now, technically, A V A^-1 has values in Gl(n, E)
Step 7:
Replacing V -> A V A^-1 changes
Replacing V -> A V A^-1 changes
X_g -> A^g X A^-1
As A V A^-1 is in GL(n, E), A^g X A^-1 can be normlized (mult. by
scalar in K) to be in Gl(n, E)
Expand All @@ -543,7 +549,7 @@ function _minimize(V::GModule{<:Oscar.GAPGroup, <:AbstractAlgebra.FPModule{AbsSi
d = reduce(lcm, [x[2] for x = ld], init = 1)

s = subfields(base_ring(V))

s = [x for x in s if degree(x[1]) >= d*degree(k)]
sort!(s, lt = (a,b) -> degree(a[1]) < degree(b[1]))
for (m, mm) in s
Expand Down Expand Up @@ -600,7 +606,7 @@ function _minimize(V::GModule{<:Oscar.GAPGroup, <:AbstractAlgebra.FPModule{AbsSi
#we need Gal(E/k) as the quotient of A/U
q, mq = quo(domain(mA), U)
X = Dict( g => map_entries(mA(preimage(mq, g)), AA) * X[preimage(mq, g)] * AAi for g = q)
for (g, x) = X
for (g, x) = X
lf = findfirst(!iszero, x)
x *= inv(x[lf])
X[g] = map_entries(pseudo_inv(mm), x)
Expand Down Expand Up @@ -636,7 +642,7 @@ function _minimize(V::GModule{<:Oscar.GAPGroup, <:AbstractAlgebra.FPModule{AbsSi
LD = Dict{AbsSimpleNumFieldOrderIdeal, Int}()
LI = Dict{AbsSimpleNumFieldEmbedding, Int}()
for (p, d) = ld
if p == -1
if p == -1
@assert d == 2
if signature(k)[2] == 0
for e = real_embeddings(k)
Expand All @@ -659,21 +665,21 @@ function _minimize(V::GModule{<:Oscar.GAPGroup, <:AbstractAlgebra.FPModule{AbsSi
C, mC = automorphism_group(PermGroup, EF)
gE = mE_EF(E[1])
hBC = hom(C, B, [[b for b = B if mC(c)(gE) == mE_EF(mB(b)(E[1]))][1] for c = gens(C)])
gF = mF_EF(F[1])
U, mU = sub(C, [c for c = C if mC(c)(gF) == gF])
gF = mF_EF(F[1])
U, mU = sub(C, [c for c = C if mC(c)(gF) == gF])
MEF = MultGrp(EF)
#inflate
s = Dict{NTuple{2, elem_type(U)}, elem_type(MEF)}((f, g) => MEF(mE_EF(s[(hBC(f), hBC(g))])) for f = U for g = U)


D = gmodule(U, [hom(MEF, MEF, mC(mU(x))) for x = gens(U)])
Sigma = CoChain{2,PermGroupElem, MultGrpElem{AbsSimpleNumFieldElem}}(D, s)

fl, mu = Oscar.GaloisCohomology_Mod.is_coboundary(Sigma)
@assert fl
#inflate X
X = Dict( g => map_entries(mE_EF, X[preimage(h, hBC(mU(g)))]) *mu(g).data for g = U)
@hassert :MinField 1 isone_cochain(X, mU*mC)
@hassert :MinField 1 isone_cochain(X, mU*mC)
@vtime :MinField 2 BB, BBi = hilbert90_generic(X, mU*mC)
c = content_ideal(BB)
sd = Hecke.short_elem(inv(c))
Expand All @@ -697,7 +703,8 @@ end
function irreducible_modules(::QQField, G::Oscar.GAPGroup)
#if cyclo is not minimal, this is not irreducible
z = irreducible_modules(CyclotomicField, G)
return [gmodule(QQ, descent_to_minimal_degree_field(m)) for m in z]
temp = map(x -> galois_orbit_sum(character(x)), z)
return [gmodule(QQ, descent_to_minimal_degree_field(z[i])) for i in unique(i -> temp[i], 1:length(temp))]
end

function irreducible_modules(::ZZRing, G::Oscar.GAPGroup)
Expand Down Expand Up @@ -926,7 +933,8 @@ function Oscar.sub(C::GModule{<:Any, <:AbstractAlgebra.FPModule{T}}, m::MatElem{

y = GAP.Globals.MTX.InducedActionSubmoduleNB(g, x)
F = free_module(k, nrows(b))
return gmodule(F, Group(C), [hom(F, F, matrix([preimage(h, x[i, j]) for i in 1:GAPWrap.NrRows(x), j in 1:GAPWrap.NrCols(x)])) for x = y.generators]), hom(F, C.M, b)
D = gmodule(F, Group(C), [hom(F, F, matrix([preimage(h, x[i, j]) for i in 1:GAPWrap.NrRows(x), j in 1:GAPWrap.NrCols(x)])) for x = y.generators])
return D, hom(C, D, b)
return b
end

Expand All @@ -936,7 +944,8 @@ function Oscar.sub(M::GModule{<:Any, <:AbstractAlgebra.FPModule{T}}, f::Abstract
@assert codomain(f) == M.M
S = domain(f)
Sac = [hom(S, S, [preimage(f, h(f(x))) for x in gens(S)]) for h in M.ac]
return gmodule(S, M.G, Sac)
D = gmodule(S, M.G, Sac)
return D, hom(D, M, f)
end

function gmodule(k::Nemo.FinField, C::GModule{<:Any, <:AbstractAlgebra.FPModule{<:FinFieldElem}})
Expand Down Expand Up @@ -1324,14 +1333,14 @@ function Oscar.is_coboundary(c::CoChain{1,PermGroupElem,MultGrpElem{AbsSimpleNum
cnt = 0
while true
local Y
while true
while true
Y = rand(K, -5:5)
iszero(Y) || break
end
cnt += 1
S = sum(mA(emb(g))(Y)*c((g,)).data for g = G)
is_zero(S) || return true, mK(S)
if cnt > 10
if cnt > 10
error("should not happen")
end
end
Expand Down
3 changes: 3 additions & 0 deletions experimental/GModule/src/Misc.jl
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,9 @@ Hecke.restrict(::Hecke.NumFieldEmb, ::Map{QQField, AbsSimpleNumField}) = complex
function relative_field(m::Map{<:AbstractAlgebra.Field, <:AbstractAlgebra.Field})
k = domain(m)
K = codomain(m)
if k == base_field(K)
return defining_polynomial(K), Hecke.coordinates, representation_matrix
end
@assert base_field(k) == base_field(K)
kt, t = polynomial_ring(k, cached = false)
f = defining_polynomial(K)
Expand Down
93 changes: 93 additions & 0 deletions experimental/GModule/src/Types.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
mutable struct GModuleHom{ G, T1, T2} <: Map{GModule{G, T1}, GModule{G, T2}, OscarMap, GModuleHom}

GM1::GModule{G, T1}
GM2::GModule{G, T2}
module_map::Map{T1, T2}

function GModuleHom(
M1::GModule,
M2::GModule,
mp::Map;
check::Bool = false
)
# Need to require that
# 1. Both GModules have the same group
# 2. The group action is respected
@req M1.G === M2.G "groups need to be identical"
@req domain(mp) === M1.M && codomain(mp) === M2.M "map need to map 1st module into 2nd"
#not every hom is a G-Hom...that is what check is supposed to do - eventually
#see 2.
if check #only works if mp is a morphism so that "*" and "==" are doing
#s.th. useful
@assert all(g->action(M1, g)*mp == mp*action(M2, g), gens(M1.G))
end

return new{typeof(M1.G), typeof(M1.M), typeof(M2.M)}(M1, M2, mp)
end
end

function hom(M1::GModule{T}, M2::GModule{T}, mp::Map; check::Bool = true) where T <: AbstractAlgebra.Group
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe add some tests for the new code?

return GModuleHom(M1, M2, mp; check)
end

function hom(M1::GModule{T}, M2::GModule{T}, mp::MatElem; check::Bool = true) where T <: AbstractAlgebra.Group
return GModuleHom(M1, M2, hom(M1.M, M2.M, mp); check)
end

domain(M::GModuleHom) = M.GM1
codomain(M::GModuleHom) = M.GM2
parent(M::GModuleHom) = Hecke.MapParent(domain(M), codomain(M), "homomorphisms")

mutable struct GModuleElem{T}
parent::GModule
data::T
end

parent(a::GModuleElem) = a.parent

function (C::GModule)(a::Union{ModuleElem, FinGenAbGroupElem})
@req parent(a) === C.M "wrong parent for $a"
return GModuleElem(C, a)
end

function ==(a::GModuleElem, b::GModuleElem)
@req parent(a) === parent(b) "parents differ"
return a.data == b.data
end

function hash(a::GModuleElem, u::UInt)
return hash(a.data, u)
end

function +(a::GModuleElem, b::GModuleElem)
@req parent(a) === parent(b) "parents differ"
return GModuleElem(parent(a), a.data + b.data)
end

function -(a::GModuleElem, b::GModuleElem)
@req parent(a) === parent(b) "parents differ"
return GModuleElem(parent(a), a.data - b.data)
end

function -(a::GModuleElem)
return GModuleElem(parent(a), -a.data)
end

function *(a::GModuleElem, g::GroupElem)
@req parent(a).G === parent(g) "group element has wrong parent"
return GModuleElem(parent(a), action(parent(a), g, a.data))
end

function (A::GModuleHom)(a::GModuleElem)
@req parent(a) === domain(A) "element has wrong parent"
return GModuleElem(codomain(A), A.module_map(a.data))
end

function kernel(A::GModuleHom)
return sub(A, kernel(A.module_map)[2])
end

function image(A::GModuleHom)
return sub(A, image(A.module_map)[2])
end

Loading