From 59d6b665ae6296bd3c3ce996b1a896619a1b3981 Mon Sep 17 00:00:00 2001 From: Antony Della Vecchia Date: Wed, 4 Dec 2024 10:58:26 +0100 Subject: [PATCH 1/9] rebase --- .../AlgebraicShifting/src/PartialShift.jl | 103 +++++++++++++++--- 1 file changed, 89 insertions(+), 14 deletions(-) diff --git a/experimental/AlgebraicShifting/src/PartialShift.jl b/experimental/AlgebraicShifting/src/PartialShift.jl index 3f912e1c8764..a2874afb49dc 100644 --- a/experimental/AlgebraicShifting/src/PartialShift.jl +++ b/experimental/AlgebraicShifting/src/PartialShift.jl @@ -256,16 +256,17 @@ function exterior_shift(K::SimplicialComplex, g::MatElem) end @doc raw""" - exterior_shift(F::Field, K::SimplicialComplex, w::WeylGroupElem) - exterior_shift(F::Field, K::UniformHypergraph, w::WeylGroupElem) - exterior_shift(K::SimplicialComplex, w::WeylGroupElem) - exterior_shift(K::UniformHypergraph, w::WeylGroupElem) - exterior_shift(K::SimplicialComplex) - exterior_shift(K::UniformHypergraph) + exterior_shift(F::Field, K::SimplicialComplex, w::WeylGroupElem; las_vegas=false) + exterior_shift(F::Field, K::UniformHypergraph, w::WeylGroupElem; las_vegas=false) + exterior_shift(K::SimplicialComplex, w::WeylGroupElem; las_vegas=false) + exterior_shift(K::UniformHypergraph, w::WeylGroupElem; las_vegas=false) + exterior_shift(K::SimplicialComplex; las_vegas=false) + exterior_shift(K::UniformHypergraph; las_vegas=false) Computes the (partial) exterior shift of a simplical complex or uniform hypergraph `K` with respect to the Weyl group element `w` and the field `F`. If the field is not given then `QQ` is used during the computation. -If `w` is not given then `longest_element(weyl_group(:A, n_vertices(K) - 1))` is used +If `w` is not given then `longest_element(weyl_group(:A, n_vertices(K) - 1))` is used. +Setting `las_vegas=true` will run the algorithm with a random change of basis matrix and repeat the algorithm untill # Examples ```jldoctest @@ -317,27 +318,101 @@ julia> L = exterior_shift(GF(2), K, w) Abstract simplicial complex of dimension 2 on 6 vertices ``` """ -function exterior_shift(F::Field, K::ComplexOrHypergraph, p::PermGroupElem) +function exterior_shift(F::Field, K::ComplexOrHypergraph, + p::PermGroupElem; las_vegas::Bool=false) n = n_vertices(K) @req n == degree(parent(p)) "number of vertices - 1 should equal the rank of the root system" - + las_vegas && return exterior_shift_lv(F, K, p) return exterior_shift(K, rothe_matrix(F, p)) end -function exterior_shift(F::Field, K::ComplexOrHypergraph, w::WeylGroupElem) +function exterior_shift(F::Field, K::ComplexOrHypergraph, w::WeylGroupElem; kw...) n = n_vertices(K) phi = isomorphism(PermGroup, parent(w)) - return exterior_shift(F, K, phi(w)) + return exterior_shift(F, K, phi(w); kw) end -function exterior_shift(F::Field, K::ComplexOrHypergraph) +function exterior_shift(F::Field, K::ComplexOrHypergraph; kw...) n = n_vertices(K) W = weyl_group(:A, n - 1) - return exterior_shift(F, K, longest_element(W)) + return exterior_shift(F, K, longest_element(W); kw) +end + +exterior_shift(K::ComplexOrHypergraph; kw...) = exterior_shift(QQ, K; kw) + +################################################################################ +# Las Vegas Partial Shifting + +function random_rothe_matrix(F::Field, p::PermGroupElem) + char = characteristic(F) + range = char == 0 ? 100 : char + u = identity_matrix(F, n) + n = degree(parent(p)) + for (i, j) in inversions(p) + u[i, j] = F.(round.(Integer, range .* rand(i)) .- (range // 2)) + end + + return u * permutation_matrix(F, p) +end + +function random_shift(F::Field, K::ComplexOrHypergraph, p::PermGroupElem;) + n = n_vertices(K) + exterior_shift(K, random_rothe_matrix(F, p)) end -exterior_shift(K::ComplexOrHypergraph) = exterior_shift(QQ, K) +random_shift(K::ComplexOrHypergraph, p::PermGroupElem) = random_shift(QQ, K, p) +# returns true if the dst is the partial shift of src with respect to w +function check_shifted(F::Field, + src::UniformHypergraph, + dst::UniformHypergraph, + p::PermGroupElem) + dst_faces = faces(dst) + if length(dst_faces) == 1 + max_face = dst_faces[1] + else + max_face = max(dst_faces...) + end + num_rows = length(dst_faces) + n = n_vertices(src) + k = face_size(src) + nCk = sort(subsets(n, k)) + max_face_index = findfirst(x -> x == max_face, nCk) + cols = nCk[1:max_face_index - 1] + r = rothe_matrix(F, p) + + if max_face_index > num_rows + M = compound_matrix(r, src)[collect(1:num_rows), collect(1:length(cols))] + Oscar.ModStdQt.ref_ff_rc!(M) + nCk[independent_columns(M)] == dst_faces && return false + end + return true +end + +function check_shifted(F::Field, + src::SimplicialComplex, + dst::SimplicialComplex, + p::PermGroupElem) + n = n_vertices(src) + f_vec = f_vector(src) + k = length(f_vec) + + while k > 1 + uhg_src = uniform_hypergraph(complex_faces(src, k - 1), n) + uhg_dst = uniform_hypergraph(complex_faces(dst, k - 1), n) + !check_shifted(F, uhg_src, uhg_dst, p) && return false + k -= 1 + end + return true +end + +function exterior_shift_lv(F::Field, K::ComplexOrHypergraph, p::PermGroupElem) + sample_size = characteristic(F) == 0 ? 10 : 100 + shift = partialsort!([random_shift(F, K, p) for _ in 1:sample_size], 1; + lt=isless_lex) + check_shifted(F, K, shift, p) && return shift + return exterior_shift_lv(F, K, p) +end ############################################################################### # Symmetric shift From 59ab29dd790587c1040e3ba46ebee973911e0eb0 Mon Sep 17 00:00:00 2001 From: Antony Della Vecchia Date: Wed, 4 Dec 2024 11:03:28 +0100 Subject: [PATCH 2/9] properly pass kwargs --- experimental/AlgebraicShifting/src/PartialShift.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/experimental/AlgebraicShifting/src/PartialShift.jl b/experimental/AlgebraicShifting/src/PartialShift.jl index a2874afb49dc..5d25cf14b520 100644 --- a/experimental/AlgebraicShifting/src/PartialShift.jl +++ b/experimental/AlgebraicShifting/src/PartialShift.jl @@ -329,16 +329,16 @@ end function exterior_shift(F::Field, K::ComplexOrHypergraph, w::WeylGroupElem; kw...) n = n_vertices(K) phi = isomorphism(PermGroup, parent(w)) - return exterior_shift(F, K, phi(w); kw) + return exterior_shift(F, K, phi(w); kw...) end function exterior_shift(F::Field, K::ComplexOrHypergraph; kw...) n = n_vertices(K) W = weyl_group(:A, n - 1) - return exterior_shift(F, K, longest_element(W); kw) + return exterior_shift(F, K, longest_element(W); kw...) end -exterior_shift(K::ComplexOrHypergraph; kw...) = exterior_shift(QQ, K; kw) +exterior_shift(K::ComplexOrHypergraph; kw...) = exterior_shift(QQ, K; kw...) ################################################################################ # Las Vegas Partial Shifting From 7a290db615f179abdeb86c2f63894d49344d6a9e Mon Sep 17 00:00:00 2001 From: Antony Della Vecchia Date: Wed, 4 Dec 2024 11:14:03 +0100 Subject: [PATCH 3/9] typo in docs --- experimental/AlgebraicShifting/src/PartialShift.jl | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/experimental/AlgebraicShifting/src/PartialShift.jl b/experimental/AlgebraicShifting/src/PartialShift.jl index 5d25cf14b520..546287334065 100644 --- a/experimental/AlgebraicShifting/src/PartialShift.jl +++ b/experimental/AlgebraicShifting/src/PartialShift.jl @@ -266,7 +266,7 @@ end Computes the (partial) exterior shift of a simplical complex or uniform hypergraph `K` with respect to the Weyl group element `w` and the field `F`. If the field is not given then `QQ` is used during the computation. If `w` is not given then `longest_element(weyl_group(:A, n_vertices(K) - 1))` is used. -Setting `las_vegas=true` will run the algorithm with a random change of basis matrix and repeat the algorithm untill +Setting `las_vegas=true` will run the algorithm with a random change of basis matrix and repeat the algorithm until the shift is found. # Examples ```jldoctest @@ -351,7 +351,6 @@ function random_rothe_matrix(F::Field, p::PermGroupElem) for (i, j) in inversions(p) u[i, j] = F.(round.(Integer, range .* rand(i)) .- (range // 2)) end - return u * permutation_matrix(F, p) end From 0e3ad1cc40d8d7abc74d5b7f503d7e77ff11fcdf Mon Sep 17 00:00:00 2001 From: Antony Della Vecchia Date: Wed, 4 Dec 2024 14:10:09 +0100 Subject: [PATCH 4/9] more tidying --- .../AlgebraicShifting/src/PartialShift.jl | 40 ++++++++----------- 1 file changed, 16 insertions(+), 24 deletions(-) diff --git a/experimental/AlgebraicShifting/src/PartialShift.jl b/experimental/AlgebraicShifting/src/PartialShift.jl index 546287334065..eec10d5b0b3c 100644 --- a/experimental/AlgebraicShifting/src/PartialShift.jl +++ b/experimental/AlgebraicShifting/src/PartialShift.jl @@ -346,10 +346,10 @@ exterior_shift(K::ComplexOrHypergraph; kw...) = exterior_shift(QQ, K; kw...) function random_rothe_matrix(F::Field, p::PermGroupElem) char = characteristic(F) range = char == 0 ? 100 : char - u = identity_matrix(F, n) n = degree(parent(p)) + u = identity_matrix(F, n) for (i, j) in inversions(p) - u[i, j] = F.(round.(Integer, range .* rand(i)) .- (range // 2)) + u[i, j] = F.(round.(Integer, range .* rand()) .- (range // 2)) end return u * permutation_matrix(F, p) end @@ -361,45 +361,37 @@ end random_shift(K::ComplexOrHypergraph, p::PermGroupElem) = random_shift(QQ, K, p) -# returns true if the dst is the partial shift of src with respect to w -function check_shifted(F::Field, - src::UniformHypergraph, - dst::UniformHypergraph, - p::PermGroupElem) - dst_faces = faces(dst) - if length(dst_faces) == 1 - max_face = dst_faces[1] - else - max_face = max(dst_faces...) - end - num_rows = length(dst_faces) +# returns true if the target is the partial shift of src with respect to p +function check_shifted(F::Field, src::UniformHypergraph, + target::UniformHypergraph, p::PermGroupElem) + target_faces = faces(target) + max_face = length(target_faces) == 1 ? target_faces[1] : max(target_faces...) + num_rows = length(target_faces) n = n_vertices(src) k = face_size(src) nCk = sort(subsets(n, k)) max_face_index = findfirst(x -> x == max_face, nCk) + # limits the columns by the max face of source cols = nCk[1:max_face_index - 1] r = rothe_matrix(F, p) - - if max_face_index > num_rows + + if max_face_index > num_rows M = compound_matrix(r, src)[collect(1:num_rows), collect(1:length(cols))] Oscar.ModStdQt.ref_ff_rc!(M) - nCk[independent_columns(M)] == dst_faces && return false + nCk[independent_columns(M)] != target_faces && return false end return true end -function check_shifted(F::Field, - src::SimplicialComplex, - dst::SimplicialComplex, - p::PermGroupElem) +function check_shifted(F::Field, src::SimplicialComplex, + target::SimplicialComplex, p::PermGroupElem) n = n_vertices(src) f_vec = f_vector(src) k = length(f_vec) - while k > 1 uhg_src = uniform_hypergraph(complex_faces(src, k - 1), n) - uhg_dst = uniform_hypergraph(complex_faces(dst, k - 1), n) - !check_shifted(F, uhg_src, uhg_dst, p) && return false + uhg_target = uniform_hypergraph(complex_faces(target, k - 1), n) + !check_shifted(F, uhg_src, uhg_target, p) && return false k -= 1 end return true From 8d6c7713ccfb7474c1a0c25db79eb38e8c8b4223 Mon Sep 17 00:00:00 2001 From: Antony Della Vecchia Date: Wed, 4 Dec 2024 17:30:45 +0100 Subject: [PATCH 5/9] corrected check algo --- experimental/AlgebraicShifting/src/PartialShift.jl | 10 ++++++---- .../AlgebraicShifting/src/PartialShiftGraph.jl | 2 ++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/experimental/AlgebraicShifting/src/PartialShift.jl b/experimental/AlgebraicShifting/src/PartialShift.jl index eec10d5b0b3c..653d78155439 100644 --- a/experimental/AlgebraicShifting/src/PartialShift.jl +++ b/experimental/AlgebraicShifting/src/PartialShift.jl @@ -364,9 +364,11 @@ random_shift(K::ComplexOrHypergraph, p::PermGroupElem) = random_shift(QQ, K, p) # returns true if the target is the partial shift of src with respect to p function check_shifted(F::Field, src::UniformHypergraph, target::UniformHypergraph, p::PermGroupElem) - target_faces = faces(target) + target_faces = sort(faces(target)) max_face = length(target_faces) == 1 ? target_faces[1] : max(target_faces...) - num_rows = length(target_faces) + # currently number of faces of src and target are the same + # this may change in the future + num_rows = length(faces(src)) n = n_vertices(src) k = face_size(src) nCk = sort(subsets(n, k)) @@ -378,7 +380,7 @@ function check_shifted(F::Field, src::UniformHypergraph, if max_face_index > num_rows M = compound_matrix(r, src)[collect(1:num_rows), collect(1:length(cols))] Oscar.ModStdQt.ref_ff_rc!(M) - nCk[independent_columns(M)] != target_faces && return false + nCk[independent_columns(M)] != target_faces[1:end - 1] && return false end return true end @@ -402,7 +404,7 @@ function exterior_shift_lv(F::Field, K::ComplexOrHypergraph, p::PermGroupElem) shift = partialsort!([random_shift(F, K, p) for _ in 1:sample_size], 1; lt=isless_lex) check_shifted(F, K, shift, p) && return shift - return exterior_shift_lv(F, K, p) + return nothing #exterior_shift_lv(F, K, p) end ############################################################################### diff --git a/experimental/AlgebraicShifting/src/PartialShiftGraph.jl b/experimental/AlgebraicShifting/src/PartialShiftGraph.jl index 0110ea93f509..6041d6670d61 100644 --- a/experimental/AlgebraicShifting/src/PartialShiftGraph.jl +++ b/experimental/AlgebraicShifting/src/PartialShiftGraph.jl @@ -1,3 +1,4 @@ +# TODO: change Vector -> Set const EdgeLabels = Dict{Tuple{Int, Int}, Vector{WeylGroupElem}} function isless_lex(S1::Set{Set{Int}}, S2::Set{Set{Int}}) @@ -181,6 +182,7 @@ function partial_shift_graph(F::Field, complexes::Vector{T}, parallel::Bool = false, show_progress::Bool = true, task_size::Int=100) where T <: ComplexOrHypergraph + # see TODO above about changing EdgeLabels type # Deal with trivial case if length(complexes) == 1 @req is_shifted(complexes[1]) "The list of complexes should be closed under shifting by elements of W" From 1f67bef971bba64ca71fa04ccff19240e33f95d2 Mon Sep 17 00:00:00 2001 From: antonydellavecchia Date: Fri, 6 Dec 2024 11:07:55 +0100 Subject: [PATCH 6/9] adds suggestion from PR #4260 --- .../AlgebraicShifting/src/PartialShiftGraph.jl | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/experimental/AlgebraicShifting/src/PartialShiftGraph.jl b/experimental/AlgebraicShifting/src/PartialShiftGraph.jl index 6041d6670d61..ecb13d5108e1 100644 --- a/experimental/AlgebraicShifting/src/PartialShiftGraph.jl +++ b/experimental/AlgebraicShifting/src/PartialShiftGraph.jl @@ -217,18 +217,11 @@ function partial_shift_graph(F::Field, complexes::Vector{T}, Oscar.put_params(channels, codomain(phi)) map_function = pmap end - try - if show_progress - edge_labels = reduce((d1, d2) -> mergewith!(vcat, d1, d2), - @showprogress map_function( + try + edge_labels = reduce((d1, d2) -> mergewith!(vcat, d1, d2), + @showprogress enabled=show_progress map_function( Ks -> multi_edges(F, phi.(W), Ks, complex_labels), Iterators.partition(enumerate(complexes), task_size))) - else - edge_labels = reduce((d1, d2) -> mergewith!(vcat, d1, d2), - map_function( - Ks -> multi_edges(F, phi.(W), Ks, complex_labels), - Iterators.partition(enumerate(complexes), task_size))) - end graph = graph_from_edges(Directed, [[i,j] for (i,j) in keys(edge_labels)]) return (graph, Dict(k => inv(phi).(v) for (k, v) in edge_labels), From a7ea06a37928fcb2962f45c4d652324cd502225e Mon Sep 17 00:00:00 2001 From: Antony Della Vecchia Date: Tue, 10 Dec 2024 16:49:22 +0100 Subject: [PATCH 7/9] adds verbose printing + modification to lv algo --- .../src/AlgebraicShifting.jl | 1 + .../AlgebraicShifting/src/PartialShift.jl | 97 +++---------------- .../AlgebraicShifting/src/SymmetricShift.jl | 73 ++++++++++++++ src/Oscar.jl | 3 + 4 files changed, 90 insertions(+), 84 deletions(-) create mode 100644 experimental/AlgebraicShifting/src/SymmetricShift.jl diff --git a/experimental/AlgebraicShifting/src/AlgebraicShifting.jl b/experimental/AlgebraicShifting/src/AlgebraicShifting.jl index 9b652bd32358..7c7ad5de04b5 100644 --- a/experimental/AlgebraicShifting/src/AlgebraicShifting.jl +++ b/experimental/AlgebraicShifting/src/AlgebraicShifting.jl @@ -1,5 +1,6 @@ include("UniformHypergraph.jl") include("PartialShift.jl") +include("SymmetricShift.jl") include("PartialShiftGraph.jl") export UniformHypergraph diff --git a/experimental/AlgebraicShifting/src/PartialShift.jl b/experimental/AlgebraicShifting/src/PartialShift.jl index 653d78155439..3d5f6d17d58f 100644 --- a/experimental/AlgebraicShifting/src/PartialShift.jl +++ b/experimental/AlgebraicShifting/src/PartialShift.jl @@ -343,20 +343,19 @@ exterior_shift(K::ComplexOrHypergraph; kw...) = exterior_shift(QQ, K; kw...) ################################################################################ # Las Vegas Partial Shifting -function random_rothe_matrix(F::Field, p::PermGroupElem) - char = characteristic(F) - range = char == 0 ? 100 : char +function random_rothe_matrix(p::PermGroupElem) n = degree(parent(p)) - u = identity_matrix(F, n) + u = identity_matrix(QQ, n) for (i, j) in inversions(p) - u[i, j] = F.(round.(Integer, range .* rand()) .- (range // 2)) + # random.seed!(UInt) + u[i, j] = QQ(Rational(rand() - 0.5)) end - return u * permutation_matrix(F, p) + return u * permutation_matrix(QQ, p) end function random_shift(F::Field, K::ComplexOrHypergraph, p::PermGroupElem;) n = n_vertices(K) - exterior_shift(K, random_rothe_matrix(F, p)) + exterior_shift(K, random_rothe_matrix(p)) end random_shift(K::ComplexOrHypergraph, p::PermGroupElem) = random_shift(QQ, K, p) @@ -400,82 +399,12 @@ function check_shifted(F::Field, src::SimplicialComplex, end function exterior_shift_lv(F::Field, K::ComplexOrHypergraph, p::PermGroupElem) - sample_size = characteristic(F) == 0 ? 10 : 100 - shift = partialsort!([random_shift(F, K, p) for _ in 1:sample_size], 1; - lt=isless_lex) - check_shifted(F, K, shift, p) && return shift - return nothing #exterior_shift_lv(F, K, p) -end - -############################################################################### -# Symmetric shift -############################################################################### - -""" - symmetric_shift(F::Field, K::SimplicialComplex) - -Returns the symmetric shift of `K` - -TODO: add more docs and and expose for users -""" -function symmetric_shift(F::Field, K::SimplicialComplex, p::PermGroupElem) - n = n_vertices(K) - Fy, y = polynomial_ring(F, :y => (1:n, 1:n); cached=false) - change_of_basis = rothe_matrix(Fy, p) * permutation_matrix(ZZ, p) * generic_unipotent_matrix(Fy) - - Rx, x = polynomial_ring(Fy, n) - # the generators of the stanley reisner ideal are combinations of [x_1, ..., x_n] - R_K, _ = stanley_reisner_ring(Rx, K) - - # the computation is a over the field of fractions Fyx - # we use a different ring to generate monomial_basis, coefficients need to be a field, - # but we want to avoid using fraction field of Ry during row reduction - mb_ring, z = graded_polynomial_ring(F, n; cached=false) - input_faces = Vector{Int}[] - for r in 2:dim(K) + 1 - mb = reverse(monomial_basis(mb_ring, r)) - A = Vector{elem_type(Fy)}[] - mb_exponents = first.(collect.(exponents.(mb))) # gets monomial exponents - - for b in mb - # need to compare with some alternatives - transformed_monomial = evaluate(b, change_of_basis * gens(R_K)) - - # we need to iterate through exponents here since the functions terms, coefficients or exponents - # do not return 0 terms and we need to make sure the generic col aligns with the others - # this is needed for the case when the field has finite characteristic - # we use the lift because currently there is no function to get the coeff of - # a MPolyQuoRingElem, which means we also need to check if it's zero before adding the coefficient - col = [ - !is_zero(R_K(monomial(Rx, e))) ? coeff(lift(transformed_monomial), e) : Fy(0) - for e in mb_exponents] - push!(A, col) - end - C = matrix(Fy, reduce(hcat, A)) - Oscar.ModStdQt.ref_ff_rc!(C) - smallest_basis_el = z[r]^r - smallest_index = findfirst(a -> a == smallest_basis_el, mb) - col_indices = filter(x -> x >= smallest_index, independent_columns(C)) - monomial_exponents = first.(exponents.(mb[col_indices])) - - # adjustment to convert monomial to simplex - for me in monomial_exponents - shifted_set = Int[] - index_count = 1 - for (i, e) in enumerate(me) - for j in 1:e - push!(shifted_set, i - (r - index_count)) - index_count += 1 - end - end - push!(input_faces, shifted_set) - end + shift = random_shift(F, K, p) + count = 1 + while !check_shifted(F, K, shift, p) + count += 1 + shift = random_shift(F, K, p) end - - return simplicial_complex(input_faces) -end - -function symmetric_shift(F::Field, K::SimplicialComplex, w::WeylGroupElem) - iso = isomorphism(PermGroup, parent(w)) - return symmetric_shift(F, K, iso(w)) + @vprint :AlgebraicShifting 1 "Number of random shifts computed: $count\n" + return shift end diff --git a/experimental/AlgebraicShifting/src/SymmetricShift.jl b/experimental/AlgebraicShifting/src/SymmetricShift.jl new file mode 100644 index 000000000000..c91bc9807dcc --- /dev/null +++ b/experimental/AlgebraicShifting/src/SymmetricShift.jl @@ -0,0 +1,73 @@ + +############################################################################### +# Symmetric shift +############################################################################### + +""" + symmetric_shift(F::Field, K::SimplicialComplex) + +Returns the symmetric shift of `K` + +TODO: add more docs and and expose for users +""" +function symmetric_shift(F::Field, K::SimplicialComplex, p::PermGroupElem) + n = n_vertices(K) + Fy, y = polynomial_ring(F, :y => (1:n, 1:n); cached=false) + change_of_basis = rothe_matrix(Fy, p) * permutation_matrix(ZZ, p) * generic_unipotent_matrix(Fy) + + Rx, x = polynomial_ring(Fy, n) + # the generators of the stanley reisner ideal are combinations of [x_1, ..., x_n] + R_K, _ = stanley_reisner_ring(Rx, K) + + # the computation is a over the field of fractions Fyx + # we use a different ring to generate monomial_basis, coefficients need to be a field, + # but we want to avoid using fraction field of Ry during row reduction + mb_ring, z = graded_polynomial_ring(F, n; cached=false) + input_faces = Vector{Int}[] + for r in 2:dim(K) + 1 + mb = reverse(monomial_basis(mb_ring, r)) + A = Vector{elem_type(Fy)}[] + mb_exponents = first.(collect.(exponents.(mb))) # gets monomial exponents + + for b in mb + # need to compare with some alternatives + transformed_monomial = evaluate(b, change_of_basis * gens(R_K)) + + # we need to iterate through exponents here since the functions terms, coefficients or exponents + # do not return 0 terms and we need to make sure the generic col aligns with the others + # this is needed for the case when the field has finite characteristic + # we use the lift because currently there is no function to get the coeff of + # a MPolyQuoRingElem, which means we also need to check if it's zero before adding the coefficient + col = [ + !is_zero(R_K(monomial(Rx, e))) ? coeff(lift(transformed_monomial), e) : Fy(0) + for e in mb_exponents] + push!(A, col) + end + C = matrix(Fy, reduce(hcat, A)) + Oscar.ModStdQt.ref_ff_rc!(C) + smallest_basis_el = z[r]^r + smallest_index = findfirst(a -> a == smallest_basis_el, mb) + col_indices = filter(x -> x >= smallest_index, independent_columns(C)) + monomial_exponents = first.(exponents.(mb[col_indices])) + + # adjustment to convert monomial to simplex + for me in monomial_exponents + shifted_set = Int[] + index_count = 1 + for (i, e) in enumerate(me) + for j in 1:e + push!(shifted_set, i - (r - index_count)) + index_count += 1 + end + end + push!(input_faces, shifted_set) + end + end + + return simplicial_complex(input_faces) +end + +function symmetric_shift(F::Field, K::SimplicialComplex, w::WeylGroupElem) + iso = isomorphism(PermGroup, parent(w)) + return symmetric_shift(F, K, iso(w)) +end diff --git a/src/Oscar.jl b/src/Oscar.jl index 2f89eea2b9fa..c6eebc9fec38 100644 --- a/src/Oscar.jl +++ b/src/Oscar.jl @@ -140,6 +140,9 @@ function __init__() __GAP_info_messages_off() __init_group_libraries() + add_verbosity_scope(:AlgebraicShifting) + add_assertion_scope(:AlgebraicShifting) + add_verbosity_scope(:K3Auto) add_assertion_scope(:K3Auto) From 35b1ec09f62eaba634fc7307f739f6592c55f37e Mon Sep 17 00:00:00 2001 From: antonydellavecchia Date: Tue, 17 Dec 2024 18:22:08 +0100 Subject: [PATCH 8/9] random rothe matrix for finite fields --- .../AlgebraicShifting/src/PartialShift.jl | 27 ++++++++++++++----- 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/experimental/AlgebraicShifting/src/PartialShift.jl b/experimental/AlgebraicShifting/src/PartialShift.jl index 3d5f6d17d58f..1a49a2ee9709 100644 --- a/experimental/AlgebraicShifting/src/PartialShift.jl +++ b/experimental/AlgebraicShifting/src/PartialShift.jl @@ -343,19 +343,34 @@ exterior_shift(K::ComplexOrHypergraph; kw...) = exterior_shift(QQ, K; kw...) ################################################################################ # Las Vegas Partial Shifting -function random_rothe_matrix(p::PermGroupElem) +function random_rothe_matrix(F::QQField, p::PermGroupElem) n = degree(parent(p)) - u = identity_matrix(QQ, n) + u = identity_matrix(F, n) for (i, j) in inversions(p) - # random.seed!(UInt) - u[i, j] = QQ(Rational(rand() - 0.5)) + u[i, j] = F(Rational(rand() - 0.5)) end - return u * permutation_matrix(QQ, p) + return u * permutation_matrix(F, p) +end + +function random_rothe_matrix(F::Field, p::PermGroupElem) + @req !iszero(characteristic(F)) "Field should have positive characteristic" + range = characteristic(F) + n = degree(parent(p)) + u = identity_matrix(F, n) + for (i, j) in inversions(p) + u[i, j] = F(rand(1:char-1)) + end + return u * permutation_matrix(F, p) +end + +function random_shift(F::QQField, K::ComplexOrHypergraph, p::PermGroupElem;) + n = n_vertices(K) + exterior_shift(K, random_rothe_matrix(F, p)) end function random_shift(F::Field, K::ComplexOrHypergraph, p::PermGroupElem;) n = n_vertices(K) - exterior_shift(K, random_rothe_matrix(p)) + exterior_shift(K, random_rothe_matrix(F, p)) end random_shift(K::ComplexOrHypergraph, p::PermGroupElem) = random_shift(QQ, K, p) From 484fcd610f58c41456a105bdb5a37da495bacb7f Mon Sep 17 00:00:00 2001 From: antonydellavecchia Date: Tue, 17 Dec 2024 18:33:31 +0100 Subject: [PATCH 9/9] seperated las vegas style for finite fields --- .../AlgebraicShifting/src/PartialShift.jl | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/experimental/AlgebraicShifting/src/PartialShift.jl b/experimental/AlgebraicShifting/src/PartialShift.jl index 1a49a2ee9709..97f053077283 100644 --- a/experimental/AlgebraicShifting/src/PartialShift.jl +++ b/experimental/AlgebraicShifting/src/PartialShift.jl @@ -358,17 +358,17 @@ function random_rothe_matrix(F::Field, p::PermGroupElem) n = degree(parent(p)) u = identity_matrix(F, n) for (i, j) in inversions(p) - u[i, j] = F(rand(1:char-1)) + u[i, j] = F(rand(1:range)) end return u * permutation_matrix(F, p) end -function random_shift(F::QQField, K::ComplexOrHypergraph, p::PermGroupElem;) +function random_shift(F::QQField, K::ComplexOrHypergraph, p::PermGroupElem) n = n_vertices(K) exterior_shift(K, random_rothe_matrix(F, p)) end -function random_shift(F::Field, K::ComplexOrHypergraph, p::PermGroupElem;) +function random_shift(F::Field, K::ComplexOrHypergraph, p::PermGroupElem) n = n_vertices(K) exterior_shift(K, random_rothe_matrix(F, p)) end @@ -414,6 +414,20 @@ function check_shifted(F::Field, src::SimplicialComplex, end function exterior_shift_lv(F::Field, K::ComplexOrHypergraph, p::PermGroupElem) + # this might need to be changed based on the characteristic + # we expect that the larger the characteristic the smaller the sample needs to be + # setting to 100 now for good measure + sample_size = 100 + shift = partialsort!([random_shift(F, K, p) for _ in 1:sample_size], 1; + lt=isless_lex) + + check_shifted(F, K, shift, p) && return shift + + # this should be updated to not throw an error + error("Could not find the full shift using $sample_size samples") +end + +function exterior_shift_lv(F::QQField, K::ComplexOrHypergraph, p::PermGroupElem) shift = random_shift(F, K, p) count = 1 while !check_shifted(F, K, shift, p)