From 2f2e7a7577895d4e8f3be596663bf5622ff07e53 Mon Sep 17 00:00:00 2001 From: Morgan Rodgers Date: Wed, 11 Mar 2026 11:47:35 +0100 Subject: [PATCH 01/23] first commit --- experimental/LadderGame/README.md | 6 ++++++ experimental/LadderGame/docs/doc.main | 5 +++++ experimental/LadderGame/docs/src/ladder_game.md | 11 +++++++++++ experimental/LadderGame/src/LadderGame.jl | 6 ++++++ experimental/LadderGame/test/ladder_game.jl | 4 ++++ 5 files changed, 32 insertions(+) create mode 100644 experimental/LadderGame/README.md create mode 100644 experimental/LadderGame/docs/doc.main create mode 100644 experimental/LadderGame/docs/src/ladder_game.md create mode 100644 experimental/LadderGame/src/LadderGame.jl create mode 100644 experimental/LadderGame/test/ladder_game.jl diff --git a/experimental/LadderGame/README.md b/experimental/LadderGame/README.md new file mode 100644 index 000000000000..ed29c0407d4c --- /dev/null +++ b/experimental/LadderGame/README.md @@ -0,0 +1,6 @@ +# Ladder Game + +## Aims + + +## Status diff --git a/experimental/LadderGame/docs/doc.main b/experimental/LadderGame/docs/doc.main new file mode 100644 index 000000000000..ebc25752cb13 --- /dev/null +++ b/experimental/LadderGame/docs/doc.main @@ -0,0 +1,5 @@ +[ + "Ladder Game" => [ + "ladder_game.md" + ], +] diff --git a/experimental/LadderGame/docs/src/ladder_game.md b/experimental/LadderGame/docs/src/ladder_game.md new file mode 100644 index 000000000000..5a3c793f05c0 --- /dev/null +++ b/experimental/LadderGame/docs/src/ladder_game.md @@ -0,0 +1,11 @@ +```@meta +CurrentModule = Oscar +CollapsedDocStrings = true +DocTestSetup = Oscar.doctestsetup() +``` + +# Ladder Game + +```@docs + +``` diff --git a/experimental/LadderGame/src/LadderGame.jl b/experimental/LadderGame/src/LadderGame.jl new file mode 100644 index 000000000000..b420b8b77546 --- /dev/null +++ b/experimental/LadderGame/src/LadderGame.jl @@ -0,0 +1,6 @@ +################################################################################ +# Ladder Game +# +# +# +################################################################################ diff --git a/experimental/LadderGame/test/ladder_game.jl b/experimental/LadderGame/test/ladder_game.jl new file mode 100644 index 000000000000..d893a873388c --- /dev/null +++ b/experimental/LadderGame/test/ladder_game.jl @@ -0,0 +1,4 @@ +@testset "combinatorics/ladder_game.jl" begin + + +end From 3cb1c31275bb5da73ba3c3b0748b6c8f058fb897 Mon Sep 17 00:00:00 2001 From: Morgan Rodgers Date: Fri, 13 Mar 2026 14:18:43 +0100 Subject: [PATCH 02/23] initial code for draft --- experimental/LadderGame/src/LadderGame.jl | 244 ++++++++++++++++++++++ 1 file changed, 244 insertions(+) diff --git a/experimental/LadderGame/src/LadderGame.jl b/experimental/LadderGame/src/LadderGame.jl index b420b8b77546..0c0264856e11 100644 --- a/experimental/LadderGame/src/LadderGame.jl +++ b/experimental/LadderGame/src/LadderGame.jl @@ -4,3 +4,247 @@ # # ################################################################################ + +module LadderGame + +using Oscar + + +# Compute A\G/U +# we need: a subgroup ladder L = (A_i)_(0<=i<=a) +# Need a transversal chain for U: +# subgroup chain (U_i)_(0<=i<=k) +# transversals (S_i)_(0-> NN (injection) +function ladder_game(L, G, U) + r = ladder_start(G, U) + H = L[1] + for i in 2:length(L) + if is_subgroup(H, L[i]) + r = up_step(L[i],U,r) + else + r = down_step(L[i], U, r) + end + H = L[i] + end + return r +end + +function ladder_start(G, U) + st = [get_transversal_chain(U)] + r = LadderData( + # Ai = G + # T = [ one(G) ] + # mT = ** map G ->G, x :-> one(G) ** + # I = [ one(G) ] + # S3 = [ (one(G), one(G)) ] + # Di = [ one(G) ] + # St = st + # g,s for env variable "F" set to false + ) + # what about this environment variable "F" set to false? + return r +end + +function down_step(A, U, rec) + r = LadderData( + # Ai = A + # Aim1 = rec.Ai + # last = rec + # g,s for ev variable "F" set to false + ) + T, mT = transversal(rec.Ai, A) + r.T = T + r.mT = mT + Di = [] + S3 = [] + St = [] + I = [] + for a in rec.Di + tmp = [] + for t in T + if ~(t in tmp) + d = t*a + st = rec.St[a] + S1 = intersect(U, A^d) + S2 = intersect(U, R.Ai^a) + # assert S1 subset S2 + # assert st[1][1] == S2 + # assert S2 == intersect(U, R.Ai^d) + st, Sta = _induce_chain(S1, mT, st ; conj=d) + # assert length(Sta) == Index(S2, S1) + _, ss = transversal(S2, S1) + # assert length({ss(x) : x in Sta}) == #Sta + append!(Di,d) + append!(St, st) + for u in Sta + tt = mT(d*u*inv(a)) + include!(tmp, tt) + include!(I, tt*a) + append!(S3, (d,u) ) + # assert tt*a*inv(u)*inv(d) in A + end + end + end + # assert T == tmp + end + r.Di = Di + r.I = I + r.S3 = S3 + r.St = St + return r +end + +function up_step(A, U, rec) + r = LadderData( + # Ai = A + # Aim1 = rec.Ai + # last = rec + # g,s for ev variable "F" set to false + ) + + T, mT = transversal(A, R.Ai) + r.T = T + r.mT = mT + Di = [] + S3 = [] + St = [] + I = [] + + seen = [] + data = [] + cls = [] + cls_data = [] + + for a in rec.Di + if a in cls + p = index(cls, a) + rep = cls_data[p][1] + rep_u = cls_data[p][2] + new = false + else + rep = nothing + new = true + end + + tt = [] + for t in T + (~new && ~is_one(t)) && continue + ta = t*a + at, ut = _get_rep(ta, rec) + # assert ta*inv(ut)*inv(at) in r.Aim1 + # assert at in rec.Di + rep===nothing && (rep=at, rep_u = ut) + at in cls || (include!(cls, at), append!(cls_data, (rep, rep_u*inv(ut)) )) + at == rep && append!(tt, ut*inv(rep_u)) + is_one(t) && (include!(I, a), append!(S3, (rep, rep_u*inv(ut)) )) + end + if new + append!(Di, rep) + append!(St, [[ (intersect(A^rep, U), tt) ] rec.St[rep]] ) # in magma code: rec.St[Position(R.Di, rep)] + # assert Index(St[end][1][1], St[end][2][1]) == length(tt) + end + end + + r.Di = Di + r.I = I + r.St = St + r.S3 = S3 + + return r +end + +# I think this gives a transversal chain ??? +# can streamline wrt tUU / last_tUU +function _induce_chain(V, Tm, C ; conj=nothing) + # Tm is a MAP: transversal map for C[1][1]/V + # assert V subgroup C[1][1] + c = [ (subgroup(V, []), [one(V)]) ] + conj===nothing && (conj = one(C[1][1])) + last_tUU = [ one(C[end][1]) ] + tUU = change_universe(last_tUU, C[1][1]) # - unnecessary??? + tU = [ Tm( one(universe(codomain(Tm)))^inv(conj) ) ] # isn't this just Tm(1)? + for i in (length(C)-1):-1:1 + U = intersect(C[i][1], V) + tUU = change_universe(last_tUU, C[i][1]) + tV = [] + change_universe!(last_tUU, C[i][1]) + for t in last_tUU, s in C[i][2] + x = t*s + if x in V + append!(tV, x) + length(tU)*length(tV) == length(last_tUU)*length(C[i][2]) && break + else + xx = Tm(x^inv(conj)) + if ~(xx in tU) + include!(tU, xx) + append!(tUU, x) + length(tU)*length(tV) == length(tUU)*length(C[i][2]) && break + end + end + end + # assert length(tV) == index(U, c[end][1]) + # assert length(tU) == index(C[i][1], U) + # assert length(tU)*length(tV) == length(last_tUU)*length(C[i][2]) + + last_tUU = tUU + length(tV) != 1 && append!(c, (U, tV) ) + end + + return reverse(c), tUU +end + +function get_transversal_chain(U) + c = [U] + while length(U) != 1 + I = support(U) + U = stabilizer(U, rep(I)) + append!(c, U) + end + C = [] + for i in 1:(length(c)-1) + append!(C, (c[i], transversal(c[i], c[i+1])) ) + end + append!(C, (c[end], [one(c[end])]) ) + + return C +end + +function get_rep(g, rec) + F = rec.F + if F!==nothing + rec = F[end] + else + F = [] + RR = rec + while is_assigned(rec.last) + append!(F, rec) + rec = rec.last + end + # check fuckery with "F" + end + + dim1 = one(R.Ai) + uim1 = dim1 + for i in length(F):-1:1 + F = F[i] + if order(R.Ai) < order(R.Aim1) + t = R.mT(g*inv(dim1*uim1)) + p = position(R.I, t*dim1) + else + p = position(R.I, dim1) + end + d = R.S3[p][1] + u = R.S3[p][2] + dim1 = d + uim1 = u*uim1 + end + + return dim1, uim1 +end + + +end From 425e9b755fd8e6fcdb65ff78291ad53c448f4404 Mon Sep 17 00:00:00 2001 From: Morgan Rodgers Date: Tue, 17 Mar 2026 20:38:00 +0100 Subject: [PATCH 03/23] progress --- experimental/LadderGame/src/LadderGame.jl | 98 +++++++++++++++-------- 1 file changed, 64 insertions(+), 34 deletions(-) diff --git a/experimental/LadderGame/src/LadderGame.jl b/experimental/LadderGame/src/LadderGame.jl index 0c0264856e11..cf0f963aee8f 100644 --- a/experimental/LadderGame/src/LadderGame.jl +++ b/experimental/LadderGame/src/LadderGame.jl @@ -10,6 +10,24 @@ module LadderGame using Oscar +struct LadderData + A::PermGroup + Aprev::PermGroup + T::Vector + Tmap::Map + D::Vector + St::Vector + I::Vector + m::Map + + function LadderData(A, Aprev) + rec = new() + rec.A = A + rec.Aprev = Aprev + return rec + end +end + # Compute A\G/U # we need: a subgroup ladder L = (A_i)_(0<=i<=a) # Need a transversal chain for U: @@ -20,7 +38,7 @@ using Oscar # Test functions: For each i with A_i+1 <= A_i, # tau_i : A_i+1\A_i >-> NN (injection) function ladder_game(L, G, U) - r = ladder_start(G, U) + r = _ladder_start(G, U) H = L[1] for i in 2:length(L) if is_subgroup(H, L[i]) @@ -33,19 +51,18 @@ function ladder_game(L, G, U) return r end -function ladder_start(G, U) +function _ladder_start(G, U) st = [get_transversal_chain(U)] - r = LadderData( - # Ai = G - # T = [ one(G) ] - # mT = ** map G ->G, x :-> one(G) ** - # I = [ one(G) ] - # S3 = [ (one(G), one(G)) ] - # Di = [ one(G) ] - # St = st - # g,s for env variable "F" set to false - ) - # what about this environment variable "F" set to false? + r = LadderData(G,G) + r.T = [one(G)] + r.Tmap = [ map_from_func(G, G, x -> one(G)) ] + r.D = [one(G)] + r.St = [st] + r.I = [one(G)] + r.m = map_from_func(r.I, (r.D, U), x -> (one(G), one(U))) + # g,s for env variable "F" set to nothing + # what about this environment variable "F" set to nothing? + return r end @@ -106,7 +123,7 @@ function up_step(A, U, rec) # g,s for ev variable "F" set to false ) - T, mT = transversal(A, R.Ai) + T, mT = transversal(A, rec.Ai) r.T = T r.mT = mT Di = [] @@ -159,19 +176,30 @@ end # I think this gives a transversal chain ??? # can streamline wrt tUU / last_tUU -function _induce_chain(V, Tm, C ; conj=nothing) +function _induce_chain(V, Tm, C ; conj=one(C[1][1])) # Tm is a MAP: transversal map for C[1][1]/V - # assert V subgroup C[1][1] - c = [ (subgroup(V, []), [one(V)]) ] - conj===nothing && (conj = one(C[1][1])) + # assert is_subgroup(V, C[1][1]) + + + + + + + c = Tuple{PermGroup, Vector{PermGroupElem}}[ (sub(V, [one(V)])[1], [one(V)]) ] + # conj===nothing && (conj = one(C[1][1])) + # last_tUU = [ one(C[end][1]) ] - tUU = change_universe(last_tUU, C[1][1]) # - unnecessary??? + # tUU = change_universe(last_tUU, C[1][1]) # - unnecessary??? + tUU = copy(last_tUU) tU = [ Tm( one(universe(codomain(Tm)))^inv(conj) ) ] # isn't this just Tm(1)? + for i in (length(C)-1):-1:1 - U = intersect(C[i][1], V) tUU = change_universe(last_tUU, C[i][1]) - tV = [] change_universe!(last_tUU, C[i][1]) + + U = intersect(C[i][1], V) + tV = [] + for t in last_tUU, s in C[i][2] x = t*s if x in V @@ -197,23 +225,25 @@ function _induce_chain(V, Tm, C ; conj=nothing) return reverse(c), tUU end -function get_transversal_chain(U) - c = [U] - while length(U) != 1 - I = support(U) - U = stabilizer(U, rep(I)) - append!(c, U) - end - C = [] - for i in 1:(length(c)-1) - append!(C, (c[i], transversal(c[i], c[i+1])) ) +function get_transversal_chain(U::PermGroup) + # c = PermGroup[U] + U0 = U + C = Tuple{PermGroup, Vector{PermGroupElem}}[] + while length(U0) != 1 + s = first(moved_points(U0)) + U = stabilizer(U0, s)[1] + T = right_transversal(U0, U) + push!(C, (U0, T) ) + U0 = U end - append!(C, (c[end], [one(c[end])]) ) - + push!(C, (U0, [one(U0)])) return C end -function get_rep(g, rec) + + + +function _get_rep(g, rec) F = rec.F if F!==nothing rec = F[end] From f36bc62cc08ad90f85b849e3daaffad9f999c5d0 Mon Sep 17 00:00:00 2001 From: Morgan Rodgers Date: Tue, 24 Mar 2026 16:50:42 +0100 Subject: [PATCH 04/23] Add methods for Young subgroups / ladder --- experimental/LadderGame/src/LadderGame.jl | 42 ++++++++++++++++++++--- 1 file changed, 38 insertions(+), 4 deletions(-) diff --git a/experimental/LadderGame/src/LadderGame.jl b/experimental/LadderGame/src/LadderGame.jl index cf0f963aee8f..640d84af20c8 100644 --- a/experimental/LadderGame/src/LadderGame.jl +++ b/experimental/LadderGame/src/LadderGame.jl @@ -37,7 +37,7 @@ end # T_i in R(A_i\A_i+1) or R(A_i+1\A_i) as appropriate # Test functions: For each i with A_i+1 <= A_i, # tau_i : A_i+1\A_i >-> NN (injection) -function ladder_game(L, G, U) +function ladder_game(L, G::PermGroup, U::PermGroup) r = _ladder_start(G, U) H = L[1] for i in 2:length(L) @@ -51,7 +51,7 @@ function ladder_game(L, G, U) return r end -function _ladder_start(G, U) +function _ladder_start(G::PermGroup, U::PermGroup) st = [get_transversal_chain(U)] r = LadderData(G,G) r.T = [one(G)] @@ -66,7 +66,7 @@ function _ladder_start(G, U) return r end -function down_step(A, U, rec) +function down_step(A::PermGroup, U::PermGroup, rec::LadderData) r = LadderData( # Ai = A # Aim1 = rec.Ai @@ -115,7 +115,7 @@ function down_step(A, U, rec) return r end -function up_step(A, U, rec) +function up_step(A::PermGroup, U::PermGroup, rec::LadderData) r = LadderData( # Ai = A # Aim1 = rec.Ai @@ -276,5 +276,39 @@ function _get_rep(g, rec) return dim1, uim1 end +function young_subgroup(p::Vector{T} ; full::T=sum(p)) where T<:IntegerUnion + s = full - sum(p) + # should error if s < 0 + s == 0 && return inner_direct_product([symmetric_group(i) for i in p]) + return inner_direct_product([symmetric_group(i) for i in vcat(p, ones(T, s))]) +end + + +function young_subgroup_ladder( p::Vector{T} ; full::T=sum(p)) where T<:IntegerUnion + n = sum(p) + s = n - p[1] + L = PermGroup[] + pp = copy(p) + while s!=0 + if p[2]==1 + deleteat!(pp, 2) + pp[1]+=1 + prepend!(L, young_subgroup(pp ; full=full)) + else + prepend!(L, young_subgroup(pp ; full=full)) + pp[2]-=1 + insert!(pp,2,1) + prepend!(L, young_subgroup(pp ; full=full)) + deleteat!(pp, 2) + pp[1]+=1 + end + s = n-pp[1] + end + prepend!(L, young_subgroup([pp[1]] ; full=full)) + + return L +end + + end From d0ecf54b8fe809571483578a3216f15279343fbf Mon Sep 17 00:00:00 2001 From: Morgan Rodgers Date: Wed, 1 Apr 2026 11:01:27 +0200 Subject: [PATCH 05/23] better types --- experimental/LadderGame/src/LadderGame.jl | 66 +++++++++++++++++++---- 1 file changed, 56 insertions(+), 10 deletions(-) diff --git a/experimental/LadderGame/src/LadderGame.jl b/experimental/LadderGame/src/LadderGame.jl index 640d84af20c8..e153166aae59 100644 --- a/experimental/LadderGame/src/LadderGame.jl +++ b/experimental/LadderGame/src/LadderGame.jl @@ -20,7 +20,7 @@ struct LadderData I::Vector m::Map - function LadderData(A, Aprev) + function LadderData(A::PermGroup, Aprev::PermGroup) rec = new() rec.A = A rec.Aprev = Aprev @@ -276,39 +276,85 @@ function _get_rep(g, rec) return dim1, uim1 end -function young_subgroup(p::Vector{T} ; full::T=sum(p)) where T<:IntegerUnion +function young_subgroup(p::Vector{T} ; full::T=sum(p)) where T<:Integer s = full - sum(p) # should error if s < 0 s == 0 && return inner_direct_product([symmetric_group(i) for i in p]) return inner_direct_product([symmetric_group(i) for i in vcat(p, ones(T, s))]) end - -function young_subgroup_ladder( p::Vector{T} ; full::T=sum(p)) where T<:IntegerUnion +# Test method - groups only +# works - matches Magma +function _young_subgroup_ladder( p::Vector{T} ; full::T=sum(p)) where T<:Integer n = sum(p) - s = n - p[1] L = PermGroup[] pp = copy(p) + pushfirst!(L, young_subgroup(pp ; full=full)) + s = n - pp[1] while s!=0 - if p[2]==1 + if pp[2]==1 deleteat!(pp, 2) pp[1]+=1 - prepend!(L, young_subgroup(pp ; full=full)) else - prepend!(L, young_subgroup(pp ; full=full)) pp[2]-=1 insert!(pp,2,1) - prepend!(L, young_subgroup(pp ; full=full)) + pushfirst!(L, young_subgroup(pp ; full=full)) deleteat!(pp, 2) pp[1]+=1 end + pushfirst!(L, young_subgroup(pp ; full=full)) s = n-pp[1] end - prepend!(L, young_subgroup([pp[1]] ; full=full)) return L end + + + + +function young_subgroup_ladder( p::Vector{T} ; full::T=sum(p)) where T<:Integer + n = sum(p) + L = LadderData[] + pp = copy(p) + H = young_subgroup(pp ; full=full) + s = n - pp[1] + while s!=0 + if pp[2]==1 + + Hprev = H + deleteat!(pp, 2) + pp[1]+=1 + H = young_subgroup(pp ; full=full) + pushfirst!(L, young_subgroup(pp ; full=full)) + + else + + Hprev = H + pp[2]-=1 + insert!(pp,2,1) + H = young_subgroup(pp ; full=full) + pushfirst!(L, young_subgroup(pp ; full=full)) + + + Hprev = H + deleteat!(pp, 2) + pp[1]+=1 + H = young_subgroup(pp ; full=full) + pushfirst!(L, young_subgroup(pp ; full=full)) + + end + s = n-pp[1] + end + + return L +end + + + + + + end From afafae499c10a230d0fa77e38b06650617431066 Mon Sep 17 00:00:00 2001 From: Morgan Rodgers Date: Mon, 6 Jul 2026 12:44:09 +0200 Subject: [PATCH 06/23] improve file structure --- experimental/LadderGame/src/LadderGame.jl | 349 +----------------- .../LadderGame/src/LadderGameTypes.jl | 17 + experimental/LadderGame/src/main.jl | 324 ++++++++++++++++ 3 files changed, 343 insertions(+), 347 deletions(-) create mode 100644 experimental/LadderGame/src/LadderGameTypes.jl create mode 100644 experimental/LadderGame/src/main.jl diff --git a/experimental/LadderGame/src/LadderGame.jl b/experimental/LadderGame/src/LadderGame.jl index e153166aae59..13247343c067 100644 --- a/experimental/LadderGame/src/LadderGame.jl +++ b/experimental/LadderGame/src/LadderGame.jl @@ -9,352 +9,7 @@ module LadderGame using Oscar - -struct LadderData - A::PermGroup - Aprev::PermGroup - T::Vector - Tmap::Map - D::Vector - St::Vector - I::Vector - m::Map - - function LadderData(A::PermGroup, Aprev::PermGroup) - rec = new() - rec.A = A - rec.Aprev = Aprev - return rec - end -end - -# Compute A\G/U -# we need: a subgroup ladder L = (A_i)_(0<=i<=a) -# Need a transversal chain for U: -# subgroup chain (U_i)_(0<=i<=k) -# transversals (S_i)_(0-> NN (injection) -function ladder_game(L, G::PermGroup, U::PermGroup) - r = _ladder_start(G, U) - H = L[1] - for i in 2:length(L) - if is_subgroup(H, L[i]) - r = up_step(L[i],U,r) - else - r = down_step(L[i], U, r) - end - H = L[i] - end - return r -end - -function _ladder_start(G::PermGroup, U::PermGroup) - st = [get_transversal_chain(U)] - r = LadderData(G,G) - r.T = [one(G)] - r.Tmap = [ map_from_func(G, G, x -> one(G)) ] - r.D = [one(G)] - r.St = [st] - r.I = [one(G)] - r.m = map_from_func(r.I, (r.D, U), x -> (one(G), one(U))) - # g,s for env variable "F" set to nothing - # what about this environment variable "F" set to nothing? - - return r -end - -function down_step(A::PermGroup, U::PermGroup, rec::LadderData) - r = LadderData( - # Ai = A - # Aim1 = rec.Ai - # last = rec - # g,s for ev variable "F" set to false - ) - T, mT = transversal(rec.Ai, A) - r.T = T - r.mT = mT - Di = [] - S3 = [] - St = [] - I = [] - for a in rec.Di - tmp = [] - for t in T - if ~(t in tmp) - d = t*a - st = rec.St[a] - S1 = intersect(U, A^d) - S2 = intersect(U, R.Ai^a) - # assert S1 subset S2 - # assert st[1][1] == S2 - # assert S2 == intersect(U, R.Ai^d) - st, Sta = _induce_chain(S1, mT, st ; conj=d) - # assert length(Sta) == Index(S2, S1) - _, ss = transversal(S2, S1) - # assert length({ss(x) : x in Sta}) == #Sta - append!(Di,d) - append!(St, st) - for u in Sta - tt = mT(d*u*inv(a)) - include!(tmp, tt) - include!(I, tt*a) - append!(S3, (d,u) ) - # assert tt*a*inv(u)*inv(d) in A - end - end - end - # assert T == tmp - end - r.Di = Di - r.I = I - r.S3 = S3 - r.St = St - return r -end - -function up_step(A::PermGroup, U::PermGroup, rec::LadderData) - r = LadderData( - # Ai = A - # Aim1 = rec.Ai - # last = rec - # g,s for ev variable "F" set to false - ) - - T, mT = transversal(A, rec.Ai) - r.T = T - r.mT = mT - Di = [] - S3 = [] - St = [] - I = [] - - seen = [] - data = [] - cls = [] - cls_data = [] - - for a in rec.Di - if a in cls - p = index(cls, a) - rep = cls_data[p][1] - rep_u = cls_data[p][2] - new = false - else - rep = nothing - new = true - end - - tt = [] - for t in T - (~new && ~is_one(t)) && continue - ta = t*a - at, ut = _get_rep(ta, rec) - # assert ta*inv(ut)*inv(at) in r.Aim1 - # assert at in rec.Di - rep===nothing && (rep=at, rep_u = ut) - at in cls || (include!(cls, at), append!(cls_data, (rep, rep_u*inv(ut)) )) - at == rep && append!(tt, ut*inv(rep_u)) - is_one(t) && (include!(I, a), append!(S3, (rep, rep_u*inv(ut)) )) - end - if new - append!(Di, rep) - append!(St, [[ (intersect(A^rep, U), tt) ] rec.St[rep]] ) # in magma code: rec.St[Position(R.Di, rep)] - # assert Index(St[end][1][1], St[end][2][1]) == length(tt) - end - end - - r.Di = Di - r.I = I - r.St = St - r.S3 = S3 - - return r -end - -# I think this gives a transversal chain ??? -# can streamline wrt tUU / last_tUU -function _induce_chain(V, Tm, C ; conj=one(C[1][1])) - # Tm is a MAP: transversal map for C[1][1]/V - # assert is_subgroup(V, C[1][1]) - - - - - - - c = Tuple{PermGroup, Vector{PermGroupElem}}[ (sub(V, [one(V)])[1], [one(V)]) ] - # conj===nothing && (conj = one(C[1][1])) - # - last_tUU = [ one(C[end][1]) ] - # tUU = change_universe(last_tUU, C[1][1]) # - unnecessary??? - tUU = copy(last_tUU) - tU = [ Tm( one(universe(codomain(Tm)))^inv(conj) ) ] # isn't this just Tm(1)? - - for i in (length(C)-1):-1:1 - tUU = change_universe(last_tUU, C[i][1]) - change_universe!(last_tUU, C[i][1]) - - U = intersect(C[i][1], V) - tV = [] - - for t in last_tUU, s in C[i][2] - x = t*s - if x in V - append!(tV, x) - length(tU)*length(tV) == length(last_tUU)*length(C[i][2]) && break - else - xx = Tm(x^inv(conj)) - if ~(xx in tU) - include!(tU, xx) - append!(tUU, x) - length(tU)*length(tV) == length(tUU)*length(C[i][2]) && break - end - end - end - # assert length(tV) == index(U, c[end][1]) - # assert length(tU) == index(C[i][1], U) - # assert length(tU)*length(tV) == length(last_tUU)*length(C[i][2]) - - last_tUU = tUU - length(tV) != 1 && append!(c, (U, tV) ) - end - - return reverse(c), tUU -end - -function get_transversal_chain(U::PermGroup) - # c = PermGroup[U] - U0 = U - C = Tuple{PermGroup, Vector{PermGroupElem}}[] - while length(U0) != 1 - s = first(moved_points(U0)) - U = stabilizer(U0, s)[1] - T = right_transversal(U0, U) - push!(C, (U0, T) ) - U0 = U - end - push!(C, (U0, [one(U0)])) - return C -end - - - - -function _get_rep(g, rec) - F = rec.F - if F!==nothing - rec = F[end] - else - F = [] - RR = rec - while is_assigned(rec.last) - append!(F, rec) - rec = rec.last - end - # check fuckery with "F" - end - - dim1 = one(R.Ai) - uim1 = dim1 - for i in length(F):-1:1 - F = F[i] - if order(R.Ai) < order(R.Aim1) - t = R.mT(g*inv(dim1*uim1)) - p = position(R.I, t*dim1) - else - p = position(R.I, dim1) - end - d = R.S3[p][1] - u = R.S3[p][2] - dim1 = d - uim1 = u*uim1 - end - - return dim1, uim1 -end - -function young_subgroup(p::Vector{T} ; full::T=sum(p)) where T<:Integer - s = full - sum(p) - # should error if s < 0 - s == 0 && return inner_direct_product([symmetric_group(i) for i in p]) - return inner_direct_product([symmetric_group(i) for i in vcat(p, ones(T, s))]) -end - -# Test method - groups only -# works - matches Magma -function _young_subgroup_ladder( p::Vector{T} ; full::T=sum(p)) where T<:Integer - n = sum(p) - L = PermGroup[] - pp = copy(p) - pushfirst!(L, young_subgroup(pp ; full=full)) - s = n - pp[1] - while s!=0 - if pp[2]==1 - deleteat!(pp, 2) - pp[1]+=1 - else - pp[2]-=1 - insert!(pp,2,1) - pushfirst!(L, young_subgroup(pp ; full=full)) - deleteat!(pp, 2) - pp[1]+=1 - end - pushfirst!(L, young_subgroup(pp ; full=full)) - s = n-pp[1] - end - - return L -end - - - - - - - -function young_subgroup_ladder( p::Vector{T} ; full::T=sum(p)) where T<:Integer - n = sum(p) - L = LadderData[] - pp = copy(p) - H = young_subgroup(pp ; full=full) - s = n - pp[1] - while s!=0 - if pp[2]==1 - - Hprev = H - deleteat!(pp, 2) - pp[1]+=1 - H = young_subgroup(pp ; full=full) - pushfirst!(L, young_subgroup(pp ; full=full)) - - else - - Hprev = H - pp[2]-=1 - insert!(pp,2,1) - H = young_subgroup(pp ; full=full) - pushfirst!(L, young_subgroup(pp ; full=full)) - - - Hprev = H - deleteat!(pp, 2) - pp[1]+=1 - H = young_subgroup(pp ; full=full) - pushfirst!(L, young_subgroup(pp ; full=full)) - - end - s = n-pp[1] - end - - return L -end - - - - - +include("LadderGameTypes.jl") +include("main.jl") end diff --git a/experimental/LadderGame/src/LadderGameTypes.jl b/experimental/LadderGame/src/LadderGameTypes.jl new file mode 100644 index 000000000000..59d8a99f7e27 --- /dev/null +++ b/experimental/LadderGame/src/LadderGameTypes.jl @@ -0,0 +1,17 @@ +struct LadderData + A::PermGroup + Aprev::PermGroup + T::Vector + Tmap::Map + D::Vector + St::Vector + I::Vector + m::Map + + function LadderData(A::PermGroup, Aprev::PermGroup) + rec = new() + rec.A = A + rec.Aprev = Aprev + return rec + end +end diff --git a/experimental/LadderGame/src/main.jl b/experimental/LadderGame/src/main.jl new file mode 100644 index 000000000000..5f87c4cc79c7 --- /dev/null +++ b/experimental/LadderGame/src/main.jl @@ -0,0 +1,324 @@ + +# Compute A\G/U +# we need: a subgroup ladder L = (A_i)_(0<=i<=a) +# Need a transversal chain for U: +# subgroup chain (U_i)_(0<=i<=k) +# transversals (S_i)_(0-> NN (injection) +function ladder_game(L, G::PermGroup, U::PermGroup) + r = _ladder_start(G, U) + H = L[1] + for i in 2:length(L) + if is_subgroup(H, L[i]) + r = up_step(L[i],U,r) + else + r = down_step(L[i], U, r) + end + H = L[i] + end + return r +end + +function _ladder_start(G::PermGroup, U::PermGroup) + st = [get_transversal_chain(U)] + r = LadderData(G,G) + r.T = [one(G)] + r.Tmap = [ map_from_func(G, G, x -> one(G)) ] + r.D = [one(G)] + r.St = [st] + r.I = [one(G)] + r.m = map_from_func(r.I, (r.D, U), x -> (one(G), one(U))) + # g,s for env variable "F" set to nothing + # what about this environment variable "F" set to nothing? + + return r +end + +function down_step(A::PermGroup, U::PermGroup, rec::LadderData) + r = LadderData( + # Ai = A + # Aim1 = rec.Ai + # last = rec + # g,s for ev variable "F" set to false + ) + T, mT = transversal(rec.Ai, A) + r.T = T + r.mT = mT + Di = [] + S3 = [] + St = [] + I = [] + for a in rec.Di + tmp = [] + for t in T + if ~(t in tmp) + d = t*a + st = rec.St[a] + S1 = intersect(U, A^d) + S2 = intersect(U, R.Ai^a) + # assert S1 subset S2 + # assert st[1][1] == S2 + # assert S2 == intersect(U, R.Ai^d) + st, Sta = _induce_chain(S1, mT, st ; conj=d) + # assert length(Sta) == Index(S2, S1) + _, ss = transversal(S2, S1) + # assert length({ss(x) : x in Sta}) == #Sta + append!(Di,d) + append!(St, st) + for u in Sta + tt = mT(d*u*inv(a)) + include!(tmp, tt) + include!(I, tt*a) + append!(S3, (d,u) ) + # assert tt*a*inv(u)*inv(d) in A + end + end + end + # assert T == tmp + end + r.Di = Di + r.I = I + r.S3 = S3 + r.St = St + return r +end + +function up_step(A::PermGroup, U::PermGroup, rec::LadderData) + r = LadderData( + # Ai = A + # Aim1 = rec.Ai + # last = rec + # g,s for ev variable "F" set to false + ) + + T, mT = transversal(A, rec.Ai) + r.T = T + r.mT = mT + Di = [] + S3 = [] + St = [] + I = [] + + seen = [] + data = [] + cls = [] + cls_data = [] + + for a in rec.Di + if a in cls + p = index(cls, a) + rep = cls_data[p][1] + rep_u = cls_data[p][2] + new = false + else + rep = nothing + new = true + end + + tt = [] + for t in T + (~new && ~is_one(t)) && continue + ta = t*a + at, ut = _get_rep(ta, rec) + # assert ta*inv(ut)*inv(at) in r.Aim1 + # assert at in rec.Di + rep===nothing && (rep=at, rep_u = ut) + at in cls || (include!(cls, at), append!(cls_data, (rep, rep_u*inv(ut)) )) + at == rep && append!(tt, ut*inv(rep_u)) + is_one(t) && (include!(I, a), append!(S3, (rep, rep_u*inv(ut)) )) + end + if new + append!(Di, rep) + append!(St, [[ (intersect(A^rep, U), tt) ] rec.St[rep]] ) # in magma code: rec.St[Position(R.Di, rep)] + # assert Index(St[end][1][1], St[end][2][1]) == length(tt) + end + end + + r.Di = Di + r.I = I + r.St = St + r.S3 = S3 + + return r +end + +# I think this gives a transversal chain ??? +# can streamline wrt tUU / last_tUU +function _induce_chain(V, Tm, C ; conj=one(C[1][1])) + # Tm is a MAP: transversal map for C[1][1]/V + # assert is_subgroup(V, C[1][1]) + + + + + + + c = Tuple{PermGroup, Vector{PermGroupElem}}[ (sub(V, [one(V)])[1], [one(V)]) ] + # conj===nothing && (conj = one(C[1][1])) + # + last_tUU = [ one(C[end][1]) ] + # tUU = change_universe(last_tUU, C[1][1]) # - unnecessary??? + tUU = copy(last_tUU) + tU = [ Tm( one(universe(codomain(Tm)))^inv(conj) ) ] # isn't this just Tm(1)? + + for i in (length(C)-1):-1:1 + tUU = change_universe(last_tUU, C[i][1]) + change_universe!(last_tUU, C[i][1]) + + U = intersect(C[i][1], V) + tV = [] + + for t in last_tUU, s in C[i][2] + x = t*s + if x in V + append!(tV, x) + length(tU)*length(tV) == length(last_tUU)*length(C[i][2]) && break + else + xx = Tm(x^inv(conj)) + if ~(xx in tU) + include!(tU, xx) + append!(tUU, x) + length(tU)*length(tV) == length(tUU)*length(C[i][2]) && break + end + end + end + # assert length(tV) == index(U, c[end][1]) + # assert length(tU) == index(C[i][1], U) + # assert length(tU)*length(tV) == length(last_tUU)*length(C[i][2]) + + last_tUU = tUU + length(tV) != 1 && append!(c, (U, tV) ) + end + + return reverse(c), tUU +end + +function get_transversal_chain(U::PermGroup) + # c = PermGroup[U] + U0 = U + C = Tuple{PermGroup, Vector{PermGroupElem}}[] + while length(U0) != 1 + s = first(moved_points(U0)) + U = stabilizer(U0, s)[1] + T = right_transversal(U0, U) + push!(C, (U0, T) ) + U0 = U + end + push!(C, (U0, [one(U0)])) + return C +end + + + + +function _get_rep(g, rec) + F = rec.F + if F!==nothing + rec = F[end] + else + F = [] + RR = rec + while is_assigned(rec.last) + append!(F, rec) + rec = rec.last + end + # check fuckery with "F" + end + + dim1 = one(R.Ai) + uim1 = dim1 + for i in length(F):-1:1 + F = F[i] + if order(R.Ai) < order(R.Aim1) + t = R.mT(g*inv(dim1*uim1)) + p = position(R.I, t*dim1) + else + p = position(R.I, dim1) + end + d = R.S3[p][1] + u = R.S3[p][2] + dim1 = d + uim1 = u*uim1 + end + + return dim1, uim1 +end + +function young_subgroup(p::Vector{T} ; full::T=sum(p)) where T<:Integer + s = full - sum(p) + # should error if s < 0 + s == 0 && return inner_direct_product([symmetric_group(i) for i in p]) + return inner_direct_product([symmetric_group(i) for i in vcat(p, ones(T, s))]) +end + +# Test method - groups only +# works - matches Magma +function _young_subgroup_ladder( p::Vector{T} ; full::T=sum(p)) where T<:Integer + n = sum(p) + L = PermGroup[] + pp = copy(p) + pushfirst!(L, young_subgroup(pp ; full=full)) + s = n - pp[1] + while s!=0 + if pp[2]==1 + deleteat!(pp, 2) + pp[1]+=1 + else + pp[2]-=1 + insert!(pp,2,1) + pushfirst!(L, young_subgroup(pp ; full=full)) + deleteat!(pp, 2) + pp[1]+=1 + end + pushfirst!(L, young_subgroup(pp ; full=full)) + s = n-pp[1] + end + + return L +end + + + + + + + +function young_subgroup_ladder( p::Vector{T} ; full::T=sum(p)) where T<:Integer + n = sum(p) + L = LadderData[] + pp = copy(p) + H = young_subgroup(pp ; full=full) + s = n - pp[1] + while s!=0 + if pp[2]==1 + + Hprev = H + deleteat!(pp, 2) + pp[1]+=1 + H = young_subgroup(pp ; full=full) + pushfirst!(L, young_subgroup(pp ; full=full)) + + else + + Hprev = H + pp[2]-=1 + insert!(pp,2,1) + H = young_subgroup(pp ; full=full) + pushfirst!(L, young_subgroup(pp ; full=full)) + + + Hprev = H + deleteat!(pp, 2) + pp[1]+=1 + H = young_subgroup(pp ; full=full) + pushfirst!(L, young_subgroup(pp ; full=full)) + + end + s = n-pp[1] + end + + return L +end From fb2411399bd0948156b3fe866b24b7a63053f998 Mon Sep 17 00:00:00 2001 From: Morgan Rodgers Date: Mon, 6 Jul 2026 16:55:04 +0200 Subject: [PATCH 07/23] work on types --- .../LadderGame/src/LadderGameTypes.jl | 57 ++++++++++++++++++- experimental/LadderGame/src/main.jl | 12 ++-- 2 files changed, 61 insertions(+), 8 deletions(-) diff --git a/experimental/LadderGame/src/LadderGameTypes.jl b/experimental/LadderGame/src/LadderGameTypes.jl index 59d8a99f7e27..0fc59f38ca50 100644 --- a/experimental/LadderGame/src/LadderGameTypes.jl +++ b/experimental/LadderGame/src/LadderGameTypes.jl @@ -1,4 +1,5 @@ -struct LadderData +struct LadderStep + is_up_step::Bool A::PermGroup Aprev::PermGroup T::Vector @@ -8,10 +9,62 @@ struct LadderData I::Vector m::Map - function LadderData(A::PermGroup, Aprev::PermGroup) + function LadderStep(A::PermGroup, Aprev::PermGroup) rec = new() + if is_subset(Aprev, A) + rec.is_up_step = true + elseif is_subset(Aprev, A) + rec.is_up_step = false + else + # throw an error + end rec.A = A rec.Aprev = Aprev + # construct T / Tmap or do this only when needed? return rec end + + function LadderStep(A::PermGroup, Aprev::PermGroup, T::Vector) + rec = new() + if is_subset(Aprev, A) + rec.is_up_step = true + elseif is_subset(Aprev, A) + rec.is_up_step = false + else + # throw an error + end + rec.A = A + rec.Aprev = Aprev + rec.T = T + # construct a tmap + return rec + end + + function LadderStep(A::PermGroup, Aprev::PermGroup, T::Vector, Tmap::Map) + rec = new() + if is_subset(Aprev, A) + rec.is_up_step = true + elseif is_subset(Aprev, A) + rec.is_up_step = false + else + # throw an error + end + rec.A = A + rec.Aprev = Aprev + rec.T = T + rec.Tmap = Tmap + return rec + end + +end + + +struct SubgroupLadder + L::Vector{LadderStep} + + function SubgroupLadder(S::Vector{PermGroup}) + rec = new() + + rec.L = [ LadderStep(S[i+1], S[i])] + end end diff --git a/experimental/LadderGame/src/main.jl b/experimental/LadderGame/src/main.jl index 5f87c4cc79c7..058e2121c5a6 100644 --- a/experimental/LadderGame/src/main.jl +++ b/experimental/LadderGame/src/main.jl @@ -24,7 +24,7 @@ end function _ladder_start(G::PermGroup, U::PermGroup) st = [get_transversal_chain(U)] - r = LadderData(G,G) + r = LadderStep(G,G) r.T = [one(G)] r.Tmap = [ map_from_func(G, G, x -> one(G)) ] r.D = [one(G)] @@ -37,8 +37,8 @@ function _ladder_start(G::PermGroup, U::PermGroup) return r end -function down_step(A::PermGroup, U::PermGroup, rec::LadderData) - r = LadderData( +function down_step(A::PermGroup, U::PermGroup, rec::LadderStep) + r = LadderStep( # Ai = A # Aim1 = rec.Ai # last = rec @@ -86,8 +86,8 @@ function down_step(A::PermGroup, U::PermGroup, rec::LadderData) return r end -function up_step(A::PermGroup, U::PermGroup, rec::LadderData) - r = LadderData( +function up_step(A::PermGroup, U::PermGroup, rec::LadderStep) + r = LadderStep( # Ai = A # Aim1 = rec.Ai # last = rec @@ -288,7 +288,7 @@ end function young_subgroup_ladder( p::Vector{T} ; full::T=sum(p)) where T<:Integer n = sum(p) - L = LadderData[] + L = LadderStep[] pp = copy(p) H = young_subgroup(pp ; full=full) s = n - pp[1] From bc602f1a060d242c4bff86e9a282bf197528c559 Mon Sep 17 00:00:00 2001 From: Morgan Rodgers Date: Mon, 6 Jul 2026 16:55:22 +0200 Subject: [PATCH 08/23] comments --- experimental/LadderGame/src/main.jl | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/experimental/LadderGame/src/main.jl b/experimental/LadderGame/src/main.jl index 058e2121c5a6..96adadbe9d06 100644 --- a/experimental/LadderGame/src/main.jl +++ b/experimental/LadderGame/src/main.jl @@ -1,13 +1,16 @@ # Compute A\G/U +# TODO indices should start at 1... # we need: a subgroup ladder L = (A_i)_(0<=i<=a) -# Need a transversal chain for U: -# subgroup chain (U_i)_(0<=i<=k) -# transversals (S_i)_(0-> NN (injection) +# Need a transversal chain for U: +# subgroup chain (U_i)_(0<=i<=k) +# transversals (S_i)_(0 Date: Tue, 7 Jul 2026 13:42:42 +0200 Subject: [PATCH 09/23] improve types --- .../LadderGame/src/LadderGameTypes.jl | 45 +++++++++++++++++-- 1 file changed, 42 insertions(+), 3 deletions(-) diff --git a/experimental/LadderGame/src/LadderGameTypes.jl b/experimental/LadderGame/src/LadderGameTypes.jl index 0fc59f38ca50..b4257f7358cd 100644 --- a/experimental/LadderGame/src/LadderGameTypes.jl +++ b/experimental/LadderGame/src/LadderGameTypes.jl @@ -59,12 +59,51 @@ struct LadderStep end -struct SubgroupLadder - L::Vector{LadderStep} +# SubgroupLadder stores Vector{LadderStep} +# with some special tools for adding steps. + +struct SubgroupLadder <: AbstractVector{LadderStep} + S::Vector{LadderStep} function SubgroupLadder(S::Vector{PermGroup}) rec = new() - rec.L = [ LadderStep(S[i+1], S[i])] + rec.S = [ LadderStep(S[i+1], S[i])] end end + +data(L::SubgroupLadder) = L.S + +################################################################################ +# +# Array-like functionality +# +################################################################################ + +function Base.size(L::SubgroupLadder) + return size(data(L)) +end + +function Base.length(L::SubgroupLadder) + return length(data(L)) +end + +function Base.getindex(L::SubgroupLadder, i::IntegerUnion) + return getindex(data(L), Int(i)) +end + +# I don't think we want to support this +# function Base.setindex!(L::SubgroupLadder, s::LadderStep, i::IntegerUnion) +# return setindex!(data(L), s, Int(i)) +# end + +function Base.copy(L::SubgroupLadder) + return SubgroupLadder(copy(data(L))) +end + +function Base.push!(L::SubgroupLadder, s::LadderStep) + # require or assert that this is actually a step + @req last(L).A == s.Aprev "Incompatible LadderStep" + push!(L.S, s) + return L +end From 0352b7513164da53f5120287ed8008e54f7c080f Mon Sep 17 00:00:00 2001 From: Morgan Rodgers Date: Tue, 7 Jul 2026 15:34:55 +0200 Subject: [PATCH 10/23] fix imports from Oscar --- experimental/LadderGame/src/LadderGame.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/experimental/LadderGame/src/LadderGame.jl b/experimental/LadderGame/src/LadderGame.jl index 13247343c067..84beb8b8a482 100644 --- a/experimental/LadderGame/src/LadderGame.jl +++ b/experimental/LadderGame/src/LadderGame.jl @@ -7,7 +7,8 @@ module LadderGame -using Oscar +using ..Oscar +using ..Oscar: IntegerUnion include("LadderGameTypes.jl") include("main.jl") From da088ba906b760f90e497d48d58f23ccf1e83e6a Mon Sep 17 00:00:00 2001 From: Morgan Rodgers Date: Tue, 7 Jul 2026 15:47:02 +0200 Subject: [PATCH 11/23] use mutable structs --- experimental/LadderGame/src/LadderGameTypes.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/experimental/LadderGame/src/LadderGameTypes.jl b/experimental/LadderGame/src/LadderGameTypes.jl index b4257f7358cd..24bcae33fd40 100644 --- a/experimental/LadderGame/src/LadderGameTypes.jl +++ b/experimental/LadderGame/src/LadderGameTypes.jl @@ -1,4 +1,4 @@ -struct LadderStep +mutable struct LadderStep is_up_step::Bool A::PermGroup Aprev::PermGroup @@ -62,7 +62,7 @@ end # SubgroupLadder stores Vector{LadderStep} # with some special tools for adding steps. -struct SubgroupLadder <: AbstractVector{LadderStep} +mutable struct SubgroupLadder <: AbstractVector{LadderStep} S::Vector{LadderStep} function SubgroupLadder(S::Vector{PermGroup}) From 77898aad7ec9206f057b704b757022feeb0bf306 Mon Sep 17 00:00:00 2001 From: Morgan Rodgers Date: Tue, 7 Jul 2026 15:55:01 +0200 Subject: [PATCH 12/23] fix `_ladder_start` and `ladder_game` argument types --- experimental/LadderGame/src/main.jl | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/experimental/LadderGame/src/main.jl b/experimental/LadderGame/src/main.jl index 96adadbe9d06..1e3338cc472b 100644 --- a/experimental/LadderGame/src/main.jl +++ b/experimental/LadderGame/src/main.jl @@ -10,8 +10,10 @@ # Need a transversal chain for U: # subgroup chain (U_i)_(0<=i<=k) # transversals (S_i)_(0 one(G)) ] - r.D = [one(G)] - r.St = [st] - r.I = [one(G)] - r.m = map_from_func(r.I, (r.D, U), x -> (one(G), one(U))) - # g,s for env variable "F" set to nothing - # what about this environment variable "F" set to nothing? - - return r +function _ladder_start!(S::LadderStep, U::PermGroup) + @assert S.A == S.Aprev "Initial ladder step must be trivial" + isdefined(S, :T) || S.T = [one(S.A)] + isdefined(S, :Tmap) || S.Tmap = [map_from_func(G, G, x -> one(S.A))] + S.D = [one(S.A)] + S.St = [get_transversal_chain(U)] + S.I = [one(S.A)] + S.m = map_from_func(S.I, (S.D, U), x -> (one(S.A), one(U))) + return L end function down_step(A::PermGroup, U::PermGroup, rec::LadderStep) From a8b30f1278287402c7f671b8cd6d5d89e6bc9c89 Mon Sep 17 00:00:00 2001 From: Morgan Rodgers Date: Tue, 7 Jul 2026 17:40:59 +0200 Subject: [PATCH 13/23] minor --- .../LadderGame/src/LadderGameTypes.jl | 31 ++++++++++--------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/experimental/LadderGame/src/LadderGameTypes.jl b/experimental/LadderGame/src/LadderGameTypes.jl index 24bcae33fd40..00a815c3e1c3 100644 --- a/experimental/LadderGame/src/LadderGameTypes.jl +++ b/experimental/LadderGame/src/LadderGameTypes.jl @@ -1,43 +1,46 @@ mutable struct LadderStep is_up_step::Bool + A::PermGroup Aprev::PermGroup - T::Vector + + T::Vector{PermGroupElem} Tmap::Map + D::Vector St::Vector I::Vector m::Map function LadderStep(A::PermGroup, Aprev::PermGroup) - rec = new() + S = new() if is_subset(Aprev, A) - rec.is_up_step = true + S.is_up_step = true elseif is_subset(Aprev, A) - rec.is_up_step = false + S.is_up_step = false else # throw an error end - rec.A = A - rec.Aprev = Aprev + S.A = A + S.Aprev = Aprev # construct T / Tmap or do this only when needed? - return rec + return S end function LadderStep(A::PermGroup, Aprev::PermGroup, T::Vector) - rec = new() + S = new() if is_subset(Aprev, A) - rec.is_up_step = true + S.is_up_step = true elseif is_subset(Aprev, A) - rec.is_up_step = false + S.is_up_step = false else # throw an error end - rec.A = A - rec.Aprev = Aprev - rec.T = T + S.A = A + S.Aprev = Aprev + S.T = T # construct a tmap - return rec + return S end function LadderStep(A::PermGroup, Aprev::PermGroup, T::Vector, Tmap::Map) From 177a300f6ff3d5f77294be242b5d2382c42541c7 Mon Sep 17 00:00:00 2001 From: Morgan Rodgers Date: Wed, 8 Jul 2026 12:15:28 +0200 Subject: [PATCH 14/23] `L.T` for `LadderStep` should accept `SubgroupTransversal` type --- experimental/LadderGame/src/LadderGameTypes.jl | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/experimental/LadderGame/src/LadderGameTypes.jl b/experimental/LadderGame/src/LadderGameTypes.jl index 00a815c3e1c3..8586098d4d2a 100644 --- a/experimental/LadderGame/src/LadderGameTypes.jl +++ b/experimental/LadderGame/src/LadderGameTypes.jl @@ -1,10 +1,11 @@ mutable struct LadderStep is_up_step::Bool - A::PermGroup Aprev::PermGroup + A::PermGroup + - T::Vector{PermGroupElem} + T::Union{Vector{PermGroupElem}, Oscar.SubgroupTransversal} Tmap::Map D::Vector @@ -12,7 +13,7 @@ mutable struct LadderStep I::Vector m::Map - function LadderStep(A::PermGroup, Aprev::PermGroup) + function LadderStep(Aprev::PermGroup, A::PermGroup) S = new() if is_subset(Aprev, A) S.is_up_step = true @@ -27,7 +28,7 @@ mutable struct LadderStep return S end - function LadderStep(A::PermGroup, Aprev::PermGroup, T::Vector) + function LadderStep(Aprev::PermGroup, A::PermGroup, T::Vector) S = new() if is_subset(Aprev, A) S.is_up_step = true From 2aef03d2c9d9deed24c573f8d347b3444799bf5a Mon Sep 17 00:00:00 2001 From: Morgan Rodgers Date: Thu, 9 Jul 2026 10:09:34 +0200 Subject: [PATCH 15/23] fix LadderStep --- experimental/LadderGame/src/LadderGameTypes.jl | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/experimental/LadderGame/src/LadderGameTypes.jl b/experimental/LadderGame/src/LadderGameTypes.jl index 8586098d4d2a..23b9266bea5f 100644 --- a/experimental/LadderGame/src/LadderGameTypes.jl +++ b/experimental/LadderGame/src/LadderGameTypes.jl @@ -8,11 +8,16 @@ mutable struct LadderStep T::Union{Vector{PermGroupElem}, Oscar.SubgroupTransversal} Tmap::Map + # Should these also be a Dict?????? D::Vector St::Vector + + # TODO I/m should be implemented as a Dict I::Vector m::Map + F + function LadderStep(Aprev::PermGroup, A::PermGroup) S = new() if is_subset(Aprev, A) From f02012c2baae4cdd643fbfbeb4161f77273c073b Mon Sep 17 00:00:00 2001 From: Morgan Rodgers Date: Thu, 9 Jul 2026 10:33:25 +0200 Subject: [PATCH 16/23] revision --- .../LadderGame/src/LadderGameTypes.jl | 2 +- experimental/LadderGame/src/main.jl | 235 +++++++++--------- 2 files changed, 115 insertions(+), 122 deletions(-) diff --git a/experimental/LadderGame/src/LadderGameTypes.jl b/experimental/LadderGame/src/LadderGameTypes.jl index 23b9266bea5f..6aafebfc3f1b 100644 --- a/experimental/LadderGame/src/LadderGameTypes.jl +++ b/experimental/LadderGame/src/LadderGameTypes.jl @@ -14,7 +14,7 @@ mutable struct LadderStep # TODO I/m should be implemented as a Dict I::Vector - m::Map + m::Vector F diff --git a/experimental/LadderGame/src/main.jl b/experimental/LadderGame/src/main.jl index 1e3338cc472b..a86467af28f1 100644 --- a/experimental/LadderGame/src/main.jl +++ b/experimental/LadderGame/src/main.jl @@ -10,12 +10,10 @@ # Need a transversal chain for U: # subgroup chain (U_i)_(0<=i<=k) # transversals (S_i)_(0 one(S.A))] + isdefined(S, :T) || (S.T = [one(S.A)]) + isdefined(S, :Tmap) || (S.Tmap = map_from_func(S.A, S.A, x -> one(S.A))) S.D = [one(S.A)] S.St = [get_transversal_chain(U)] S.I = [one(S.A)] S.m = map_from_func(S.I, (S.D, U), x -> (one(S.A), one(U))) - return L + return S end -function down_step(A::PermGroup, U::PermGroup, rec::LadderStep) - r = LadderStep( - # Ai = A - # Aim1 = rec.Ai - # last = rec - # g,s for ev variable "F" set to false - ) - T, mT = transversal(rec.Ai, A) - r.T = T - r.mT = mT - Di = [] - S3 = [] +function down_step(S::LadderStep, Sprev::LadderStep, U::PermGroup) + A = S.A + Aprev = S.Aprev + + isdefined(S, :T) || (S.T = right_transversal(Aprev, A)) + isdefined(S, :Tmap) || (S.Tmap = map_from_func(Aprev, Aprev, x -> S.T[index_of_coset(T, x)])) + + T = S.T + + D = [] St = [] I = [] - for a in rec.Di - tmp = [] + S3 = [] + + for (i, a) in enumerate(Sprev.D) + tmp = PermGroupElem[] for t in T if ~(t in tmp) d = t*a - st = rec.St[a] - S1 = intersect(U, A^d) - S2 = intersect(U, R.Ai^a) - # assert S1 subset S2 - # assert st[1][1] == S2 - # assert S2 == intersect(U, R.Ai^d) - st, Sta = _induce_chain(S1, mT, st ; conj=d) - # assert length(Sta) == Index(S2, S1) - _, ss = transversal(S2, S1) - # assert length({ss(x) : x in Sta}) == #Sta - append!(Di,d) - append!(St, st) + st = Sprev.St[i] + S1, _ = intersect(U, A^d) + + # not used in calculation + S2, _ = intersect(U, Aprev^a) + @assert is_subset(S1, S2) + @assert st[1][1] == S2 + @assert S2 == intersect(U, Aprev^d)[1] + + st, Sta = _induce_chain(S1, S.Tmap, st ; conj=d) + + # not used in calculation + @assert length(Sta) == index(S2, S1) + Tss = right_transversal(S2, S1) + ss = map_from_func(S2, S2, x -> Tss[index_of_coset(Tss, x)]) + @assert allunique(map(x -> ss(S2(x)), Sta)) + + push!(D,d) + push!(St, st) for u in Sta - tt = mT(d*u*inv(a)) - include!(tmp, tt) - include!(I, tt*a) - append!(S3, (d,u) ) - # assert tt*a*inv(u)*inv(d) in A + tt = S.Tmap(Aprev(d*u*inv(a))) + push!(tmp, tt) + push!(I, tt*a) + push!(S3, (d,u) ) + @assert tt*a*inv(u)*inv(d) in A end end end - # assert T == tmp + @assert Set(collect(T)) == Set(tmp) end - r.Di = Di - r.I = I - r.S3 = S3 - r.St = St - return r + S.D = D + S.St = St + S.I = I + S.m = map_from_func(S.I, (S.D, U), x -> (one(S.A), one(U))) + # S.m = map_from_func(S.I, (S.D, U), x -> ) + # S3 # TODO this should be a map + # could we use a Dict I -> (S.D, U) ??? + return S end -function up_step(A::PermGroup, U::PermGroup, rec::LadderStep) - r = LadderStep( - # Ai = A - # Aim1 = rec.Ai - # last = rec - # g,s for ev variable "F" set to false - ) - - T, mT = transversal(A, rec.Ai) - r.T = T - r.mT = mT - Di = [] +function up_step(S::LadderStep, Sprev::LadderStep, U::PermGroup) + # A::PermGroup, U::PermGroup, rec::LadderStep) + # r = LadderStep( + # # Ai = A + # # Aim1 = rec.Ai + # # last = rec + # # g,s for ev variable "F" set to false + # ) + + A = S.A + Aprev = S.Aprev + + isdefined(S, :T) || (S.T = right_transversal(A, Aprev)) + isdefined(S, :Tmap) || (S.Tmap = map_from_func(A, A, x -> S.T[index_of_coset(T, x)])) + + T = S.T + + D = [] S3 = [] St = [] I = [] seen = [] data = [] + # TODO cls/cls_data should be Dict cls = [] cls_data = [] - for a in rec.Di + for a in Aprev.D if a in cls - p = index(cls, a) + p = findfirst(a, cls) rep = cls_data[p][1] rep_u = cls_data[p][2] new = false @@ -123,65 +138,63 @@ function up_step(A::PermGroup, U::PermGroup, rec::LadderStep) for t in T (~new && ~is_one(t)) && continue ta = t*a - at, ut = _get_rep(ta, rec) - # assert ta*inv(ut)*inv(at) in r.Aim1 - # assert at in rec.Di - rep===nothing && (rep=at, rep_u = ut) - at in cls || (include!(cls, at), append!(cls_data, (rep, rep_u*inv(ut)) )) - at == rep && append!(tt, ut*inv(rep_u)) - is_one(t) && (include!(I, a), append!(S3, (rep, rep_u*inv(ut)) )) + at, ut = _get_rep(ta, Aprev) + + @assert ta*inv(ut)*inv(at) in Aprev + @assert at in Sprev.D + + rep === nothing && (rep = at, rep_u = ut) + at in cls || (push!(cls, at), push!(cls_data, (rep, rep_u*inv(ut)) )) + at == rep && push!(tt, ut*inv(rep_u)) + is_one(t) && (push!(I, a), push!(S3, (rep, rep_u*inv(ut)) )) end if new - append!(Di, rep) - append!(St, [[ (intersect(A^rep, U), tt) ] rec.St[rep]] ) # in magma code: rec.St[Position(R.Di, rep)] + push!(D, rep) + push!(St, [[ (intersect(A^rep, U)[1], tt) ] Sprev.St[findfirst(rep, Aprev.D)]] ) # in magma code: rec.St[Position(R.Di, rep)] # assert Index(St[end][1][1], St[end][2][1]) == length(tt) end end - r.Di = Di - r.I = I - r.St = St - r.S3 = S3 + S.D = D + S.St = St - return r + S.I = I + # S.m = map_from_func(S.I, (S.D, U), x -> (one(S.A), one(U))) TODO fix + # S.S3 = S3 + + return S end # I think this gives a transversal chain ??? # can streamline wrt tUU / last_tUU -function _induce_chain(V, Tm, C ; conj=one(C[1][1])) +function _induce_chain(V::PermGroup, Tm::Map, C::Vector ; conj=one(C[1][1])) # Tm is a MAP: transversal map for C[1][1]/V - # assert is_subgroup(V, C[1][1]) - - - - - + @assert is_subset(V, C[1][1]) c = Tuple{PermGroup, Vector{PermGroupElem}}[ (sub(V, [one(V)])[1], [one(V)]) ] - # conj===nothing && (conj = one(C[1][1])) - # + last_tUU = [ one(C[end][1]) ] # tUU = change_universe(last_tUU, C[1][1]) # - unnecessary??? tUU = copy(last_tUU) - tU = [ Tm( one(universe(codomain(Tm)))^inv(conj) ) ] # isn't this just Tm(1)? + tU = [ Tm( one(codomain(Tm))^inv(conj) ) ] # isn't this just Tm(1)? for i in (length(C)-1):-1:1 - tUU = change_universe(last_tUU, C[i][1]) - change_universe!(last_tUU, C[i][1]) + # tUU = change_universe(last_tUU, C[i][1]) + # change_universe!(last_tUU, C[i][1]) - U = intersect(C[i][1], V) + U, _ = intersect(C[i][1], V) tV = [] for t in last_tUU, s in C[i][2] x = t*s if x in V - append!(tV, x) + push!(tV, x) length(tU)*length(tV) == length(last_tUU)*length(C[i][2]) && break else - xx = Tm(x^inv(conj)) + xx = Tm(domain(Tm)(x^inv(conj))) if ~(xx in tU) - include!(tU, xx) - append!(tUU, x) + push!(tU, xx) + push!(tUU, x) length(tU)*length(tV) == length(tUU)*length(C[i][2]) && break end end @@ -191,7 +204,7 @@ function _induce_chain(V, Tm, C ; conj=one(C[1][1])) # assert length(tU)*length(tV) == length(last_tUU)*length(C[i][2]) last_tUU = tUU - length(tV) != 1 && append!(c, (U, tV) ) + length(tV) != 1 && push!(c, (U, tV) ) end return reverse(c), tUU @@ -213,39 +226,19 @@ function get_transversal_chain(U::PermGroup) end +function _get_rep(g::PermGroupElem, S::LadderStep) + F = S.F - -function _get_rep(g, rec) - F = rec.F - if F!==nothing - rec = F[end] - else - F = [] - RR = rec - while is_assigned(rec.last) - append!(F, rec) - rec = rec.last - end - # check fuckery with "F" - end - - dim1 = one(R.Ai) - uim1 = dim1 - for i in length(F):-1:1 - F = F[i] - if order(R.Ai) < order(R.Aim1) - t = R.mT(g*inv(dim1*uim1)) - p = position(R.I, t*dim1) - else - p = position(R.I, dim1) - end - d = R.S3[p][1] - u = R.S3[p][2] - dim1 = d - uim1 = u*uim1 + dprev = one(F[1].A) + uprev = dprev + for s in F + p = s.is_up_step ? dprev : (dprev * s.Tmap(g*inv(dprev*uprev))) + (d, u) = s.m[p] + dprev = d + uprev = u*uprev end - return dim1, uim1 + return dprev, uprev end function young_subgroup(p::Vector{T} ; full::T=sum(p)) where T<:Integer From 1ba0716f6720e7dd06d7dd87488f9dcd49079edc Mon Sep 17 00:00:00 2001 From: Morgan Rodgers Date: Thu, 9 Jul 2026 15:37:05 +0200 Subject: [PATCH 17/23] types - use Dict --- .../LadderGame/src/LadderGameTypes.jl | 125 ++++++++++-------- 1 file changed, 73 insertions(+), 52 deletions(-) diff --git a/experimental/LadderGame/src/LadderGameTypes.jl b/experimental/LadderGame/src/LadderGameTypes.jl index 6aafebfc3f1b..f36b58f9ef00 100644 --- a/experimental/LadderGame/src/LadderGameTypes.jl +++ b/experimental/LadderGame/src/LadderGameTypes.jl @@ -1,84 +1,105 @@ +mutable struct TransversalChain + C::Vector{Tuple{PermGroup, Vector{PermGroupElem}}} +end + +data(T::TransversalChain) = T.C + +function Base.size(T::TransversalChain) + return size(data(T)) +end + +function Base.length(T::TransversalChain) + return length(data(T)) +end + +Base.firstindex(T::TransversalChain) = 1 +Base.lastindex(T::TransversalChain) = length(T) + +function Base.getindex(T::TransversalChain, i::IntegerUnion) + return getindex(data(T), Int(i)) +end + + +function TransversalChain(U::PermGroup) + U0 = U + C = Tuple{PermGroup, Vector{PermGroupElem}}[] + while length(U0) != 1 + s = first(moved_points(U0)) + U = stabilizer(U0, s)[1] + T = right_transversal(U0, U) + push!(C, (U0, T) ) + U0 = U + end + push!(C, (U0, [one(U0)])) + + return TransversalChain(C) +end + +get_transversal_chain(U::PermGroup) = TransversalChain(U) + + + + mutable struct LadderStep is_up_step::Bool Aprev::PermGroup A::PermGroup - T::Union{Vector{PermGroupElem}, Oscar.SubgroupTransversal} Tmap::Map - # Should these also be a Dict?????? - D::Vector - St::Vector + DSt::Dict{PermGroupElem, TransversalChain} + - # TODO I/m should be implemented as a Dict - I::Vector - m::Vector + Im::Dict{PermGroupElem, Tuple{PermGroupElem, PermGroupElem}} F function LadderStep(Aprev::PermGroup, A::PermGroup) - S = new() - if is_subset(Aprev, A) - S.is_up_step = true - elseif is_subset(Aprev, A) - S.is_up_step = false - else - # throw an error - end - S.A = A - S.Aprev = Aprev - # construct T / Tmap or do this only when needed? - return S - end - - function LadderStep(Aprev::PermGroup, A::PermGroup, T::Vector) - S = new() if is_subset(Aprev, A) - S.is_up_step = true - elseif is_subset(Aprev, A) - S.is_up_step = false + u = true + elseif is_subset(A, Aprev) + u = false else # throw an error end - S.A = A - S.Aprev = Aprev - S.T = T - # construct a tmap - return S + return new(u, Aprev, A) end function LadderStep(A::PermGroup, Aprev::PermGroup, T::Vector, Tmap::Map) - rec = new() if is_subset(Aprev, A) - rec.is_up_step = true - elseif is_subset(Aprev, A) - rec.is_up_step = false + u = true + elseif is_subset(A, Aprev) + u = false else # throw an error end - rec.A = A - rec.Aprev = Aprev - rec.T = T - rec.Tmap = Tmap - return rec + return new(u, Aprev, A, T, Tmap) end +end +function _get_previous_steps(S::LadderStep)::SubArray{LadderStep, 1, SubgroupLadder, Tuple{UnitRange{Int64}}, false} + return S.F end +# function _set_previous_steps!(S::LadderStep, ) -# SubgroupLadder stores Vector{LadderStep} -# with some special tools for adding steps. +# SubgroupLadder stores Vector{LadderStep} mutable struct SubgroupLadder <: AbstractVector{LadderStep} S::Vector{LadderStep} +end - function SubgroupLadder(S::Vector{PermGroup}) - rec = new() - - rec.S = [ LadderStep(S[i+1], S[i])] +function SubgroupLadder(S::Vector{PermGroup}) + L = LadderStep[] + isempty(S) && return new(L) + push!(L, LadderStep(first(S), first(S))) + for i in 2:length(S) + push!(L, LadderStep(S[i-1], S[i])) end + + return SubgroupLadder(L) end data(L::SubgroupLadder) = L.S @@ -110,9 +131,9 @@ function Base.copy(L::SubgroupLadder) return SubgroupLadder(copy(data(L))) end -function Base.push!(L::SubgroupLadder, s::LadderStep) - # require or assert that this is actually a step - @req last(L).A == s.Aprev "Incompatible LadderStep" - push!(L.S, s) - return L -end +# function Base.push!(L::SubgroupLadder, s::LadderStep) +# # require or assert that this is actually a step +# @req last(L).A == s.Aprev "Incompatible LadderStep" +# push!(L.S, s) +# return L +# end From b0fdc9cd41b1bae05813ee1293787014faee29fc Mon Sep 17 00:00:00 2001 From: Morgan Rodgers Date: Thu, 9 Jul 2026 15:37:16 +0200 Subject: [PATCH 18/23] update to use Dict --- experimental/LadderGame/src/main.jl | 148 +++++++++++----------------- 1 file changed, 55 insertions(+), 93 deletions(-) diff --git a/experimental/LadderGame/src/main.jl b/experimental/LadderGame/src/main.jl index a86467af28f1..9f9979fe021c 100644 --- a/experimental/LadderGame/src/main.jl +++ b/experimental/LadderGame/src/main.jl @@ -29,10 +29,12 @@ function _ladder_start!(S::LadderStep, U::PermGroup) @assert S.A == S.Aprev "Initial ladder step must be trivial" isdefined(S, :T) || (S.T = [one(S.A)]) isdefined(S, :Tmap) || (S.Tmap = map_from_func(S.A, S.A, x -> one(S.A))) - S.D = [one(S.A)] - S.St = [get_transversal_chain(U)] - S.I = [one(S.A)] - S.m = map_from_func(S.I, (S.D, U), x -> (one(S.A), one(U))) + S.DSt = Dict(one(S.A) => get_transversal_chain(U)) + # S.D = [one(S.A)] + # S.St = [get_transversal_chain(U)] + S.Im = Dict(one(S.A) => (one(S.A), one(U))) + # S.I = [one(S.A)] + # S.m = map_from_func(S.I, (S.D, U), x -> (one(S.A), one(U))) return S end @@ -45,17 +47,14 @@ function down_step(S::LadderStep, Sprev::LadderStep, U::PermGroup) T = S.T - D = [] - St = [] - I = [] - S3 = [] + DSt = Dict{PermGroupElem, TransversalChain}() + Im = Dict{PermGroupElem, Tuple{PermGroupElem, PermGroupElem}}() - for (i, a) in enumerate(Sprev.D) + for (a, st) in Sprev.DSt tmp = PermGroupElem[] for t in T if ~(t in tmp) d = t*a - st = Sprev.St[i] S1, _ = intersect(U, A^d) # not used in calculation @@ -64,7 +63,7 @@ function down_step(S::LadderStep, Sprev::LadderStep, U::PermGroup) @assert st[1][1] == S2 @assert S2 == intersect(U, Aprev^d)[1] - st, Sta = _induce_chain(S1, S.Tmap, st ; conj=d) + st2, Sta = _induce_chain(S1, S.Tmap, st ; conj=d) # not used in calculation @assert length(Sta) == index(S2, S1) @@ -72,38 +71,24 @@ function down_step(S::LadderStep, Sprev::LadderStep, U::PermGroup) ss = map_from_func(S2, S2, x -> Tss[index_of_coset(Tss, x)]) @assert allunique(map(x -> ss(S2(x)), Sta)) - push!(D,d) - push!(St, st) + DSt[d] = st2 for u in Sta tt = S.Tmap(Aprev(d*u*inv(a))) push!(tmp, tt) - push!(I, tt*a) - push!(S3, (d,u) ) + Im[tt*a] = (d,u) @assert tt*a*inv(u)*inv(d) in A end end end @assert Set(collect(T)) == Set(tmp) end - S.D = D - S.St = St - S.I = I - S.m = map_from_func(S.I, (S.D, U), x -> (one(S.A), one(U))) - # S.m = map_from_func(S.I, (S.D, U), x -> ) - # S3 # TODO this should be a map - # could we use a Dict I -> (S.D, U) ??? + S.DSt = DSt + S.Im = Im + return S end function up_step(S::LadderStep, Sprev::LadderStep, U::PermGroup) - # A::PermGroup, U::PermGroup, rec::LadderStep) - # r = LadderStep( - # # Ai = A - # # Aim1 = rec.Ai - # # last = rec - # # g,s for ev variable "F" set to false - # ) - A = S.A Aprev = S.Aprev @@ -112,10 +97,8 @@ function up_step(S::LadderStep, Sprev::LadderStep, U::PermGroup) T = S.T - D = [] - S3 = [] - St = [] - I = [] + DSt = Dict{PermGroupElem, TransversalChain}() + Im = Dict{PermGroupElem, Tuple{PermGroupElem, PermGroupElem}}() seen = [] data = [] @@ -123,7 +106,7 @@ function up_step(S::LadderStep, Sprev::LadderStep, U::PermGroup) cls = [] cls_data = [] - for a in Aprev.D + for (a, st) in Sprev.DSt if a in cls p = findfirst(a, cls) rep = cls_data[p][1] @@ -138,45 +121,43 @@ function up_step(S::LadderStep, Sprev::LadderStep, U::PermGroup) for t in T (~new && ~is_one(t)) && continue ta = t*a - at, ut = _get_rep(ta, Aprev) + at, ut = _get_rep(ta, Sprev) + + println("how are we getting here?") @assert ta*inv(ut)*inv(at) in Aprev - @assert at in Sprev.D + @assert at in keys(Sprev.DSt) rep === nothing && (rep = at, rep_u = ut) at in cls || (push!(cls, at), push!(cls_data, (rep, rep_u*inv(ut)) )) at == rep && push!(tt, ut*inv(rep_u)) - is_one(t) && (push!(I, a), push!(S3, (rep, rep_u*inv(ut)) )) + is_one(t) && (Im[a] = (rep, rep_u*inv(ut))) end if new - push!(D, rep) - push!(St, [[ (intersect(A^rep, U)[1], tt) ] Sprev.St[findfirst(rep, Aprev.D)]] ) # in magma code: rec.St[Position(R.Di, rep)] - # assert Index(St[end][1][1], St[end][2][1]) == length(tt) + # TODO need to be able to EXTEND a stabilizer chain + DSt[rep] = TransversalChain([[ (intersect(A^rep, U)[1], tt) ]; st]) + + @assert index(St[end][1][1], St[end][2][1]) == length(tt) end end - S.D = D - S.St = St - - S.I = I - # S.m = map_from_func(S.I, (S.D, U), x -> (one(S.A), one(U))) TODO fix - # S.S3 = S3 + S.DSt = DSt + S.Im = Im return S end # I think this gives a transversal chain ??? # can streamline wrt tUU / last_tUU -function _induce_chain(V::PermGroup, Tm::Map, C::Vector ; conj=one(C[1][1])) - # Tm is a MAP: transversal map for C[1][1]/V +function _induce_chain(V::PermGroup, Tm::Map, C::TransversalChain ; conj=one(C[1][1])) + # Tm is a transversal map for C[1][1]/V @assert is_subset(V, C[1][1]) c = Tuple{PermGroup, Vector{PermGroupElem}}[ (sub(V, [one(V)])[1], [one(V)]) ] - last_tUU = [ one(C[end][1]) ] - # tUU = change_universe(last_tUU, C[1][1]) # - unnecessary??? + last_tUU = (C[1][1]).([ one(C[end][1]) ]) tUU = copy(last_tUU) - tU = [ Tm( one(codomain(Tm))^inv(conj) ) ] # isn't this just Tm(1)? + tU = [ Tm( one(domain(Tm))^inv(conj) ) ] # isn't this just Tm(1)? for i in (length(C)-1):-1:1 # tUU = change_universe(last_tUU, C[i][1]) @@ -207,27 +188,12 @@ function _induce_chain(V::PermGroup, Tm::Map, C::Vector ; conj=one(C[1][1])) length(tV) != 1 && push!(c, (U, tV) ) end - return reverse(c), tUU -end - -function get_transversal_chain(U::PermGroup) - # c = PermGroup[U] - U0 = U - C = Tuple{PermGroup, Vector{PermGroupElem}}[] - while length(U0) != 1 - s = first(moved_points(U0)) - U = stabilizer(U0, s)[1] - T = right_transversal(U0, U) - push!(C, (U0, T) ) - U0 = U - end - push!(C, (U0, [one(U0)])) - return C + return TransversalChain(reverse(c)), tUU end - +# Recursive recognition method function _get_rep(g::PermGroupElem, S::LadderStep) - F = S.F + F = _get_previous_steps(S) dprev = one(F[1].A) uprev = dprev @@ -241,6 +207,14 @@ function _get_rep(g::PermGroupElem, S::LadderStep) return dprev, uprev end + + +################################################################################ +# +# Young subgroup ladders +# +################################################################################ + function young_subgroup(p::Vector{T} ; full::T=sum(p)) where T<:Integer s = full - sum(p) # should error if s < 0 @@ -248,7 +222,6 @@ function young_subgroup(p::Vector{T} ; full::T=sum(p)) where T<:Integer return inner_direct_product([symmetric_group(i) for i in vcat(p, ones(T, s))]) end -# Test method - groups only # works - matches Magma function _young_subgroup_ladder( p::Vector{T} ; full::T=sum(p)) where T<:Integer n = sum(p) @@ -275,44 +248,33 @@ function _young_subgroup_ladder( p::Vector{T} ; full::T=sum(p)) where T<:Integer end - - - - - +# TODO make transversal maps, integrate into each LadderStep function young_subgroup_ladder( p::Vector{T} ; full::T=sum(p)) where T<:Integer n = sum(p) L = LadderStep[] pp = copy(p) - H = young_subgroup(pp ; full=full) + Hprev = young_subgroup(pp ; full=full) s = n - pp[1] while s!=0 if pp[2]==1 - - Hprev = H deleteat!(pp, 2) pp[1]+=1 - H = young_subgroup(pp ; full=full) - pushfirst!(L, young_subgroup(pp ; full=full)) - else - - Hprev = H pp[2]-=1 insert!(pp,2,1) - H = young_subgroup(pp ; full=full) - pushfirst!(L, young_subgroup(pp ; full=full)) - - - Hprev = H + H = Hprev + Hprev = young_subgroup(pp ; full=full) + pushfirst!(L, LadderStep(Hprev, H)) deleteat!(pp, 2) pp[1]+=1 - H = young_subgroup(pp ; full=full) - pushfirst!(L, young_subgroup(pp ; full=full)) - end + H = Hprev + Hprev = young_subgroup(pp ; full=full) + pushfirst!(L, LadderStep(Hprev, H)) s = n-pp[1] end - return L + pushfirst!(L, LadderStep(Hprev,Hprev)) + + return SubgroupLadder(L) end From 1f00a2012d0d29f0b804f21ca3022645e2b630a9 Mon Sep 17 00:00:00 2001 From: Morgan Rodgers Date: Thu, 9 Jul 2026 15:47:08 +0200 Subject: [PATCH 19/23] delete remnants --- experimental/LadderGame/src/main.jl | 4 ---- 1 file changed, 4 deletions(-) diff --git a/experimental/LadderGame/src/main.jl b/experimental/LadderGame/src/main.jl index 9f9979fe021c..a698b9c426c4 100644 --- a/experimental/LadderGame/src/main.jl +++ b/experimental/LadderGame/src/main.jl @@ -30,11 +30,7 @@ function _ladder_start!(S::LadderStep, U::PermGroup) isdefined(S, :T) || (S.T = [one(S.A)]) isdefined(S, :Tmap) || (S.Tmap = map_from_func(S.A, S.A, x -> one(S.A))) S.DSt = Dict(one(S.A) => get_transversal_chain(U)) - # S.D = [one(S.A)] - # S.St = [get_transversal_chain(U)] S.Im = Dict(one(S.A) => (one(S.A), one(U))) - # S.I = [one(S.A)] - # S.m = map_from_func(S.I, (S.D, U), x -> (one(S.A), one(U))) return S end From 6af407fe2c1cc9e338dfd56e459dede44ce4aab6 Mon Sep 17 00:00:00 2001 From: Morgan Rodgers Date: Thu, 9 Jul 2026 16:23:15 +0200 Subject: [PATCH 20/23] ironing details --- .../LadderGame/src/LadderGameTypes.jl | 10 ++++-- experimental/LadderGame/src/main.jl | 32 +++++++++---------- 2 files changed, 23 insertions(+), 19 deletions(-) diff --git a/experimental/LadderGame/src/LadderGameTypes.jl b/experimental/LadderGame/src/LadderGameTypes.jl index f36b58f9ef00..943ef1580ff4 100644 --- a/experimental/LadderGame/src/LadderGameTypes.jl +++ b/experimental/LadderGame/src/LadderGameTypes.jl @@ -41,7 +41,7 @@ get_transversal_chain(U::PermGroup) = TransversalChain(U) mutable struct LadderStep - is_up_step::Bool + is_up_step::Union{Nothing, Bool} Aprev::PermGroup A::PermGroup @@ -57,7 +57,9 @@ mutable struct LadderStep F function LadderStep(Aprev::PermGroup, A::PermGroup) - if is_subset(Aprev, A) + if Aprev == A + u = nothing + elseif is_subset(Aprev, A) u = true elseif is_subset(A, Aprev) u = false @@ -68,7 +70,9 @@ mutable struct LadderStep end function LadderStep(A::PermGroup, Aprev::PermGroup, T::Vector, Tmap::Map) - if is_subset(Aprev, A) + if Aprev == A + u = nothing + elseif is_subset(Aprev, A) u = true elseif is_subset(A, Aprev) u = false diff --git a/experimental/LadderGame/src/main.jl b/experimental/LadderGame/src/main.jl index a698b9c426c4..ee7872ea0149 100644 --- a/experimental/LadderGame/src/main.jl +++ b/experimental/LadderGame/src/main.jl @@ -12,17 +12,13 @@ # transversals (S_i)_(0 Date: Thu, 9 Jul 2026 16:37:15 +0200 Subject: [PATCH 21/23] TODO comment --- experimental/LadderGame/src/main.jl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/experimental/LadderGame/src/main.jl b/experimental/LadderGame/src/main.jl index ee7872ea0149..d51855f17add 100644 --- a/experimental/LadderGame/src/main.jl +++ b/experimental/LadderGame/src/main.jl @@ -268,7 +268,9 @@ function young_subgroup_ladder( p::Vector{T} ; full::T=sum(p)) where T<:Integer pushfirst!(L, LadderStep(Hprev,Hprev)) + # TODO fix: when we have an up-step, we want the PREV step to get an F for (i, s) in enumerate(L) + s.is_up_step === nothing && continue s.is_up_step && (s.F = view(L, 1:i)) end From 52e1fad753aa528664a880664f8752765db81344 Mon Sep 17 00:00:00 2001 From: Morgan Rodgers Date: Thu, 9 Jul 2026 17:18:51 +0200 Subject: [PATCH 22/23] revert nothing union --- experimental/LadderGame/src/LadderGameTypes.jl | 13 ++++++------- experimental/LadderGame/src/main.jl | 8 ++++---- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/experimental/LadderGame/src/LadderGameTypes.jl b/experimental/LadderGame/src/LadderGameTypes.jl index 943ef1580ff4..edc70783ef65 100644 --- a/experimental/LadderGame/src/LadderGameTypes.jl +++ b/experimental/LadderGame/src/LadderGameTypes.jl @@ -41,7 +41,7 @@ get_transversal_chain(U::PermGroup) = TransversalChain(U) mutable struct LadderStep - is_up_step::Union{Nothing, Bool} + is_up_step::Bool Aprev::PermGroup A::PermGroup @@ -57,9 +57,7 @@ mutable struct LadderStep F function LadderStep(Aprev::PermGroup, A::PermGroup) - if Aprev == A - u = nothing - elseif is_subset(Aprev, A) + if is_subset(Aprev, A) u = true elseif is_subset(A, Aprev) u = false @@ -70,9 +68,7 @@ mutable struct LadderStep end function LadderStep(A::PermGroup, Aprev::PermGroup, T::Vector, Tmap::Map) - if Aprev == A - u = nothing - elseif is_subset(Aprev, A) + if is_subset(Aprev, A) u = true elseif is_subset(A, Aprev) u = false @@ -122,6 +118,9 @@ function Base.length(L::SubgroupLadder) return length(data(L)) end +Base.firstindex(L::SubgroupLadder) = 1 +Base.lastindex(L::SubgroupLadder) = length(L) + function Base.getindex(L::SubgroupLadder, i::IntegerUnion) return getindex(data(L), Int(i)) end diff --git a/experimental/LadderGame/src/main.jl b/experimental/LadderGame/src/main.jl index d51855f17add..9dc649590848 100644 --- a/experimental/LadderGame/src/main.jl +++ b/experimental/LadderGame/src/main.jl @@ -14,7 +14,7 @@ function ladder_game!(L::SubgroupLadder, G::PermGroup, U::PermGroup) sprev = L[1] for s in L - s.is_up_step === nothing && (_ladder_start(s, U), continue) + s.A == s.Aprev && (_ladder_start(s, U), continue) s.is_up_step ? up_step(s, sprev, U) : down_step(s, sprev, U) sprev = s end @@ -268,10 +268,10 @@ function young_subgroup_ladder( p::Vector{T} ; full::T=sum(p)) where T<:Integer pushfirst!(L, LadderStep(Hprev,Hprev)) - # TODO fix: when we have an up-step, we want the PREV step to get an F + L = SubgroupLadder(L) for (i, s) in enumerate(L) - s.is_up_step === nothing && continue - s.is_up_step && (s.F = view(L, 1:i)) + s.A == s.Aprev && continue + s.is_up_step && (L[i-1].F = view(L, 1:i-1)) end return SubgroupLadder(L) From 3afe1c17a8cf72032ff118040f466064d7592572 Mon Sep 17 00:00:00 2001 From: Morgan Rodgers Date: Thu, 9 Jul 2026 17:39:26 +0200 Subject: [PATCH 23/23] getting "key not found" error for some reason --- experimental/LadderGame/src/main.jl | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/experimental/LadderGame/src/main.jl b/experimental/LadderGame/src/main.jl index 9dc649590848..9bf6001aff71 100644 --- a/experimental/LadderGame/src/main.jl +++ b/experimental/LadderGame/src/main.jl @@ -101,8 +101,7 @@ function up_step(S::LadderStep, Sprev::LadderStep, U::PermGroup) for (a, st) in Sprev.DSt if a in cls p = findfirst(a, cls) - rep = cls_data[p][1] - rep_u = cls_data[p][2] + (rep, rep_u) = cls_data[p] new = false else rep = nothing @@ -113,14 +112,12 @@ function up_step(S::LadderStep, Sprev::LadderStep, U::PermGroup) for t in T (~new && ~is_one(t)) && continue ta = t*a - at, ut = _get_rep(ta, Sprev) - - println("how are we getting here?") + (at, ut) = _get_rep(ta, Sprev) @assert ta*inv(ut)*inv(at) in Aprev @assert at in keys(Sprev.DSt) - rep === nothing && (rep = at, rep_u = ut) + rep === nothing && ((rep, rep_u) = (at, ut)) at in cls || (push!(cls, at), push!(cls_data, (rep, rep_u*inv(ut)) )) at == rep && push!(tt, ut*inv(rep_u)) is_one(t) && (Im[a] = (rep, rep_u*inv(ut))) @@ -190,12 +187,13 @@ function _get_rep(g::PermGroupElem, S::LadderStep) dprev = one(F[1].A) uprev = dprev for s in F - p = s.is_up_step ? dprev : (dprev * s.Tmap(g*inv(dprev*uprev))) - (d, u) = s.m[p] + p = s.is_up_step ? dprev : (dprev * s.Tmap(domain(s.Tmap)(g*inv(dprev*uprev)))) + println(keys(s.Im)) + println() + (d, u) = s.Im[p] dprev = d uprev = u*uprev end - return dprev, uprev end