From e7d1cf8f68a6593c8ffa2de95630137f6bfc78fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20G=C3=B6ttgens?= Date: Wed, 18 Oct 2023 17:47:23 +0200 Subject: [PATCH 01/27] Add stdlib compat bounds to `test/Project.toml` (#2928) --- test/Project.toml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/Project.toml b/test/Project.toml index b4bd5000790f..ef473db5904c 100644 --- a/test/Project.toml +++ b/test/Project.toml @@ -9,4 +9,9 @@ Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" [compat] Aqua = "0.7" +Distributed = "1.6" Documenter = "0.27, 1.0" +PrettyTables = "2.2.7" +Printf = "1.6" +Random = "1.6" +Test = "1.6" From a98d2d55152b1b29655ab92dd968d90a99238481 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Wed, 18 Oct 2023 18:09:19 +0200 Subject: [PATCH 02/27] Compare 'nothing' using === in more places (#2933) --- src/Combinatorics/Matroids/matroids.jl | 2 +- src/Combinatorics/Matroids/properties.jl | 2 +- src/Groups/matrices/MatGrp.jl | 6 ++++-- src/Modules/ModulesGraded.jl | 2 +- src/TropicalGeometry/groebner_fan.jl | 2 +- 5 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/Combinatorics/Matroids/matroids.jl b/src/Combinatorics/Matroids/matroids.jl index 20bac8879b83..03598d7d7ae3 100644 --- a/src/Combinatorics/Matroids/matroids.jl +++ b/src/Combinatorics/Matroids/matroids.jl @@ -43,7 +43,7 @@ Matroid of rank 3 on 7 elements ``` """ function matroid_from_revlex_basis_encoding(rvlx::String, r::IntegerUnion, n::IntegerUnion) - if match(r"[^*0]",rvlx)!=nothing + if match(r"[^*0]",rvlx) !== nothing error("The revlex encoding uses only `*` and `0`") end if length(rvlx)!= binomial(n,r) diff --git a/src/Combinatorics/Matroids/properties.jl b/src/Combinatorics/Matroids/properties.jl index b820a74a72fd..f5d1d2e28c03 100644 --- a/src/Combinatorics/Matroids/properties.jl +++ b/src/Combinatorics/Matroids/properties.jl @@ -161,7 +161,7 @@ function flats_impl(M::Matroid, r::Union{Int,Nothing}, num_flats::Int, pm_flats) jl_flats = reverse(jl_flats) end matroid_flats = [[M.groundset[i] for i in flat] for flat in jl_flats] - if r != nothing + if r !== nothing if r<0 || r>rank(M) error("The specified rank needs to be between 0 and the rank of the matroid.") end diff --git a/src/Groups/matrices/MatGrp.jl b/src/Groups/matrices/MatGrp.jl index 5b9f3e85d6a5..4f88d7635bae 100644 --- a/src/Groups/matrices/MatGrp.jl +++ b/src/Groups/matrices/MatGrp.jl @@ -305,7 +305,9 @@ Base.in(x::MatElem, G::MatrixGroup) = lies_in(x,G,nothing)[1] function Base.in(x::MatrixGroupElem, G::MatrixGroup) isdefined(x,:X) && return lies_in(x.elm,G,x.X)[1] _is_true, x_gap = lies_in(x.elm,G,nothing) - if x_gap !=nothing x.X = x_gap end + if x_gap !== nothing + x.X = x_gap + end return _is_true end @@ -340,7 +342,7 @@ function (G::MatrixGroup)(x::MatrixGroupElem; check::Bool=true) else _is_true, x_gap = lies_in(x.elm,G,nothing) @req _is_true "Element not in the group" - if x_gap == nothing + if x_gap === nothing return MatrixGroupElem(G,x.elm) end return MatrixGroupElem(G,x.elm,x_gap) diff --git a/src/Modules/ModulesGraded.jl b/src/Modules/ModulesGraded.jl index bd87f1f77fb1..6affa0a4ebab 100644 --- a/src/Modules/ModulesGraded.jl +++ b/src/Modules/ModulesGraded.jl @@ -1374,7 +1374,7 @@ function Base.show(io::IO, b::BettiTable) column_widths[j] = max(col_width_from_sum, col_width_from_header) + 2 end - if b.project == nothing + if b.project === nothing for i in 1:ngens(parent(x[1][2])) ngens(parent(x[1][2])) > 1 && println(io, "Betti Table for component ", i) L = sort(unique(collect(x[k][2][i] for k in 1:length(x)))) diff --git a/src/TropicalGeometry/groebner_fan.jl b/src/TropicalGeometry/groebner_fan.jl index 66f08b5219c0..bca1461d3fe3 100644 --- a/src/TropicalGeometry/groebner_fan.jl +++ b/src/TropicalGeometry/groebner_fan.jl @@ -114,7 +114,7 @@ julia> G3 = [x1^2+x2,x2^2+x3,x3+1] x2^2 + x3 x3 + 1 -julia> homogeneity_vector(G3) == nothing +julia> homogeneity_vector(G3) === nothing true ``` From f9d829406c3cd231d09c633315d6474cfed397c1 Mon Sep 17 00:00:00 2001 From: Matthias Zach <85350711+HechtiDerLachs@users.noreply.github.com> Date: Wed, 18 Oct 2023 19:24:23 +0200 Subject: [PATCH 03/27] Exterior powers of finitely presented modules (#2879) * Implement a prototype for exterior powers of free modules. * Implement Koszul complexes associated to elements of free modules. * Preserve gradings and implement koszul dual bases. * Implement induced maps on exterior powers. * Some tweaks. * Move everything to appropriate places. * Implement iteration over module monomials of a specific degree. * Add trailing zeroes to the Koszul complex. * Allow custom parents and no caching. * Revert "Implement iteration over module monomials of a specific degree." This reverts commit 48b9752cd289ed9a0aad65abd160c475ce544cb3. * Extend optional caching to Koszul complexes. * Add extra multiplication function. * Some tweaks. * Customize printing. * Add pure and inv_pure. * Put the check back in. * Migrate the OrderedMultiIndex. * Export the new functionality. * Clean up the include statements. * Implement hom method. * Rename pure and decompose functions. * Migrate tests. * Clean up exports from LieAlgebra.jl. * Fix tests. * Some improvements in localizations. * Implement exterior powers for subquos. * Some fixes. * Reroute koszul complexes to use the non-Singular methods. * Deprecate old singular methods. * Repair Koszul homology. * Remove duplicate methods and use singular's depth. * Add tests. * Add some assertions. * Some tweaks for the ordered multiindices. * Pass on the check flag for construction of complexes. * Fix doctests and add a truely generic method for the depth computation. --- experimental/LieAlgebras/src/LieAlgebras.jl | 5 +- src/Combinatorics/OrderedMultiIndex.jl | 185 ++++++++++++++ src/Modules/ExteriorPowers/ExteriorPowers.jl | 4 + src/Modules/ExteriorPowers/FreeModules.jl | 192 +++++++++++++++ src/Modules/ExteriorPowers/Generic.jl | 184 ++++++++++++++ src/Modules/ExteriorPowers/SubQuo.jl | 81 +++++++ src/Modules/Modules.jl | 1 + src/Modules/UngradedModules.jl | 4 +- src/Modules/homological-algebra.jl | 238 ++++++++++++++----- src/Oscar.jl | 1 + src/Rings/mpoly-ideals.jl | 3 +- src/Rings/mpoly-localizations.jl | 10 + src/exports.jl | 6 + test/AlgebraicGeometry/Schemes/runtests.jl | 1 + test/Combinatorics/OrderedMultiIndex.jl | 27 +++ test/Combinatorics/runtests.jl | 1 + test/Modules/ExteriorPowers.jl | 180 ++++++++++++++ test/Modules/homological-algebra.jl | 49 +++- test/Modules/runtests.jl | 1 + 19 files changed, 1098 insertions(+), 75 deletions(-) create mode 100644 src/Combinatorics/OrderedMultiIndex.jl create mode 100644 src/Modules/ExteriorPowers/ExteriorPowers.jl create mode 100644 src/Modules/ExteriorPowers/FreeModules.jl create mode 100644 src/Modules/ExteriorPowers/Generic.jl create mode 100644 src/Modules/ExteriorPowers/SubQuo.jl create mode 100644 test/Combinatorics/OrderedMultiIndex.jl create mode 100644 test/Modules/ExteriorPowers.jl diff --git a/experimental/LieAlgebras/src/LieAlgebras.jl b/experimental/LieAlgebras/src/LieAlgebras.jl index d062077d1a39..9200fa18e83e 100644 --- a/experimental/LieAlgebras/src/LieAlgebras.jl +++ b/experimental/LieAlgebras/src/LieAlgebras.jl @@ -41,6 +41,7 @@ import ..Oscar: image, inv, is_abelian, + is_exterior_power, is_isomorphism, is_nilpotent, is_perfect, @@ -82,14 +83,12 @@ export coefficient_vector export coerce_to_lie_algebra_elem export combinations export derived_algebra -export exterior_power export general_linear_lie_algebra export highest_weight_module export hom_direct_sum export hom_power export is_direct_sum export is_dual -export is_exterior_power export is_self_normalizing export is_standard_module export is_symmetric_power @@ -143,14 +142,12 @@ export base_modules export bracket export coerce_to_lie_algebra_elem export derived_algebra -export exterior_power export general_linear_lie_algebra export highest_weight_module export hom_direct_sum export hom_power export is_direct_sum export is_dual -export is_exterior_power export is_self_normalizing export is_standard_module export is_symmetric_power diff --git a/src/Combinatorics/OrderedMultiIndex.jl b/src/Combinatorics/OrderedMultiIndex.jl new file mode 100644 index 000000000000..8e8eaf630dca --- /dev/null +++ b/src/Combinatorics/OrderedMultiIndex.jl @@ -0,0 +1,185 @@ +######################################################################## +# Ordered multiindices of the form 0 < i₁ < i₂ < … < iₚ ≤ n. +# +# For instance, these provide a coherent way to enumerate the generators +# of an exterior power ⋀ ᵖ M of a module M given a chosen set of +# generators of M. But they can also be used for other purposes +# like enumerating subsets of p elements out of a set with n elements. +######################################################################## +mutable struct OrderedMultiIndex{IntType<:IntegerUnion} + i::Vector{IntType} + n::IntType + + function OrderedMultiIndex(i::Vector{T}, n::T) where {T<:IntegerUnion} + @assert all(k->i[k](x in indices(b)), indices(a)) && return 0, indices(a) + + p = length(a) + q = length(b) + result_indices = vcat(indices(a), indices(b)) + sign = 1 + + # bubble sort result_indices and keep track of the sign + for k in p:-1:1 + l = k + c = result_indices[l] + while l < p + q && c > result_indices[l+1] + result_indices[l] = result_indices[l+1] + sign = -sign + l = l+1 + end + result_indices[l] = c + end + return sign, result_indices +end + +# For two ordered multiindices i = (0 < i₁ < i₂ < … < iₚ ≤ n) +# and j = (0 < j₁ < j₂ < … < jᵣ ≤ n) this returns a pair `(sign, a)` +# with `sign` either 0 in case that iₖ = jₗ for some k and l, +# or ±1 depending on the number of transpositions needed to put +# (i₁, …, iₚ, j₁, …, jᵣ) into a strictly increasing order to produce `a`. +function _wedge(a::OrderedMultiIndex{T}, b::OrderedMultiIndex{T}) where {T} + sign, ind = _mult(a, b) + iszero(sign) && return sign, a + return sign, OrderedMultiIndex(ind, bound(a)) +end + +function _wedge(a::Vector{T}) where {T <: OrderedMultiIndex} + isempty(a) && error("list must not be empty") + isone(length(a)) && return 1, first(a) + k = div(length(a), 2) + b = a[1:k] + c = a[k+1:end] + sign_b, ind_b = _wedge(b) + sign_c, ind_c = _wedge(c) + sign, ind = _wedge(ind_b, ind_c) + return sign * sign_b * sign_c, ind +end + +function ==(a::OrderedMultiIndex{T}, b::OrderedMultiIndex{T}) where {T} + return bound(a) == bound(b) && indices(a) == indices(b) +end + +######################################################################## +# A data type to facilitate iteration over all ordered multiindices +# of the form 0 < i₁ < i₂ < … < iₚ ≤ n for fixed 0 ≤ p ≤ n. +# +# Example: +# +# for i in OrderedMultiIndexSet(3, 5) +# # do something with i = (0 < i₁ < i₂ < i₃ ≤ 5). +# end +######################################################################## +mutable struct OrderedMultiIndexSet + n::Int + p::Int + + function OrderedMultiIndexSet(p::Int, n::Int) + @assert 0 <= p <= n "invalid bounds" + return new(n, p) + end +end + +bound(I::OrderedMultiIndexSet) = I.n +index_length(I::OrderedMultiIndexSet) = I.p + +Base.eltype(I::OrderedMultiIndexSet) = OrderedMultiIndex +Base.length(I::OrderedMultiIndexSet) = binomial(bound(I), index_length(I)) + +function Base.iterate(I::OrderedMultiIndexSet) + ind = OrderedMultiIndex([i for i in 1:index_length(I)], bound(I)) + return ind, ind +end + +function Base.iterate(I::OrderedMultiIndexSet, state::OrderedMultiIndex) + bound(I) == bound(state) || error("index not compatible with set") + ind = copy(indices(state)) + l = length(state) + while l > 0 && ind[l] == bound(I) - length(state) + l + l = l - 1 + end + iszero(l) && return nothing + ind[l] = ind[l] + 1 + l = l + 1 + while l <= length(state) + ind[l] = ind[l-1] + 1 + l = l + 1 + end + result = OrderedMultiIndex(ind, bound(I)) + return result, result +end + +function Base.show(io::IO, ind::OrderedMultiIndex) + i = indices(ind) + print(io, "0 ") + for i in indices(ind) + print(io, "< $i ") + end + print(io, "<= $(bound(ind))") +end + +# For an ordered multiindex i = (0 < i₁ < i₂ < … < iₚ ≤ n) this +# returns the number k so that i appears at the k-th spot in the +# enumeration of all ordered multiindices for this pair 0 ≤ p ≤ n. +function linear_index(ind::OrderedMultiIndex) + n = bound(ind) + p = length(ind) + iszero(p) && return 1 + isone(p) && return ind[1] + i = indices(ind) + return binomial(n, p) - binomial(n - first(i) + 1, p) + linear_index(OrderedMultiIndex(i[2:end].-first(i), n-first(i))) +end + +# For a pair 0 ≤ p ≤ n return the k-th ordered multiindex in the +# enumeration of all ordered multiindices (0 < i₁ < i₂ < … < iₚ ≤ n). +function ordered_multi_index(k::Int, p::Int, n::Int) + (k < 1 || k > binomial(n, p)) && error("index out of range") + iszero(p) && return OrderedMultiIndex(Int[], n) + isone(p) && return OrderedMultiIndex([k], n) + n == p && return OrderedMultiIndex([k for k in 1:n], n) + bin = binomial(n, p) + i1 = findfirst(j->(bin - binomial(n - j, p) > k - 1), 1:n-p) + if i1 === nothing + prev_res = ordered_multi_index(k - bin + 1, p-1, p-1) + k = n-p+1 + return OrderedMultiIndex(pushfirst!(indices(prev_res).+k, k), n) + else + prev_res = ordered_multi_index(k - bin + binomial(n - i1 + 1, p), p-1, n - i1) + return OrderedMultiIndex(pushfirst!(indices(prev_res).+i1, i1), n) + end +end + diff --git a/src/Modules/ExteriorPowers/ExteriorPowers.jl b/src/Modules/ExteriorPowers/ExteriorPowers.jl new file mode 100644 index 000000000000..d09a136908d8 --- /dev/null +++ b/src/Modules/ExteriorPowers/ExteriorPowers.jl @@ -0,0 +1,4 @@ +#include("Helpers.jl") Moved to src/Combinatorics/OrderedMultiIndex.jl +include("FreeModules.jl") +include("SubQuo.jl") +include("Generic.jl") diff --git a/src/Modules/ExteriorPowers/FreeModules.jl b/src/Modules/ExteriorPowers/FreeModules.jl new file mode 100644 index 000000000000..a40481dc0f88 --- /dev/null +++ b/src/Modules/ExteriorPowers/FreeModules.jl @@ -0,0 +1,192 @@ +######################################################################## +# Exterior powers of free modules +# +# For F = Rⁿ we provide methods to create ⋀ ᵖF for arbitrary 0 ≤ p ≤ n. +# These modules are cached in F and know that they are an exterior +# power of F. This allows us to implement the wedge product of their +# elements. +######################################################################## + +# User facing constructor for ⋀ ᵖ F. +function exterior_power(F::FreeMod, p::Int; cached::Bool=true) + (p < 0 || p > rank(F)) && error("index out of bounds") + + if cached + powers = _exterior_powers(F) + haskey(powers, p) && return powers[p]::Tuple{typeof(F), <:Map} + end + + R = base_ring(F) + n = rank(F) + result = FreeMod(R, binomial(n, p)) + + # In case F was graded, we have to take an extra detour. + if is_graded(F) + G = grading_group(F) + weights = elem_type(G)[] + for ind in OrderedMultiIndexSet(p, n) + push!(weights, sum(degree(F[i]) for i in indices(ind); init=zero(G))) + end + result = grade(result, weights) + end + + # Create the multiplication map + function my_mult(u::FreeModElem...) + isempty(u) && return result[1] # only the case p=0 + @assert all(x->parent(x)===F, u) "elements must live in the same module" + @assert length(u) == p "need a $p-tuple of elements" + return wedge(collect(u), parent=result) + end + function my_mult(u::Tuple) + return my_mult(u...) + end + + function my_decomp(u::FreeModElem) + parent(u) === result || error("element does not belong to the correct module") + k = findfirst(x->x==u, gens(result)) + k === nothing && error("element must be a generator of the module") + ind = ordered_multi_index(k, p, n) + e = gens(F) + return Tuple(e[i] for i in indices(ind)) + end + + mult_map = MapFromFunc(Hecke.TupleParent(Tuple([zero(F) for f in 1:p])), result, my_mult, my_decomp) + inv_mult_map = MapFromFunc(result, domain(mult_map), my_decomp, my_mult) + @assert domain(mult_map) === parent(Tuple(zero(F) for i in 1:p)) "something went wrong with the parents" + + # Store the map in the attributes + set_attribute!(result, :multiplication_map, mult_map) + set_attribute!(result, :wedge_pure_function, mult_map) + set_attribute!(result, :wedge_generator_decompose_function, inv_mult_map) + set_attribute!(result, :is_exterior_power, (F, p)) + + cached && (_exterior_powers(F)[p] = (result, mult_map)) + + # Set the variable names for printing + orig_symb = String.(symbols(F)) + new_symb = Symbol[] + if iszero(p) + new_symb = [Symbol("1")] + else + for ind in OrderedMultiIndexSet(p, n) + symb_str = orig_symb[ind[1]] + for i in 2:p + symb_str = symb_str * "∧" * orig_symb[ind[i]] + end + push!(new_symb, Symbol(symb_str)) + end + end + result.S = new_symb + + set_attribute!(result, :show => show_exterior_product) + + return result, mult_map +end + +function symbols(F::FreeMod) + return F.S +end + + +######################################################################## +# Koszul homology +######################################################################## + +function koszul_complex(v::FreeModElem; cached::Bool=true) + F = parent(v) + R = base_ring(F) + n = rank(F) + ext_powers = [exterior_power(F, p, cached=cached)[1] for p in 0:n] + boundary_maps = [wedge_multiplication_map(ext_powers[i+1], ext_powers[i+2], v) for i in 0:n-1] + Z = is_graded(F) ? graded_free_module(R, []) : free_module(R, 0) + pushfirst!(boundary_maps, hom(Z, domain(first(boundary_maps)), elem_type(domain(first(boundary_maps)))[])) + push!(boundary_maps, hom(codomain(last(boundary_maps)), Z, [zero(Z) for i in 1:ngens(codomain(last(boundary_maps)))])) + return chain_complex(boundary_maps, seed=-1, check=false) +end + +function koszul_complex(v::FreeModElem, M::ModuleFP; cached::Bool=true) + K = koszul_complex(v, cached=cached) + KM = tensor_product(K, M) + return KM +end + +function koszul_homology(v::FreeModElem, i::Int; cached::Bool=true) + F = parent(v) + n = rank(F) + + # Catch the edge cases + if i == n # This captures the homological degree zero due to the convention of the chain_complex constructor + phi = wedge_multiplication_map(exterior_power(F, 0, cached=cached)[1], F, v) + return kernel(phi)[1] + end + + if iszero(i) # Homology at the last entry of the complex. + phi = wedge_multiplication_map(exterior_power(F, n-1)[1], exterior_power(F, n, cached=cached)[1], v) + return cokernel(phi)[1] + end + + ext_powers = [exterior_power(F, n-p, cached=cached)[1] for p in i-1:i+1] + boundary_maps = [wedge_multiplication_map(ext_powers[p+1], ext_powers[p], v) for p in 2:-1:1] + K = chain_complex(boundary_maps, check=false) + return homology(K, 1) +end + +function koszul_homology(v::FreeModElem, M::ModuleFP, i::Int; cached::Bool=true) + F = parent(v) + n = rank(F) + + # Catch the edge cases + if i == n # This captures the homological degree zero due to the convention of the chain_complex constructor + phi = wedge_multiplication_map(exterior_power(F, 0, cached=cached)[1], F, v) + K = chain_complex([phi], check=false) + KM = tensor_product(K, M) + return kernel(map(KM, 1))[1] + end + + if iszero(i) # Homology at the last entry of the complex. + phi = wedge_multiplication_map(exterior_power(F, n-1)[1], exterior_power(F, n, cached=cached)[1], v) + K = chain_complex([phi], check=false) + KM = tensor_product(K, M) + return cokernel(map(K, 1)) # TODO: cokernel does not seem to return a map by default. Why? + end + + ext_powers = [exterior_power(F, n-p, cached=cached)[1] for p in i-1:i+1] + boundary_maps = [wedge_multiplication_map(ext_powers[p+1], ext_powers[p], v) for p in 2:-1:1] + K = chain_complex(boundary_maps, check=false) + KM = tensor_product(K, M) + return homology(KM, 1) +end + +function koszul_dual(F::FreeMod; cached::Bool=true) + success, M, p = is_exterior_power(F) + !success && error("module must be an exterior power of some other module") + return exterior_power(M, rank(M) - p, cached=cached)[1] +end + +function koszul_duals(v::Vector{T}; cached::Bool=true) where {T<:FreeModElem} + isempty(v) && error("list of elements must not be empty") + all(u->parent(u) === parent(first(v)), v[2:end]) || error("parent mismatch") + + F = parent(first(v)) + success, M, p = is_exterior_power(F) + n = rank(M) + success || error("element must be an exterior product") + k = [findfirst(x->x==u, gens(F)) for u in v] + any(x->x===nothing, k) && error("elements must be generators of the module") + ind = [ordered_multi_index(r, p, n) for r in k] + comp = [ordered_multi_index([i for i in 1:n if !(i in indices(I))], n) for I in ind] + lin_ind = linear_index.(comp) + F_dual = koszul_dual(F, cached=cached) + results = [F_dual[j] for j in lin_ind] + for r in 1:length(v) + sign, _ = _wedge(ind[r], comp[r]) + isone(sign) || (results[r] = -results[r]) + end + return results +end + +function koszul_dual(v::FreeModElem; cached::Bool=true) + return first(koszul_duals([v], cached=cached)) +end + + diff --git a/src/Modules/ExteriorPowers/Generic.jl b/src/Modules/ExteriorPowers/Generic.jl new file mode 100644 index 000000000000..40f43cec914f --- /dev/null +++ b/src/Modules/ExteriorPowers/Generic.jl @@ -0,0 +1,184 @@ +# We need to cache eventually created exterior powers. +@attr Dict{Int, Tuple{T, <:Map}} function _exterior_powers(F::T) where {T<:ModuleFP} + return Dict{Int, Tuple{typeof(F), Map}}() +end + +# User facing method to ask whether F = ⋀ ᵖ M for some M. +# This returns a triple `(true, M, p)` in the affirmative case +# and `(false, F, 0)` otherwise. +function is_exterior_power(M::ModuleFP) + if has_attribute(M, :is_exterior_power) + MM, p = get_attribute(M, :is_exterior_power) + return (true, MM, p) + end + return (false, M, 0) +end + +# Printing of exterior powers +function show_exterior_product(io::IO, M::ModuleFP) + success, F, p = is_exterior_power(M) + success || error("module is not an exterior power") + print(io, "⋀^$p($F)") +end + +function show_exterior_product(io::IO, ::MIME"text/html", M::ModuleFP) + success, F, p = is_exterior_power(M) + success || error("module is not an exterior power") + io = IOContext(io, :compact => true) + print(io, "⋀^$p$F") +end + +function multiplication_map(M::ModuleFP) + has_attribute(M, :multiplication_map) || error("module is not an exterior power") + return get_attribute(M, :multiplication_map)::Map +end + +function wedge_pure_function(M::ModuleFP) + has_attribute(M, :wedge_pure_function) || error("module is not an exterior power") + return get_attribute(M, :wedge_pure_function)::Map +end + +function wedge_generator_decompose_function(M::ModuleFP) + has_attribute(M, :wedge_generator_decompose_function) || error("module is not an exterior power") + return get_attribute(M, :wedge_generator_decompose_function)::Map +end + +# Given two exterior powers F = ⋀ ᵖM and G = ⋀ ʳM and an element +# v ∈ ⋀ ʳ⁻ᵖ M this constructs the module homomorphism associated +# to +# +# v ∧ - : F → G, u ↦ v ∧ u. +# +# We also allow v ∈ M considered as ⋀ ¹M and the same holds in +# the cases p = 1 and r = 1. +function wedge_multiplication_map(F::ModuleFP, G::ModuleFP, v::ModuleFPElem) + success, orig_mod, p = is_exterior_power(F) + if !success + Fwedge1, _ = exterior_power(F, 1) + id = hom(F, Fwedge1, gens(Fwedge1)) + tmp = wedge_multiplication_map(Fwedge1, G, v) + return compose(id, tmp) + end + + success, orig_mod_2, q = is_exterior_power(G) + if !success + Gwedge1, _ = exterior_power(G, 1) + id = hom(Gwedge1, G, gens(G)) + tmp = wedge_multiplication_map(F, Gwedge1, v) + return compose(tmp, id) + end + + orig_mod === orig_mod_2 || error("modules must be exterior powers of the same module") + H = parent(v) + + # In case v comes from the original module, convert. + if H === orig_mod + M, _ = exterior_power(orig_mod, 1) + w = M(coordinates(v)) + return wedge_multiplication_map(F, G, w) + end + + success, orig_mod_2, r = is_exterior_power(H) + success || error("element is not an exterior product") + orig_mod_2 === orig_mod || error("element is not an exterior product for the correct module") + p + r == q || error("powers are incompatible") + + # map the generators + img_gens = [wedge(v, e, parent=G) for e in gens(F)] + return hom(F, G, img_gens) +end + +# The wedge product of two or more elements. +function wedge(u::ModuleFPElem, v::ModuleFPElem; + parent::ModuleFP=begin + success, F, p = is_exterior_power(Oscar.parent(u)) + if !success + F = Oscar.parent(u) + p = 1 + end + success, _, q = is_exterior_power(Oscar.parent(v)) + !success && (q = 1) + exterior_power(F, p + q)[1] + end + ) + success1, F1, p = is_exterior_power(Oscar.parent(u)) + if !success1 + F = Oscar.parent(u) + Fwedge1, _ = exterior_power(F1, 1) + return wedge(Fwedge1(coordinates(u)), v, parent=parent) + end + + success2, F2, q = is_exterior_power(Oscar.parent(v)) + if !success2 + F = Oscar.parent(v) + Fwedge1, _ = exterior_power(F1, 1) + return wedge(u, Fwedge1(coordinates(v)), parent=parent) + end + + F1 === F2 || error("modules are not exterior powers of the same original module") + n = ngens(F1) + + result = zero(parent) + for (i, a) in coordinates(u) + ind_i = ordered_multi_index(i, p, n) + for (j, b) in coordinates(v) + ind_j = ordered_multi_index(j, q, n) + sign, k = _wedge(ind_i, ind_j) + iszero(sign) && continue + result = result + sign * a * b * parent[linear_index(k)] + end + end + return result +end + +function wedge(u::Vector{T}; + parent::ModuleFP=begin + r = 0 + isempty(u) && error("list must not be empty") + F = Oscar.parent(first(u)) # initialize variable + for v in u + success, F, p = is_exterior_power(Oscar.parent(v)) + if !success + F = Oscar.parent(v) + p = 1 + end + r = r + p + end + exterior_power(F, r)[1] + end + ) where {T<:ModuleFPElem} + isempty(u) && error("list must not be empty") + isone(length(u)) && return first(u) + k = div(length(u), 2) + result = wedge(wedge(u[1:k]), wedge(u[k+1:end]), parent=parent) + @assert Oscar.parent(result) === parent + return result +end + +function induced_map_on_exterior_power(phi::FreeModuleHom{<:FreeMod, <:FreeMod, Nothing}, p::Int; + domain::FreeMod=exterior_power(Oscar.domain(phi), p)[1], + codomain::FreeMod=exterior_power(Oscar.codomain(phi), p)[1] + ) + F = Oscar.domain(phi) + m = rank(F) + G = Oscar.codomain(phi) + n = rank(G) + + imgs = phi.(gens(F)) + img_gens = [wedge(imgs[indices(ind)], parent=codomain) for ind in OrderedMultiIndexSet(p, m)] + return hom(domain, codomain, img_gens) +end + +# The induced map on exterior powers +function hom(M::FreeMod, N::FreeMod, phi::FreeModuleHom) + success, F, p = is_exterior_power(M) + success || error("module is not an exterior power") + success, FF, q = is_exterior_power(N) + success || error("module is not an exterior power") + F === domain(phi) || error("map not compatible") + FF === codomain(phi) || error("map not compatible") + p == q || error("exponents must agree") + return induced_map_on_exterior_power(phi, p, domain=M, codomain=N) +end + + diff --git a/src/Modules/ExteriorPowers/SubQuo.jl b/src/Modules/ExteriorPowers/SubQuo.jl new file mode 100644 index 000000000000..2659f108994f --- /dev/null +++ b/src/Modules/ExteriorPowers/SubQuo.jl @@ -0,0 +1,81 @@ +function exterior_power(M::SubquoModule, p::Int; cached::Bool=true) + n = rank(ambient_free_module(M)) + R = base_ring(M) + ((p >= 0) && (p <= n)) || error("exponent out of range") + + if cached + powers = _exterior_powers(M) + haskey(powers, p) && return powers[p] + end + + result = M # Initialize variable + if iszero(p) + F = FreeMod(R, 1) + result, _ = sub(F, [F[1]]) + else + C = presentation(M) + phi = map(C, 1) + result, mm = _exterior_power(phi, p) + end + + function my_mult(u::SubquoModuleElem...) + isempty(u) && return result[1] # only the case p=0 + @assert all(x->parent(x)===M, u) "elements must live in the same module" + @assert length(u) == p "need a $p-tuple of elements" + return wedge(collect(u), parent=result) + end + function my_mult(u::Tuple) + return my_mult(u...) + end + + function my_decomp(u::SubquoModuleElem) + parent(u) === result || error("element does not belong to the correct module") + k = findfirst(x->x==u, gens(result)) + k === nothing && error("element must be a generator of the module") + ind = ordered_multi_index(k, p, n) + e = gens(M) + return Tuple(e[i] for i in indices(ind)) + end + + mult_map = MapFromFunc(Hecke.TupleParent(Tuple([zero(M) for f in 1:p])), result, my_mult, my_decomp) + inv_mult_map = MapFromFunc(result, domain(mult_map), my_decomp, my_mult) + + set_attribute!(result, :multiplication_map, mult_map) + set_attribute!(result, :wedge_pure_function, mult_map) + set_attribute!(result, :wedge_generator_decompose_function, inv_mult_map) + + set_attribute!(result, :is_exterior_power, (M, p)) + cached && (_exterior_powers(M)[p] = (result, mult_map)) + + # Set the variable names for printing + orig_symb = ["$(e)" for e in ambient_representatives_generators(M)] + new_symb = Symbol[] + if iszero(p) + new_symb = [Symbol("1")] + else + for ind in OrderedMultiIndexSet(p, n) + symb_str = orig_symb[ind[1]] + for i in 2:p + symb_str = symb_str * "∧" * orig_symb[ind[i]] + end + push!(new_symb, Symbol(symb_str)) + end + end + + symbols(result) = new_symb + return result, mult_map +end + +function _exterior_power(phi::FreeModuleHom, p::Int) + F = codomain(phi) + R = base_ring(F) + rel = domain(phi) + Fp, mult_map = exterior_power(F, p) + Fq, _ = exterior_power(F, p-1) + img_gens = [wedge(e, f) for e in gens(Fq) for f in phi.(gens(rel))] + G = FreeMod(R, length(img_gens)) + psi = hom(G, Fp, img_gens) + # TODO: the `cokernel` command does not have consistent output over all types of rings. + return (base_ring(codomain(phi)) isa Union{MPolyLocRing, MPolyQuoLocRing} ? cokernel(psi)[1] : cokernel(psi)), mult_map +end + diff --git a/src/Modules/Modules.jl b/src/Modules/Modules.jl index 2250bd9944a2..e4fb0dde98f7 100644 --- a/src/Modules/Modules.jl +++ b/src/Modules/Modules.jl @@ -8,4 +8,5 @@ include("ModulesGraded.jl") include("module-localizations.jl") include("local_rings.jl") include("mpolyquo.jl") +include("ExteriorPowers/ExteriorPowers.jl") diff --git a/src/Modules/UngradedModules.jl b/src/Modules/UngradedModules.jl index 1271711be57d..ae175fe8e861 100644 --- a/src/Modules/UngradedModules.jl +++ b/src/Modules/UngradedModules.jl @@ -4060,8 +4060,8 @@ function chain_complex(V::ModuleFPHom...; seed::Int = 0) return ComplexOfMorphisms(ModuleFP, collect(V); typ = :chain, seed = seed) end -function chain_complex(V::Vector{<:ModuleFPHom}; seed::Int = 0) - return ComplexOfMorphisms(ModuleFP, V; typ = :chain, seed = seed) +function chain_complex(V::Vector{<:ModuleFPHom}; seed::Int = 0, check::Bool=true) + return ComplexOfMorphisms(ModuleFP, V; typ = :chain, seed = seed, check=check) end #################### diff --git a/src/Modules/homological-algebra.jl b/src/Modules/homological-algebra.jl index dd89ff51b79e..a34f2ccd649f 100644 --- a/src/Modules/homological-algebra.jl +++ b/src/Modules/homological-algebra.jl @@ -289,23 +289,27 @@ julia> V = [x*y, x*z, y*z] y*z julia> koszul_homology(V, F, 0) -Submodule with 3 generators -1 -> y*z*e[1] -2 -> x*z*e[1] -3 -> x*y*e[1] -represented as subquotient with no relations. +Subquotient of Submodule with 1 generator +1 -> e[1]∧e[2]∧e[3] +by Submodule with 3 generators +1 -> y*z*e[1]∧e[2]∧e[3] +2 -> -x*z*e[1]∧e[2]∧e[3] +3 -> x*y*e[1]∧e[2]∧e[3] julia> koszul_homology(V, F, 1) -Submodule with 3 generators -1 -> -z*e[1] + z*e[2] -2 -> y*e[2] -3 -> x*e[1] -represented as subquotient with no relations. +Subquotient of Submodule with 2 generators +1 -> y*e[1]∧e[3] \otimes e[1] + z*e[2]∧e[3] \otimes e[1] +2 -> x*e[1]∧e[2] \otimes e[1] - z*e[2]∧e[3] \otimes e[1] +by Submodule with 3 generators +1 -> -x*z*e[1]∧e[2] \otimes e[1] - y*z*e[1]∧e[3] \otimes e[1] +2 -> x*y*e[1]∧e[2] \otimes e[1] - y*z*e[2]∧e[3] \otimes e[1] +3 -> x*y*e[1]∧e[3] \otimes e[1] + x*z*e[2]∧e[3] \otimes e[1] julia> koszul_homology(V, F, 2) -Submodule with 1 generator -1 -> 0 -represented as subquotient with no relations. +Subquotient of Submodule with 1 generator +1 -> x*y*e[1] \otimes e[1] + x*z*e[2] \otimes e[1] + y*z*e[3] \otimes e[1] +by Submodule with 1 generator +1 -> x*y*e[1] \otimes e[1] + x*z*e[2] \otimes e[1] + y*z*e[3] \otimes e[1] ``` ```jldoctest @@ -316,46 +320,85 @@ julia> TC = ideal(R, [x*z-y^2, w*z-x*y, w*y-x^2]); julia> F = free_module(R, 1); julia> koszul_homology(gens(TC), F, 0) -Submodule with 3 generators -1 -> (-x*z + y^2)*e[1] -2 -> (-w*z + x*y)*e[1] -3 -> (-w*y + x^2)*e[1] -represented as subquotient with no relations. +Subquotient of Submodule with 1 generator +1 -> e[1]∧e[2]∧e[3] +by Submodule with 3 generators +1 -> (w*y - x^2)*e[1]∧e[2]∧e[3] +2 -> (-w*z + x*y)*e[1]∧e[2]∧e[3] +3 -> (x*z - y^2)*e[1]∧e[2]∧e[3] julia> koszul_homology(gens(TC), F, 1) -Submodule with 3 generators -1 -> y*e[1] - z*e[2] -2 -> x*e[1] - y*e[2] -3 -> w*e[1] - x*e[2] -represented as subquotient with no relations. +Subquotient of Submodule with 2 generators +1 -> z*e[1]∧e[2] \otimes e[1] + y*e[1]∧e[3] \otimes e[1] + x*e[2]∧e[3] \otimes e[1] +2 -> y*e[1]∧e[2] \otimes e[1] + x*e[1]∧e[3] \otimes e[1] + w*e[2]∧e[3] \otimes e[1] +by Submodule with 3 generators +1 -> (-w*z + x*y)*e[1]∧e[2] \otimes e[1] + (-w*y + x^2)*e[1]∧e[3] \otimes e[1] +2 -> (x*z - y^2)*e[1]∧e[2] \otimes e[1] + (-w*y + x^2)*e[2]∧e[3] \otimes e[1] +3 -> (x*z - y^2)*e[1]∧e[3] \otimes e[1] + (w*z - x*y)*e[2]∧e[3] \otimes e[1] julia> koszul_homology(gens(TC), F, 2) -Submodule with 1 generator -1 -> 0 -represented as subquotient with no relations. +Subquotient of Submodule with 1 generator +1 -> (-x*z + y^2)*e[1] \otimes e[1] + (-w*z + x*y)*e[2] \otimes e[1] + (-w*y + x^2)*e[3] \otimes e[1] +by Submodule with 1 generator +1 -> (x*z - y^2)*e[1] \otimes e[1] + (w*z - x*y)*e[2] \otimes e[1] + (w*y - x^2)*e[3] \otimes e[1] ``` """ -function koszul_homology(V::Vector{T}, M::ModuleFP{T}, i::Int) where T <: MPolyRingElem - error("not implemented for the given type of module.") +function koszul_homology(V::Vector{T}, F::ModuleFP{T}, i::Int) where T <: MPolyRingElem + R = base_ring(F) + @assert all(x->parent(x)===R, V) "rings are incompatible" + if is_graded(F) && is_graded(R) + return _koszul_homology_graded(V, F, i) + elseif !is_graded(F) && !is_graded(R) + return _koszul_homology(V, F, i) + else + error("can not compute the koszul homology of a non-graded module over a graded ring") + end end -function koszul_homology(V::Vector{T},F::FreeMod{T}, i::Int) where T <: MPolyRingElem - R = base_ring(F) - @req coefficient_ring(R) isa AbstractAlgebra.Field "The coefficient ring must be a field" - @assert parent(V[1]) == R - @assert all(x->parent(x) == R, V) - I = ideal(R, V) - singular_assure(I) - MX = singular_module(F) - SG = Singular.Module(base_ring(MX), MX(zero(F))) - SU = Singular.LibHomolog.KoszulHomology(I.gens.S, SG, i) - FFF = free_module(R, rank(SU)) - MG = ModuleGens(FFF, SU) - UO = SubModuleOfFreeModule(FFF, MG) - return SubquoModule(UO) +function _koszul_homology(V::Vector{T}, F::ModuleFP{T}, i::Int) where T <: MPolyRingElem + r = length(V) + R = base_ring(F) + if iszero(r) + iszero(i) && return F + return FreeMod(R, 0) + end + Rr = FreeMod(R, r) + v = sum(x*e for (x, e) in zip(V, gens(Rr)); init=zero(Rr)) + return koszul_homology(v, F, i) # See src/Modules/ExteriorPowers/FreeMod.jl +end + +function _koszul_homology_graded(V::Vector{T},F::ModuleFP{T}, i::Int) where T <: MPolyRingElem + r = length(V) + R = base_ring(F) + if iszero(r) + iszero(i) && return F + return graded_free_module(R, 0) + end + Rr = graded_free_module(R, r) + v = sum(x*e for (x, e) in zip(V, gens(Rr)); init=zero(Rr)) + return koszul_homology(v, F, i) # See src/Modules/ExteriorPowers/FreeMod.jl +end + +# The old version invoking Singular is below. This proved to be slower in the assembly +# of the Koszul complex than the new one using the exterior powers of modules and +# the wedge product. We leave the code snippets here for reference. +function _koszul_homology_from_singular(V::Vector{T},F::FreeMod{T}, i::Int) where T <: MPolyRingElem{<:FieldElem} + R = base_ring(F) + @req coefficient_ring(R) isa AbstractAlgebra.Field "The coefficient ring must be a field" + @assert parent(V[1]) == R + @assert all(x->parent(x) == R, V) + I = ideal(R, V) + singular_assure(I) + MX = singular_module(F) + SG = Singular.Module(base_ring(MX), MX(zero(F))) + SU = Singular.LibHomolog.KoszulHomology(I.gens.S, SG, i) + FFF = free_module(R, rank(SU)) + MG = ModuleGens(FFF, SU) + UO = SubModuleOfFreeModule(FFF, MG) + return SubquoModule(UO) end -function koszul_homology(V::Vector{T}, M::SubquoModule{T}, i::Int) where T <: MPolyRingElem +function _koszul_homology_from_singular(V::Vector{T}, M::SubquoModule{T}, i::Int) where T <: MPolyRingElem R = base_ring(M) @req coefficient_ring(R) isa AbstractAlgebra.Field "The coefficient ring must be a field" @assert parent(V[1]) == R @@ -445,11 +488,46 @@ julia> depth(I, M) 1 ``` """ -function depth(I::MPolyIdeal{T}, M::ModuleFP{T}) where T <: MPolyRingElem - error("not implemented for the given type of module.") +function depth(I::Ideal{T}, F::ModuleFP{T}) where T <: RingElem + # One truely generic method not bound to polynomial rings + R = base_ring(F) + R === base_ring(I) || error("rings are incompatible") + f = small_generating_set(I) + n = length(f) + iszero(n) && return 0 + + i = findfirst(k->!iszero(koszul_homology(f, F, k)), n:-1:0) + i === nothing && return 0 + return i - 1 end -function depth(I::MPolyIdeal{T}, F::FreeMod{T}) where T <: MPolyRingElem +# The heuristic over units in the syzygy matrix works generically. +# However, we can not assume that this has been implemented for all +# kinds of ideals, so here's a backup. +small_generating_set(I::Ideal) = gens(I) + +# It turned out that despite the quick assembly of the Koszul complex +# in Oscar the computation of depth is much faster in singular: +function depth(I::MPolyIdeal{T}, F::ModuleFP{T}) where T <: MPolyRingElem{<:FieldElem} + return _depth_from_singular(I, F) +end + +# The Singular implementation suggests that one can compute the depth +# also from below and finding the first vanishing Koszul homology. +function _depth_from_below(I::Ideal{T}, F::ModuleFP{T}) where T <: RingElem + R = base_ring(F) + R === base_ring(I) || error("rings are incompatible") + f = small_generating_set(I) + n = length(f) + iszero(n) && return 0 + + i = findfirst(j->iszero(koszul_homology(f, F, j)), 0:n) + i === nothing && return 0 + # i is the first entry of [0, 1, 2, ..., n] for which... + return n - i + 2 +end + +function _depth_from_singular(I::MPolyIdeal{T}, F::FreeMod{T}) where T <: MPolyRingElem R = base_ring(I) @req coefficient_ring(R) isa AbstractAlgebra.Field "The coefficient ring must be a field" @assert base_ring(I) == base_ring(F) @@ -460,7 +538,7 @@ function depth(I::MPolyIdeal{T}, F::FreeMod{T}) where T <: MPolyRingElem return Singular.LibHomolog.depth(SG, I.gens.S) end -function depth(I::MPolyIdeal{T}, M::SubquoModule{T}) where T <: MPolyRingElem +function _depth_from_singular(I::MPolyIdeal{T}, M::SubquoModule{T}) where T <: MPolyRingElem R = base_ring(I) @req coefficient_ring(R) isa AbstractAlgebra.Field "The coefficient ring must be a field" @assert base_ring(I) == base_ring(M) @@ -495,20 +573,35 @@ julia> V = gens(R) z julia> koszul_matrix(V, 3) -[z -y x] +[x y z] julia> koszul_matrix(V, 2) -[-y x 0] -[-z 0 x] -[ 0 -z y] +[-y -z 0] +[ x 0 -z] +[ 0 x y] julia> koszul_matrix(V, 1) -[x] -[y] -[z] +[ z] +[-y] +[ x] ``` """ function koszul_matrix(V::Vector{T}, i::Int) where T <: MPolyRingElem + r = length(V) + iszero(r) && error("list must not be empty") + R = parent(first(V)) + @assert all(x->parent(x)===R, V) "parent mismatch" + + Rr = FreeMod(R, r) + v = sum(x*e for (x, e) in zip(V, gens(Rr)); init=zero(Rr)) + Ci, _ = exterior_power(Rr, r-i) + Cip1, _ = exterior_power(Rr, r-i+1) + phi = wedge_multiplication_map(Ci, Cip1, v) + return matrix(phi) +end + +# Deprecated code below; left for reference for how to import things from Singular +function _koszul_matrix_from_singular(V::Vector{T}, i::Int) where T <: MPolyRingElem @assert 1 <= i <= length(V) R = parent(V[1]) @assert all(x->parent(x) == R, V) @@ -535,23 +628,46 @@ julia> V = gens(R) julia> K = koszul_complex(V); julia> matrix(map(K, 2)) -[-y x 0] -[-z 0 x] -[ 0 -z y] +[-y -z 0] +[ x 0 -z] +[ 0 x y] julia> Kd = hom(K, free_module(R, 1)); julia> matrix(map(Kd, 1)) -[-y -z 0] -[ x 0 -z] -[ 0 x y] +[-y x 0] +[-z 0 x] +[ 0 -z y] ``` """ function koszul_complex(V::Vector{T}) where T <: MPolyRingElem + r = length(V) + iszero(r) && error("list must not be empty") + R = parent(first(V)) + @assert all(x->parent(x)===R, V) "parent mismatch" + + F = FreeMod(R, r) + v = sum(x*e for (x, e) in zip(V, gens(F)); init=zero(F)) + return koszul_complex(v) +end + +function koszul_complex(V::Vector{T}, M::ModuleFP{T}) where T <: MPolyRingElem + r = length(V) + iszero(r) && error("list must not be empty") + R = base_ring(M) + @assert all(x->parent(x)===R, V) "parent mismatch" + + F = FreeMod(R, r) + v = sum(x*e for (x, e) in zip(V, gens(F)); init=zero(F)) + return koszul_complex(v, M) +end + +# Deprecated code below; left for reference for how to import things from Singular +function _koszul_complex_from_singular(V::Vector{T}) where T <: MPolyRingElem R = parent(V[1]) @assert all(x->parent(x) == R, V) n = length(V) - KM = [koszul_matrix(V, i) for i=n:-1:1] + KM = [_koszul_matrix_from_singular(V, i) for i=n:-1:1] F = free_module(R, 0) G = free_module(R, 1) diff --git a/src/Oscar.jl b/src/Oscar.jl index ff63dee4df6e..c5124855181a 100644 --- a/src/Oscar.jl +++ b/src/Oscar.jl @@ -221,6 +221,7 @@ include("Polymake/polymake_to_oscar.jl") include("Combinatorics/Graphs/functions.jl") include("Combinatorics/SimplicialComplexes.jl") +include("Combinatorics/OrderedMultiIndex.jl") include("Combinatorics/Matroids/JMatroids.jl") include("Combinatorics/Matroids/matroid_strata_grassmannian.jl") diff --git a/src/Rings/mpoly-ideals.jl b/src/Rings/mpoly-ideals.jl index 349647f5f212..0f35a2369221 100644 --- a/src/Rings/mpoly-ideals.jl +++ b/src/Rings/mpoly-ideals.jl @@ -1453,13 +1453,12 @@ julia> small_generating_set(J) x*y^2 - z ``` """ -function small_generating_set(I::MPolyIdeal) +function small_generating_set(I::MPolyIdeal{T}) where {T<:MPolyElem{<:FieldElem}} # For non-homogeneous ideals, we do not have a notion of minimal generating # set, but Singular.mstd still provides a good heuristic to find a small # generating set. R = base_ring(I) - @req coefficient_ring(R) isa Field "The coefficient ring must be a field" # in the ungraded case, mstd's heuristic returns smaller gens when recomputing gb sing_gb, sing_min = Singular.mstd(singular_generators(I)) diff --git a/src/Rings/mpoly-localizations.jl b/src/Rings/mpoly-localizations.jl index 6729cb078028..b2e77299c9e1 100644 --- a/src/Rings/mpoly-localizations.jl +++ b/src/Rings/mpoly-localizations.jl @@ -1797,6 +1797,15 @@ function coordinates( ) where {LRT<:MPolyLocRing{<:Any, <:Any, <:Any, <:Any, <:MPolyPowersOfElement}} L = base_ring(I) parent(a) === L || return coordinates(L(a), I, check=check) + + b = numerator(a) + if b in pre_saturated_ideal(I) + x = coordinates(b, pre_saturated_ideal(I)) + q = denominator(a) + # multiplications sparse*dense have to be carried out this way round. + return transpose(mul(pre_saturation_data(I), transpose(L(one(q), q, check=false)*change_base_ring(L, x)))) + end + @check a in I "the given element is not in the ideal" !is_saturated(I) && _replace_pre_saturated_ideal(I, saturated_ideal(I), prod(denominators(inverted_set(L)); init=one(base_ring(L)))) # Computing the saturation first is cheaper than the generic Posur method J = pre_saturated_ideal(I) @@ -2227,6 +2236,7 @@ function ideal_membership( L = base_ring(I) parent(a) == L || return L(a) in I b = numerator(a) + b in pre_saturated_ideal(I) && return true return b in saturated_ideal(I) end diff --git a/src/exports.jl b/src/exports.jl index ffbdea7af468..0cd89e5ff4ee 100644 --- a/src/exports.jl +++ b/src/exports.jl @@ -691,6 +691,7 @@ export indicator export induce export induce_shift export induced_automorphism +export induced_map_on_exterior_power export induced_cyclic export induced_ring_ordering export initial @@ -762,6 +763,7 @@ export is_embedded export is_empty export is_equal_with_morphism export is_equidimensional +export is_exterior_power export is_faithful export is_fano export is_feasible @@ -1471,6 +1473,10 @@ export walls export wdeglex export wdegrevlex export weakly_connected_components +export wedge +export wedge_multiplication_map +export wedge_pure_function +export wedge_generator_decompose_function export weight export weight_cone export weight_ordering diff --git a/test/AlgebraicGeometry/Schemes/runtests.jl b/test/AlgebraicGeometry/Schemes/runtests.jl index 8eaa97e9139b..ad8c22ee9ae1 100644 --- a/test/AlgebraicGeometry/Schemes/runtests.jl +++ b/test/AlgebraicGeometry/Schemes/runtests.jl @@ -29,3 +29,4 @@ include("MorphismFromRationalFunctions.jl") include("AffineRationalPoint.jl") include("ProjectiveRationalPoint.jl") include("BlowupMorphism.jl") + diff --git a/test/Combinatorics/OrderedMultiIndex.jl b/test/Combinatorics/OrderedMultiIndex.jl new file mode 100644 index 000000000000..ee989802aa71 --- /dev/null +++ b/test/Combinatorics/OrderedMultiIndex.jl @@ -0,0 +1,27 @@ +@testset "ordered multiindices" begin + I = Oscar.ordered_multi_index([1, 2, 5], 5) + I1 = Oscar.ordered_multi_index([1], 5) + I2 = Oscar.ordered_multi_index([2], 5) + I5 = Oscar.ordered_multi_index([5], 5) + J = Oscar.ordered_multi_index([3, 4], 5) + K = Oscar.ordered_multi_index([2, 4], 5) + @test "$(Oscar._wedge(I, J)[2])" == "0 < 1 < 2 < 3 < 4 < 5 <= 5" + sign, ind = Oscar._wedge([I2, I5, I1]) + @test ind == I + @test sign == 1 + sign, ind = Oscar._wedge([I2, I1, I5]) + @test ind == I + @test sign == -1 + + sign, ind = Oscar._wedge(J, K) + @test sign == 0 + sign, ind = Oscar._wedge(I, K) + @test sign == 0 + + c = [ind for ind in Oscar.OrderedMultiIndexSet(3, 5)] + @test length(c) == binomial(5, 3) + + @test all(x->c[Oscar.linear_index(x)] == x, Oscar.OrderedMultiIndexSet(3, 5)) + + @test [Oscar.ordered_multi_index(k, 3, 5) for k in 1:binomial(5, 3)] == collect(Oscar.OrderedMultiIndexSet(3, 5)) +end diff --git a/test/Combinatorics/runtests.jl b/test/Combinatorics/runtests.jl index e8ff4ce363ae..413f194d83d6 100644 --- a/test/Combinatorics/runtests.jl +++ b/test/Combinatorics/runtests.jl @@ -6,3 +6,4 @@ include("Matroids/Matroids.jl") include("Matroids/Chow_Ring.jl") include("Graph.jl") include("Matroids/matroid_strata_grassmannian.jl") +include("OrderedMultiIndex.jl") diff --git a/test/Modules/ExteriorPowers.jl b/test/Modules/ExteriorPowers.jl new file mode 100644 index 000000000000..349fda9be1e5 --- /dev/null +++ b/test/Modules/ExteriorPowers.jl @@ -0,0 +1,180 @@ +@testset "exterior powers of modules" begin + R, (x, y, u, v, w) = QQ[:x, :y, :u, :v, :w] + F = FreeMod(R, 5) + Fwedge3, _ = Oscar.exterior_power(F, 3) + tmp, _ = Oscar.exterior_power(F, 3, cached=false) + @test tmp !== Fwedge3 + @test Fwedge3 === Oscar.exterior_power(F, 3)[1] + Fwedge1, _ = Oscar.exterior_power(F, 1) + Fwedge2, _ = Oscar.exterior_power(F, 2) + + success, orig_mod, q = Oscar.is_exterior_power(Fwedge3) + @test success + @test orig_mod === F + @test q == 3 + + v = sum(gens(R)[i]*F[i] for i in 1:5) + phi0 = Oscar.wedge_multiplication_map(exterior_power(F, 0)[1], F, v) + phi1 = Oscar.wedge_multiplication_map(F, exterior_power(F, 2)[1], v) + @test iszero(compose(phi0, phi1)) + @test image(phi0)[1] == kernel(phi1)[1] + phi2 = Oscar.wedge_multiplication_map(Fwedge1, Fwedge2, v) + phi2_alt = Oscar.wedge_multiplication_map(Oscar.exterior_power(F, 1, cached=false)[1], Oscar.exterior_power(F, 2, cached=false)[1], v) + @test domain(phi2) !== domain(phi2_alt) + @test codomain(phi2) !== codomain(phi2_alt) + phi3 = Oscar.wedge_multiplication_map(Fwedge2, Fwedge3, v) + @test !iszero(phi2) + @test !iszero(phi3) + img, _ = image(phi2) + ker, _ = kernel(phi3) + @test img == ker + @test iszero(compose(phi2, phi3)) + + @test Oscar.wedge([F[1], F[2], F[4]]) == - Oscar.wedge([F[2], F[1], F[4]]) == Oscar.wedge([F[4], F[1], F[2]]) + + K = koszul_complex(v) + @test all(i->iszero(homology(K, i)), 1:5) + + for i in 1:5 + @test iszero(koszul_homology(v, i)) + @test iszero(koszul_homology(v, F, i)) + end + + @test !iszero(koszul_homology(v, 0)) + @test !iszero(koszul_homology(v, F, 0)) +end + +@testset "exterior powers of graded modules" begin + R, (x, y, u, v, w) = QQ[:x, :y, :u, :v, :w] + S, (x, y, u, v, w) = grade(R) + F = graded_free_module(S, [1, 1, 1, 1, -2]) + Fwedge1, _ = Oscar.exterior_power(F, 1) + Fwedge2, _ = Oscar.exterior_power(F, 2) + Fwedge3, _ = Oscar.exterior_power(F, 3) + @test is_graded(Fwedge3) + + S1 = graded_free_module(S, 1) + I, inc_I = sub(S1, [f^3*S1[1] for f in gens(S)]) + + Oscar.koszul_dual(Fwedge2[3]) + + dual_basis = Oscar.koszul_duals(gens(Fwedge1)) + tmp = [Oscar.wedge(u, v) for (u, v) in zip(dual_basis, gens(Fwedge1))] + Fwedge5, _ = Oscar.exterior_power(F, 5) + @test all(x->x==Fwedge5[1], tmp) + + dual_basis = Oscar.koszul_duals(gens(Fwedge2)) + tmp = [Oscar.wedge(u, v) for (u, v) in zip(dual_basis, gens(Fwedge2))] + @test all(x->x==Fwedge5[1], tmp) +end + +@testset "induced maps on exterior powers" begin + R, (x, y, u, v, w) = QQ[:x, :y, :u, :v, :w] + + R5 = FreeMod(R, 5) + R4 = FreeMod(R, 4) + + A = R[x y u v; 7*y u v w; u 5*v w x; v w x y; w 4*x y u] + phi = hom(R5, R4, A) + + phi_2 = Oscar.induced_map_on_exterior_power(phi, 2) + + for ind in Oscar.OrderedMultiIndexSet(2, 5) + imgs = [phi(R5[i]) for i in Oscar.indices(ind)] + img = Oscar.wedge(imgs) + @test img == phi_2(domain(phi_2)[Oscar.linear_index(ind)]) + end + + phi_3 = Oscar.induced_map_on_exterior_power(phi, 3) + + A3 = matrix(phi_3) + for ind1 in Oscar.OrderedMultiIndexSet(3, 5) + for ind2 in Oscar.OrderedMultiIndexSet(3, 4) + @test A3[Oscar.linear_index(ind1), Oscar.linear_index(ind2)] == det(A[Oscar.indices(ind1), Oscar.indices(ind2)]) + end + end + + psi = hom(R4, R5, transpose(A)) + psi_2 = Oscar.induced_map_on_exterior_power(psi, 2) + @test compose(phi_2, psi_2) == Oscar.induced_map_on_exterior_power(compose(phi, psi), 2) + psi_3 = Oscar.induced_map_on_exterior_power(psi, 3) + @test compose(phi_3, psi_3) == Oscar.induced_map_on_exterior_power(compose(phi, psi), 3) + psi_3_alt = Oscar.induced_map_on_exterior_power(psi, 3, domain = Oscar.exterior_power(R4, 3, cached=false)[1], codomain = Oscar.exterior_power(R5, 3, cached=false)[1]) + @test matrix(psi_3) == matrix(psi_3_alt) + @test domain(psi_3) !== domain(psi_3_alt) + @test codomain(psi_3) !== codomain(psi_3_alt) + + psi_3_alt = hom(domain(psi_3), codomain(psi_3), psi) + @test psi_3_alt == psi_3 +end + +@testset "multiplication map" begin + R, (x, y, u, v, w) = QQ[:x, :y, :u, :v, :w] + + F = FreeMod(R, 5) + F3, mm = Oscar.exterior_power(F, 3) + v = (F[1], F[3], F[4]) + u = (F[1], F[4], F[3]) + @test mm(v) == -mm(u) + w = mm(v) + @test Oscar.wedge_pure_function(F3)(v) == w + @test Oscar.wedge_generator_decompose_function(F3)(w) == v + @test preimage(mm, w) == v +end + +@testset "printing" begin + R, (x, y, u, v, w) = QQ[:x, :y, :u, :v, :w] + + F = FreeMod(R, 5) + F3, mm = Oscar.exterior_power(F, 3) + v = (F[1], F[3], F[4]) + u = (F[1], F[4], F[3]) + + @test "$(mm(v))" == "e[1]∧e[3]∧e[4]" + @test "$(F3)" == "⋀^3(Free module of rank 5 over Multivariate polynomial ring in 5 variables over QQ)" + + eu = sum(f*e for (f, e) in zip(gens(R), gens(F))) + K = koszul_complex(eu) + for i in 1:5 + @test "$(K[i])" == "⋀^$(5-i)($F)" + end +end + +@testset "exterior powers of subquos" begin + R, (x, y, z, w) = QQ[:x, :y, :z, :w] + + M = R[x y z; y-1 z-2 w] + + I = ideal(R, minors(M, 2)) + + A, pr = quo(R, I) + + phi = hom(FreeMod(A, 2), FreeMod(A, 3), change_base_ring(A, M)) + + MM = cokernel(phi) + + MM2, mm2 = exterior_power(MM, 2) + MM1, mm1 = exterior_power(MM, 1) + MM0, mm0 = exterior_power(MM, 0) + MM3, mm3 = exterior_power(MM, 3) + + @test iszero(MM3) + + (u, v, w) = gens(MM1) + uv = wedge(u, v) + (U, V, W) = gens(MM) + @test uv == mm2((U, V)) + @test (U, V) == preimage(mm2, uv) + uv = wedge(u, v) + uw = wedge(u, w) + vw = wedge(v, w) + psi = hom(FreeMod(A, 3), MM2, [uv, uw, vw]) + @test !iszero(kernel(psi)[1]) + @test parent(wedge(u, v)) === MM2 + + d02 = Oscar.wedge_multiplication_map(MM0, MM2, uv + vw) + d01 = Oscar.wedge_multiplication_map(MM0, MM1, u + 2*v - w) + d12 = Oscar.wedge_multiplication_map(MM1, MM2, u + 2*v - w) + @test iszero(compose(d01, d12)) + @test iszero(wedge([u, v, w])) +end diff --git a/test/Modules/homological-algebra.jl b/test/Modules/homological-algebra.jl index d9f00d13f7b9..6c2bdd42f52f 100644 --- a/test/Modules/homological-algebra.jl +++ b/test/Modules/homological-algebra.jl @@ -33,17 +33,22 @@ end R, (x, y) = polynomial_ring(QQ, ["x", "y"]); V = gens(R) KM = koszul_matrix(V, 1) - @test nrows(KM) == 2 - @test KM[1] == R[1] + KMS = Oscar._koszul_matrix_from_singular(V, 1) + @test nrows(KM) == nrows(KMS) == 2 + @test ncols(KM) == ncols(KMS) + #@test KM[1] == R[1] # Custom test for the deprecated Singular code end @testset "mpoly_affine_homological-algebra.koszul_complex" begin R, (x, y) = polynomial_ring(QQ, ["x", "y"]); V = gens(R) K = koszul_complex(V) + KS = Oscar._koszul_complex_from_singular(V) KM = matrix(map(K, 2)) - @test ncols(KM) == 2 - @test KM[1, 1] == -R[2] + KMS = matrix(map(KS, 2)) + @test nrows(KM) == nrows(KMS) == 1 + @test ncols(KM) == ncols(KMS) + #@test KM[1, 1] == -R[2]# Custom test for the deprecated Singular code end @testset "mpoly_affine_homological-algebra.koszul_homology" begin @@ -53,7 +58,9 @@ end M = quo(F, U)[1] V = [x, x*z-z] @test is_zero(koszul_homology(V, M, 0)) == false + @test is_zero(Oscar._koszul_homology_from_singular(V, M, 0)) == false @test is_zero(koszul_homology(V, M, 1)) == true + @test is_zero(Oscar._koszul_homology_from_singular(V, M, 1)) == true end @testset "mpoly_affine_homological-algebra.depth" begin @@ -62,10 +69,40 @@ end U = matrix([x*y]) M = quo(F, U)[1] I = ideal(R, gens(R)) - @test depth(I, M) == 1 + @test depth(I, M) == Oscar._depth_from_singular(I, M) == 1 R, (x, y, z) = polynomial_ring(QQ, ["x", "y", "z"]); F = free_module(R, 1); I = ideal(R, [x*z-z, x*y-y, x]) - @test depth(I, F) == 3 + @test depth(I, F) == Oscar._depth_from_singular(I, F) == 3 +end + +@testset "singular vs oscar comparison" begin + n = 3 + R, _ = polynomial_ring(QQ, "x"=>1:n) + FR = FreeMod(R, 1) + IR = ideal(R, gens(R)) + IR = IR*IR + f = gens(IR) + K0 = koszul_complex(f) + K1 = koszul_complex(f, FR) + HK0 = [homology(K0, i) for i in 0:ngens(IR)] + HK1 = [homology(K1, i) for i in 0:ngens(IR)] + HK2 = [koszul_homology(f, FR, i) for i in 0:ngens(IR)] + @test iszero.(HK1) == iszero.(HK2) == iszero.(HK0) +end + +@testset "generic depth routine" begin + P, _ = QQ[:u, :v] + R, (x, y) = polynomial_ring(P, ["x", "y"]); + F = free_module(R, 1) + U = matrix([x*y]) + M = quo(F, U)[1] + I = ideal(R, gens(R)) + @test depth(I, M) == 1 + + R, (x, y, z) = polynomial_ring(QQ, ["x", "y", "z"]); + F = free_module(R, 1); + I = ideal(R, [x*z-z, x*y-y, x]) + @test depth(I, F) == 3 end diff --git a/test/Modules/runtests.jl b/test/Modules/runtests.jl index 2584fb970b49..371da7a1fb20 100644 --- a/test/Modules/runtests.jl +++ b/test/Modules/runtests.jl @@ -10,3 +10,4 @@ include("local_rings.jl") include("MPolyQuo.jl") include("homological-algebra.jl") include("ProjectiveModules.jl") +include("ExteriorPowers.jl") From 2c7e3a48e88ec861f68ce549cfeeafdcbe7f5d76 Mon Sep 17 00:00:00 2001 From: Johannes Schmitt Date: Thu, 19 Oct 2023 17:56:32 +0200 Subject: [PATCH 04/27] Relax signature of `==(::MPolyIdeal, ::MPolyIdeal)` (#2937) --- docs/src/CommutativeAlgebra/ideals.md | 4 ++-- src/Rings/mpoly-ideals.jl | 14 ++++++++------ test/Rings/mpoly-graded.jl | 15 ++++++++------- test/Rings/mpoly.jl | 7 +++++++ 4 files changed, 25 insertions(+), 15 deletions(-) diff --git a/docs/src/CommutativeAlgebra/ideals.md b/docs/src/CommutativeAlgebra/ideals.md index fdfe621b5b7b..6ef414b5a9ea 100644 --- a/docs/src/CommutativeAlgebra/ideals.md +++ b/docs/src/CommutativeAlgebra/ideals.md @@ -167,13 +167,13 @@ is_monomial(f::MPolyRingElem) ### Containment of Ideals ```@docs -is_subset(I::MPolyIdeal{T}, J::MPolyIdeal{T}) where T +is_subset(I::MPolyIdeal, J::MPolyIdeal) ``` ### Equality of Ideals ```@docs -==(I::MPolyIdeal{T}, J::MPolyIdeal{T}) where T +==(I::MPolyIdeal, J::MPolyIdeal) ``` ### Ideal Membership diff --git a/src/Rings/mpoly-ideals.jl b/src/Rings/mpoly-ideals.jl index 0f35a2369221..d40761cbc00b 100644 --- a/src/Rings/mpoly-ideals.jl +++ b/src/Rings/mpoly-ideals.jl @@ -66,11 +66,11 @@ end # elementary operations ####################################################### @doc raw""" - check_base_rings(I::MPolyIdeal{T}, J::MPolyIdeal{T}) where T + check_base_rings(I::MPolyIdeal, J::MPolyIdeal) Throws an error if the base rings of the ideals `I` and `J` do not coincide. """ -function check_base_rings(I::MPolyIdeal{T}, J::MPolyIdeal{T}) where T +function check_base_rings(I::MPolyIdeal, J::MPolyIdeal) if !isequal(base_ring(I), base_ring(J)) error("Base rings must coincide.") end @@ -970,7 +970,7 @@ end ####################################################### @doc raw""" - ==(I::MPolyIdeal{T}, J::MPolyIdeal{T}) where T + ==(I::MPolyIdeal, J::MPolyIdeal) Return `true` if `I` is equal to `J`, `false` otherwise. @@ -989,7 +989,8 @@ julia> I == J false ``` """ -function ==(I::MPolyIdeal{T}, J::MPolyIdeal{T}) where T +function ==(I::MPolyIdeal, J::MPolyIdeal) + check_base_rings(I, J) I === J && return true gens(I) == gens(J) && return true return issubset(I, J) && issubset(J, I) @@ -999,7 +1000,7 @@ end ####################################################### @doc raw""" - is_subset(I::MPolyIdeal{T}, J::MPolyIdeal{T}) where T + is_subset(I::MPolyIdeal, J::MPolyIdeal) Return `true` if `I` is contained in `J`, `false` otherwise. @@ -1018,7 +1019,8 @@ julia> is_subset(I, J) true ``` """ -function is_subset(I::MPolyIdeal{T}, J::MPolyIdeal{T}) where T +function is_subset(I::MPolyIdeal, J::MPolyIdeal) + check_base_rings(I, J) return Singular.iszero(Singular.reduce(singular_generators(I), singular_groebner_generators(J))) end diff --git a/test/Rings/mpoly-graded.jl b/test/Rings/mpoly-graded.jl index 512103593fa5..69bede808e34 100644 --- a/test/Rings/mpoly-graded.jl +++ b/test/Rings/mpoly-graded.jl @@ -421,7 +421,7 @@ end -@testset "homogenizaton: big principal ideal" begin +@testset "homogenization: big principal ideal" begin # It is easy to honogenize a principal ideal: just homogenize the gen! # Do not really need lots of vars; just a "large" single polynomial LotsOfVars = 250; @@ -463,9 +463,10 @@ end x^3*y^2+x*y*z^3+x*y+y^2, x^2*y^3*w+y^3*z^2*w-y*z^3*w^2-y*w^2], W1, "h"); Ih_std = homogenization(I, "h") - Ih_expected = ideal(Ih_W1) + Ih_expected = ideal(base_ring(Ih_std), Ih_W1) @test Ih_std == Ih_expected Ih = homogenization(I, W1, "h") + Ih_expected = ideal(base_ring(Ih), Ih_W1) @test Ih == Ih_expected Ih_W2 = homogenization([x*y*z^3+x^3*y^2+y^2+x*y, x*y*z^2*w+x^3*w^2+x^3*y*w+w^2, @@ -473,19 +474,19 @@ end x^5*w^3+x^3*y^3*z*w-y*z^2*w^2+2*x^5*y*w^2+x^2*w^3+x^5*y^2*w+y^3*z*w+x*y^2*z*w+x^2*y*w^2, y*z^3*w^2-y^3*z^2*w-x^2*y^3*w+y*w^2], W2, "h"); - Ih_expected = ideal(Ih_W2) Ih = homogenization(I, W2, "h") + Ih_expected = ideal(base_ring(Ih), Ih_W2) @test Ih == Ih_expected Ih_W3 = homogenization([x^2*y^3*w+y^3*z^2*w-y*z^3*w^2-y*w^2, x^3*y*w+x*y*z^2*w+x^3*w^2+w^2, x^3*y^2+y^2+x*y*z^3+x*y], W3, "h"); - Ih_expected = ideal(Ih_W3) Ih = homogenization(I, W3, "h") + Ih_expected = ideal(base_ring(Ih), Ih_W3) @test Ih == Ih_expected # Ih_W4 = ???? - # Ih_expected = ideal(Ih_W4) # Ih = homogenization(I, W4, "h") + # Ih_expected = ideal(base_ring(Ih), Ih_W4) # @test Ih = Ih_expected Ih_W2a = homogenization([x*y*z^3+x^3*y^2+y^2+x*y, x*y*z^2*w+x^3*w^2+x^3*y*w+w^2, @@ -493,12 +494,12 @@ end y*z^3*w^2-y^3*z^2*w-x^2*y^3*w+y*w^2, x^5*w^3+x^3*y^3*z*w-y*z^2*w^2+2*x^5*y*w^2+x^2*w^3+x^5*y^2*w+y^3*z*w+x*y^2*z*w+x^2*y*w^2], W2a, "h"); - Ih_expected = ideal(Ih_W2a) Ih = homogenization(I, W2a, "h") + Ih_expected = ideal(base_ring(Ih), Ih_W2a) @test Ih == Ih_expected # Ih_W2b = ???? - # Ih_expected = ideal(Ih_W2b) # Ih = homogenization(I, W2b, "h") + # Ih_expected = ideal(base_ring(Ih), Ih_W2b) # @test Ih == Ih_expected end diff --git a/test/Rings/mpoly.jl b/test/Rings/mpoly.jl index c96f125d6fa7..e015ae932b9f 100644 --- a/test/Rings/mpoly.jl +++ b/test/Rings/mpoly.jl @@ -85,6 +85,13 @@ end @test intersect(I,J,P) == ideal(R,[x^2*y^2, x^4, x*y^4]) @test intersect(I,J,P) == intersect([I,J,P]) + @test I != J + RR, (xx, yy) = grade(R, [1, 1]) + @test_throws ErrorException ideal(R, [x]) == ideal(RR, [xx]) + @test is_subset(I, I) + RR, (xx, yy) = polynomial_ring(QQ, ["xx", "yy"]) + @test_throws ErrorException is_subset(ideal(R, [x]), ideal(RR, [xx])) + f = x^2 + y^2 g = x^4*y - x*y^3 I = [f, g] From 223c302b0fcf3699f1a91ff12f732f12457b3a51 Mon Sep 17 00:00:00 2001 From: Matthias Zach <85350711+HechtiDerLachs@users.noreply.github.com> Date: Fri, 20 Oct 2023 12:03:40 +0200 Subject: [PATCH 05/27] All monomial for free standard graded modules (#2894) * Implement iteration over module monomials of a specific degree (in standard grading) --- experimental/Schemes/Auxiliary.jl | 1 + src/InvariantTheory/InvariantTheory.jl | 3 + src/Modules/Iterators.jl | 78 ++++++++++++++++++++++++++ src/Modules/Modules.jl | 1 + test/Modules/GradedModules.jl | 13 +++++ test/Modules/ModulesGraded.jl | 12 ++++ 6 files changed, 108 insertions(+) create mode 100644 src/Modules/Iterators.jl diff --git a/experimental/Schemes/Auxiliary.jl b/experimental/Schemes/Auxiliary.jl index 4a9dc29f51a3..0011e24915d3 100644 --- a/experimental/Schemes/Auxiliary.jl +++ b/experimental/Schemes/Auxiliary.jl @@ -383,3 +383,4 @@ end ### Generic pullback and pushforward for composite maps pushforward(f::Generic.CompositeMap, a::Any) = pushforward(map2(f), pushforward(map1(f), a)) pullback(f::Generic.CompositeMap, a::Any) = pullback(map1(f), pullback(map2(f), a)) + diff --git a/src/InvariantTheory/InvariantTheory.jl b/src/InvariantTheory/InvariantTheory.jl index acd3e20f95ab..25caf32dbdf7 100644 --- a/src/InvariantTheory/InvariantTheory.jl +++ b/src/InvariantTheory/InvariantTheory.jl @@ -6,3 +6,6 @@ include("primary_invariants.jl") include("secondary_invariants.jl") include("fundamental_invariants.jl") include("affine_algebra.jl") + +# postponed inclusion from src/Modules/Modules.jl due to dependency +include("../Modules/Iterators.jl") diff --git a/src/Modules/Iterators.jl b/src/Modules/Iterators.jl new file mode 100644 index 000000000000..d6f6c3fc2699 --- /dev/null +++ b/src/Modules/Iterators.jl @@ -0,0 +1,78 @@ +### Iteration over monomials in modules of a certain degree +struct AllModuleMonomials{ModuleType<:FreeMod} + F::ModuleType + d::Int + + function AllModuleMonomials(F::FreeMod{T}, d::Int) where {T <: MPolyDecRingElem} + is_graded(F) || error("module must be graded") + S = base_ring(F) + is_standard_graded(S) || error("iterator implemented only for the standard graded case") + return new{typeof(F)}(F, d) + end +end + +underlying_module(amm::AllModuleMonomials) = amm.F +degree(amm::AllModuleMonomials) = amm.d + +function all_monomials(F::FreeMod{T}, d::Int) where {T<:MPolyDecRingElem} + return AllModuleMonomials(F, d) +end + +Base.eltype(amm::AllModuleMonomials{T}) where {T} = elem_type(T) + +function Base.length(amm::AllModuleMonomials) + F = underlying_module(amm) + r = rank(F) + R = base_ring(F) + d = degree(amm) + result = 0 + for i in 1:r + d_loc = d - Int(degree(F[i])[1]) + d_loc < 0 && continue + result = result + length(all_monomials(R, d_loc)) + end + return result +end + +function Base.iterate(amm::AllModuleMonomials, state::Nothing = nothing) + i = 1 + F = underlying_module(amm) + d = degree(amm) + R = base_ring(F) + + i = findfirst(i -> d - Int(degree(F[i])[1]) >= 0, 1:ngens(F)) + i === nothing && return nothing + d_loc = d - Int(degree(F[i])[1]) + + mon_it = all_monomials(R, d_loc) + res = iterate(mon_it, nothing) + res === nothing && i == ngens(F) && return nothing + + x, s = res + return x*F[1], (i, mon_it, s) +end + +function Base.iterate(amm::AllModuleMonomials, state::Tuple{Int, AllMonomials, Vector{Int}}) + F = underlying_module(amm) + d = degree(amm) + R = base_ring(F) + + i, mon_it, s = state + res = iterate(mon_it, s) + if res === nothing + i = findnext(i -> d - Int(degree(F[i])[1]) >= 0, 1:ngens(F), i + 1) + i === nothing && return nothing + d_loc = d - Int(degree(F[i])[1]) + + mon_it = all_monomials(R, d_loc) + res_loc = iterate(mon_it, nothing) + res_loc === nothing && i == ngens(F) && return nothing + + x, s = res_loc + return x*F[i], (i, mon_it, s) + end + + x, s = res + return x*F[i], (i, mon_it, s) +end + diff --git a/src/Modules/Modules.jl b/src/Modules/Modules.jl index e4fb0dde98f7..f83dc77e3cb3 100644 --- a/src/Modules/Modules.jl +++ b/src/Modules/Modules.jl @@ -10,3 +10,4 @@ include("local_rings.jl") include("mpolyquo.jl") include("ExteriorPowers/ExteriorPowers.jl") +#include("Iterators.jl") # inclusion postponed to src/InvariantTheory/InvariantTheory.jl due to dependencies diff --git a/test/Modules/GradedModules.jl b/test/Modules/GradedModules.jl index 517e63c5d7b7..5742bd7fd83d 100644 --- a/test/Modules/GradedModules.jl +++ b/test/Modules/GradedModules.jl @@ -68,3 +68,16 @@ end K = kernel(phi)[1] @test (iszero(quo(M2,K)) && iszero(quo(K,M2))) # mathematical equality end + +@testset "all_monomials for graded free modules" begin + R, (x, y, u, v, w) = QQ[:x, :y, :u, :v, :w] + S, (x, y, u, v, w) = grade(R) + + F = graded_free_module(S, [-1, 2]) + + for d in -4:4 + amm = Oscar.all_monomials(F, d) + @test d < -1 || !isempty(amm) + @test all(x->degree(x) == grading_group(F)([d]), amm) + end +end diff --git a/test/Modules/ModulesGraded.jl b/test/Modules/ModulesGraded.jl index bb0485d6be5e..58ad2a64b0ae 100644 --- a/test/Modules/ModulesGraded.jl +++ b/test/Modules/ModulesGraded.jl @@ -1176,3 +1176,15 @@ end @test Int(degree(gen(N, 1))[2]) == -2 end +@testset "all_monomials for graded free modules" begin + R, (x, y, u, v, w) = QQ[:x, :y, :u, :v, :w] + S, (x, y, u, v, w) = grade(R) + + F = graded_free_module(S, [-1, 2]) + + for d in -4:4 + amm = Oscar.all_monomials(F, d) + @test d < -1 || !isempty(amm) + @test all(x->degree(x) == grading_group(F)([d]), amm) + end +end From be964717154bd46691449e59683c26c6d8c65274 Mon Sep 17 00:00:00 2001 From: Laura Voggesberger <101730185+voggesbe@users.noreply.github.com> Date: Fri, 20 Oct 2023 12:55:09 +0200 Subject: [PATCH 06/27] Simple Lie algebras and root systems (#2572) --- .../LieAlgebras/docs/src/introduction.md | 1 + .../LieAlgebras/docs/src/lie_algebras.md | 1 + experimental/LieAlgebras/src/LieAlgebra.jl | 7 + experimental/LieAlgebras/src/LieAlgebras.jl | 21 ++ experimental/LieAlgebras/src/root_systems.jl | 237 ++++++++++++++++++ .../LieAlgebras/src/simple_lie_algebra.jl | 158 ++++++++++++ .../LieAlgebras/test/LieAlgebra-test.jl | 5 + .../LieAlgebras/test/root_systems-test.jl | 7 + experimental/LieAlgebras/test/runtests.jl | 1 + .../test/simple_lie_algebra-test.jl | 29 +++ src/Oscar.jl | 1 + 11 files changed, 468 insertions(+) create mode 100644 experimental/LieAlgebras/src/root_systems.jl create mode 100644 experimental/LieAlgebras/src/simple_lie_algebra.jl create mode 100644 experimental/LieAlgebras/test/root_systems-test.jl create mode 100644 experimental/LieAlgebras/test/simple_lie_algebra-test.jl diff --git a/experimental/LieAlgebras/docs/src/introduction.md b/experimental/LieAlgebras/docs/src/introduction.md index 6ab3f70f4793..76a9bbead968 100644 --- a/experimental/LieAlgebras/docs/src/introduction.md +++ b/experimental/LieAlgebras/docs/src/introduction.md @@ -18,6 +18,7 @@ This part of OSCAR is in an experimental state; please see [Adding new projects Please direct questions about this part of OSCAR to the following people: * [Lars Göttgens](https://lgoe.li/) +* [Laura Voggesberger](https://www.ruhr-uni-bochum.de/ffm/Lehrstuehle/Lehrstuhl-VI/voggesberger.html) You can ask questions in the [OSCAR Slack](https://www.oscar-system.org/community/#slack). diff --git a/experimental/LieAlgebras/docs/src/lie_algebras.md b/experimental/LieAlgebras/docs/src/lie_algebras.md index 70c3dd958867..a40cda0b2a94 100644 --- a/experimental/LieAlgebras/docs/src/lie_algebras.md +++ b/experimental/LieAlgebras/docs/src/lie_algebras.md @@ -24,6 +24,7 @@ coefficients(::LieAlgebraElem) coeff(::LieAlgebraElem, ::Int) getindex(::LieAlgebraElem, ::Int) symbols(::LieAlgebra) +characteristic(L::LieAlgebra) ``` ## Special functions for `LinearLieAlgebra`s diff --git a/experimental/LieAlgebras/src/LieAlgebra.jl b/experimental/LieAlgebras/src/LieAlgebra.jl index f82583821247..d9c6ba931665 100644 --- a/experimental/LieAlgebras/src/LieAlgebra.jl +++ b/experimental/LieAlgebras/src/LieAlgebra.jl @@ -57,6 +57,13 @@ function basis(L::LieAlgebra, i::Int) return L([(j == i ? one(R) : zero(R)) for j in 1:dim(L)]) end +@doc raw""" + characteristic(L::LieAlgebra) -> Int + +Return the characteristic of the coefficient ring of the Lie algebra `L`. +""" +characteristic(L::LieAlgebra) = characteristic(coefficient_ring(L)) + @doc raw""" zero(L::LieAlgebra{C}) -> LieAlgebraElem{C} diff --git a/experimental/LieAlgebras/src/LieAlgebras.jl b/experimental/LieAlgebras/src/LieAlgebras.jl index 9200fa18e83e..e8f51c3c181d 100644 --- a/experimental/LieAlgebras/src/LieAlgebras.jl +++ b/experimental/LieAlgebras/src/LieAlgebras.jl @@ -21,6 +21,7 @@ import ..Oscar: canonical_projections, center, centralizer, + characteristic, coeff, coefficient_ring, coefficients, @@ -72,6 +73,8 @@ export LieSubalgebra export LieAlgebraModule, LieAlgebraModuleElem export LieAlgebraModuleHom export LinearLieAlgebra, LinearLieAlgebraElem +export RootSystem +export SimpleLieAlgebra, SimpleLieAlgebraElem export abelian_lie_algebra export abstract_module @@ -79,10 +82,14 @@ export base_lie_algebra export base_module export base_modules export bracket +export cartan_matrix +export chevalley_basis export coefficient_vector export coerce_to_lie_algebra_elem export combinations export derived_algebra +export dynkin_diagram +export exterior_power export general_linear_lie_algebra export highest_weight_module export hom_direct_sum @@ -97,8 +104,11 @@ export is_tensor_product export lie_algebra export matrix_repr_basis export multicombinations +export number_of_roots export permutations export permutations_with_sign +export root_system +export root_system_type export special_linear_lie_algebra export special_orthogonal_lie_algebra export standard_module @@ -120,6 +130,8 @@ include("LieAlgebraModuleHom.jl") include("iso_oscar_gap.jl") include("iso_gap_oscar.jl") include("GapWrapper.jl") +include("root_systems.jl") +include("simple_lie_algebra.jl") end @@ -133,6 +145,8 @@ export LieAlgebraModule, LieAlgebraModuleElem export LieAlgebraModuleHom export LieSubalgebra export LinearLieAlgebra, LinearLieAlgebraElem +export RootSystem +export SimpleLieAlgebra, SimpleLieAlgebraElem export abelian_lie_algebra export abstract_module @@ -140,8 +154,12 @@ export base_lie_algebra export base_module export base_modules export bracket +export cartan_matrix +export chevalley_basis export coerce_to_lie_algebra_elem export derived_algebra +export dynkin_diagram +export exterior_power export general_linear_lie_algebra export highest_weight_module export hom_direct_sum @@ -155,6 +173,9 @@ export is_tensor_power export is_tensor_product export lie_algebra export matrix_repr_basis +export number_of_roots +export root_system +export root_system_type export special_linear_lie_algebra export special_orthogonal_lie_algebra export standard_module diff --git a/experimental/LieAlgebras/src/root_systems.jl b/experimental/LieAlgebras/src/root_systems.jl new file mode 100644 index 000000000000..5630a19aa958 --- /dev/null +++ b/experimental/LieAlgebras/src/root_systems.jl @@ -0,0 +1,237 @@ +mutable struct RootSystem + roots::Vector{Vector{Int}} + simple_roots::Vector{Vector{Int}} + positive_roots::Vector{Vector{Int}} + root_system_type::Tuple{Symbol,Int} + GAP_root_system::GAP.GapObj + function RootSystem(S::Symbol, n::Int) + # S is a symbol detailing the type of the indecomposable root system + # e.g. "A", "B", "C",... and n is an integer for the number of simple roots + S1 = GAP.Obj(S) + RS = GAP.Globals.RootSystem(S1, n) + sR = Vector{Vector{Int}}(GAP.Globals.SimpleSystem(RS)) + Ro1 = Vector{Vector{Int}}(GAP.Globals.PositiveRoots(RS)) + Ro2 = Vector{Vector{Int}}(GAP.Globals.NegativeRoots(RS)) + Ro = vcat(Ro1, Ro2) + t = (S, n) + return new(Ro, sR, Ro1, t, RS) + end +end + +############################################################################### +# +# Basic manipulation +# +############################################################################### +@doc raw""" + number_of_roots(R::RootSystem) + +Return the numbers of roots in the root system `R`. +""" +number_of_roots(R::RootSystem) = size(R.roots)[1] + +@doc raw""" + number_of_roots(S::Symbol, n::Int) + +Return the numbers of roots in the root system of type `S` +""" +number_of_roots(S::Symbol, n::Int) = number_of_roots(root_system(S, n)) + +@doc raw""" + getindex(R::RootSystem, r::Int) + +Return the `r`-th root of the root system `R`. +""" +getindex(R::RootSystem, r::Int) = getindex(R.roots, r) + +@doc raw""" + root_system_type(R::RootSystem) + +Return the Dynkin type of the root system `R`. +""" +root_system_type(R::RootSystem) = R.root_system_type + +root_system_type_string(R::RootSystem) = + string(R.root_system_type[1]) * string(R.root_system_type[2]) + +############################################################################### +# +# String I/O +# +############################################################################### + +function Base.show(io::IO, R::RootSystem) + print(io, "Root system of type $(root_system_type_string(R))") +end + +############################################################################### +# +# Comparison +# +############################################################################### + +function Base.:(==)(R1::RootSystem, R2::RootSystem) + return R1.root_system_type == R2.root_system_type && R1.roots == R2.roots +end + +function Base.hash(R::RootSystem, h::UInt) + b = 0x9d96557cb5f07773 % UInt + h = hash(R.root_system_type, h) + h = hash(R.roots, h) + return xor(h, b) +end +############################################################################### +# +# Constructor +# +############################################################################### + +@doc raw""" + root_system(S::Symbol, n::Int) -> RootSystem + +Return the root system of type `Sn` where `S` is a symbol consisting out of +a single letter `A`, `B`, `C`, `D`, `E`, `F`, `G`. +The allowed values for `n` depend on the choice of `S`. +""" +function root_system(S::Symbol, n::Int) + @req _root_system_type_supported_by_GAP(S, n) "Unknown Dynkin type or not supported by GAP" + return RootSystem(S, n) +end + +############################################################################### +# +# further functions +# +############################################################################### + +function _root_system_type_supported_by_GAP(S, n) + S in [:A, :B, :C, :D, :E, :F, :G] || return false + n >= 1 || return false + S == :D && n < 4 && return false + S == :E && !(n in [6, 7, 8]) && return false + S == :F && n != 4 && return false + S == :G && n != 2 && return false + return true +end + +@doc raw""" + cartan_matrix(S::Symbol, n::Int) -> Matrix{QQFieldElem} + +Return the Cartan matrix of the root system of type `Sn`. +For the semantics of the arguments, refer to `root_system(S::Symbol, n::Int)` ref. +""" +function cartan_matrix(S::Symbol, n::Int) + return cartan_matrix(root_system(S, n)) +end + +@doc raw""" + cartan_matrix(R::RootSystem) -> Matrix{QQFieldElem} + +Return the Cartan matrix of the root system `R`. +""" +function cartan_matrix(R::RootSystem) + RS = R.GAP_root_system + CG = GAP.Globals.CartanMatrix(RS) + C = matrix(QQ, CG) + return C +end + +@doc raw""" + dynkin_diagram(S::Symbol, n::Int) + +Return the Dynkin diagram of the root system of type `Sn`. +For the semantics of the arguments, refer to [root_system(S::Symbol, n::Int)` ref. +""" +function dynkin_diagram(S::Symbol, n::Int) + @req _root_system_type_supported_by_GAP(S, n) "Unknown Dynkin type or not supported by GAP" + D = "" + + if S == :A + for i in 1:(n - 1) + D = D * string(i) * " - " + end + D = D * string(n) + + elseif S == :B + if n == 1 + D = string(n) + else + for i in 1:(n - 2) + D = D * string(i) * " - " + end + D = D * string(n - 1) * " >=> " * string(n) + end + + elseif S == :C + if n == 1 + D = string(n) + else + for i in 1:(n - 2) + D = D * string(i) * " - " + end + D = D * string(n - 1) * " <=< " * string(n) + end + + elseif S == :D + if n >= 4 + for i in 1:(4 * n - 10) + D = D * " " + end + D = D * string(n - 1) * "\n" + for i in 1:(4 * n - 11) + D = D * " " + end + D = D * "/\n" + for i in 1:(n - 3) + D = D * string(i) * " - " + end + D = D * string(n - 2) * "\n" + for i in 1:(4 * n - 12) + D = D * " " + end + D = D * " \\ \n" + for i in 1:(4 * n - 10) + D = D * " " + end + D = D * string(n) + else + error("This root system doesn't exist.") + end + + elseif S == :E + if n == 6 + D = "1 - 3 - 4 - 5 - 6\n |\n 2" + elseif n == 7 + D = "1 - 3 - 4 - 5 - 6 - 7\n |\n 2" + elseif n == 8 + D = "1 - 3 - 4 - 5 - 6 - 7 - 8\n |\n 2" + else + error("This root system doesn't exist.") + end + + elseif S == :F + if n == 4 + D = "1 - 2 >=> 3 - 4" + else + error("This root system doesn't exist.") + end + elseif S == :G + if n == 2 + D = "1 >>> 2" + else + error("This root system doesn't exist.") + end + else + error("This root system doesn't exist.") + end + print(D) +end + +@doc raw""" + dynkin_diagram(R::RootSystem) + +Return the Dynkin diagram of the root system `R` +""" +function dynkin_diagram(R::RootSystem) + return dynkin_diagram(R.root_system_type...) +end diff --git a/experimental/LieAlgebras/src/simple_lie_algebra.jl b/experimental/LieAlgebras/src/simple_lie_algebra.jl new file mode 100644 index 000000000000..50af8073c0ff --- /dev/null +++ b/experimental/LieAlgebras/src/simple_lie_algebra.jl @@ -0,0 +1,158 @@ +#Construct a simple Lie algebra over a given field with a given root system +@attributes mutable struct SimpleLieAlgebra{C<:FieldElem} <: LieAlgebra{C} + R::Field + root_system::RootSystem + dim::Int + s::Vector{Symbol} + root_system_type::Tuple{Symbol,Int} + struct_consts::Matrix{SRow{C}} + function SimpleLieAlgebra{C}( + R::Field, S::Symbol, n::Int; cached::Bool=true + ) where {C<:FieldElem} + RS = root_system(S, n) + return get_cached!(SimpleLieAlgebraDict, (R, RS), cached) do + dimL = number_of_roots(RS) + length(RS.simple_roots) + s = [Symbol("e_$i") for i in 1:dimL] + st = root_system_type(RS) + #get the structure constants of the Lie algebra L + #note that it is enough to do this over QQ, as we can later coerce the constants + #into the field R + coeffs_iso = inv(Oscar.iso_oscar_gap(QQ)) + LG = GAP.Globals.SimpleLieAlgebra(GAP.Obj(S), n, domain(coeffs_iso)) + sc_table_G = + ( + entry -> (entry[1], Vector{elem_type(QQ)}(map(coeffs_iso, entry[2]))) + ).( + Matrix{Tuple{Vector{Int},Vector{GAP.Obj}}}( + (GAP.Globals.StructureConstantsTable(GAPWrap.Basis(LG)))[1:dimL] + ) + ) + struct_consts = Matrix{SRow{elem_type(R)}}(undef, dimL, dimL) + for i in 1:dimL, j in 1:dimL + struct_consts[i, j] = sparse_row( + R, Tuple{Int,elem_type(R)}[(k, R(c)) for (k, c) in zip(sc_table_G[i, j]...)] + ) + end + new{C}(R, RS, dimL, s, st, struct_consts) + end::SimpleLieAlgebra{C} + end +end + +const SimpleLieAlgebraDict = CacheDictType{Tuple{Field,RootSystem},SimpleLieAlgebra}() + +mutable struct SimpleLieAlgebraElem{C<:FieldElem} <: LieAlgebraElem{C} + parent::SimpleLieAlgebra{C} + mat::MatElem{C} +end + +############################################################################### +# +# Basic manipulation +# +############################################################################### + +parent_type(::Type{SimpleLieAlgebraElem{C}}) where {C<:FieldElem} = SimpleLieAlgebra{C} + +elem_type(::Type{SimpleLieAlgebra{C}}) where {C<:FieldElem} = SimpleLieAlgebraElem{C} + +parent(x::SimpleLieAlgebraElem) = x.parent + +coefficient_ring(L::SimpleLieAlgebra{C}) where {C<:FieldElem} = L.R::parent_type(C) + +dim(L::SimpleLieAlgebra) = L.dim + +root_system(L::SimpleLieAlgebra) = L.root_system + +root_system_type(L::SimpleLieAlgebra) = L.root_system_type + +function symbols(L::SimpleLieAlgebra) + return L.s +end + +############################################################################### +# +# String I/O +# +############################################################################### + +function Base.show(io::IO, ::MIME"text/plain", L::SimpleLieAlgebra) + io = pretty(io) + println(io, "Simple Lie algebra") + println(io, Indent(), "of type $(root_system_type_string(root_system(L)))", Dedent()) + println(io, Indent(), "of dimension $(dim(L))", Dedent()) + print(io, "over ") + print(io, Lowercase(), coefficient_ring(L)) +end + +function Base.show(io::IO, L::SimpleLieAlgebra) + if get(io, :supercompact, false) + print(io, "Simple Lie algebra $(root_system_type_string(root_system(L)))") + else + io = pretty(io) + print( + io, "Simple Lie algebra $(root_system_type_string(root_system(L))) over ", Lowercase() + ) + print(IOContext(io, :supercompact => true), coefficient_ring(L)) + end +end + +############################################################################### +# +# Arithmetic operations +# +############################################################################### + +# Binary operations + +function bracket( + x::SimpleLieAlgebraElem{C}, y::SimpleLieAlgebraElem{C} +) where {C<:FieldElem} + check_parent(x, y) + L = parent(x) + mat = sum( + cxi * cyj * L.struct_consts[i, j] for (i, cxi) in enumerate(coefficients(x)), + (j, cyj) in enumerate(coefficients(y)); + init=sparse_row(coefficient_ring(L)), + ) + return L(mat) +end +############################################################################### +# +# Constructors +# +############################################################################### + +@doc raw""" + lie_algebra(R::Field, S::Symbol, n::Int; cached::Bool=true) -> SimpleLieAlgebra{elem_type(R)} + +Construct the simple Lie algebra over the field `R` with root system of type `Sn` (see `root_system(S::Symbol, n::Int)` ref). +The internally used basis of this Lie algebra is the Chevalley basis. +""" +function lie_algebra(R::Field, S::Symbol, n::Int; cached::Bool=true) + return SimpleLieAlgebra{elem_type(R)}(R, S, n; cached) +end + +############################################################################### +# +# Chevalley basis +# +############################################################################### + +@doc raw""" + chevalley_basis(L::SimpleLieAlgebra{T}) -> NTuple{3,Vector{SimpleLieAlgebraElem{T}}} + +Return the Chevalley basis of the simple Lie algebra `L` in three vectors, stating first the positive root vectors, +then the negative root vectors, and finally the basis of the Cartan subalgebra. The order of root vectors corresponds +to the order of the roots in the root system. +""" +function chevalley_basis(L::SimpleLieAlgebra) + RS = root_system(L) + n = length(RS.positive_roots) + B = basis(L) + # root vectors + r_plus = B[1:n] + r_minus = B[(n + 1):(2 * n)] + # basis for cartan algebra + h = B[(2 * n + 1):dim(L)] + return (r_plus, r_minus, h) +end diff --git a/experimental/LieAlgebras/test/LieAlgebra-test.jl b/experimental/LieAlgebras/test/LieAlgebra-test.jl index 3588eb5c1e7b..8e8eb23c72bc 100644 --- a/experimental/LieAlgebras/test/LieAlgebra-test.jl +++ b/experimental/LieAlgebras/test/LieAlgebra-test.jl @@ -18,6 +18,8 @@ function lie_algebra_conformance_test( @test coefficient_ring(x) === coefficient_ring(L) @test elem_type(coefficient_ring(L)) == C + @test characteristic(L) == characteristic(coefficient_ring(L)) + # this block stays only as long as `ngens` and `gens` are not specialized for Lie algebras @test dim(L) == ngens(L) @test basis(L) == gens(L) @@ -26,6 +28,8 @@ function lie_algebra_conformance_test( @test dim(L) == length(basis(L)) @test all(i -> basis(L, i) == basis(L)[i], 1:dim(L)) + @test dim(L) == length(symbols(L)) + @test iszero(zero(L)) @test coefficients(x) == [coeff(x, i) for i in 1:dim(L)] @@ -102,6 +106,7 @@ end include("AbstractLieAlgebra-test.jl") include("LinearLieAlgebra-test.jl") +include("simple_lie_algebra-test.jl") @testset "LieAlgebras.LieAlgebra" begin @testset "universal_enveloping_algebra" begin diff --git a/experimental/LieAlgebras/test/root_systems-test.jl b/experimental/LieAlgebras/test/root_systems-test.jl new file mode 100644 index 000000000000..e74f44b3ec43 --- /dev/null +++ b/experimental/LieAlgebras/test/root_systems-test.jl @@ -0,0 +1,7 @@ +@testset "LieAlgebras.RootSystem" begin + R = root_system(:F, 4) + @test cartan_matrix(R) == + matrix(QQ, 4, 4, [2, -1, 0, 0, -1, 2, -2, 0, 0, -1, 2, -1, 0, 0, -1, 2]) + @test number_of_roots(R) == 48 + @test number_of_roots(:F, 4) == number_of_roots(R) +end diff --git a/experimental/LieAlgebras/test/runtests.jl b/experimental/LieAlgebras/test/runtests.jl index f13f718ec084..f6216cc2fb20 100644 --- a/experimental/LieAlgebras/test/runtests.jl +++ b/experimental/LieAlgebras/test/runtests.jl @@ -7,3 +7,4 @@ include("LieAlgebraIdeal-test.jl") include("LieAlgebraHom-test.jl") include("LieAlgebraModule-test.jl") include("LieAlgebraModuleHom-test.jl") +include("root_systems-test.jl") diff --git a/experimental/LieAlgebras/test/simple_lie_algebra-test.jl b/experimental/LieAlgebras/test/simple_lie_algebra-test.jl new file mode 100644 index 000000000000..69b0b5cdc017 --- /dev/null +++ b/experimental/LieAlgebras/test/simple_lie_algebra-test.jl @@ -0,0 +1,29 @@ +@testset "LieAlgebras.SimpleLieAlgebra" begin + @testset "conformance tests" begin + @testset "B2(QQ)" begin + L = lie_algebra(QQ, :B, 2) + lie_algebra_conformance_test( + L, SimpleLieAlgebra{QQFieldElem}, SimpleLieAlgebraElem{QQFieldElem} + ) + end + + @testset "A3(CF(4))" begin + L = lie_algebra(cyclotomic_field(4)[1], :A, 3) + lie_algebra_conformance_test( + L, SimpleLieAlgebra{nf_elem}, SimpleLieAlgebraElem{nf_elem} + ) + end + end + + @testset "constructors and basic properties" begin + L = lie_algebra(QQ, :A, 2) + @test dim(L) == 8 + @test coefficient_ring(L) == QQ + @test root_system(L) == RootSystem(:A, 2) + @test root_system_type(L) == (:A, 2) + @test characteristic(L) == 0 + @test chevalley_basis(L) == ( + [basis(L, i) for i in 1:3], [basis(L, i) for i in 4:6], [basis(L, i) for i in 7:8] + ) + end +end diff --git a/src/Oscar.jl b/src/Oscar.jl index c5124855181a..579e22327d28 100644 --- a/src/Oscar.jl +++ b/src/Oscar.jl @@ -90,6 +90,7 @@ function __init__() "forms", # bilinear/sesquilinear/quadratic forms "primgrp", # primitive groups library "repsn", # constructing representations of finite groups + "sla", # computing with simple Lie algebras "smallgrp", # small groups library "transgrp", # transitive groups library "wedderga", # provides a function to compute Schur indices From 4a3be4c53a56d16d1efee263d5a14c7325e644c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20G=C3=B6ttgens?= Date: Fri, 20 Oct 2023 13:42:50 +0200 Subject: [PATCH 07/27] Add some more tests to the bibtool CI job (#2919) --- .bibtoolrsc | 24 ++++++++++++++++++++++++ .github/workflows/BibtoolCI.yml | 4 +++- docs/oscar_references.bib | 14 +++++++------- 3 files changed, 34 insertions(+), 8 deletions(-) diff --git a/.bibtoolrsc b/.bibtoolrsc index 105067ee74c8..a2cf6fac65a0 100644 --- a/.bibtoolrsc +++ b/.bibtoolrsc @@ -61,3 +61,27 @@ key.format = { %+8.1n(author) } { %2d(year) } } + +# Enforce "{...}" around fields +rewrite.rule {"^\"\([^#]*\)\"$" "{\1}"} +rewrite.rule {"^ *\([0-9]*\) *$" "{\1}"} + +# Remove empty fields +rewrite.rule {"^{ *}$"} + +# Unify page range separator +rewrite.rule {pages "\([0-9]+\) *\(-\|---\|–\) *\([0-9]+\)" "\1--\3"} + +# Check that 1800<=year<=2029 +check.rule { year "^[\"{]1[89][0-9][0-9][\"}]$" } +check.rule { year "^[\"{]20[0-2][0-9][\"}]$" } +check.error.rule { year "" "\@ \$: Year has to be a suitable number" } + +# Check that the doi field is not a URL +check.error.rule { doi "\://" "\@ \$: doi field should not be a URL" } + +# Check that the url field is not a DOI +check.error.rule { url "doi\.org/" "\@ \$: url field should not contain a doi. Use the doi field instead" } + +# Check that no field contains a LaTeX url command, as DocumenterCitations.jl prints them ugly +check.error.rule { "\\url" "\@ \$: LaTeX's `\\url` commands are not supported" } diff --git a/.github/workflows/BibtoolCI.yml b/.github/workflows/BibtoolCI.yml index aa51fad22ee3..0cee0db8bc53 100644 --- a/.github/workflows/BibtoolCI.yml +++ b/.github/workflows/BibtoolCI.yml @@ -25,7 +25,9 @@ jobs: sudo apt-get install -y bibtool - name: Execute bibtool and check for changes run: | - bibtool docs/oscar_references.bib -o docs/oscar_references.bib + bibtool docs/oscar_references.bib -o docs/oscar_references.bib 2>&1 | tee bibtool.log + test \! -s bibtool.log + rm bibtool.log if [ -n "$(git status --porcelain)" ]; then echo "We employ bibtool to standardize the bibtex entries of our reference list." echo "Your changes to the bibliography do not follow this standard." diff --git a/docs/oscar_references.bib b/docs/oscar_references.bib index 27912d155e25..38eb9ebdd1e0 100644 --- a/docs/oscar_references.bib +++ b/docs/oscar_references.bib @@ -128,7 +128,7 @@ @Article{BDLPSS13 journal = {Journal of Symbolic Computation}, volume = {51}, note = {Effective Methods in Algebraic Geometry}, - pages = {99-114}, + pages = {99--114}, year = {2013}, doi = {10.1016/j.jsc.2012.07.002} } @@ -695,7 +695,7 @@ @Article{FGLM93 journal = {Journal of Symbolic Computation}, volume = {16}, number = {4}, - pages = {329-344}, + pages = {329--344}, year = {1993}, doi = {10.1006/jsco.1993.1051} } @@ -707,7 +707,7 @@ @Article{FJR17 volume = {22}, number = {1}, publisher = {Mathematical Sciences Publishers}, - pages = {235-303}, + pages = {235--303}, year = {2017}, month = {Oct}, doi = {10.2140/gt.2018.22.235} @@ -736,7 +736,7 @@ @Article{FY04 number = {3}, publisher = {Springer Science and Business Media {LLC}}, pages = {515--536}, - year = 2004, + year = {2004}, month = {mar}, doi = {10.1007/s00222-003-0327-2} } @@ -1011,7 +1011,7 @@ @InCollection{IR96 title = {The {M}c{K}ay correspondence for finite subgroups of ${\rm SL}(3,\mathbb C)$}, booktitle = {Higher-dimensional complex varieties ({T}rento, 1994)}, publisher = {de Gruyter}, - pages = {221-240}, + pages = {221--240}, year = {1996}, location = {Berlin} } @@ -1509,8 +1509,8 @@ @MastersThesis{Peg14 title = {Chow Rings of Toric Varieties}, note = {Refereed by Prof. Dr. Eva Maria Feichtner and Dr. Emanuele Delucchi}, address = {Faculty of Mathematics}, - year = 2014, - month = 9, + year = {2014}, + month = {9}, school = {University of Bremen} } From 18a5f9a6cd82bc41646e0ebab2c59571d88914f4 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Fri, 20 Oct 2023 13:45:24 +0200 Subject: [PATCH 08/27] Avoid various obsolete function and type names (#2938) --- .../FrameWorks/ring_localizations.md | 2 +- docs/src/CommutativeAlgebra/localizations.md | 4 +- experimental/GaloisGrp/src/Solve.jl | 2 +- experimental/IntersectionTheory/src/Bott.jl | 2 +- experimental/IntersectionTheory/src/Main.jl | 4 +- .../IntersectionTheory/test/runtests.jl | 2 +- .../PlaneCurve/src/AffinePlaneCurve.jl | 2 +- .../src/lattices_with_isometry.jl | 2 +- experimental/Schemes/IdealSheaves.jl | 4 +- experimental/Schemes/ProjectiveModules.jl | 10 ++-- experimental/Schemes/SpaceGerms.jl | 8 +-- experimental/Schemes/WeilDivisor.jl | 2 +- .../AffineSchemes/Objects/Constructors.jl | 22 ++++---- .../ToricMorphisms/attributes.jl | 4 +- .../Matroids/matroid_strata_grassmannian.jl | 4 +- src/Modules/ModulesGraded.jl | 4 +- src/Modules/UngradedModules.jl | 10 ++-- src/Rings/MPolyQuo.jl | 2 +- src/Rings/groebner.jl | 14 +++--- src/Rings/localization_interface.jl | 16 +++--- src/Rings/mpoly-ideals.jl | 2 +- src/Rings/mpoly-local.jl | 6 +-- src/Rings/mpoly-localizations.jl | 48 +++++++++--------- src/Rings/mpolyquo-localizations.jl | 18 +++---- src/TropicalGeometry/groebner_fan.jl | 50 +++++++++---------- src/exports.jl | 2 +- .../Schemes/AffineSchemes.jl | 4 +- .../Schemes/FunctionFields.jl | 2 +- test/Modules/ModulesGraded.jl | 2 +- test/Modules/module-localizations.jl | 12 ++--- test/Rings/MPolyQuo.jl | 10 ++-- test/Rings/integer-localizations.jl | 14 +++--- test/Rings/mpoly-local.jl | 6 +-- test/Rings/mpoly-localizations.jl | 50 +++++++++---------- test/Rings/mpolyquo-localizations.jl | 34 ++++++------- test/Rings/nmod-localizations.jl | 8 +-- test/Serialization/Algebras.jl | 2 +- 37 files changed, 194 insertions(+), 196 deletions(-) diff --git a/docs/src/CommutativeAlgebra/FrameWorks/ring_localizations.md b/docs/src/CommutativeAlgebra/FrameWorks/ring_localizations.md index 527c58535d4a..b5e99cca28e7 100644 --- a/docs/src/CommutativeAlgebra/FrameWorks/ring_localizations.md +++ b/docs/src/CommutativeAlgebra/FrameWorks/ring_localizations.md @@ -21,7 +21,7 @@ localized rings should belong to the `AbsLocalizedRing` abstract type. The basic functionality that has to be realized for any concrete instance of `AbsMultSet` is the containment check for elements in multiplicatively closed subsets via the `in` function. -For each concrete instance of `AbsLocalizedRing`, the `Localization` constructor as well as the +For each concrete instance of `AbsLocalizedRing`, the `localization` constructor as well as the functions `base_ring` and `inverted_set` need to be implemented. Moreover, as for any other type of rings in OSCAR, methods for the standardized set of functions of OSCAR's general [Ring Interface](@ref) must be supplied. diff --git a/docs/src/CommutativeAlgebra/localizations.md b/docs/src/CommutativeAlgebra/localizations.md index 6482ec597d2f..09b9312ffd6b 100644 --- a/docs/src/CommutativeAlgebra/localizations.md +++ b/docs/src/CommutativeAlgebra/localizations.md @@ -237,7 +237,7 @@ Complement julia> RQ, p = quo(R, I); -julia> RQL, iota = Localization(RQ, U); +julia> RQL, iota = localization(RQ, U); julia> phi = compose(p, iota); @@ -340,7 +340,7 @@ Complement julia> RQ, p = quo(R, I); -julia> RQL, iota = Localization(RQ, U); +julia> RQL, iota = localization(RQ, U); julia> phi = compose(p, iota); diff --git a/experimental/GaloisGrp/src/Solve.jl b/experimental/GaloisGrp/src/Solve.jl index 61907bd31472..3a275cc28be0 100644 --- a/experimental/GaloisGrp/src/Solve.jl +++ b/experimental/GaloisGrp/src/Solve.jl @@ -324,7 +324,7 @@ function length_bound(C::GaloisCtx, S::SubField, x::Union{QQFieldElem,NumFieldEl end f = parent(defining_polynomial(S.fld))(x) if iszero(f) - return fmpz(1) + return ZZRingElem(1) end B = Oscar.GaloisGrp.upper_bound(C, S.pe).val diff --git a/experimental/IntersectionTheory/src/Bott.jl b/experimental/IntersectionTheory/src/Bott.jl index 6a2599fba33e..f4c6250dec7a 100644 --- a/experimental/IntersectionTheory/src/Bott.jl +++ b/experimental/IntersectionTheory/src/Bott.jl @@ -11,7 +11,7 @@ struct TnRep n::Int w::Vector function TnRep(w::Vector{W}) where W - # be sure to use fmpz to avoid overflow + # be sure to use ZZRingElem to avoid overflow W == Int && return new(length(w), ZZ.(w)) new(length(w), w) end diff --git a/experimental/IntersectionTheory/src/Main.jl b/experimental/IntersectionTheory/src/Main.jl index 634e2167959c..c5d68c7a7989 100644 --- a/experimental/IntersectionTheory/src/Main.jl +++ b/experimental/IntersectionTheory/src/Main.jl @@ -740,7 +740,7 @@ betti(X::AbstractVariety) = length.(basis(X)) Compute the integral of a Chow ring element. If the abstract_variety $X$ has a (unique) point class `X.point`, the integral will be a -number (an `fmpq` or a function field element). Otherwise the 0-dimensional +number (an `QQFieldElem` or a function field element). Otherwise the 0-dimensional part of $x$ is returned. """ function integral(x::MPolyDecRingOrQuoElem) @@ -886,7 +886,7 @@ end function _a_hat_genus(x::MPolyDecRingOrQuoElem) n = get_attribute(parent(x), :abstract_variety_dim) # the Taylor series of (sqrt(t)/2)/sinh(sqrt(t)/2) - R, t = PowerSeriesRing(QQ, 2n+1, "t") + R, t = power_series_ring(QQ, 2n+1, "t") s = divexact(t, exp(QQ(1//2)*t)-exp(-QQ(1//2)*t)) taylor = [coeff(s, 2i) for i in 0:n] _genus(x, taylor) diff --git a/experimental/IntersectionTheory/test/runtests.jl b/experimental/IntersectionTheory/test/runtests.jl index f01ea2804018..0019989aef02 100644 --- a/experimental/IntersectionTheory/test/runtests.jl +++ b/experimental/IntersectionTheory/test/runtests.jl @@ -148,7 +148,7 @@ let pushforward = IntersectionTheory.pushforward @test euler_characteristic(cotangent_bundle(P2)) == -1 hilb = hilbert_polynomial(P2) t = gens(parent(hilb))[1] - @test hilb isa fmpq_poly + @test hilb isa QQPolyRingElem @test hilb == 1 + 3//2*t + 1//2*t^2 # Grassmannian diff --git a/experimental/PlaneCurve/src/AffinePlaneCurve.jl b/experimental/PlaneCurve/src/AffinePlaneCurve.jl index 258842f24501..f9ce00932a4c 100644 --- a/experimental/PlaneCurve/src/AffinePlaneCurve.jl +++ b/experimental/PlaneCurve/src/AffinePlaneCurve.jl @@ -439,7 +439,7 @@ function intersection_multiplicity(C::AffinePlaneCurve{S}, D::AffinePlaneCurve{S P.ambient_dim == 2 || error("The point needs to be in a two dimensional space") R = parent(C.eq) m = ideal_point(R, P) - r = Localization(R, m) + r = localization(R, m) I = ideal(r, [C.eq, D.eq]) G = Oscar.groebner_assure(I) return Singular.vdim(G.S) diff --git a/experimental/QuadFormAndIsom/src/lattices_with_isometry.jl b/experimental/QuadFormAndIsom/src/lattices_with_isometry.jl index 24f74a4e3537..a94b9bfd355c 100644 --- a/experimental/QuadFormAndIsom/src/lattices_with_isometry.jl +++ b/experimental/QuadFormAndIsom/src/lattices_with_isometry.jl @@ -1902,7 +1902,7 @@ function _divides(k::IntExt, n::Int) end @doc raw""" - kernel_lattice(Lf::ZZLatWithIsom, p::Union{fmpz_poly, QQPolyRingElem}) + kernel_lattice(Lf::ZZLatWithIsom, p::Union{ZZPolyRingElem, QQPolyRingElem}) -> ZZLatWithIsom Given a lattice with isometry $(L, f)$ and a polynomial $p$ with rational diff --git a/experimental/Schemes/IdealSheaves.jl b/experimental/Schemes/IdealSheaves.jl index 80f8f56222af..9f1034adaec1 100644 --- a/experimental/Schemes/IdealSheaves.jl +++ b/experimental/Schemes/IdealSheaves.jl @@ -682,7 +682,7 @@ function order_on_divisor( den_mult = _minimal_power_such_that(J, x->(issubset(quotient(x+K, bR), J)))[1]-1 return num_mult - den_mult # # Deprecated code computing symbolic powers explicitly: -# L, map = Localization(OO(U), +# L, map = localization(OO(U), # MPolyComplementOfPrimeIdeal(saturated_ideal(I(U))) # ) # typeof(L)<:Union{MPolyLocRing{<:Any, <:Any, <:Any, <:Any, @@ -1153,7 +1153,7 @@ function _cofactors(comp::Vector{<:Ideal}) R = base_ring(first(comp)) all(x->base_ring(x)===R, comp) || error("ideals must be defined over the same ring") n = length(comp) - pairwise_cof = one(MatrixSpace(R, n, n)) + pairwise_cof = identity_matrix(R, n) for i in 1:n-1 for j in i+1:n I = ideal(R, vcat(gens(comp[i]), gens(comp[j]))) diff --git a/experimental/Schemes/ProjectiveModules.jl b/experimental/Schemes/ProjectiveModules.jl index f9637430355a..3dbe2b1d4361 100644 --- a/experimental/Schemes/ProjectiveModules.jl +++ b/experimental/Schemes/ProjectiveModules.jl @@ -100,7 +100,7 @@ function _is_projective_without_denominators(A::MatElem; projectors = MatElem[] # The local projectors on each component expon = Int[] for k in 1:l - L, inc = Localization(R, complement_equation(U[k])) # We can not use OO(U[k]) directly, because + L, inc = localization(R, complement_equation(U[k])) # We can not use OO(U[k]) directly, because # we'd be missing the map in that case. success, p, k = _is_projective_without_denominators(change_base_ring(L, A), unit=L(unit), task=task) !success && return false, zero_matrix(R, n, n), 0 @@ -167,7 +167,7 @@ function _is_projective_without_denominators(A::MatElem; add_row!(B, -A[k, j], i, k) end Asub = B[[k for k in 1:m if k != i], [k for k in 1:n if k !=j]] - Rloc, inc = Localization(R, u) + Rloc, inc = localization(R, u) push!(sub_localizations, (Rloc, inc)) # We expect a pair (Q, k) consisting of a matrix Q defined over Rloc, # but liftable to a matrix over R without effort. The local projector @@ -262,7 +262,7 @@ _lifted_numerator(a::MPolyQuoLocRingElem) = lifted_numerator(a) # This deserves special constructors, because we can deliver maps for # # lifting which is not possible in general. # ######################################################################## -function Localization(A::MPolyQuoRing, f::MPolyQuoRingElem) +function localization(A::MPolyQuoRing, f::MPolyQuoRingElem) R = base_ring(A) U = MPolyPowersOfElement(R, [lift(f)]) W = MPolyLocRing(R, U) @@ -286,7 +286,7 @@ function Localization(A::MPolyQuoRing, f::MPolyQuoRingElem) return L, MapFromFunc(A, L, func, func_inv) end -function Localization(A::MPolyLocRing, f::MPolyLocRingElem) +function localization(A::MPolyLocRing, f::MPolyLocRingElem) R = base_ring(A) d = numerator(f) U = MPolyPowersOfElement(R, [d]) @@ -307,7 +307,7 @@ function Localization(A::MPolyLocRing, f::MPolyLocRingElem) return L, MapFromFunc(A, L, func, func_inv) end -function Localization(A::MPolyQuoLocRing, f::MPolyQuoLocRingElem) +function localization(A::MPolyQuoLocRing, f::MPolyQuoLocRingElem) R = base_ring(A) d = lifted_numerator(f) U = MPolyPowersOfElement(R, [d]) diff --git a/experimental/Schemes/SpaceGerms.jl b/experimental/Schemes/SpaceGerms.jl index f7c7caa42cbf..46ce418b8d95 100644 --- a/experimental/Schemes/SpaceGerms.jl +++ b/experimental/Schemes/SpaceGerms.jl @@ -166,7 +166,7 @@ Spectrum julia> representative(XS) == X true -julia> L, phi = Localization(R,complement_of_point_ideal(R,[0,0,0])); +julia> L, phi = localization(R,complement_of_point_ideal(R,[0,0,0])); julia> IL = phi(I); @@ -404,7 +404,7 @@ function SpaceGerm(X::AbsSpec, a::Vector{T}) where T<:Union{Integer, FieldElem} kk = coefficient_ring(R) b = [kk.(v) for v in a] ## throws an error, if vector entries are not compatible U = MPolyComplementOfKPointIdeal(R,b) - Y = Spec(Localization(OO(X), U)[1]) + Y = Spec(localization(OO(X), U)[1]) Z = SpaceGerm(Y) set_attribute!(Z,:representative,X) return SpaceGerm(Y) @@ -485,7 +485,7 @@ function HypersurfaceGerm(X::AbsSpec, a::Vector{T}) where T<:Union{Integer, Fiel kk = coefficient_ring(R) b = [kk.(v) for v in a] ## throws an error, if vector entries are not compatible U = MPolyComplementOfKPointIdeal(R,b) - LX,_ = Localization(OO(X), U) + LX,_ = localization(OO(X), U) mingens = minimal_generating_set(modulus(LX)) length(mingens) == 1 || error("not a hypersurface") f = mingens[1] @@ -560,7 +560,7 @@ function CompleteIntersectionGerm(X::AbsSpec, a::Vector{T}) where T<:Union{Integ kk = coefficient_ring(R) b = [kk.(v) for v in a] ## throws an error, if vector entries are not compatible U = MPolyComplementOfKPointIdeal(R,b) - L,_ = Localization(OO(X), U) + L,_ = localization(OO(X), U) mingens = minimal_generating_set(modulus(L)) ## TODO: Should be dim(L) and not dim(Spec(L)), but dim for localized ## quotients is only repaired on the geometric side as of now!!! diff --git a/experimental/Schemes/WeilDivisor.jl b/experimental/Schemes/WeilDivisor.jl index 4195f70f1990..c46062d18519 100644 --- a/experimental/Schemes/WeilDivisor.jl +++ b/experimental/Schemes/WeilDivisor.jl @@ -596,7 +596,7 @@ function _subsystem(L::LinearSystem, P::IdealSheaf, n) numerators = [numerator(g)*divexact(common_denominator, denominator(g)) for g in loc_rep] # compute a symbolic power - RP, _ = Localization(OO(U), complement_of_prime_ideal(saturated_ideal(P(U)))) + RP, _ = localization(OO(U), complement_of_prime_ideal(saturated_ideal(P(U)))) PP = RP(prime_ideal(inverted_set(RP))) K = function_field(X) diff --git a/src/AlgebraicGeometry/Schemes/AffineSchemes/Objects/Constructors.jl b/src/AlgebraicGeometry/Schemes/AffineSchemes/Objects/Constructors.jl index d4b5d2a03294..015b11b3f279 100644 --- a/src/AlgebraicGeometry/Schemes/AffineSchemes/Objects/Constructors.jl +++ b/src/AlgebraicGeometry/Schemes/AffineSchemes/Objects/Constructors.jl @@ -50,7 +50,7 @@ Spectrum at complement of prime ideal(x) ``` """ -Spec(R::MPolyRing, U::AbsMPolyMultSet) = Spec(Localization(R, U)[1]) +Spec(R::MPolyRing, U::AbsMPolyMultSet) = Spec(localization(R, U)[1]) @doc raw""" @@ -408,7 +408,7 @@ function hypersurface_complement(X::SpecType, f::RingElem) where {SpecType<:AbsS h = lifted_numerator(f) U = MPolyPowersOfElement(h) simplify!(U) - W, _ = Localization(OO(X), U) + W, _ = localization(OO(X), U) Y = Spec(W) set_attribute!(Y, :ambient_space, ambient_space(X)) return Y @@ -419,7 +419,7 @@ function hypersurface_complement(X::SpecType, f::RingElem) where {SpecType<:AbsS h = numerator(f) U = MPolyPowersOfElement(h) simplify!(U) - W, _ = Localization(OO(X), U) + W, _ = localization(OO(X), U) Y = Spec(W) set_attribute!(Y, :ambient_space, ambient_space(X)) return Y @@ -429,7 +429,7 @@ function hypersurface_complement(X::SpecType, f::RingElem) where {SpecType<:AbsS parent(f) == OO(X) || return hypersurface_complement(X, OO(X)(f)) U = MPolyPowersOfElement(f) simplify!(U) - W, _ = Localization(OO(X), U) + W, _ = localization(OO(X), U) Y = Spec(W) set_attribute!(Y, :ambient_space, ambient_space(X)) return Y @@ -439,7 +439,7 @@ function hypersurface_complement(X::SpecType, f::RingElem) where {SpecType<:AbsS parent(f) == OO(X) || return hypersurface_complement(X, OO(X)(f)) U = MPolyPowersOfElement(lift(f)) simplify!(U) - W, _ = Localization(OO(X), U) + W, _ = localization(OO(X), U) Y = Spec(W) set_attribute!(Y, :ambient_space, ambient_space(X)) return Y @@ -487,7 +487,7 @@ function hypersurface_complement(X::SpecType, f::Vector{<:RingElem}) where {Spec h = lifted_numerator.(f) U = MPolyPowersOfElement(ambient_coordinate_ring(X), h) simplify!(U) - W, _ = Localization(OO(X), U) + W, _ = localization(OO(X), U) Y = Spec(W) set_attribute!(Y, :ambient_space, ambient_space(X)) return Y @@ -498,7 +498,7 @@ function hypersurface_complement(X::SpecType, f::Vector{<:RingElem}) where {Spec h = numerator.(f) U = MPolyPowersOfElement(ambient_coordinate_ring(X), h) simplify!(U) - W, _ = Localization(OO(X), U) + W, _ = localization(OO(X), U) Y = Spec(W) set_attribute!(Y, :ambient_space, ambient_space(X)) return Y @@ -508,7 +508,7 @@ function hypersurface_complement(X::SpecType, f::Vector{<:RingElem}) where {Spec all(x->(parent(x) == OO(X)), f) || return hypersurface_complement(X, OO(X).(f)) U = MPolyPowersOfElement(ambient_coordinate_ring(X), f) simplify!(U) - W, _ = Localization(OO(X), U) + W, _ = localization(OO(X), U) Y = Spec(W) set_attribute!(Y, :ambient_space, ambient_space(X)) return Y @@ -518,7 +518,7 @@ function hypersurface_complement(X::SpecType, f::Vector{<:RingElem}) where {Spec all(x->(parent(x) == OO(X)), f) || return hypersurface_complement(X, OO(X).(f)) U = MPolyPowersOfElement(ambient_coordinate_ring(X), lift.(f)) simplify!(U) - W, _ = Localization(OO(X), U) + W, _ = localization(OO(X), U) Y = Spec(W) set_attribute!(Y, :ambient_space, ambient_space(X)) return Y @@ -686,7 +686,7 @@ function Base.intersect( ) where {BRT<:Ring} R = ambient_coordinate_ring(X) R === ambient_coordinate_ring(Y) || error("schemes can not be compared") - return Spec(Localization(R, inverted_set(OO(X)) * inverted_set(OO(Y)))[1]) + return Spec(localization(R, inverted_set(OO(X)) * inverted_set(OO(Y)))[1]) end @@ -825,7 +825,7 @@ function closure( <:MPolyPowersOfElement}} @check issubset(X, Y) "the first argument is not a subset of the second" #is_closed_embedding(X, Y) && return X - W, _ = Localization(inverted_set(OO(X))*inverted_set(OO(Y))) + W, _ = localization(inverted_set(OO(X))*inverted_set(OO(Y))) I = ideal(W, W.(gens(modulus(OO(X))))) Isat = saturated_ideal(I) R = ambient_coordinate_ring(Y) diff --git a/src/AlgebraicGeometry/ToricVarieties/ToricMorphisms/attributes.jl b/src/AlgebraicGeometry/ToricVarieties/ToricMorphisms/attributes.jl index 20618e699bed..f16b6f3d4e3c 100644 --- a/src/AlgebraicGeometry/ToricVarieties/ToricMorphisms/attributes.jl +++ b/src/AlgebraicGeometry/ToricVarieties/ToricMorphisms/attributes.jl @@ -258,7 +258,7 @@ function _my_mult(u::PointVector{ZZRingElem}, A::ZZMatrix) m = length(u) m == nrows(A) || error("sizes incompatible") n = ncols(A) - result = zero(MatrixSpace(ZZ, 1, n)) + result = zero_matrix(ZZ, 1, n) for k in 1:n result[1, k] = sum(u[i]*A[i, k] for i in 1:m; init=zero(ZZ)) end @@ -267,7 +267,7 @@ end function _to_ZZ_matrix(u::PointVector{ZZRingElem}) n = length(u) - result = zero(MatrixSpace(ZZ, 1, n)) + result = zero_matrix(ZZ, 1, n) for i in 1:n result[1, i] = u[i] end diff --git a/src/Combinatorics/Matroids/matroid_strata_grassmannian.jl b/src/Combinatorics/Matroids/matroid_strata_grassmannian.jl index ad9651176b81..166a145d18b8 100644 --- a/src/Combinatorics/Matroids/matroid_strata_grassmannian.jl +++ b/src/Combinatorics/Matroids/matroid_strata_grassmannian.jl @@ -272,7 +272,7 @@ function matroid_stratum_matrix_coordinates_given_ring(d::Int, n::Int, #S = localizing_semigroup(d, n, Bs, MC, B, R, x, xdict) S = MPolyPowersOfElement(R , basesX) - SinvR , iota = Localization(R, S) + SinvR , iota = localization(R, S) # X = make_coordinate_matrix(d, n, MC, B, R, x, xdict) Igens = unique!([det(X[:, nb]) for nb in NBsNotVariable ]) @@ -403,7 +403,7 @@ function matroid_realization_space_given_ring(d::Int, n::Int, M::Matroid, S = MPolyPowersOfElement(R , basesX) #S = realization_localizing_semigroup(basesX); - SinvR , iota = Localization(R, S) + SinvR , iota = localization(R, S) Igens = [det(X[:, nb]) for nb in NBsNotVariable ] diff --git a/src/Modules/ModulesGraded.jl b/src/Modules/ModulesGraded.jl index 6affa0a4ebab..357e58fb7f2c 100644 --- a/src/Modules/ModulesGraded.jl +++ b/src/Modules/ModulesGraded.jl @@ -1424,7 +1424,7 @@ function Base.show(io::IO, b::BettiTable) parent(b.project) == parent(x[1][2]) || error("projection vector has wrong type") print(io, "Betti Table for scalar product of grading with ", b.project.coeff, "\n") print(io, " ") - L = Vector{fmpz}(undef,0) + L = Vector{ZZRingElem}(undef,0) for i in 1:length(x) temp_sum = (b.project.coeff * transpose(x[i][2].coeff))[1] Base.push!(L, temp_sum) @@ -2283,7 +2283,7 @@ function _constant_sub_matrix( ind_cod = _indices_of_generators_of_degree(G, d) m = length(ind_dom) n = length(ind_cod) - result = zero(MatrixSpace(kk, m, n)) + result = zero_matrix(kk, m, n) for i in 1:m for j in 1:n c = phi(F[ind_dom[i]])[ind_cod[j]] diff --git a/src/Modules/UngradedModules.jl b/src/Modules/UngradedModules.jl index ae175fe8e861..127f52afe00c 100644 --- a/src/Modules/UngradedModules.jl +++ b/src/Modules/UngradedModules.jl @@ -47,7 +47,7 @@ julia> P = ideal(R, [x, y, z]); julia> U = complement_of_prime_ideal(P); -julia> RL, _ = Localization(R, U); +julia> RL, _ = localization(R, U); julia> FRL = free_module(RL, 2, "f") Free module of rank 2 over Localization of multivariate polynomial ring in 3 variables over QQ at complement of prime ideal(x, y, z) @@ -63,7 +63,7 @@ Free module of rank 2 over RQ julia> RQ(x)*FRQ[1] x*g[1] -julia> RQL, _ = Localization(RQ, U); +julia> RQL, _ = localization(RQ, U); julia> FRQL = free_module(RQL, 2, "h") Free module of rank 2 over Localization of quotient of multivariate polynomial ring at complement of prime ideal @@ -1763,7 +1763,7 @@ julia> P = ideal(R, [x, y, z]); julia> U = complement_of_prime_ideal(P); -julia> RL, _ = Localization(R, U); +julia> RL, _ = localization(R, U); julia> FRL = free_module(RL, 1) Free module of rank 1 over Localization of multivariate polynomial ring in 3 variables over QQ at complement of prime ideal(x, y, z) @@ -1809,7 +1809,7 @@ by Submodule with 3 generators 2 -> 2*x^2*e[1] 3 -> z^4*e[1] -julia> RQL, _ = Localization(RQ, U); +julia> RQL, _ = localization(RQ, U); julia> FRQL = free_module(RQL, 1) Free module of rank 1 over Localization of quotient of multivariate polynomial ring at complement of prime ideal @@ -1886,7 +1886,7 @@ julia> B = Rg[4*x*y^3 (2*x+y)^4] julia> F2 = graded_free_module(Rg,[0,0]) Graded free module Rg^2([0]) of rank 2 over Rg -julia> M1 = SubQuo(F2, A1, B) +julia> M1 = SubquoModule(F2, A1, B) Graded subquotient of submodule of F2 generated by 1 -> x*e[1] + y*e[2] 2 -> 2*x^2*e[1] + 3*y^2*e[2] diff --git a/src/Rings/MPolyQuo.jl b/src/Rings/MPolyQuo.jl index 8b4500b32dbe..0cae2fc41440 100644 --- a/src/Rings/MPolyQuo.jl +++ b/src/Rings/MPolyQuo.jl @@ -125,7 +125,7 @@ end # framework. # # Say you have a new type `MyType` for the `coefficient_ring` of a -# polynomial ring `P` and you would like to make the `MPolyQuo` +# polynomial ring `P` and you would like to make the `MPolyQuoRing` # structure useful for quotients of the form `P/I`. Then you would # declare # diff --git a/src/Rings/groebner.jl b/src/Rings/groebner.jl index 9183c422e888..f798daa03714 100644 --- a/src/Rings/groebner.jl +++ b/src/Rings/groebner.jl @@ -1496,7 +1496,7 @@ end # modular gröbner basis techniques using Singular @doc raw""" - groebner_basis_modular(I::MPolyIdeal{fmpq_mpoly}; ordering::MonomialOrdering = default_ordering(base_ring(I)), certify::Bool = false) + groebner_basis_modular(I::MPolyIdeal{QQMPolyRingElem}; ordering::MonomialOrdering = default_ordering(base_ring(I)), certify::Bool = false) Compute the reduced Gröbner basis of `I` w.r.t. `ordering` using a multi-modular strategy. @@ -1520,7 +1520,7 @@ with respect to the ordering degrevlex([x, y, z]) ``` """ -function groebner_basis_modular(I::MPolyIdeal{fmpq_mpoly}; ordering::MonomialOrdering = default_ordering(base_ring(I)), +function groebner_basis_modular(I::MPolyIdeal{QQMPolyRingElem}; ordering::MonomialOrdering = default_ordering(base_ring(I)), certify::Bool = false) # small function to get a canonically sorted reduced gb @@ -1547,7 +1547,7 @@ function groebner_basis_modular(I::MPolyIdeal{fmpq_mpoly}; ordering::MonomialOrd std_basis_crt_previous = std_basis_mod_p_lifted n_stable_primes = 0 - d = fmpz(p) + d = ZZRingElem(p) unlucky_primes_in_a_row = 0 done = false while !done @@ -1572,16 +1572,16 @@ function groebner_basis_modular(I::MPolyIdeal{fmpq_mpoly}; ordering::MonomialOrd is_stable = true for (i, f) in enumerate(std_basis_mod_p_lifted) if !iszero(f - std_basis_crt_previous[i]) - std_basis_crt_previous[i], _ = induce_crt(std_basis_crt_previous[i], d, f, fmpz(p), true) + std_basis_crt_previous[i], _ = induce_crt(std_basis_crt_previous[i], d, f, ZZRingElem(p), true) stable = false end end if is_stable n_stable_primes += 1 end - d *= fmpz(p) + d *= ZZRingElem(p) end - final_gb = fmpq_mpoly[induce_rational_reconstruction(f, d, parent = base_ring(I)) for f in std_basis_crt_previous] + final_gb = QQMPolyRingElem[induce_rational_reconstruction(f, d, parent = base_ring(I)) for f in std_basis_crt_previous] I.gb[ordering] = IdealGens(final_gb, ordering) if certify @@ -1594,7 +1594,7 @@ function groebner_basis_modular(I::MPolyIdeal{fmpq_mpoly}; ordering::MonomialOrd return I.gb[ordering] end -function induce_rational_reconstruction(f::fmpz_mpoly, d::fmpz; parent = 1) +function induce_rational_reconstruction(f::ZZMPolyRingElem, d::ZZRingElem; parent = 1) g = MPolyBuildCtx(parent) for (c, v) in zip(AbstractAlgebra.coefficients(f), AbstractAlgebra.exponent_vectors(f)) fl, r, s = Hecke.rational_reconstruction(c, d) diff --git a/src/Rings/localization_interface.jl b/src/Rings/localization_interface.jl index 82146d54cc42..bef27cf6874f 100644 --- a/src/Rings/localization_interface.jl +++ b/src/Rings/localization_interface.jl @@ -103,7 +103,7 @@ Complement of prime ideal(x) in multivariate polynomial ring in 3 variables over QQ -julia> Rloc, _ = Localization(U); +julia> Rloc, _ = localization(U); julia> R === base_ring(Rloc) true @@ -131,7 +131,7 @@ Complement of prime ideal(x) in multivariate polynomial ring in 3 variables over QQ -julia> Rloc, _ = Localization(U); +julia> Rloc, _ = localization(U); julia> U === inverted_set(Rloc) true @@ -143,12 +143,12 @@ end ### required functionality @doc raw""" - Localization(U::AbsMultSet) + localization(U::AbsMultSet) Given a multiplicatively closed subset of a multivariate polynomial ring ``R``, say, return the localization of ``R`` at ``U`` together with the localization map ``R`` ``\to`` ``R[U^{-1}]``. - Localization(R::Ring, U::AbsMultSet) + localization(R::Ring, U::AbsMultSet) Given a multiplicatively closed subset ``U`` of ``R``, proceed as above. @@ -165,7 +165,7 @@ Complement of prime ideal(x) in multivariate polynomial ring in 3 variables over QQ -julia> Rloc, iota = Localization(R, U); +julia> Rloc, iota = localization(R, U); julia> Rloc Localization @@ -183,13 +183,13 @@ defined by z -> z ``` """ -function Localization(S::AbsMultSet) +function localization(S::AbsMultSet) error("localizations at multiplicatively closed sets of type $(typeof(S)) are not implemented") end -function Localization(R::Ring, U::AbsMultSet) +function localization(R::Ring, U::AbsMultSet) R == ambient_ring(U) || error("ring and multiplicative set are incompatible") - return Localization(U) + return localization(U) end @doc raw""" diff --git a/src/Rings/mpoly-ideals.jl b/src/Rings/mpoly-ideals.jl index d40761cbc00b..6719c25d1a99 100644 --- a/src/Rings/mpoly-ideals.jl +++ b/src/Rings/mpoly-ideals.jl @@ -1455,7 +1455,7 @@ julia> small_generating_set(J) x*y^2 - z ``` """ -function small_generating_set(I::MPolyIdeal{T}) where {T<:MPolyElem{<:FieldElem}} +function small_generating_set(I::MPolyIdeal{T}) where {T<:MPolyRingElem{<:FieldElem}} # For non-homogeneous ideals, we do not have a notion of minimal generating # set, but Singular.mstd still provides a good heuristic to find a small # generating set. diff --git a/src/Rings/mpoly-local.jl b/src/Rings/mpoly-local.jl index 1f8ca423d4c1..d48c7890a9dc 100644 --- a/src/Rings/mpoly-local.jl +++ b/src/Rings/mpoly-local.jl @@ -31,7 +31,7 @@ mutable struct MPolyRingLoc{T} <: AbstractAlgebra.Ring where T <: AbstractAlgebr end end -function Oscar.Localization(R::MPolyRing{S}, m::Oscar.MPolyIdeal) where S +function Oscar.localization(R::MPolyRing{S}, m::Oscar.MPolyIdeal) where S return MPolyRingLoc(R, m) end @@ -70,13 +70,13 @@ end function MPolyRingElemLoc(f::MPolyRingElem{T}, m::Oscar.MPolyIdeal) where {T} R = parent(f) - return MPolyRingElemLoc{T}(f//R(1), Localization(R, m), false) + return MPolyRingElemLoc{T}(f//R(1), localization(R, m), false) end function MPolyRingElemLoc(f::AbstractAlgebra.Generic.Frac, m::Oscar.MPolyIdeal) R = parent(numerator(f)) B = base_ring(R) - return MPolyRingElemLoc{elem_type(B)}(f, Localization(R, m)) + return MPolyRingElemLoc{elem_type(B)}(f, localization(R, m)) end ############################################################################### diff --git a/src/Rings/mpoly-localizations.jl b/src/Rings/mpoly-localizations.jl index b2e77299c9e1..ba1bc2f5c80b 100644 --- a/src/Rings/mpoly-localizations.jl +++ b/src/Rings/mpoly-localizations.jl @@ -1182,9 +1182,7 @@ defined by ``` """ localization(R::MPolyRing, U::AbsMPolyMultSet) -###localization is an Abstract Algebra alias for Localization - -function Localization(S::AbsMPolyMultSet) +function localization(S::AbsMPolyMultSet) R = ambient_ring(S) Rloc = MPolyLocRing(R, S) #iota = MapFromFunc(R, Rloc, x -> Rloc(x)) @@ -1192,19 +1190,19 @@ function Localization(S::AbsMPolyMultSet) return Rloc, iota end -function Localization(R::MPolyRing, ord::MonomialOrdering) +function localization(R::MPolyRing, ord::MonomialOrdering) @assert R === ord.R - return Localization(MPolyLeadingMonOne(ord)) + return localization(MPolyLeadingMonOne(ord)) end ### Successive localizations are handled by the dispatch for products -function Localization( +function localization( W::MPolyLocRing{BRT, BRET, RT, RET, MST}, S::AbsMPolyMultSet{BRT, BRET, RT, RET} ) where {BRT, BRET, RT, RET, MST} issubset(S, inverted_set(W)) && return W, identity_map(W) U = S*inverted_set(W) - L, _ = Localization(U) + L, _ = localization(U) #return L, MapFromFunc(W, L, (x->(L(numerator(x), denominator(x), check=false)))) return L, MPolyLocalizedRingHom(W, L, hom(base_ring(W), L, L.(gens(base_ring(W)))), check=false) end @@ -1212,9 +1210,9 @@ end ### additional constructors MPolyLocRing(R::RingType, P::MPolyIdeal{RingElemType}; check::Bool=true) where {RingType, RingElemType} = MPolyLocRing(R, MPolyComplementOfPrimeIdeal(P); check) -Localization(R::MPolyRing, v::Vector{T}) where {T<:MPolyRingElem} = Localization(MPolyPowersOfElement(R, v)) +localization(R::MPolyRing, v::Vector{T}) where {T<:MPolyRingElem} = localization(MPolyPowersOfElement(R, v)) -function Localization( +function localization( W::MPolyLocRing{BRT, BRET, RT, RET, MPolyPowersOfElement{BRT, BRET, RT, RET}}, f::RET ) where {BRT, BRET, RT, RET<:RingElement} @@ -1231,13 +1229,13 @@ function Localization( #return L, MapFromFunc(W, L, (x->L(numerator(x), denominator(x), check=false))) end -function Localization( +function localization( W::MPolyLocRing{BRT, BRET, RT, RET, MPolyPowersOfElement{BRT, BRET, RT, RET}}, v::Vector{RET} ) where {BRT, BRET, RT, RET} V = W for f in v - V = Localization(V, f) + V = localization(V, f) end return V, MPolyLocalizedRingHom(W, V, hom(base_ring(W), V, V.(gens(base_ring(W)))), check=false) #return V, MapFromFunc(W, V, (x->V(numerator(x), denominator(x), check=false))) @@ -1688,7 +1686,7 @@ julia> f = x+y+z+w-1; julia> T = MPolyPowersOfElement(f); -julia> RL,phiL = Localization(R,T); +julia> RL,phiL = localization(R,T); julia> I=ideal(RL,RL.([x+y+z,w-1])) Ideal @@ -2200,7 +2198,7 @@ function saturated_ideal( R = base_ring(W) J = ideal(R, numerator.(gens(I))) for U in sets(inverted_set(W)) - L, _ = Localization(U) + L, _ = localization(U) J = saturated_ideal(L(J)) end if with_generator_transition @@ -2431,7 +2429,7 @@ function coordinates( if length(U) == 1 if !has_attribute(I, :popped_ideal) - W, _ = Localization(R, U[1]) + W, _ = localization(R, U[1]) popped_ideal = W(pre_saturated_ideal(I)) set_attribute!(I, :popped_ideal, popped_ideal) end @@ -2448,11 +2446,11 @@ function coordinates( if !isnothing(i) if !has_attribute(I, :popped_ideal) S = popat!(U, i) - W, _ = Localization(base_ring(L), S) + W, _ = localization(base_ring(L), S) popped_ideal = ideal(W, pre_saturated_ideal(I)) saturated_ideal(popped_ideal, with_generator_transition=true) set_attribute!(I, :popped_ideal, popped_ideal) - Wnext, _ = Localization(R, MPolyProductOfMultSets(R, U)) + Wnext, _ = localization(R, MPolyProductOfMultSets(R, U)) next_ideal = Wnext(pre_saturated_ideal(popped_ideal)) set_attribute!(I, :next_ideal, next_ideal) end @@ -2466,11 +2464,11 @@ function coordinates( else if !has_attribute(I, :popped_ideal) S = pop!(U) - W, _ = Localization(base_ring(L), S) + W, _ = localization(base_ring(L), S) popped_ideal = ideal(W, pre_saturated_ideal(I)) saturated_ideal(popped_ideal, with_generator_transition=true) set_attribute!(I, :popped_ideal, popped_ideal) - Wnext, _ = Localization(R, MPolyProductOfMultSets(R, U)) + Wnext, _ = localization(R, MPolyProductOfMultSets(R, U)) next_ideal = Wnext(pre_saturated_ideal(popped_ideal)) set_attribute!(I, :next_ideal, next_ideal) end @@ -2496,7 +2494,7 @@ function ideal_membership( if length(U) == 1 if !has_attribute(I, :popped_ideal) - W, _ = Localization(R, U[1]) + W, _ = localization(R, U[1]) popped_ideal = W(pre_saturated_ideal(I)) set_attribute!(I, :popped_ideal, popped_ideal) end @@ -2510,11 +2508,11 @@ function ideal_membership( if !isnothing(i) if !has_attribute(I, :popped_ideal) S = popat!(U, i) - W, _ = Localization(base_ring(L), S) + W, _ = localization(base_ring(L), S) popped_ideal = ideal(W, pre_saturated_ideal(I)) saturated_ideal(popped_ideal, with_generator_transition=true) set_attribute!(I, :popped_ideal, popped_ideal) - Wnext, _ = Localization(R, MPolyProductOfMultSets(R, U)) + Wnext, _ = localization(R, MPolyProductOfMultSets(R, U)) next_ideal = Wnext(pre_saturated_ideal(popped_ideal)) set_attribute!(I, :next_ideal, next_ideal) end @@ -2523,11 +2521,11 @@ function ideal_membership( else if !has_attribute(I, :popped_ideal) S = pop!(U) - W, _ = Localization(base_ring(L), S) + W, _ = localization(base_ring(L), S) popped_ideal = ideal(W, pre_saturated_ideal(I)) saturated_ideal(popped_ideal, with_generator_transition=true) set_attribute!(I, :popped_ideal, popped_ideal) - Wnext, _ = Localization(R, MPolyProductOfMultSets(R, U)) + Wnext, _ = localization(R, MPolyProductOfMultSets(R, U)) next_ideal = Wnext(pre_saturated_ideal(popped_ideal)) set_attribute!(I, :next_ideal, next_ideal) end @@ -2685,7 +2683,7 @@ function MPolyLocalizedRingHom( a::Vector{RingElemType} ) where {RingElemType<:RingElem} res = hom(R, S, a, check=false) - W, _ = Localization(units_of(R)) + W, _ = localization(units_of(R)) return MPolyLocalizedRingHom(W, S, res) end @@ -2944,7 +2942,7 @@ function divides(a::MPolyLocRingElem, b::MPolyLocRingElem) end # This had to be moved after the definition of the elements. -function Localization(R::MPolyRing, f::MPolyRingElem) +function localization(R::MPolyRing, f::MPolyRingElem) U = MPolyPowersOfElement(R, [f]) L = MPolyLocRing(R, U) function func(a::MPolyRingElem) diff --git a/src/Rings/mpolyquo-localizations.jl b/src/Rings/mpolyquo-localizations.jl index dbd05d8e21ac..2426e217a461 100644 --- a/src/Rings/mpolyquo-localizations.jl +++ b/src/Rings/mpolyquo-localizations.jl @@ -315,31 +315,31 @@ Map defined by a julia-function ###localization is an Abstract Algebra alias for Localization -function Localization(Q::MPolyQuoRing{RET}, S::MultSetType) where {RET <: RingElem, MultSetType <: AbsMultSet} - L = MPolyQuoLocRing(base_ring(Q), modulus(Q), S, Q, Localization(S)[1]) +function localization(Q::MPolyQuoRing{RET}, S::MultSetType) where {RET <: RingElem, MultSetType <: AbsMultSet} + L = MPolyQuoLocRing(base_ring(Q), modulus(Q), S, Q, localization(S)[1]) return L, MapFromFunc(Q, L, (x->L(lift(x)))) end -function Localization( +function localization( L::MPolyQuoLocRing{BRT, BRET, RT, RET, MST}, S::AbsMPolyMultSet{BRT, BRET, RT, RET} ) where {BRT, BRET, RT, RET, MST} ambient_ring(S) == base_ring(L) || error("multiplicative set does not belong to the correct ring") issubset(S, inverted_set(L)) && return L, MapFromFunc(L, L, x->x) U = inverted_set(L)*S - W = MPolyQuoLocRing(base_ring(L), modulus(underlying_quotient(L)), U, underlying_quotient(L), Localization(U)[1]) + W = MPolyQuoLocRing(base_ring(L), modulus(underlying_quotient(L)), U, underlying_quotient(L), localization(U)[1]) return W, MapFromFunc(L, W, (x->W(lifted_numerator(x), lifted_denominator(x), check=false))) end function MPolyQuoLocRing(R::RT, I::Ideal{RET}, T::MultSetType) where {RT<:MPolyRing, RET<:MPolyRingElem, MultSetType<:AbsMultSet} - return MPolyQuoLocRing(R, I, T, quo(R, I)[1], Localization(T)[1]) + return MPolyQuoLocRing(R, I, T, quo(R, I)[1], localization(T)[1]) end function MPolyQuoLocRing(R::RT) where {RT<:MPolyRing} I = ideal(R, zero(R)) Q, _ = quo(R, I) U = units_of(R) - W, _ = Localization(U) + W, _ = localization(U) return MPolyQuoLocRing(R, I, U, Q, W) end @@ -347,7 +347,7 @@ function MPolyQuoLocRing(Q::RT) where {RT<:MPolyQuoRing} R = base_ring(Q) I = modulus(Q) U = units_of(R) - W, _ = Localization(U) + W, _ = localization(U) return MPolyQuoLocRing(R, I, U, Q, W) end @@ -575,7 +575,7 @@ Complement julia> RQ, p = quo(R, I); -julia> RQL, iota = Localization(RQ, U); +julia> RQL, iota = localization(RQ, U); julia> is_unit(iota(p(x))) true @@ -1625,7 +1625,7 @@ julia> RQ,phiQ = quo(R,Q); julia> T = MPolyComplementOfKPointIdeal(R,[0,0,0,0]); -julia> RQL, phiQL = Localization(RQ,T); +julia> RQL, phiQL = localization(RQ,T); julia> I = ideal(RQL,RQL.([x,z])) Ideal diff --git a/src/TropicalGeometry/groebner_fan.jl b/src/TropicalGeometry/groebner_fan.jl index bca1461d3fe3..0a54f22f96b2 100644 --- a/src/TropicalGeometry/groebner_fan.jl +++ b/src/TropicalGeometry/groebner_fan.jl @@ -57,7 +57,7 @@ julia> rays_modulo_lineality(homogeneity_space(G3)) ``` """ function homogeneity_space(G::Vector{<:MPolyRingElem}) - inequalities = fmpq_mat(0,0) + inequalities = QQMatrix(0,0) equations = Vector{Vector{Int}}() for g in G alpha,tail_exponents = Iterators.peel(exponents(g)) @@ -73,11 +73,11 @@ end @doc raw""" homogeneity_vector(G::Vector{<:MPolyRingElem}) -Return a positive `Vector{fmpz}` under which every element of `G` is weighted +Return a positive `Vector{ZZRingElem}` under which every element of `G` is weighted homogeneous. If no such vector exists, return `nothing`. # Note -Suppose `G` is the reduced Groebner basis of an ideal `I` with respect to a global ordering. If a `Vector{fmpz}` is returned, then `I` is weighted homogeneous with respect to it. If `nothing` is returned, then `I` is not weighted homogeneous with respect to any positive weight vector. +Suppose `G` is the reduced Groebner basis of an ideal `I` with respect to a global ordering. If a `Vector{ZZRingElem}` is returned, then `I` is weighted homogeneous with respect to it. If `nothing` is returned, then `I` is not weighted homogeneous with respect to any positive weight vector. # Examples ```jldoctest @@ -130,7 +130,7 @@ function homogeneity_vector(G::Vector{<:MPolyRingElem}) # test if homogeneitySpace contains the ones vector n = ambient_dim(homogeneitySpace) - homogeneityVector = ones(fmpz,n) + homogeneityVector = ones(ZZRingElem,n) if homogeneityVector in homogeneitySpace return homogeneityVector end @@ -150,7 +150,7 @@ end @doc raw""" - maximal_groebner_cone(G::Oscar.IdealGens{<:MPolyRingElem}; homogeneityWeight::Union{Nothing,Vector{fmpz}}=nothing) + maximal_groebner_cone(G::Oscar.IdealGens{<:MPolyRingElem}; homogeneityWeight::Union{Nothing,Vector{ZZRingElem}}=nothing) Returns the maximal Groebner cone of a Groebner basis `G`, i.e., the closure of all weight vectors with respect to whose weighted ordering `G` is a Groebner basis (independent of tie-breaker). @@ -188,7 +188,7 @@ function maximal_groebner_cone(G::Oscar.IdealGens{<:MPolyRingElem}) return maximal_groebner_cone(G,ord,homogeneityWeight) end -function maximal_groebner_cone(G::Oscar.IdealGens{<:MPolyRingElem}, homogeneityWeight::Union{Vector{fmpz},Nothing}) +function maximal_groebner_cone(G::Oscar.IdealGens{<:MPolyRingElem}, homogeneityWeight::Union{Vector{ZZRingElem},Nothing}) @assert is_groebner_basis(G) ord = ordering(G) G = collect(G) @@ -203,7 +203,7 @@ function maximal_groebner_cone(G::Vector{<:MPolyRingElem}, ord::MonomialOrdering return intersect(C,positiveOrthant) end -function maximal_groebner_cone(G::Vector{<:MPolyRingElem}, ord::MonomialOrdering, homogeneityWeight::Vector{fmpz}) +function maximal_groebner_cone(G::Vector{<:MPolyRingElem}, ord::MonomialOrdering, homogeneityWeight::Vector{ZZRingElem}) # calling with a positive homogeneityWeight # means that C does not be restricted to the positive orthant return maximal_groebner_cone_extended(G,ord) @@ -220,7 +220,7 @@ function maximal_groebner_cone_extended(G::Vector{<:MPolyRingElem}, ord::Monomia end # if there are none, which means G is monomial, return the entire ambient space if isempty(inequalities) - return cone_from_inequalities(fmpq_mat(0,ngens(base_ring(ord)))) + return cone_from_inequalities(QQMatrix(0,ngens(base_ring(ord)))) end return cone_from_inequalities(matrix(QQ,inequalities)) end @@ -235,11 +235,11 @@ function unique_identifying_point(C::Cone) R,_ = rays_modulo_lineality(C) # if there are none, return zero vector if isempty(R) - return zeros(fmpz,ambient_dim(C)) + return zeros(ZZRingElem,ambient_dim(C)) end # otherwise compute the sum of rays, cast it to a rational vector # and return a primitive integer vector - pt = Vector{fmpq}(sum(R)) + pt = Vector{QQFieldElem}(sum(R)) return numerator.(pt .* lcm(denominator.(pt))) end @@ -256,7 +256,7 @@ end # Returns a primitive outer normal vector for each facet. function outer_normal_vectors(C::Cone) outerNormalMatrix = linear_inequality_matrix(facets(C)) - normals = Vector{Vector{fmpz}}() + normals = Vector{Vector{ZZRingElem}}() for i in 1:nrows(outerNormalMatrix) v = [outerNormalMatrix[i,:]...] push!(normals,numerator.(v .* lcm(denominator.(v)))) @@ -268,16 +268,16 @@ end # Returns the initial form of polynomial g with respect to weight vector u. # Requires a monomial ordering that is compatible with respect to u, i.e., the leading monomial is of highest weighted degree. -function initial(g::MPolyRingElem, ordering::MonomialOrdering, u::Vector{fmpz}) +function initial(g::MPolyRingElem, ordering::MonomialOrdering, u::Vector{ZZRingElem}) lt,tail = Iterators.peel(terms(g,ordering=ordering)); - d = dot(u,fmpz.(leading_exponent_vector(lt))) - initial_terms = [s for s in tail if dot(u,fmpz.(leading_exponent_vector(s)))==d] + d = dot(u,ZZRingElem.(leading_exponent_vector(lt))) + initial_terms = [s for s in tail if dot(u,ZZRingElem.(leading_exponent_vector(s)))==d] push!(initial_terms,lt) return sum(initial_terms) end # Applies the function above to each polynomial in a list of polynomials. -function initial(G::Vector{<:MPolyRingElem}, ord::MonomialOrdering, u::Vector{fmpz}) +function initial(G::Vector{<:MPolyRingElem}, ord::MonomialOrdering, u::Vector{ZZRingElem}) return initial.(G,Ref(ord),Ref(u)) end @@ -329,9 +329,9 @@ end # in direction v function groebner_flip(G::Vector{<:MPolyRingElem}, ordG::MonomialOrdering, - homogeneityVector::Union{Vector{fmpz},Nothing}, - interior_facet_point::Vector{fmpz}, - outer_normal_vector::Vector{fmpz}) + homogeneityVector::Union{Vector{ZZRingElem},Nothing}, + interior_facet_point::Vector{ZZRingElem}, + outer_normal_vector::Vector{ZZRingElem}) R = parent(first(G)) n = ngens(R) adjacentOrdering = groebner_flip_adjacent_ordering(R,homogeneityVector,interior_facet_point,outer_normal_vector) @@ -343,9 +343,9 @@ end # helper functions for groebner_flip function groebner_flip_adjacent_ordering(R::MPolyRing, - homogeneityVector::Vector{fmpz}, - interior_facet_point::Vector{fmpz}, - outer_normal_vector::Vector{fmpz}) + homogeneityVector::Vector{ZZRingElem}, + interior_facet_point::Vector{ZZRingElem}, + outer_normal_vector::Vector{ZZRingElem}) return weight_ordering(Int.(homogeneityVector), weight_ordering(Int.(interior_facet_point), weight_ordering(Int.(outer_normal_vector), @@ -354,8 +354,8 @@ end function groebner_flip_adjacent_ordering(R::MPolyRing, homogeneityVector::Nothing, - interior_facet_point::Vector{fmpz}, - outer_normal_vector::Vector{fmpz}) + interior_facet_point::Vector{ZZRingElem}, + outer_normal_vector::Vector{ZZRingElem}) return weight_ordering(Int.(interior_facet_point), weight_ordering(Int.(outer_normal_vector), revlex(R))) @@ -368,7 +368,7 @@ function polyhedral_fan_from_cones(listOfCones::Vector{<:Cone}) ### # Collect incidence information ### - fanRays = Vector{Vector{fmpq}}() + fanRays = Vector{Vector{QQFieldElem}}() fanIncidences = Vector{Vector{Int}}() for cone in listOfCones coneIncidence = Vector{Int}() @@ -447,7 +447,7 @@ function groebner_fan(I::MPolyIdeal; return_groebner_bases::Bool=false, return_o C = maximal_groebner_cone(G,ord,homogeneityWeight) workingList = [(G,ord,C,unique_identifying_point(C))] # list of Groebner cones whose neighbours may be unknown finishedList = typeof(workingList)() # list of Groebner cones whose neighbours are known - finishedFacets = Vector{Vector{fmpz}}() # list of interior facet points whose facet has been traversed + finishedFacets = Vector{Vector{ZZRingElem}}() # list of interior facet points whose facet has been traversed ### diff --git a/src/exports.jl b/src/exports.jl index 0cd89e5ff4ee..2ec90f620678 100644 --- a/src/exports.jl +++ b/src/exports.jl @@ -88,7 +88,7 @@ export LazyPolyRing export LinearHalfspace export LinearHyperplane export LinearProgram, linear_program -export Localization +export localization export MPolyComplementOfKPointIdeal export MPolyComplementOfPrimeIdeal export MPolyDecRing diff --git a/test/AlgebraicGeometry/Schemes/AffineSchemes.jl b/test/AlgebraicGeometry/Schemes/AffineSchemes.jl index 498ae846f1ea..db3bc356ec15 100644 --- a/test/AlgebraicGeometry/Schemes/AffineSchemes.jl +++ b/test/AlgebraicGeometry/Schemes/AffineSchemes.jl @@ -96,7 +96,7 @@ end plane = hypersurface_complement(disjoint_plane_and_line, y) @test dim(line) == 1 @test dim(plane) == 2 - A3_localized_along_line = Spec(Localization(R, complement_of_prime_ideal(ideal(R, [x, y])))[1]) + A3_localized_along_line = Spec(localization(R, complement_of_prime_ideal(ideal(R, [x, y])))[1]) @test dim(A3_localized_along_line) == 2 @test dim(standard_spec(A3_localized_along_line)) == 2 @@ -121,7 +121,7 @@ end plane = hypersurface_complement(disjoint_plane_and_line, y) @test dim(line) == 2 @test dim(plane) == 3 - A3_localized_along_line = Spec(Localization(R, complement_of_prime_ideal(ideal(R, [x, y])))[1]) + A3_localized_along_line = Spec(localization(R, complement_of_prime_ideal(ideal(R, [x, y])))[1]) @test dim(A3_localized_along_line) == 2 @test dim(standard_spec(A3_localized_along_line)) == 2 P = ideal(R, R(5)) diff --git a/test/AlgebraicGeometry/Schemes/FunctionFields.jl b/test/AlgebraicGeometry/Schemes/FunctionFields.jl index b5b3dc12c6eb..c968fa55a3f1 100644 --- a/test/AlgebraicGeometry/Schemes/FunctionFields.jl +++ b/test/AlgebraicGeometry/Schemes/FunctionFields.jl @@ -3,7 +3,7 @@ @test is_irreducible(Spec(R)) @test is_irreducible(Spec(R, ideal(R, x))) @test !is_irreducible(Spec(R, ideal(R, x*y))) - @test is_irreducible(Spec(Localization(R, units_of(R))[1])) + @test is_irreducible(Spec(localization(R, units_of(R))[1])) @test !is_irreducible(Spec(R, ideal(R, x*y), units_of(R))) P = projective_space(QQ, 2) diff --git a/test/Modules/ModulesGraded.jl b/test/Modules/ModulesGraded.jl index 58ad2a64b0ae..64798663d69e 100644 --- a/test/Modules/ModulesGraded.jl +++ b/test/Modules/ModulesGraded.jl @@ -122,7 +122,7 @@ end (2*x^2+x*y)*x (2*y^3+y*x^2)] B = Rg[4*x*y^3 (2*x+y)^4] F2 = graded_free_module(Rg, [0,0]) - M1 = SubQuo(F2, A1, B) + M1 = SubquoModule(F2, A1, B) @test degrees_of_generators(M1) == [Z[1], 2*Z[1]] F = graded_free_module(Rg, 2) O = [x*F[1]+y*F[2],y*F[2]] diff --git a/test/Modules/module-localizations.jl b/test/Modules/module-localizations.jl index 879a79752cd8..d3c53439d4e5 100644 --- a/test/Modules/module-localizations.jl +++ b/test/Modules/module-localizations.jl @@ -2,7 +2,7 @@ kk = QQ R, (x,y) = QQ["x", "y"] U = MPolyComplementOfKPointIdeal(R, [0, 0]) - L, _ = Localization(U) + L, _ = localization(U) F = FreeMod(L, 3) A = L[x 0 1; 0 y y^2] B = L[x^2 0 x; 0 y^2 y^3] @@ -18,7 +18,7 @@ @test represents_element(x*F[3], K) T = MPolyPowersOfElement(R, [x, y]) - W, _ = Localization(T) + W, _ = localization(T) F = FreeMod(W, 2) A = W[x 0; 0 y^2] B = W[x^2//y y] @@ -29,7 +29,7 @@ end @testset "module localizations 2" begin R, (x,y) = QQ["x", "y"] U = MPolyPowersOfElement(x+y) - S, _ = Localization(U) + S, _ = localization(U) F = FreeMod(S, 2) Fb = base_ring_module(F) A = S[x//(x+y); y//(x+y)^2] @@ -42,7 +42,7 @@ end @test v*A == b V = MPolyComplementOfPrimeIdeal(ideal(R, [x,y])) - S, _ = Localization(V) + S, _ = localization(V) A = S[x//(x+y+1); y*(x-5)^3] b = matrix(S, 1, 1, [(x+y)*x + 5*y//(x+y+2)^10]) success, v = Oscar.has_solution(A, b) @@ -76,7 +76,7 @@ end @testset "module localizations 3" begin R, (x,y) = QQ["x", "y"] U = MPolyPowersOfElement(x^7) - S, _ = Localization(U) + S, _ = localization(U) F = FreeMod(S, 1) A = S[x^4*y^2; x^2*y] B = S[y^8; y^9] @@ -94,7 +94,7 @@ end # An example of maximal Cohen-Macaulay modules and their # matrix factorization. R, (x, y) = QQ["x", "y"] - W, _ = Localization(R, units_of(R)) + W, _ = localization(R, units_of(R)) F1 = FreeMod(W, 1) M, _ = quo(F1, W[x^3+y^4;]) F2 = FreeMod(W, 2) diff --git a/test/Rings/MPolyQuo.jl b/test/Rings/MPolyQuo.jl index 1b20129f3b8e..a69c7e82b8c2 100644 --- a/test/Rings/MPolyQuo.jl +++ b/test/Rings/MPolyQuo.jl @@ -175,19 +175,19 @@ end @test modulus(R) == ideal(R,[zero(R)]) @test modulus(A) == I U=MPolyComplementOfKPointIdeal(R,[0,0,0]) - Rl,_ = Localization(R,U) + Rl,_ = localization(R,U) Il = Rl(I) Al, _ = quo(Rl, Il) @test modulus(Rl) == ideal(Rl,[zero(Rl)]) @test modulus(Al) == Il U2=MPolyComplementOfPrimeIdeal(ideal(R,[x^2+1,y-x,z])) - Rl2,_ = Localization(R,U2) + Rl2,_ = localization(R,U2) Il2 = Rl2(I) Al2,_ = quo(Rl2,Il2) @test modulus(Rl2) == ideal(Rl2,[zero(Rl2)]) @test modulus(Al2) == Il2 U3=MPolyPowersOfElement(x+y) - Rl3,_ = Localization(R,U3) + Rl3,_ = localization(R,U3) Il3 = Rl3(I) Al3,_ = quo(Rl3,Il3) @test modulus(Rl3) == ideal(Rl3,[zero(Rl3)]) @@ -213,7 +213,7 @@ end @testset "issue #1901" begin R, (x,y,z) = polynomial_ring(QQ, ["x", "y", "z"]) - L, _ = Localization(R, powers_of_element(R[1])) + L, _ = localization(R, powers_of_element(R[1])) S, (s0, s1, s2) = polynomial_ring(L, ["s0", "s1", "s2"]) I = ideal(S, [x*s0 - y*s1^2, y*s0 - z*s2^7]) Q, _ = quo(S, I) @@ -264,7 +264,7 @@ end R, (x, y) = QQ["x", "y"] I = ideal(R, 1-x*y) o = revlex([x, y]) - Q = MPolyQuo(R, I, o) + Q = MPolyQuoRing(R, I, o) @test Oscar._divides_hack(one(Q), Q(y))[2] == Q(x) end diff --git a/test/Rings/integer-localizations.jl b/test/Rings/integer-localizations.jl index e1b07a8b8564..037a0a40c01c 100644 --- a/test/Rings/integer-localizations.jl +++ b/test/Rings/integer-localizations.jl @@ -4,7 +4,7 @@ using Oscar -import Oscar: base_ring, inverted_set, ambient_ring, Localization, parent, numerator, denominator, one, zero, reduce_fraction +import Oscar: base_ring, inverted_set, ambient_ring, localization, parent, numerator, denominator, one, zero, reduce_fraction import Oscar.AbstractAlgebra: elem_type, parent_type export FmpzComplementOfPrimeIdeal, FmpzPowersOfElement, FmpzComplementOfZeroIdeal @@ -142,17 +142,17 @@ base_ring(W::FmpzLocalizedRing) = ZZ::ZZRing inverted_set(W::FmpzLocalizedRing{MultSetType}) where {MultSetType} = W.S::MultSetType ### required extensions of the localization function -function Localization(S::FmpzComplementOfPrimeIdeal) +function localization(S::FmpzComplementOfPrimeIdeal) L = FmpzLocalizedRing(S) return L, MapFromFunc(base_ring(L), L, x->L(x)) end -function Localization(S::FmpzComplementOfZeroIdeal) +function localization(S::FmpzComplementOfZeroIdeal) L = FmpzLocalizedRing(S) return L, MapFromFunc(base_ring(L), L, x->L(x)) end -function Localization(S::FmpzPowersOfElement) +function localization(S::FmpzPowersOfElement) L = FmpzLocalizedRing(S) return L, MapFromFunc(base_ring(L), L, x->L(x)) end @@ -241,7 +241,7 @@ parent_type(T::Type{FmpzLocalizedRingElem{MultSetType}}) where {MultSetType} = F @test !(33 in S) @test 5*5*7 in S @test ambient_ring(S) == ZZ - W, _ = Localization(S) + W, _ = localization(S) @test base_ring(W) == ambient_ring(S) @test inverted_set(W) == S a = W(3) @@ -258,7 +258,7 @@ parent_type(T::Type{FmpzLocalizedRingElem{MultSetType}}) where {MultSetType} = F @test !(13*4289729837 in U) @test 5783790198374098 in U @test ambient_ring(U) == ZZ - W, _ = Localization(U) + W, _ = localization(U) @test base_ring(W) == ambient_ring(U) @test inverted_set(W) == U a = W(4, 17) @@ -273,7 +273,7 @@ parent_type(T::Type{FmpzLocalizedRingElem{MultSetType}}) where {MultSetType} = F @test 234890 in O @test !(0 in O) @test ambient_ring(O) == ZZ - W, _ = Localization(O) + W, _ = localization(O) @test base_ring(W) == ambient_ring(O) @test inverted_set(W) == O a = W(4, 17) diff --git a/test/Rings/mpoly-local.jl b/test/Rings/mpoly-local.jl index f432e7f16ecc..101376615a73 100644 --- a/test/Rings/mpoly-local.jl +++ b/test/Rings/mpoly-local.jl @@ -1,7 +1,7 @@ @testset "mpoly-loc constructors" begin R, (x, y, z) = polynomial_ring(QQ, ["x", "y", "z"]) m = ideal(R, [y - 1, x - 2, z - 3]) - Q = Localization(R, m) + Q = localization(R, m) I = ideal(Q, [x - 2, (y - 1)^2*z]) a = Q(x//(1 + x)) @@ -12,7 +12,7 @@ end @testset "mpoly-loc operations" begin R, (x, y, z) = polynomial_ring(QQ, ["x", "y", "z"]) m = ideal(R, [y - 1, x - 2, z - 3]) - Q = Localization(R, m) + Q = localization(R, m) I = ideal(Q, [x - 2, (y - 1)^2*z]) J = ideal(Q, [x - 2, y - 1]) a = Q(x//(1 + x)) @@ -42,7 +42,7 @@ end @testset "mpoly-loc groebner" begin R, (x, y, z) = polynomial_ring(QQ, ["x", "y", "z"]) m = ideal(R, [y - 1, x - 2, z - 3]) - Q = Localization(R, m) + Q = localization(R, m) I = ideal(Q, [x - 2, (y - 1)^2*z]) J = ideal(Q, [x - 1, y - 1]) diff --git a/test/Rings/mpoly-localizations.jl b/test/Rings/mpoly-localizations.jl index bc56ebf79e55..7036345a93f7 100644 --- a/test/Rings/mpoly-localizations.jl +++ b/test/Rings/mpoly-localizations.jl @@ -8,9 +8,9 @@ const rng = Oscar.get_seeded_rng() m = ideal(R, [x, y]) I = ideal(R, f) S = MPolyComplementOfPrimeIdeal(I) - V, _ = Localization(S) + V, _ = localization(S) T = MPolyComplementOfKPointIdeal(R, [ZZ(1), ZZ(0)]) - W, _ = Localization(T) + W, _ = localization(T) k = QQ R, variab = k["x", "y"] @@ -25,7 +25,7 @@ const rng = Oscar.get_seeded_rng() @test ambient_ring(S) == R @test !( f in S ) @test x in S - V, _ = Localization(S) + V, _ = localization(S) @test base_ring(V) == R @test inverted_set(V) == S @@ -34,7 +34,7 @@ const rng = Oscar.get_seeded_rng() @test typeof(point_coordinates(T)) == Vector{elem_type(k)} @test x in T @test !(x-p in T) - W, _ = Localization(T) + W, _ = localization(T) a = W(R(1)) b = W(2) @@ -81,7 +81,7 @@ const rng = Oscar.get_seeded_rng() R, (x, y, z) = polynomial_ring(QQ, ["x", "y", "z"]) o = degrevlex([x, y])*negdegrevlex([z]) - S, _ = Localization(R, o) + S, _ = localization(R, o) @test z + 1 in inverted_set(S) @test !(x + 1 in inverted_set(S)) I = ideal(S, [x + y + z, x^2 + y^2 + z^3]) @@ -137,7 +137,7 @@ end @test (5*f in S) @test x^3*y in S @test !(x^19*(x+y) in S) - W, _ = Localization(S) + W, _ = localization(S) @test x*y^2 in S @test !(x*(x+y) in S) @test W(1//x) == 1/W(x) @@ -158,9 +158,9 @@ end @test f in S @test !(5*f in S) - U, _ = Localization(R, f) - V, _ = Localization(U, x) - W, _ = Localization(V, 5*f) + U, _ = localization(R, f) + V, _ = localization(U, x) + W, _ = localization(V, 5*f) phi = MPolyLocalizedRingHom(R, W, [W(1//x), W(y//f)]) @test phi(x*f) == phi(domain(phi)(x*f)) @@ -189,9 +189,9 @@ end # T = MPolyComplementOfKPointIdeal(R, [kk(125), kk(-45)]) # U = MPolyComplementOfPrimeIdeal(I) # -# test_Ring_interface_recursive(Localization(S)[1]) -# test_Ring_interface_recursive(Localization(T)[1]) -# test_Ring_interface_recursive(Localization(U)[1]) +# test_Ring_interface_recursive(localization(S)[1]) +# test_Ring_interface_recursive(localization(T)[1]) +# test_Ring_interface_recursive(localization(U)[1]) # should be unnecessary: https://github.com/oscar-system/Oscar.jl/pull/1459#issuecomment-1230185617 # AbstractAlgebra.promote_rule(::Type{fpMPolyRingElem}, ::Type{ZZRingElem}) = fpMPolyRingElem @@ -213,9 +213,9 @@ end T = MPolyComplementOfKPointIdeal(R, [kk(125), kk(-45)]) U = MPolyComplementOfPrimeIdeal(I) - test_Ring_interface_recursive(Localization(S)[1]) - test_Ring_interface_recursive(Localization(T)[1]) - test_Ring_interface_recursive(Localization(U)[1]) + test_Ring_interface_recursive(localization(S)[1]) + test_Ring_interface_recursive(localization(T)[1]) + test_Ring_interface_recursive(localization(U)[1]) # kk = ZZ # R, v = kk["x", "y"] @@ -230,9 +230,9 @@ end # T = MPolyComplementOfKPointIdeal(R, [kk(125), kk(-45)]) # U = MPolyComplementOfPrimeIdeal(I) # -# test_Ring_interface_recursive(Localization(S)[1]) -# test_Ring_interface_recursive(Localization(T)[1]) -# test_Ring_interface_recursive(Localization(U)[1]) +# test_Ring_interface_recursive(localization(S)[1]) +# test_Ring_interface_recursive(localization(T)[1]) +# test_Ring_interface_recursive(localization(U)[1]) end @testset "localization_at_orderings_1" begin @@ -241,7 +241,7 @@ end U = MPolyLeadingMonOne(R, o) @test y-1 in U @test !(x in U) - L, _ = Localization(R, U) + L, _ = localization(R, U) I = ideal(L, [x^2, y*(y-1)]) @test !(x in I) @test x^2 in I @@ -252,7 +252,7 @@ end @testset "localization_at_orderings_2" begin R, (x, y, z) = polynomial_ring(QQ, ["x", "y", "z"]) o = degrevlex([x, y])*negdegrevlex([z]) - S, _ = Localization(R, o) + S, _ = localization(R, o) @test z + 1 in inverted_set(S) @test !(x + 1 in inverted_set(S)) I = ideal(S, [x + y + z, (z+1)*(x^2 + y^2 + z^3)]) @@ -266,7 +266,7 @@ end p = [-5, 8, 1//2] U = MPolyComplementOfKPointIdeal(R, p) I = ideal(R, [x*(x+5), (y-8)*y-z*(x+5)]) - L, _ = Localization(R, U) + L, _ = localization(R, U) LI = L(I) @test x+5 in LI @test y-8 in LI @@ -285,21 +285,21 @@ end p = [0,0,0] U = MPolyComplementOfKPointIdeal(R, p) I = ideal(R, [x*(y-1)-z*(x-2), y*x]) - L, _ = Localization(R, U) + L, _ = localization(R, U) LI = L(I) W, _ = quo(L, LI) S = MPolyPowersOfElement(R, [y]) - RS, _ = Localization(R, S) + RS, _ = localization(R, S) RSI = RS(I) saturated_ideal(RSI, with_generator_transition=true) J = L(Oscar.pre_saturated_ideal(RSI)) z in J W, _ = quo(L, LI) S = MPolyPowersOfElement(R, [y]) - WS, _ = Localization(W, S) + WS, _ = localization(W, S) @test !iszero(W(z)) @test iszero(WS(z)) - LS, _ = Localization(L, S) + LS, _ = localization(L, S) LSI = LS(LI) @test dot(coordinates(z, LSI), gens(LSI)) == LS(z) @test !(z in Oscar.pre_saturated_ideal(LSI)) diff --git a/test/Rings/mpolyquo-localizations.jl b/test/Rings/mpolyquo-localizations.jl index 8378b10f10a2..7b1177f73ded 100644 --- a/test/Rings/mpolyquo-localizations.jl +++ b/test/Rings/mpolyquo-localizations.jl @@ -9,7 +9,7 @@ Q, p = quo(R, I) S = MPolyComplementOfKPointIdeal(R, [QQ(1), QQ(0), QQ(1), QQ(0)]) T = MPolyComplementOfKPointIdeal(R, [QQ(0), QQ(0), QQ(0), QQ(0)]) - L, _ = Localization(Q, S) + L, _ = localization(Q, S) a = L(x) b = L(y) c = L(u) @@ -68,8 +68,8 @@ g = rand(S, 0:3, 1:5, 2:8) g = rand(T, 0:3, 1:5, 2:8) g = rand(U, 0:3, 1:5, 2:8) - W, _ = Localization(U) - Localization(W, S) + W, _ = localization(U) + localization(W, S) @test base_ring(W) == R @test inverted_set(W) == U L, _ = quo(W, ideal(W, f)) @@ -84,7 +84,7 @@ h = x^4+23*x*y^3-15 Q, _ = quo(R, f) T = MPolyPowersOfElement(h^3) - W, _ = Localization(Q, T) + W, _ = localization(Q, T) @test x//(h+3*f) in W @test W(x//(h+3*f)) == W(x//h) g = W.([rand(R, 0:5, 0:2, 0:1) for i in 1:10]) @@ -98,7 +98,7 @@ h = (x+5)*(x^2+10*y)+(y-7)*(y^2-3*x) Q, _ = quo(R, h) T = MPolyComplementOfKPointIdeal(R, [-5, 7]) - W, _ = Localization(Q, T) + W, _ = localization(Q, T) @test x//(y) in W @test x//(y+h) in W g = [W(h + (x+5) - 9, y+24*x^3-8)] @@ -151,12 +151,12 @@ end T1 = MPolyComplementOfKPointIdeal(R,[0,0,0,0]) f = x+y+z+w-1 T2 = MPolyPowersOfElement(f) - RL1,phiL1 = Localization(R,T1) - RL2,phiL2 = Localization(R,T2) - RQ1L1, phiQ1L1 = Localization(RQ1,T1) - RQ1L2, phiQ1L2 = Localization(RQ1,T2) - RQ2L1, phiQ2L1 = Localization(RQ2,T1) - RQ2L2, phiQ2L2 = Localization(RQ2,T2) + RL1,phiL1 = localization(R,T1) + RL2,phiL2 = localization(R,T2) + RQ1L1, phiQ1L1 = localization(RQ1,T1) + RQ1L2, phiQ1L2 = localization(RQ1,T2) + RQ2L1, phiQ2L1 = localization(RQ2,T1) + RQ2L2, phiQ2L2 = localization(RQ2,T2) # tests for MPolyQuoRing I1 = ideal(R,[x*z*(w-1),y*z*(w-1)]) @@ -209,12 +209,12 @@ end T1 = MPolyComplementOfKPointIdeal(R,[0,0,0]) f = x-y T2 = MPolyPowersOfElement(f) - RL1,phiL1 = Localization(R,T1) - RL2,phiL2 = Localization(R,T2) - RQ1L1, phiQ1L1 = Localization(RQ1,T1) - RQ1L2, phiQ1L2 = Localization(RQ1,T2) - RQ2L1, phiQ2L1 = Localization(RQ2,T1) - RQ2L2, phiQ2L2 = Localization(RQ2,T2) + RL1,phiL1 = localization(R,T1) + RL2,phiL2 = localization(R,T2) + RQ1L1, phiQ1L1 = localization(RQ1,T1) + RQ1L2, phiQ1L2 = localization(RQ1,T2) + RQ2L1, phiQ2L1 = localization(RQ2,T1) + RQ2L2, phiQ2L2 = localization(RQ2,T2) # the ideals I1 = ideal(R,[x^2*y+y^2*z+z^2*x]) diff --git a/test/Rings/nmod-localizations.jl b/test/Rings/nmod-localizations.jl index 6c20866e4cd7..4c4f06df56d3 100644 --- a/test/Rings/nmod-localizations.jl +++ b/test/Rings/nmod-localizations.jl @@ -5,12 +5,12 @@ using Oscar import Oscar.Nemo.zzModRing -import Oscar: base_ring, inverted_set, ambient_ring, Localization, parent, numerator, denominator, one, zero +import Oscar: base_ring, inverted_set, ambient_ring, localization, parent, numerator, denominator, one, zero import Oscar.AbstractAlgebra: elem_type, parent_type export NmodComplementOfPrimeIdeal, NmodLocalizedRing, NmodLocalizedRingElem -export generator, ambient_ring, Localization, parent, numerator, denominator +export generator, ambient_ring, localization, parent, numerator, denominator ####################################################################### @@ -74,7 +74,7 @@ base_ring(W::NmodLocalizedRing) = W.R::zzModRing inverted_set(W::NmodLocalizedRing{MultSetType}) where {MultSetType} = W.S::MultSetType ### required extension of the localization function -function Localization(S::NmodComplementOfPrimeIdeal) +function localization(S::NmodComplementOfPrimeIdeal) L = NmodLocalizedRing(S) return L, MapFromFunc(base_ring(L), L, x->(L(x))) end @@ -152,7 +152,7 @@ parent_type(T::Type{NmodLocalizedRingElem{MultSetType}}) where {MultSetType} = N @test !(13*4289729837 in U) @test 5783790198374098 in U @test ambient_ring(U) == R - W, _ = Localization(U) + W, _ = localization(U) @test base_ring(W) == ambient_ring(U) @test inverted_set(W) == U a = W(4, 17) diff --git a/test/Serialization/Algebras.jl b/test/Serialization/Algebras.jl index 5df1e7e8f9d3..c03f3a950fef 100644 --- a/test/Serialization/Algebras.jl +++ b/test/Serialization/Algebras.jl @@ -7,7 +7,7 @@ cases = [ mktempdir() do path for case in cases @testset "Free Associative Algebra over $(case[4])" begin - A, g = FreeAssociativeAlgebra(case[1], ["x","y"]) + A, g = free_associative_algebra(case[1], ["x","y"]) f = case[2] * g[1] + case[3] * g[2] test_save_load_roundtrip(path, f) do loaded @test loaded == f From 80a876d4cb2931271077eb8c84ea75419658b3f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20G=C3=B6ttgens?= Date: Fri, 20 Oct 2023 14:38:36 +0200 Subject: [PATCH 09/27] Suppress noisy test (#2941) --- experimental/GModule/GModule.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/experimental/GModule/GModule.jl b/experimental/GModule/GModule.jl index 2ca57f489a79..28a1cef2ef3b 100644 --- a/experimental/GModule/GModule.jl +++ b/experimental/GModule/GModule.jl @@ -1088,7 +1088,7 @@ end #TODO: in ctx of MeatAxe & Gap: we're mostly having a rref, # but for a different ordering of entries function _rref!(V::Vector{<:MatElem{<:FieldElem}}) - @show :in, V + #@show :in, V @assert all(x->size(x) == size(V[1]), V) n = nrows(V[1]) @assert ncols(V[1]) == n From a770b86505385d507d18896c02316665daac8fdd Mon Sep 17 00:00:00 2001 From: Benjamin Lorenz Date: Fri, 20 Oct 2023 15:32:08 +0200 Subject: [PATCH 10/27] Tests: automatically run all test files (#2810) --- .codecov.yml | 2 +- .github/workflows/CI.yml | 4 + .../DeveloperDocumentation/new_developers.md | 5 + docs/src/Experimental/intro.md | 18 +- experimental/Experimental.jl | 5 +- experimental/FTheoryTools/test/runtests.jl | 5 - experimental/FTheoryTools/test/setup_tests.jl | 2 + experimental/FTheoryTools/test/tate.jl | 4 - experimental/JuLie/test/runtests.jl | 3 - experimental/LinearQuotients/test/runtests.jl | 5 - experimental/ModStd/test/runtests.jl | 2 - .../OrthogonalDiscriminants/test/runtests.jl | 7 - experimental/QuadFormAndIsom/test/runtests.jl | 4 - .../QuadFormAndIsom/test/setup_tests.jl | 1 + experimental/runtests.jl | 9 - src/utils/tests.jl | 180 ++- system/precompile.jl | 1 - test/AlgebraicGeometry/Schemes/runtests.jl | 32 - test/AlgebraicGeometry/Surfaces/runtests.jl | 4 - .../ToricVarieties/runtests.jl | 23 - test/Combinatorics/runtests.jl | 9 - test/GAP/oscarinterface.jl | 8 + test/GAP/runtests.jl | 12 - test/Groups/constructors.jl | 2 + test/Groups/runtests.jl | 25 - test/InvariantTheory/runtests.jl | 8 - test/Modules/ReesAlgebra.jl | 31 - test/Modules/runtests.jl | 13 - test/NumberTheory/runtests.jl | 5 - test/PolyhedralGeometry/cone.jl | 333 +++-- test/PolyhedralGeometry/extended.jl | 2 + test/PolyhedralGeometry/linear_program.jl | 264 ++-- test/PolyhedralGeometry/polyhedral_complex.jl | 184 ++- test/PolyhedralGeometry/polyhedral_fan.jl | 259 ++-- test/PolyhedralGeometry/polyhedron.jl | 1154 ++++++++--------- test/PolyhedralGeometry/runtests.jl | 20 - test/PolyhedralGeometry/setup_tests.jl | 11 + test/PolyhedralGeometry/types.jl | 5 +- test/Project.toml | 2 - test/Rings/runtests.jl | 43 - test/Serialization/runtests.jl | 19 - ..._save_load_roundtrip.jl => setup_tests.jl} | 6 + test/TropicalGeometry/runtests.jl | 7 - test/runtests.jl | 141 +- 44 files changed, 1357 insertions(+), 1522 deletions(-) delete mode 100644 experimental/FTheoryTools/test/runtests.jl create mode 100644 experimental/FTheoryTools/test/setup_tests.jl delete mode 100644 experimental/JuLie/test/runtests.jl delete mode 100644 experimental/LinearQuotients/test/runtests.jl delete mode 100644 experimental/ModStd/test/runtests.jl delete mode 100644 experimental/OrthogonalDiscriminants/test/runtests.jl create mode 120000 experimental/QuadFormAndIsom/test/setup_tests.jl delete mode 100644 experimental/runtests.jl delete mode 100644 test/AlgebraicGeometry/Schemes/runtests.jl delete mode 100644 test/AlgebraicGeometry/Surfaces/runtests.jl delete mode 100644 test/AlgebraicGeometry/ToricVarieties/runtests.jl delete mode 100644 test/Combinatorics/runtests.jl create mode 100644 test/GAP/oscarinterface.jl delete mode 100644 test/GAP/runtests.jl delete mode 100644 test/Groups/runtests.jl delete mode 100644 test/InvariantTheory/runtests.jl delete mode 100644 test/Modules/ReesAlgebra.jl delete mode 100644 test/Modules/runtests.jl delete mode 100644 test/NumberTheory/runtests.jl delete mode 100644 test/PolyhedralGeometry/runtests.jl create mode 100644 test/PolyhedralGeometry/setup_tests.jl delete mode 100644 test/Rings/runtests.jl delete mode 100644 test/Serialization/runtests.jl rename test/Serialization/{test_save_load_roundtrip.jl => setup_tests.jl} (92%) delete mode 100644 test/TropicalGeometry/runtests.jl diff --git a/.codecov.yml b/.codecov.yml index fb4e01a4038d..f059c5db3112 100644 --- a/.codecov.yml +++ b/.codecov.yml @@ -1,7 +1,7 @@ codecov: notify: # Keep this in sync with the number of CI jobs uploading coverage. - after_n_builds: 3 + after_n_builds: 4 coverage: status: project: diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index ea15785fc5e5..356b3e4439a8 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -27,6 +27,7 @@ jobs: - '1.9' - '~1.10.0-0' - 'nightly' + group: [ 'short', 'long' ] os: - ubuntu-latest include: @@ -50,6 +51,9 @@ jobs: if: runner.os == 'macOS' # restrict number of openMP threads on macOS due to oversubscription run: echo "OMP_NUM_THREADS=1" >> $GITHUB_ENV + - name: "set test subgroup" + if: ${{ matrix.group }} != '' + run: echo "OSCAR_TEST_SUBSET=${{matrix.group}}" >> $GITHUB_ENV - name: "Run tests" uses: julia-actions/julia-runtest@latest with: diff --git a/docs/src/DeveloperDocumentation/new_developers.md b/docs/src/DeveloperDocumentation/new_developers.md index a2b8c40d18a3..f12a8168f35d 100644 --- a/docs/src/DeveloperDocumentation/new_developers.md +++ b/docs/src/DeveloperDocumentation/new_developers.md @@ -106,6 +106,11 @@ Oscar.test_module Oscar.get_seeded_rng ``` +If a test folder contains a file called `setup_tests.jl` it is included +automatically before each file (directly) in this directory. This can be used +to define helper functions that are used in multiple test files, for example +`test_save_load_roundtrip` for serialization. + ### Adding documentation For more information on docstrings, please read our page on [Documenting OSCAR code](@ref). There are two places where documentation can be added: diff --git a/docs/src/Experimental/intro.md b/docs/src/Experimental/intro.md index fd23c136c861..54ab71dac7ef 100644 --- a/docs/src/Experimental/intro.md +++ b/docs/src/Experimental/intro.md @@ -34,14 +34,18 @@ experimental/PACKAGE_NAME/ ├── src │   └── PACKAGE_NAME.jl └── test - └── runtests.jl + └── *.jl ``` -The files `src/PACKAGE_NAME.jl` and `test/runtests.jl` are mandatory as they -are used by Oscar.jl to find your code and tests. The file `docs/doc.main` is -used for integrating your documentation in the Oscar manual under the -`Experimental` section. Optionally please provide a `README.md` describing your -project and its goals, especially if you are starting from scratch and don't -have any documentation yet. +The file `src/PACKAGE_NAME.jl` and at least one `.jl` file in the `test/` +directory are mandatory and are used by Oscar.jl to find your code and tests. +If there is a `test/runtests.jl` then only this file is executed during +testing, otherwise all `.jl` files will be run automatically (in a random +order). + +The file `docs/doc.main` is used for integrating your documentation in the +Oscar manual under the `Experimental` section. Optionally please provide a +`README.md` describing your project and its goals, especially if you are +starting from scratch and don't have any documentation yet. !!! note There are still older projects in `experimental` from before the diff --git a/experimental/Experimental.jl b/experimental/Experimental.jl index f4ebeab839e6..e344f17cce62 100644 --- a/experimental/Experimental.jl +++ b/experimental/Experimental.jl @@ -28,8 +28,9 @@ for pkg in exppkgs if !isfile(joinpath(expdir, pkg, "src", "$pkg.jl")) error("experimental/$pkg is incomplete: $pkg/src/$pkg.jl missing. See the documentation at https://docs.oscar-system.org/dev/Experimental/intro/ for details.") end - if !isfile(joinpath(expdir, pkg, "test", "runtests.jl")) - error("experimental/$pkg is incomplete: $pkg/test/runtests.jl missing. See the documentation at https://docs.oscar-system.org/dev/Experimental/intro/ for details.") + path = joinpath(expdir, pkg, "test") + if !isdir(path) || length(filter(endswith(".jl"), readdir(path))) == 0 + error("experimental/$pkg is incomplete: $pkg/test/ missing or empty. See the documentation at https://docs.oscar-system.org/dev/Experimental/intro/ for details.") end end diff --git a/experimental/FTheoryTools/test/runtests.jl b/experimental/FTheoryTools/test/runtests.jl deleted file mode 100644 index 9e88928d2fd0..000000000000 --- a/experimental/FTheoryTools/test/runtests.jl +++ /dev/null @@ -1,5 +0,0 @@ -using Test -using Oscar -set_verbosity_level(:FTheoryConstructorInformation, -1) -include("weierstrass.jl") -include("tate.jl") diff --git a/experimental/FTheoryTools/test/setup_tests.jl b/experimental/FTheoryTools/test/setup_tests.jl new file mode 100644 index 000000000000..0cbfc351b228 --- /dev/null +++ b/experimental/FTheoryTools/test/setup_tests.jl @@ -0,0 +1,2 @@ +set_verbosity_level(:FTheoryConstructorInformation, -1) +include(joinpath(Oscar.oscardir, "test", "Serialization", "setup_tests.jl")) diff --git a/experimental/FTheoryTools/test/tate.jl b/experimental/FTheoryTools/test/tate.jl index e054dfa5b3f9..f0113f9da0b5 100644 --- a/experimental/FTheoryTools/test/tate.jl +++ b/experimental/FTheoryTools/test/tate.jl @@ -30,10 +30,6 @@ t = global_tate_model(base; completeness_check = false) @test is_smooth(ambient_space(t)) == false @test toric_variety(calabi_yau_hypersurface(t)) == ambient_space(t) - isdefined(Main, :test_save_load_roundtrip) || include( - joinpath(Oscar.oscardir, "test", "Serialization", "test_save_load_roundtrip.jl") - ) - mktempdir() do path test_save_load_roundtrip(path, t) do loaded @test tate_polynomial(t) == tate_polynomial(loaded) diff --git a/experimental/JuLie/test/runtests.jl b/experimental/JuLie/test/runtests.jl deleted file mode 100644 index 4391af05abd5..000000000000 --- a/experimental/JuLie/test/runtests.jl +++ /dev/null @@ -1,3 +0,0 @@ -include("tableaux.jl") -include("schur_polynomials.jl") -include("partitions.jl") diff --git a/experimental/LinearQuotients/test/runtests.jl b/experimental/LinearQuotients/test/runtests.jl deleted file mode 100644 index 8de2e50e22d9..000000000000 --- a/experimental/LinearQuotients/test/runtests.jl +++ /dev/null @@ -1,5 +0,0 @@ -using Oscar -using Test - -include("linear_quotients-test.jl") -include("cox_rings-test.jl") diff --git a/experimental/ModStd/test/runtests.jl b/experimental/ModStd/test/runtests.jl deleted file mode 100644 index 631f2ef2794e..000000000000 --- a/experimental/ModStd/test/runtests.jl +++ /dev/null @@ -1,2 +0,0 @@ -include("ModStdQt.jl") -include("ModStdNF.jl") diff --git a/experimental/OrthogonalDiscriminants/test/runtests.jl b/experimental/OrthogonalDiscriminants/test/runtests.jl deleted file mode 100644 index 4c747aa6d4a5..000000000000 --- a/experimental/OrthogonalDiscriminants/test/runtests.jl +++ /dev/null @@ -1,7 +0,0 @@ -using Oscar -using Test - -include("gram_det.jl") -include("data.jl") -include("utils.jl") -include("theoretical.jl") diff --git a/experimental/QuadFormAndIsom/test/runtests.jl b/experimental/QuadFormAndIsom/test/runtests.jl index 6c39e86c48f5..593e1934ca23 100644 --- a/experimental/QuadFormAndIsom/test/runtests.jl +++ b/experimental/QuadFormAndIsom/test/runtests.jl @@ -98,10 +98,6 @@ end @test is_elementary_with_prime(integer_lattice_with_isometry(root_lattice(:E, 7)))[1] @test is_unimodular(integer_lattice_with_isometry(hyperbolic_plane_lattice())) - isdefined(Main, :test_save_load_roundtrip) || include( - joinpath(Oscar.oscardir, "test", "Serialization", "test_save_load_roundtrip.jl") - ) - mktempdir() do path test_save_load_roundtrip(path, Lf) do loaded @test Lf == loaded diff --git a/experimental/QuadFormAndIsom/test/setup_tests.jl b/experimental/QuadFormAndIsom/test/setup_tests.jl new file mode 120000 index 000000000000..8555be72b9b5 --- /dev/null +++ b/experimental/QuadFormAndIsom/test/setup_tests.jl @@ -0,0 +1 @@ +../../../test/Serialization/setup_tests.jl \ No newline at end of file diff --git a/experimental/runtests.jl b/experimental/runtests.jl deleted file mode 100644 index 6d42c1903e0d..000000000000 --- a/experimental/runtests.jl +++ /dev/null @@ -1,9 +0,0 @@ -for pkg in Oscar.exppkgs - include("$pkg/test/runtests.jl") -end - -# legacy files -include("GModule/test/runtests.jl") -include("ModStd/test/runtests.jl") -include("MatrixGroups/test/runtests.jl") -include("ExteriorAlgebra/test/runtests.jl") diff --git a/src/utils/tests.jl b/src/utils/tests.jl index 92736c86b566..22cbaca40952 100644 --- a/src/utils/tests.jl +++ b/src/utils/tests.jl @@ -1,46 +1,198 @@ +function _timed_include(str::String, mod::Module=Main; use_ctime::Bool=VERSION >= v"1.9.0") + if use_ctime + compile_elapsedtimes = Base.cumulative_compile_time_ns() + end + stats = @timed Base.include(identity, mod, str) + fullpath = abspath(joinpath(Base.source_dir(), str)) + # skip files which just include other files and ignore + # files outside of the oscar folder + if startswith(fullpath, Oscar.oscardir) + path = relpath(fullpath, Oscar.oscardir) + if use_ctime + compile_elapsedtimes = Base.cumulative_compile_time_ns() .- compile_elapsedtimes + compile_elapsedtimes = compile_elapsedtimes ./ 10^9 + end + rtime=NaN + if use_ctime + comptime = first(compile_elapsedtimes) + rcomptime = last(compile_elapsedtimes) + println("-> Testing $path took: runtime $(round(stats.time-comptime; digits=3)) seconds + compilation $(round(comptime-rcomptime; digits=3)) seconds + recompilation $(round(rcomptime; digits=3)) seconds, $(Base.format_bytes(stats.bytes))") + return (path=>(time=stats.time-comptime, ctime=comptime-rcomptime, rctime=rcomptime, alloc=stats.bytes/2^20)) + else + println("-> Testing $path took: $(round(stats.time; digits=3)) seconds, $(Base.format_bytes(stats.bytes))") + return (path=>(time=stats.time, alloc=stats.bytes/2^20)) + end + else + return () + end +end + +function _gather_tests(path::AbstractString; ignore=[]) + # default ignore patterns + ignorepatterns = Regex[ + # these two files seem obsolete + r"Modules/GradedModules(\.jl)?$", + r"Modules/FreeModules-graded(\.jl)?$", + # FIXME: temporarily disable AlgClosureFp tests until we resolve + # issue https://github.com/oscar-system/Oscar.jl/issues/2691 + r"Rings/AlgClosureFp(\.jl)?$", + # this can only run on the main process and not on distributed workers + # so it is included directly in runtests + r"Serialization/IPC(\.jl)?$", + ] + for i in ignore + if i isa Regex + push!(ignorepatterns, i) + elseif i isa AbstractString + if endswith(i, ".jl") + push!(ignorepatterns, Regex("$i\$")) + else + push!(ignorepatterns, Regex("$i(\\.jl)?\$")) + end + else + throw(ArgumentError("invalid ignore pattern $i")) + end + end + + if any(p->contains(path, p), ignorepatterns) + @info "ignore: $(relpath(path, Oscar.oscardir))" + return String[] + end + + if !isabspath(path) + path = joinpath(Oscar.oscardir, path) + end + + isfile(path) && return [path] + isfile("$path.jl") && return ["$path.jl"] + + # if there is a runtests.jl we ignore everything else in that folder + # except for the main Oscar test dir + isfile(joinpath(path, "runtests.jl")) && + path != joinpath(Oscar.oscardir, "test") && + return [joinpath(path, "runtests.jl")] + + tests = String[] + for entry in readdir(path; join=true) + if any(s->contains(relpath(entry, Oscar.oscardir), s), ignorepatterns) + @info "ignore: $(relpath(entry, Oscar.oscardir))" + continue + end + endswith(entry, "setup_tests.jl") && continue + # this is only for the main test/runtests.jl + endswith(entry, "runtests.jl") && continue + if isdir(entry) + append!(tests, _gather_tests(entry; ignore=ignore)) + elseif isfile(entry) && endswith(entry, ".jl") + push!(tests, entry) + end + end + return tests +end + + + + @doc raw""" - test_module(file::AbstractString; new::Bool = true) + test_module(path::AbstractString; new::Bool = true, timed::Bool=false, ignore=[]) -Run the Oscar tests in the file `test/.jl` where `file` may be a path. +Run the Oscar tests in `path`: +- if `path` is relative then it will be set to `/test/` +- if `path` is a directory, run all test files in that directory and below +- if `path` or `path.jl` is a file, run this file + +If a directory contains a `runtests.jl` file only this file will be executed, otherwise +all files will be included independently. The optional parameter `new` takes the values `false` and `true` (default). If `true`, then the tests are run in a new session, otherwise the currently active session is used. +With the optional parameter `timed` the function will return a dict mapping file +names to a named tuple with compilation times and allocations. +This only works for `new=false`. + +The parameter `ignore` can be used to pass a list of `String` or `Regex` patterns. +Test files or folders matching these will be skipped. Strings will be compared as +suffixes. +This only works for `new=false`. + For experimental modules, use [`test_experimental_module`](@ref) instead. """ -function test_module(file::AbstractString; new::Bool=true) +function test_module(path::AbstractString; new::Bool=true, timed::Bool=false, ignore=[]) julia_exe = Base.julia_cmd() project_path = Base.active_project() - rel_test_file = normpath("test", "$file.jl") - test_file = joinpath(oscardir, rel_test_file) - + if !isabspath(path) + if !startswith(path, "test") + path = joinpath("test", path) + end + rel_test_path = normpath(path) + path = joinpath(oscardir, rel_test_path) + end if new - cmd = "using Test; using Oscar; Hecke.assertions(true); include(\"$test_file\");" + @req isempty(ignore) && !timed "The `timed` and `ignore` options only work for `new=false`." + cmd = "using Test; using Oscar; Hecke.assertions(true); Oscar.test_module(\"$path\"; new=false);" @info("spawning ", `$julia_exe --project=$project_path -e \"$cmd\"`) run(`$julia_exe --project=$project_path -e $cmd`) else + testlist = _gather_tests(path; ignore=ignore) + @req !isempty(testlist) "no such file or directory: $path[.jl]" + @req isdefined(Base.Main, :Test) "You need to do \"using Test\"" - @info("Running tests for $rel_test_file in same session") - Base.include(Base.Main, test_file) + + use_ctime = timed && VERSION >= v"1.9.0-DEV" + if use_ctime + Base.cumulative_compile_timing(true) + end + stats = Dict{String,NamedTuple}() + for entry in testlist + dir = dirname(entry) + if isfile(joinpath(dir,"setup_tests.jl")) + Base.include(identity, Main, joinpath(dir,"setup_tests.jl")) + end + if timed + push!(stats, _timed_include(entry; use_ctime=use_ctime)) + else + Base.include(identity, Main, entry) + end + end + + if timed + use_ctime && Base.cumulative_compile_timing(false) + return stats + else + return nothing + end end end @doc raw""" - test_experimental_module(project::AbstractString; file::AbstractString="runtests", new::Bool = true) + test_experimental_module(project::AbstractString; file::AbstractString="", + new::Bool=true, timed::Bool=false, ignore=[]) + +Run the Oscar tests in `experimental//test/`: +- if `path` is empty then all tests in that module are run, either via `runtests.jl` or directly. +- if `path` or `path.jl` is a file in that directory only this file is run. -Run the Oscar tests in the file `experimental//test/.jl` -where `file` may be a path. The default is to run the entire test suite of the module `project`. The optional parameter `new` takes the values `false` and `true` (default). If `true`, then the tests are run in a new session, otherwise the currently active session is used. + +With the optional parameter `timed` the function will return a dict mapping file +names to a named tuple with compilation times and allocations. +This only works for `new=false`. + +The parameter `ignore` can be used to pass a list of `String` or `Regex` patterns. +Test files or folders matching these will be skipped. Strings will be compared as +suffixes. +This only works for `new=false`. """ function test_experimental_module( - project::AbstractString; file::AbstractString="runtests", new::Bool=true + project::AbstractString; file::AbstractString="", new::Bool=true, timed::Bool=false, ignore=[] ) test_file = "../experimental/$project/test/$file" - test_module(test_file; new) + test_module(test_file; new, timed=timed, ignore=ignore) end diff --git a/system/precompile.jl b/system/precompile.jl index 811783a0e13c..f0630ea0ad9a 100644 --- a/system/precompile.jl +++ b/system/precompile.jl @@ -1,7 +1,6 @@ import Pkg Pkg.add("Documenter") Pkg.add("PrettyTables") -Pkg.add("Printf") Pkg.add("Aqua") Pkg.precompile() diff --git a/test/AlgebraicGeometry/Schemes/runtests.jl b/test/AlgebraicGeometry/Schemes/runtests.jl deleted file mode 100644 index ad8c22ee9ae1..000000000000 --- a/test/AlgebraicGeometry/Schemes/runtests.jl +++ /dev/null @@ -1,32 +0,0 @@ -using Test - -include("AffineSchemes.jl") -include("AffineVariety.jl") -include("AffineAlgebraicSet.jl") -include("CartierDivisor.jl") -include("CoveredProjectiveSchemes.jl") -include("CoveredScheme.jl") -include("CoherentSheaves.jl") -include("elliptic_surface.jl") -include("FunctionFields.jl") -include("Glueing.jl") -include("IdealSheaves.jl") -include("K3.jl") -include("ProjectiveAlgebraicSet.jl") -include("ProjectiveSchemes.jl") -include("ProjectiveVarieties.jl") -include("Sheaves.jl") -include("SpaceGerms.jl") -include("SpecOpen.jl") -include("SpecialTypes.jl") -include("singular_locus.jl") -include("SimplifiedSpec.jl") -include("transforms.jl") -include("VectorBundles.jl") -include("WeilDivisor.jl") -include("duValSing.jl") -include("MorphismFromRationalFunctions.jl") -include("AffineRationalPoint.jl") -include("ProjectiveRationalPoint.jl") -include("BlowupMorphism.jl") - diff --git a/test/AlgebraicGeometry/Surfaces/runtests.jl b/test/AlgebraicGeometry/Surfaces/runtests.jl deleted file mode 100644 index e19c2fc76756..000000000000 --- a/test/AlgebraicGeometry/Surfaces/runtests.jl +++ /dev/null @@ -1,4 +0,0 @@ -using Oscar -using Test - -include("K3Auto.jl") diff --git a/test/AlgebraicGeometry/ToricVarieties/runtests.jl b/test/AlgebraicGeometry/ToricVarieties/runtests.jl deleted file mode 100644 index cb976e067355..000000000000 --- a/test/AlgebraicGeometry/ToricVarieties/runtests.jl +++ /dev/null @@ -1,23 +0,0 @@ -using Oscar -using Test - -include("affine_normal_varieties.jl") -include("normal_toric_varieties.jl") -include("hirzebruch_surfaces.jl") -include("del_pezzo_surfaces.jl") -include("projective_spaces.jl") -include("toric_blowups.jl") -include("direct_products.jl") -include("cyclic_quotient_singularities.jl") -include("toric_morphisms.jl") -include("toric_divisors.jl") -include("toric_divisor_classes.jl") -include("line_bundles.jl") -include("line_bundle_cohomologies.jl") -include("proj.jl") -include("total_space.jl") -include("intersection_numbers.jl") -include("subvarieties.jl") -include("algebraic_cycles.jl") -include("toric_schemes.jl") -include("toric_blowdowns.jl") diff --git a/test/Combinatorics/runtests.jl b/test/Combinatorics/runtests.jl deleted file mode 100644 index 413f194d83d6..000000000000 --- a/test/Combinatorics/runtests.jl +++ /dev/null @@ -1,9 +0,0 @@ -using Oscar -using Test - -include("SimplicialComplexes.jl") -include("Matroids/Matroids.jl") -include("Matroids/Chow_Ring.jl") -include("Graph.jl") -include("Matroids/matroid_strata_grassmannian.jl") -include("OrderedMultiIndex.jl") diff --git a/test/GAP/oscarinterface.jl b/test/GAP/oscarinterface.jl new file mode 100644 index 000000000000..0a7a1bb5f9d0 --- /dev/null +++ b/test/GAP/oscarinterface.jl @@ -0,0 +1,8 @@ +@testset "OscarInterface" begin + + # Test the OscarInterface package + GAP_assertion_level = GAP.Globals.AssertionLevel() + @test GAP.Globals.TestDirectory(GAP.Globals.DirectoriesPackageLibrary(GAP.Obj("OscarInterface"), GAP.Obj("tst"))) + GAP.Globals.SetAssertionLevel(GAP_assertion_level) + +end diff --git a/test/GAP/runtests.jl b/test/GAP/runtests.jl deleted file mode 100644 index 1033dd3354e5..000000000000 --- a/test/GAP/runtests.jl +++ /dev/null @@ -1,12 +0,0 @@ -using Oscar -using Test - -include("gap_to_oscar.jl") -include("iso_gap_oscar.jl") -include("iso_oscar_gap.jl") -include("oscar_to_gap.jl") - -# Test the OscarInterface package -GAP_assertion_level = GAP.Globals.AssertionLevel() -@test GAP.Globals.TestDirectory(GAP.Globals.DirectoriesPackageLibrary(GAP.Obj("OscarInterface"), GAP.Obj("tst"))) -GAP.Globals.SetAssertionLevel(GAP_assertion_level) diff --git a/test/Groups/constructors.jl b/test/Groups/constructors.jl index b5209277b83d..ce2e409f5e2c 100644 --- a/test/Groups/constructors.jl +++ b/test/Groups/constructors.jl @@ -1,3 +1,5 @@ +import Oscar.AbstractAlgebra.GroupsCore + @testset "The groups Sym(n) and Alt(n)" begin for n = 5:8 diff --git a/test/Groups/runtests.jl b/test/Groups/runtests.jl deleted file mode 100644 index 6dafc3e750f9..000000000000 --- a/test/Groups/runtests.jl +++ /dev/null @@ -1,25 +0,0 @@ -using Oscar -using Test - -include("abelian_aut.jl") -include("describe.jl") -include("spinor_norms.jl") -include("conformance.jl") -include("constructors.jl") -include("operations.jl") -include("elements.jl") -include("quotients.jl") -include("subgroups_and_cosets.jl") -include("conjugation.jl") -include("homomorphisms.jl") -include("libraries.jl") -include("directproducts.jl") -include("matrixgroups.jl") -include("gsets.jl") -include("forms.jl") -include("MatrixDisplay.jl") -include("group_characters.jl") -include("FiniteFormOrthogonalGroup.jl") -include("GrpAb.jl") -include("Permutations.jl") -include("action.jl") diff --git a/test/InvariantTheory/runtests.jl b/test/InvariantTheory/runtests.jl deleted file mode 100644 index b320f109c045..000000000000 --- a/test/InvariantTheory/runtests.jl +++ /dev/null @@ -1,8 +0,0 @@ -using Oscar -using Test - -include("invariant_rings.jl") -include("primary_invariants.jl") -include("secondary_invariants.jl") -include("fundamental_invariants.jl") -include("affine_algebra.jl") diff --git a/test/Modules/ReesAlgebra.jl b/test/Modules/ReesAlgebra.jl deleted file mode 100644 index 6a078d03c382..000000000000 --- a/test/Modules/ReesAlgebra.jl +++ /dev/null @@ -1,31 +0,0 @@ -@testset "Rees algebras" begin - R, (x,y,z) = QQ["x", "y", "z"] - F = FreeMod(R, 3) - M, inc = sub(F, [a*g for a in gens(R) for g in gens(F)]) - Q, p = quo(F, [a*F[1] for a in gens(R)]) - - S1 = Oscar.rees_algebra(F) - @test !iszero(one(S1)) - S2 = Oscar.rees_algebra(M) - @test !iszero(one(S2)) - S3 = Oscar.rees_algebra(Q) - @test !iszero(one(S3)) - - A = R[x y; x-1 z] - f = det(A) - I = ideal(R, f) - Q, _ = quo(R, I) - AQ = change_base_ring(Q, A) - FQ = FreeMod(Q, 2) - M, _ = quo(FQ, change_base_ring(Q, A)) - M_double_dual, psi = Oscar.double_dual(M) - - @test is_isomorphism(psi) - f_A = hom(FQ, FQ, AQ) - dual_f_A = dual(f_A) - @test codomain(dual_f_A) isa FreeMod - g = Oscar._versal_morphism_to_free_module(M) - - RM = Oscar.rees_algebra(g) - @test !iszero(one(RM)) -end diff --git a/test/Modules/runtests.jl b/test/Modules/runtests.jl deleted file mode 100644 index 371da7a1fb20..000000000000 --- a/test/Modules/runtests.jl +++ /dev/null @@ -1,13 +0,0 @@ -using Oscar -using Test - -include("UngradedModules.jl") -include("FreeModElem-orderings.jl") -include("ModulesGraded.jl") -include("hilbert.jl") -include("module-localizations.jl") -include("local_rings.jl") -include("MPolyQuo.jl") -include("homological-algebra.jl") -include("ProjectiveModules.jl") -include("ExteriorPowers.jl") diff --git a/test/NumberTheory/runtests.jl b/test/NumberTheory/runtests.jl deleted file mode 100644 index e706fa9d3a0b..000000000000 --- a/test/NumberTheory/runtests.jl +++ /dev/null @@ -1,5 +0,0 @@ -using Oscar -using Test - -include("nmbthy.jl") -include("galthy.jl") diff --git a/test/PolyhedralGeometry/cone.jl b/test/PolyhedralGeometry/cone.jl index c14224bfb008..f40d2d69b558 100644 --- a/test/PolyhedralGeometry/cone.jl +++ b/test/PolyhedralGeometry/cone.jl @@ -1,182 +1,171 @@ -const pm = Polymake +@testset "Cone{$T}" for (f, T) in _prepare_scalar_types() -NF, sr2 = quadratic_field(2) -Qx, x = QQ["x"] -K, (a1, a2) = embedded_number_field([x^2 - 2, x^3 - 5], [(0, 2), (0, 2)]) + pts = [1 0; 0 0; 0 1] + Cone1=positive_hull(f, pts) + R = [1 0 0; 0 0 1] + L = [0 1 0] + Cone2 = positive_hull(f, R, L) + Cone3 = positive_hull(f, R, L; non_redundant=true) + Cone4 = positive_hull(f, R) + Cone5 = positive_hull(f, [1 0 0; 1 1 0; 1 1 1; 1 0 1]) + Cone6 = positive_hull(f, [1//3 1//2; 4//5 2]) + Cone7 = positive_hull(f, [0 1]) + Cone8 = positive_hull(f, [1 1; 1 -1]) -for f in (QQ, K) - - T = elem_type(f) - - @testset "Cone{$T}" begin - - pts = [1 0; 0 0; 0 1] - Cone1=positive_hull(f, pts) - R = [1 0 0; 0 0 1] - L = [0 1 0] - Cone2 = positive_hull(f, R, L) - Cone3 = positive_hull(f, R, L; non_redundant=true) - Cone4 = positive_hull(f, R) - Cone5 = positive_hull(f, [1 0 0; 1 1 0; 1 1 1; 1 0 1]) - Cone6 = positive_hull(f, [1//3 1//2; 4//5 2]) - Cone7 = positive_hull(f, [0 1]) - Cone8 = positive_hull(f, [1 1; 1 -1]) - - @testset "core functionality" begin - @test is_pointed(Cone1) - @test issubset(Cone7, Cone1) - @test !issubset(Cone1, Cone7) - @test [1, 0] in Cone1 - @test !([-1, -1] in Cone1) - if T == QQFieldElem - @test !is_smooth(Cone2) - @test is_smooth(Cone7) - @test !is_smooth(Cone8) - end - @test is_simplicial(Cone7) - @test !is_simplicial(Cone5) - @test is_fulldimensional(Cone1) - if T == QQFieldElem - @test hilbert_basis(Cone1) isa SubObjectIterator{PointVector{ZZRingElem}} - @test length(hilbert_basis(Cone1)) == 2 - @test hilbert_basis(Cone1) == [[1, 0], [0, 1]] - @test generator_matrix(hilbert_basis(Cone1)) == matrix(QQ, [1 0; 0 1]) - end - @test nrays(Cone1) == 2 - @test rays(RayVector{T}, Cone1) isa SubObjectIterator{RayVector{T}} - @test rays(Cone1) isa SubObjectIterator{RayVector{T}} - @test rays(RayVector, Cone1) isa SubObjectIterator{RayVector{T}} - @test vector_matrix(rays(Cone1)) == matrix(f, [1 0; 0 1]) - if T == QQFieldElem - @test matrix(QQ,rays(Cone1)) == matrix(QQ, [1 0; 0 1]) - @test matrix(ZZ,rays(Cone6)) == matrix(ZZ, [2 3; 2 5]) - end - @test length(rays(Cone1)) == 2 - @test rays(Cone1) == [[1, 0], [0, 1]] - for S in [LinearHalfspace{T}, Cone{T}] - @test facets(S, Cone1) isa SubObjectIterator{S} - @test length(facets(S, Cone1)) == 2 - if T == QQFieldElem - @test linear_inequality_matrix(facets(S, Cone1)) == matrix(QQ, [-1 0; 0 -1]) - @test Oscar.linear_matrix_for_polymake(facets(S, Cone1)) == [-1 0; 0 -1] - @test ray_indices(facets(S, Cone1)) == IncidenceMatrix([[2], [1]]) - @test IncidenceMatrix(facets(S, Cone1)) == IncidenceMatrix([[2], [1]]) - if S == LinearHalfspace{T} - @test facets(S, Cone1) == linear_halfspace.([f], [[-1, 0], [0, -1]]) - end - else - @test linear_inequality_matrix(facets(S, Cone1)) == matrix(f, [0 -1; -1 0]) - @test Oscar.linear_matrix_for_polymake(facets(S, Cone1)) == [0 -1; -1 0] - @test ray_indices(facets(S, Cone1)) == IncidenceMatrix([[1], [2]]) - @test IncidenceMatrix(facets(S, Cone1)) == IncidenceMatrix([[1], [2]]) - if S == LinearHalfspace{T} - @test facets(S, Cone1) == linear_halfspace.([f], [[0, -1], [-1, 0]]) - end - end - end - @test facets(IncidenceMatrix, Cone1) == IncidenceMatrix(T == QQFieldElem ? [[2], [1]] : [[1], [2]]) - @test facets(Halfspace, Cone1) isa SubObjectIterator{LinearHalfspace{T}} - @test facets(Cone1) isa SubObjectIterator{LinearHalfspace{T}} - @test linear_span(Cone4) isa SubObjectIterator{LinearHyperplane{T}} - @test length(linear_span(Cone4)) == 1 - @test linear_span(Cone4) == [linear_hyperplane(f, [0 1 0])] - @test linear_equation_matrix(linear_span(Cone4)) == matrix(f, [0 1 0]) + @testset "core functionality" begin + @test is_pointed(Cone1) + @test issubset(Cone7, Cone1) + @test !issubset(Cone1, Cone7) + @test [1, 0] in Cone1 + @test !([-1, -1] in Cone1) + if T == QQFieldElem + @test !is_smooth(Cone2) + @test is_smooth(Cone7) + @test !is_smooth(Cone8) + end + @test is_simplicial(Cone7) + @test !is_simplicial(Cone5) + @test is_fulldimensional(Cone1) + if T == QQFieldElem + @test hilbert_basis(Cone1) isa SubObjectIterator{PointVector{ZZRingElem}} + @test length(hilbert_basis(Cone1)) == 2 + @test hilbert_basis(Cone1) == [[1, 0], [0, 1]] + @test generator_matrix(hilbert_basis(Cone1)) == matrix(QQ, [1 0; 0 1]) + end + @test nrays(Cone1) == 2 + @test rays(RayVector{T}, Cone1) isa SubObjectIterator{RayVector{T}} + @test rays(Cone1) isa SubObjectIterator{RayVector{T}} + @test rays(RayVector, Cone1) isa SubObjectIterator{RayVector{T}} + @test vector_matrix(rays(Cone1)) == matrix(f, [1 0; 0 1]) + if T == QQFieldElem + @test matrix(QQ,rays(Cone1)) == matrix(QQ, [1 0; 0 1]) + @test matrix(ZZ,rays(Cone6)) == matrix(ZZ, [2 3; 2 5]) + end + @test length(rays(Cone1)) == 2 + @test rays(Cone1) == [[1, 0], [0, 1]] + for S in [LinearHalfspace{T}, Cone{T}] + @test facets(S, Cone1) isa SubObjectIterator{S} + @test length(facets(S, Cone1)) == 2 + if T == QQFieldElem + @test linear_inequality_matrix(facets(S, Cone1)) == matrix(QQ, [-1 0; 0 -1]) + @test Oscar.linear_matrix_for_polymake(facets(S, Cone1)) == [-1 0; 0 -1] + @test ray_indices(facets(S, Cone1)) == IncidenceMatrix([[2], [1]]) + @test IncidenceMatrix(facets(S, Cone1)) == IncidenceMatrix([[2], [1]]) + if S == LinearHalfspace{T} + @test facets(S, Cone1) == linear_halfspace.([f], [[-1, 0], [0, -1]]) + end + else + @test linear_inequality_matrix(facets(S, Cone1)) == matrix(f, [0 -1; -1 0]) + @test Oscar.linear_matrix_for_polymake(facets(S, Cone1)) == [0 -1; -1 0] + @test ray_indices(facets(S, Cone1)) == IncidenceMatrix([[1], [2]]) + @test IncidenceMatrix(facets(S, Cone1)) == IncidenceMatrix([[1], [2]]) + if S == LinearHalfspace{T} + @test facets(S, Cone1) == linear_halfspace.([f], [[0, -1], [-1, 0]]) + end + end + end + @test facets(IncidenceMatrix, Cone1) == IncidenceMatrix(T == QQFieldElem ? [[2], [1]] : [[1], [2]]) + @test facets(Halfspace, Cone1) isa SubObjectIterator{LinearHalfspace{T}} + @test facets(Cone1) isa SubObjectIterator{LinearHalfspace{T}} + @test linear_span(Cone4) isa SubObjectIterator{LinearHyperplane{T}} + @test length(linear_span(Cone4)) == 1 + @test linear_span(Cone4) == [linear_hyperplane(f, [0 1 0])] + @test linear_equation_matrix(linear_span(Cone4)) == matrix(f, [0 1 0]) - @test !is_pointed(Cone2) - @test !is_pointed(Cone3) - @test !is_fulldimensional(Cone4) - @test is_fulldimensional(Cone2) - @test Cone2 == Cone3 - @test Cone4 != Cone2 - @test dim(Cone4) == 2 - @test dim(Cone2) == 3 - @test ambient_dim(Cone2) == 3 - @test lineality_space(Cone2) isa SubObjectIterator{RayVector{T}} - @test generator_matrix(lineality_space(Cone2)) == matrix(f, L) - if T == QQFieldElem - @test matrix(QQ, lineality_space(Cone2)) == matrix(QQ, L) - @test matrix(ZZ, lineality_space(Cone2)) == matrix(ZZ, L) - end - @test length(lineality_space(Cone2)) == 1 - @test lineality_space(Cone2) == [L[1, :]] - @test vector_matrix(rays(Cone4)) == matrix(f, R) - @test codim(Cone4) == 1 - @test codim(Cone3) == 0 - @test faces(Cone2, 2) isa SubObjectIterator{Cone{T}} - @test length(faces(Cone2, 2)) == 2 - @test faces(Cone4, 1) isa SubObjectIterator{Cone{T}} - @test length(faces(Cone4, 1)) == 2 - if T == QQFieldElem - @test faces(Cone2, 2) == positive_hull.(T, [[0 0 1], [1 0 0]], [[0 1 0]]) - @test ray_indices(faces(Cone2, 2)) == IncidenceMatrix([[2], [1]]) - @test IncidenceMatrix(faces(Cone2, 2)) == IncidenceMatrix([[2], [1]]) - @test faces(IncidenceMatrix, Cone2, 2) == IncidenceMatrix([[2], [1]]) - @test faces(Cone4, 1) == positive_hull.(T, [[0 0 1], [1 0 0]]) - @test ray_indices(faces(Cone4, 1)) == IncidenceMatrix([[2], [1]]) - @test IncidenceMatrix(faces(Cone4, 1)) == IncidenceMatrix([[2], [1]]) - @test faces(IncidenceMatrix, Cone4, 1) == IncidenceMatrix([[2], [1]]) - else - @test faces(Cone2, 2) == positive_hull.([f], [[1 0 0], [0 0 1]], [[0 1 0]]) - @test ray_indices(faces(Cone2, 2)) == IncidenceMatrix([[1], [2]]) - @test IncidenceMatrix(faces(Cone2, 2)) == IncidenceMatrix([[1], [2]]) - @test faces(IncidenceMatrix, Cone2, 2) == IncidenceMatrix([[1], [2]]) - @test faces(Cone4, 1) == positive_hull.([f], [[1 0 0], [0 0 1]]) - @test ray_indices(faces(Cone4, 1)) == IncidenceMatrix([[1], [2]]) - @test IncidenceMatrix(faces(Cone4, 1)) == IncidenceMatrix([[1], [2]]) - @test faces(IncidenceMatrix, Cone4, 1) == IncidenceMatrix([[1], [2]]) - end - @test IncidenceMatrix(faces(Cone5, 1)) == IncidenceMatrix([[1], [2], [3], [4]]) - @test isnothing(faces(Cone2, 1)) + @test !is_pointed(Cone2) + @test !is_pointed(Cone3) + @test !is_fulldimensional(Cone4) + @test is_fulldimensional(Cone2) + @test Cone2 == Cone3 + @test Cone4 != Cone2 + @test dim(Cone4) == 2 + @test dim(Cone2) == 3 + @test ambient_dim(Cone2) == 3 + @test lineality_space(Cone2) isa SubObjectIterator{RayVector{T}} + @test generator_matrix(lineality_space(Cone2)) == matrix(f, L) + if T == QQFieldElem + @test matrix(QQ, lineality_space(Cone2)) == matrix(QQ, L) + @test matrix(ZZ, lineality_space(Cone2)) == matrix(ZZ, L) + end + @test length(lineality_space(Cone2)) == 1 + @test lineality_space(Cone2) == [L[1, :]] + @test vector_matrix(rays(Cone4)) == matrix(f, R) + @test codim(Cone4) == 1 + @test codim(Cone3) == 0 + @test faces(Cone2, 2) isa SubObjectIterator{Cone{T}} + @test length(faces(Cone2, 2)) == 2 + @test faces(Cone4, 1) isa SubObjectIterator{Cone{T}} + @test length(faces(Cone4, 1)) == 2 + if T == QQFieldElem + @test faces(Cone2, 2) == positive_hull.(T, [[0 0 1], [1 0 0]], [[0 1 0]]) + @test ray_indices(faces(Cone2, 2)) == IncidenceMatrix([[2], [1]]) + @test IncidenceMatrix(faces(Cone2, 2)) == IncidenceMatrix([[2], [1]]) + @test faces(IncidenceMatrix, Cone2, 2) == IncidenceMatrix([[2], [1]]) + @test faces(Cone4, 1) == positive_hull.(T, [[0 0 1], [1 0 0]]) + @test ray_indices(faces(Cone4, 1)) == IncidenceMatrix([[2], [1]]) + @test IncidenceMatrix(faces(Cone4, 1)) == IncidenceMatrix([[2], [1]]) + @test faces(IncidenceMatrix, Cone4, 1) == IncidenceMatrix([[2], [1]]) + else + @test faces(Cone2, 2) == positive_hull.([f], [[1 0 0], [0 0 1]], [[0 1 0]]) + @test ray_indices(faces(Cone2, 2)) == IncidenceMatrix([[1], [2]]) + @test IncidenceMatrix(faces(Cone2, 2)) == IncidenceMatrix([[1], [2]]) + @test faces(IncidenceMatrix, Cone2, 2) == IncidenceMatrix([[1], [2]]) + @test faces(Cone4, 1) == positive_hull.([f], [[1 0 0], [0 0 1]]) + @test ray_indices(faces(Cone4, 1)) == IncidenceMatrix([[1], [2]]) + @test IncidenceMatrix(faces(Cone4, 1)) == IncidenceMatrix([[1], [2]]) + @test faces(IncidenceMatrix, Cone4, 1) == IncidenceMatrix([[1], [2]]) + end + @test IncidenceMatrix(faces(Cone5, 1)) == IncidenceMatrix([[1], [2], [3], [4]]) + @test isnothing(faces(Cone2, 1)) - @test f_vector(Cone5) == [4, 4] - @test f_vector(Cone2) == [0, 2] - @test lineality_dim(Cone5) == 0 - @test lineality_dim(Cone2) == 1 - @test facet_degrees(Cone5)[1] == 2 - @test facet_degrees(Cone6)[1] == 1 - @test ray_degrees(Cone5)[1] == 2 - @test ray_degrees(Cone6)[1] == 1 + @test f_vector(Cone5) == [4, 4] + @test f_vector(Cone2) == [0, 2] + @test lineality_dim(Cone5) == 0 + @test lineality_dim(Cone2) == 1 + @test facet_degrees(Cone5)[1] == 2 + @test facet_degrees(Cone6)[1] == 1 + @test ray_degrees(Cone5)[1] == 2 + @test ray_degrees(Cone6)[1] == 1 - @test nfacets(Cone5) == 4 - @test relative_interior_point(Cone1) == f.([1//2, 1//2]) - end + @test nfacets(Cone5) == 4 + @test relative_interior_point(Cone1) == f.([1//2, 1//2]) + end - @testset "constructors" begin - @test cone_from_inequalities(f, [-1 0 0; 0 0 -1]) == Cone2 - @test cone_from_inequalities(f, [-1 0 0; 0 0 -1]; non_redundant = true) == Cone2 - @test cone_from_inequalities(f, facets(Cone4), linear_span(Cone4)) == Cone4 - @test cone_from_inequalities(f, facets(Cone4), linear_span(Cone4); non_redundant = true) == Cone4 - @test cone_from_equations(f, [0 1 0]) == cone_from_inequalities(f, Matrix{Int}(undef, 0, 3), linear_span(Cone4)) - end - end + @testset "constructors" begin + @test cone_from_inequalities(f, [-1 0 0; 0 0 -1]) == Cone2 + @test cone_from_inequalities(f, [-1 0 0; 0 0 -1]; non_redundant = true) == Cone2 + @test cone_from_inequalities(f, facets(Cone4), linear_span(Cone4)) == Cone4 + @test cone_from_inequalities(f, facets(Cone4), linear_span(Cone4); non_redundant = true) == Cone4 + @test cone_from_equations(f, [0 1 0]) == cone_from_inequalities(f, Matrix{Int}(undef, 0, 3), linear_span(Cone4)) + end +end - @testset "transform" begin - pts = [1 0 0 0; 1 1 0 0; 1 1 1 0; 1 0 1 0] - lin = [0 0 0 1] - A = [ -6 3 1 3; - -24 7 4 13; - -31 9 5 17; - -37 11 6 20] - # We also put inverse here, since inversion in Julia produces float errors - # and we don't want to do complicated matrix conversions here. - invA = [1 2 3 -4; - 1 0 1 -1; - 1 9 0 -6; - 1 1 5 -5] - C = positive_hull(f, pts, lin) - Ctarget = positive_hull(f, pts*transpose(A), lin*transpose(A)) - for props in (["RAYS", "LINEALITY_SPACE"], - ["FACETS", "LINEAR_SPAN"]) - Ccopy = Polymake.polytope.Cone{Oscar._scalar_type_to_polymake(T)}() - for prop in props - Polymake.take(Ccopy, prop, Polymake.give(Oscar.pm_object(C), prop)) - end - Ccopy = Cone{T}(Ccopy, f) - Ccopyt = transform(Ccopy, A) - Ccopytt = transform(Ccopyt, invA) - @test Ccopy == C - @test Ctarget == Ccopyt - @test Ccopytt == C +@testset "transform $T" for (f, T) in _prepare_scalar_types() + pts = [1 0 0 0; 1 1 0 0; 1 1 1 0; 1 0 1 0] + lin = [0 0 0 1] + A = [ -6 3 1 3; + -24 7 4 13; + -31 9 5 17; + -37 11 6 20] + # We also put inverse here, since inversion in Julia produces float errors + # and we don't want to do complicated matrix conversions here. + invA = [1 2 3 -4; + 1 0 1 -1; + 1 9 0 -6; + 1 1 5 -5] + C = positive_hull(f, pts, lin) + Ctarget = positive_hull(f, pts*transpose(A), lin*transpose(A)) + for props in (["RAYS", "LINEALITY_SPACE"], + ["FACETS", "LINEAR_SPAN"]) + Ccopy = Polymake.polytope.Cone{Oscar._scalar_type_to_polymake(T)}() + for prop in props + Polymake.take(Ccopy, prop, Polymake.give(Oscar.pm_object(C), prop)) end + Ccopy = Cone{T}(Ccopy, f) + Ccopyt = transform(Ccopy, A) + Ccopytt = transform(Ccopyt, invA) + @test Ccopy == C + @test Ctarget == Ccopyt + @test Ccopytt == C end end diff --git a/test/PolyhedralGeometry/extended.jl b/test/PolyhedralGeometry/extended.jl index 6a92ac1ad77b..1d5b850e1c14 100644 --- a/test/PolyhedralGeometry/extended.jl +++ b/test/PolyhedralGeometry/extended.jl @@ -1,5 +1,7 @@ @testset "Conformance tests" begin + pm = Polymake + pts = [1 0; 0 0; 0 1] lin = [0 1 0] Cone1=positive_hull(pts) diff --git a/test/PolyhedralGeometry/linear_program.jl b/test/PolyhedralGeometry/linear_program.jl index 70408f495d2d..a148d8472cf6 100644 --- a/test/PolyhedralGeometry/linear_program.jl +++ b/test/PolyhedralGeometry/linear_program.jl @@ -1,147 +1,137 @@ -NF, sr2 = quadratic_field(2) -ENF, sre2 = Hecke.embedded_field(NF, real_embeddings(NF)[2]) -Qx, x = QQ["x"] -K, (a1, a2) = embedded_number_field([x^2 - 2, x^3 - 5], [(0, 2), (0, 2)]) +@testset "(MixedInteger)LinearProgram{$T}" for (f, T) in _prepare_scalar_types() -for f in (QQ, ENF) + pts = [1 0; 0 0; 0 1] + Q0 = convex_hull(f, pts) + Q1 = convex_hull(f, pts, [1 1]) + Q2 = convex_hull(f, pts, [1 1], [1 1]) + square = cube(f, 2) + C1 = cube(f, 2, 0, 1) + Pos = polyhedron(f, [-1 0 0; 0 -1 0; 0 0 -1], [0,0,0]) + L = polyhedron(f, [-1 0 0; 0 -1 0], [0,0]) + point = convex_hull(f, [0 1 0]) + # this is to make sure the order of some matrices below doesn't change + Polymake.prefer("beneath_beyond") do + affine_hull(point) + end + s = simplex(f, 2) + rsquare = cube(f, 2, QQFieldElem(-3,2), QQFieldElem(3,2)) - T = elem_type(f) + @testset "linear programs" begin + LP1 = linear_program(square,[1,3]) + LP2 = linear_program(square,[2,2]; k=3, convention = :min) + LP3 = linear_program(Pos,[1,2,3]) + @test LP1 isa LinearProgram{T} + @test LP2 isa LinearProgram{T} + @test LP3 isa LinearProgram{T} - @testset "(MixedInteger)LinearProgram{$T}" begin + @test solve_lp(LP1)==(4,[1,1]) + @test solve_lp(LP2)==(-1,[-1,-1]) + if T == QQFieldElem + @test string(solve_lp(LP3))==string("(inf, nothing)") + else + @test string(solve_lp(LP3))==string("((inf), nothing)") + end + end - pts = [1 0; 0 0; 0 1] - Q0 = convex_hull(f, pts) - Q1 = convex_hull(f, pts, [1 1]) - Q2 = convex_hull(f, pts, [1 1], [1 1]) - square = cube(f, 2) - C1 = cube(f, 2, 0, 1) - Pos = polyhedron(f, [-1 0 0; 0 -1 0; 0 0 -1], [0,0,0]) - L = polyhedron(f, [-1 0 0; 0 -1 0], [0,0]) - point = convex_hull(f, [0 1 0]) - # this is to make sure the order of some matrices below doesn't change - Polymake.prefer("beneath_beyond") do - affine_hull(point) - end - s = simplex(f, 2) - rsquare = cube(f, 2, QQFieldElem(-3,2), QQFieldElem(3,2)) + if T == QQFieldElem - @testset "linear programs" begin - LP1 = linear_program(square,[1,3]) - LP2 = linear_program(square,[2,2]; k=3, convention = :min) - LP3 = linear_program(Pos,[1,2,3]) - @test LP1 isa LinearProgram{T} - @test LP2 isa LinearProgram{T} - @test LP3 isa LinearProgram{T} - - @test solve_lp(LP1)==(4,[1,1]) - @test solve_lp(LP2)==(-1,[-1,-1]) - if T == QQFieldElem - @test string(solve_lp(LP3))==string("(inf, nothing)") - else - @test string(solve_lp(LP3))==string("((inf), nothing)") - end - end + @testset "mixed integer linear programs" begin + MILP1 = mixed_integer_linear_program(rsquare, [1,3], integer_variables=[1]) + MILP2 = mixed_integer_linear_program(rsquare, [2,2]; k=3, convention = :min) + MILP3 = mixed_integer_linear_program(Pos, [1,2,3]) + @test MILP1 isa MixedIntegerLinearProgram{T} + @test MILP2 isa MixedIntegerLinearProgram{T} + @test MILP3 isa MixedIntegerLinearProgram{T} + + @test solve_milp(MILP1)==(11//2,[1,3//2]) + @test solve_milp(MILP2)==(-1,[-1,-1]) + @test string(solve_milp(MILP3))==string("(inf, nothing)") + end + + @testset "LinearProgram: lp and mps files" begin + LP1 = linear_program(square,[1,3]) + LP2 = linear_program(rsquare,[2,2]; k=3, convention = :min) + + buffer = IOBuffer() + @test save_lp(buffer, LP2) === nothing + @test String(take!(buffer)) == + """ + MINIMIZE + obj: +2 x1 +2 x2 +3 + Subject To + ie0: +2 x1 >= -3 + ie1: -2 x1 >= -3 + ie2: +2 x2 >= -3 + ie3: -2 x2 >= -3 + BOUNDS + x1 free + x2 free + END + """ + MILP1 = mixed_integer_linear_program(rsquare,[1,3], integer_variables=[1]) + MILP2 = mixed_integer_linear_program(rsquare,[2,2]; k=3, convention = :max) + + @test save_mps(buffer, MILP1) === nothing + @test String(take!(buffer)) == + """ + * Class: MIP + * Rows: 5 + * Columns: 2 + * Format: MPS + * + NAME unnamed#2 + ROWS + N C0000000 + G R0000000 + G R0000001 + G R0000002 + G R0000003 + COLUMNS + M0000000 'MARKER' 'INTORG' + x1 C0000000 1 R0000000 1 + x1 R0000001 -1 + M0000000 'MARKER' 'INTEND' + x2 C0000000 3 R0000002 1 + x2 R0000003 -1 + RHS + B R0000000 -1.5 R0000001 -1.5 + B R0000002 -1.5 R0000003 -1.5 + BOUNDS + FR BND x1 + FR BND x2 + ENDATA + """ - if T == QQFieldElem - - @testset "mixed integer linear programs" begin - MILP1 = mixed_integer_linear_program(rsquare, [1,3], integer_variables=[1]) - MILP2 = mixed_integer_linear_program(rsquare, [2,2]; k=3, convention = :min) - MILP3 = mixed_integer_linear_program(Pos, [1,2,3]) - @test MILP1 isa MixedIntegerLinearProgram{T} - @test MILP2 isa MixedIntegerLinearProgram{T} - @test MILP3 isa MixedIntegerLinearProgram{T} - - @test solve_milp(MILP1)==(11//2,[1,3//2]) - @test solve_milp(MILP2)==(-1,[-1,-1]) - @test string(solve_milp(MILP3))==string("(inf, nothing)") - end - - @testset "LinearProgram: lp and mps files" begin - LP1 = linear_program(square,[1,3]) - LP2 = linear_program(rsquare,[2,2]; k=3, convention = :min) - - buffer = IOBuffer() - @test save_lp(buffer, LP2) === nothing - @test String(take!(buffer)) == - """ - MINIMIZE - obj: +2 x1 +2 x2 +3 - Subject To - ie0: +2 x1 >= -3 - ie1: -2 x1 >= -3 - ie2: +2 x2 >= -3 - ie3: -2 x2 >= -3 - BOUNDS - x1 free - x2 free - END - """ - MILP1 = mixed_integer_linear_program(rsquare,[1,3], integer_variables=[1]) - MILP2 = mixed_integer_linear_program(rsquare,[2,2]; k=3, convention = :max) - - @test save_mps(buffer, MILP1) === nothing - @test String(take!(buffer)) == - """ - * Class: MIP - * Rows: 5 - * Columns: 2 - * Format: MPS - * - NAME unnamed#2 - ROWS - N C0000000 - G R0000000 - G R0000001 - G R0000002 - G R0000003 - COLUMNS - M0000000 'MARKER' 'INTORG' - x1 C0000000 1 R0000000 1 - x1 R0000001 -1 - M0000000 'MARKER' 'INTEND' - x2 C0000000 3 R0000002 1 - x2 R0000003 -1 - RHS - B R0000000 -1.5 R0000001 -1.5 - B R0000002 -1.5 R0000003 -1.5 - BOUNDS - FR BND x1 - FR BND x2 - ENDATA - """ - - for lp in (LP1, LP2, MILP1, MILP2) - mktempdir() do path - @test save_lp(joinpath(path,"lp.lp"), lp) === nothing - loaded = load_lp(joinpath(path,"lp.lp")) - @test typeof(loaded) == typeof(lp) - @test feasible_region(lp) == feasible_region(loaded) - @test objective_function(lp) == objective_function(loaded) - @test optimal_value(lp) == optimal_value(loaded) - if lp isa MixedIntegerLinearProgram - @test optimal_solution(lp) == optimal_solution(loaded) - else - @test optimal_vertex(lp) == optimal_vertex(loaded) - end - - @test save_mps(joinpath(path,"lp.mps"), lp) === nothing - loaded = load_mps(joinpath(path,"lp.mps")) - @test typeof(loaded) == typeof(lp) - @test feasible_region(lp) == feasible_region(loaded) - @test objective_function(lp) == objective_function(loaded) - if lp.convention === :max - # mps file don't store max / min - @test optimal_value(lp) == optimal_value(loaded) - if lp isa MixedIntegerLinearProgram - @test optimal_solution(lp) == optimal_solution(loaded) - else - @test optimal_vertex(lp) == optimal_vertex(loaded) - end - end - end - end + for lp in (LP1, LP2, MILP1, MILP2) + mktempdir() do path + @test save_lp(joinpath(path,"lp.lp"), lp) === nothing + loaded = load_lp(joinpath(path,"lp.lp")) + @test typeof(loaded) == typeof(lp) + @test feasible_region(lp) == feasible_region(loaded) + @test objective_function(lp) == objective_function(loaded) + @test optimal_value(lp) == optimal_value(loaded) + if lp isa MixedIntegerLinearProgram + @test optimal_solution(lp) == optimal_solution(loaded) + else + @test optimal_vertex(lp) == optimal_vertex(loaded) + end + + @test save_mps(joinpath(path,"lp.mps"), lp) === nothing + loaded = load_mps(joinpath(path,"lp.mps")) + @test typeof(loaded) == typeof(lp) + @test feasible_region(lp) == feasible_region(loaded) + @test objective_function(lp) == objective_function(loaded) + if lp.convention === :max + # mps file don't store max / min + @test optimal_value(lp) == optimal_value(loaded) + if lp isa MixedIntegerLinearProgram + @test optimal_solution(lp) == optimal_solution(loaded) + else + @test optimal_vertex(lp) == optimal_vertex(loaded) end + end end + end end + end end diff --git a/test/PolyhedralGeometry/polyhedral_complex.jl b/test/PolyhedralGeometry/polyhedral_complex.jl index 734852859a14..0887ce7e306e 100644 --- a/test/PolyhedralGeometry/polyhedral_complex.jl +++ b/test/PolyhedralGeometry/polyhedral_complex.jl @@ -1,103 +1,95 @@ -NF, sr2 = quadratic_field(2) -Qx, x = QQ["x"] -K, a = Hecke.embedded_field(NF, real_embeddings(NF)[2]) +@testset "PolyhedralComplex{$T}" for (f, T) in _prepare_scalar_types() -for f in (QQ, K) + I = IncidenceMatrix([[1, 2, 3], [2, 4]]) + P = [0 0; 1 0; 0 1; 1 1] + P2 = [0 0 0; 1 0 0; 0 1 0; 1 1 0] + F = [4] + L = [0 0 1] - T = elem_type(f) - @testset "PolyhedralComplex{$T}" begin - - I = IncidenceMatrix([[1, 2, 3], [2, 4]]) - P = [0 0; 1 0; 0 1; 1 1] - P2 = [0 0 0; 1 0 0; 0 1 0; 1 1 0] - F = [4] - L = [0 0 1] - - @testset "constructors" begin - - @test polyhedral_complex(f, I, P) isa PolyhedralComplex{T} - @test polyhedral_complex(f, I, P, F) isa PolyhedralComplex{T} - @test polyhedral_complex(f, I, P2, F, L) isa PolyhedralComplex{T} - @test polyhedral_complex(f, I, P2, F, L; non_redundant = true) isa PolyhedralComplex{T} - @test polyhedral_complex(f, I, P2, nothing, L) isa PolyhedralComplex{T} - - end - - PC = polyhedral_complex(f, I, P) - PCF = polyhedral_complex(f, I, -P, F) - PCFL = polyhedral_complex(f, I, P2, F, L) - PCFLN = polyhedral_complex(f, I, P2, F, L; non_redundant = true) - PCL = polyhedral_complex(f, I, P2, nothing, L) - - @test common_refinement(PC, PCF) isa PolyhedralComplex{T} - PCR = common_refinement(PC, PCF) - - @test k_skeleton(PC, 1) isa PolyhedralComplex{T} - PCK = k_skeleton(PC, 1) + @testset "constructors" begin - # test constructor with re-arranged arguments - let PCF2 = polyhedral_complex(f, -P[1:3, :], I[:, 1:3], -P[4:4, :], I[:, 4:4]) - @test vertices(PCF) == vertices(PCF2) - @test rays(PCF) == rays(PCF2) - @test IncidenceMatrix(maximal_polyhedra(PCF)) == IncidenceMatrix(maximal_polyhedra(PCF2)) - end - - @testset "core functionality" begin - - @test ambient_dim(PC) == 2 - @test vertices(PC) isa SubObjectIterator{PointVector{T}} - @test length(vertices(PC)) == 4 - @test point_matrix(vertices(PC)) == matrix(f, P) - @test vertices(PC) == [[0, 0], [1, 0], [0, 1], [1, 1]] - @test rays(PCF) isa SubObjectIterator{RayVector{T}} - @test length(rays(PCF)) == 1 - @test rays(PCF) == [[-1, -1]] - @test vector_matrix(rays(PCF)) == matrix(f, [-1 -1]) - @test vertices_and_rays(PCFL) isa SubObjectIterator{Union{RayVector{T}, PointVector{T}}} - @test length(vertices_and_rays(PCFL)) == 4 - @test vertices_and_rays(PCFL) == [[0, 0, 0], [1, 0, 0], [0, 1, 0], [1, 1, 0]] - @test typeof.(vertices_and_rays(PCFL)) == [PointVector{T}, PointVector{T}, PointVector{T}, RayVector{T}] - @test vector_matrix(vertices_and_rays(PCFL)) == matrix(f, P2) - @test maximal_polyhedra(PC) isa SubObjectIterator{Polyhedron{T}} - @test length(maximal_polyhedra(PC)) == 2 - @test maximal_polyhedra(PC) == convex_hull.([f], [P[1:3, :], P[[2, 4], :]]) - @test n_maximal_polyhedra(PC) == 2 - @test is_simplicial(PC) - @test !is_pure(PCL) - @test dim(PCL) == 3 - @test polyhedra_of_dim(PC, 1) isa SubObjectIterator{Polyhedron{T}} - @test length(polyhedra_of_dim(PC, 1)) == 4 - if T == QQFieldElem - @test polyhedra_of_dim(PC, 1) == convex_hull.(T, [P[[2, 4], :], P[[1, 3], :], P[[1, 2], :], P[[2, 3], :]]) - else - @test polyhedra_of_dim(PC, 1) == convex_hull.([f], [P[[2, 4], :], P[[1, 3], :], P[[2, 3], :], P[[1, 2], :]]) - end - @test lineality_space(PCL) isa SubObjectIterator{RayVector{T}} - @test length(lineality_space(PCL)) == 1 - @test lineality_space(PCL) == [L[:]] - @test generator_matrix(lineality_space(PCL)) == matrix(QQ, L) + @test polyhedral_complex(f, I, P) isa PolyhedralComplex{T} + @test polyhedral_complex(f, I, P, F) isa PolyhedralComplex{T} + @test polyhedral_complex(f, I, P2, F, L) isa PolyhedralComplex{T} + @test polyhedral_complex(f, I, P2, F, L; non_redundant = true) isa PolyhedralComplex{T} + @test polyhedral_complex(f, I, P2, nothing, L) isa PolyhedralComplex{T} - @test lineality_dim(PCFL) == 1 - @test f_vector(PCL) == [0, 4, 4, 1] - # Since there is lineality, there are no rays or vertices - @test nrays(PCFL) == 0 - @test nvertices(PCFL) == 0 - @test npolyhedra(PCL) == 9 - @test codim(PCF) == 0 - @test is_embedded(PC) - - mfPCFLN = minimal_faces(PCFLN) - @test mfPCFLN.base_points == [P2[i, :] for i in 1:3] - rmlPCFLN = rays_modulo_lineality(PCFLN) - @test rmlPCFLN.rays_modulo_lineality == [P2[4, :]] - @test lineality_space(PCFLN) == [L[1, :]] - @test vertex_indices(maximal_polyhedra(PCFLN)) == I[:, 1:3] - @test ray_indices(maximal_polyhedra(PCFLN)) == I[:, 4:4] - @test vertex_and_ray_indices(maximal_polyhedra(PCFLN)) == I - @test IncidenceMatrix(maximal_polyhedra(PCFLN)) == I - @test maximal_polyhedra(IncidenceMatrix, PCFLN) == I - - end + end + PC = polyhedral_complex(f, I, P) + PCF = polyhedral_complex(f, I, -P, F) + PCFL = polyhedral_complex(f, I, P2, F, L) + PCFLN = polyhedral_complex(f, I, P2, F, L; non_redundant = true) + PCL = polyhedral_complex(f, I, P2, nothing, L) + + @test common_refinement(PC, PCF) isa PolyhedralComplex{T} + PCR = common_refinement(PC, PCF) + + @test k_skeleton(PC, 1) isa PolyhedralComplex{T} + PCK = k_skeleton(PC, 1) + + # test constructor with re-arranged arguments + let PCF2 = polyhedral_complex(f, -P[1:3, :], I[:, 1:3], -P[4:4, :], I[:, 4:4]) + @test vertices(PCF) == vertices(PCF2) + @test rays(PCF) == rays(PCF2) + @test IncidenceMatrix(maximal_polyhedra(PCF)) == IncidenceMatrix(maximal_polyhedra(PCF2)) + end + + @testset "core functionality" begin + + @test ambient_dim(PC) == 2 + @test vertices(PC) isa SubObjectIterator{PointVector{T}} + @test length(vertices(PC)) == 4 + @test point_matrix(vertices(PC)) == matrix(f, P) + @test vertices(PC) == [[0, 0], [1, 0], [0, 1], [1, 1]] + @test rays(PCF) isa SubObjectIterator{RayVector{T}} + @test length(rays(PCF)) == 1 + @test rays(PCF) == [[-1, -1]] + @test vector_matrix(rays(PCF)) == matrix(f, [-1 -1]) + @test vertices_and_rays(PCFL) isa SubObjectIterator{Union{RayVector{T}, PointVector{T}}} + @test length(vertices_and_rays(PCFL)) == 4 + @test vertices_and_rays(PCFL) == [[0, 0, 0], [1, 0, 0], [0, 1, 0], [1, 1, 0]] + @test typeof.(vertices_and_rays(PCFL)) == [PointVector{T}, PointVector{T}, PointVector{T}, RayVector{T}] + @test vector_matrix(vertices_and_rays(PCFL)) == matrix(f, P2) + @test maximal_polyhedra(PC) isa SubObjectIterator{Polyhedron{T}} + @test length(maximal_polyhedra(PC)) == 2 + @test maximal_polyhedra(PC) == convex_hull.([f], [P[1:3, :], P[[2, 4], :]]) + @test n_maximal_polyhedra(PC) == 2 + @test is_simplicial(PC) + @test !is_pure(PCL) + @test dim(PCL) == 3 + @test polyhedra_of_dim(PC, 1) isa SubObjectIterator{Polyhedron{T}} + @test length(polyhedra_of_dim(PC, 1)) == 4 + if T == QQFieldElem + @test polyhedra_of_dim(PC, 1) == convex_hull.(T, [P[[2, 4], :], P[[1, 3], :], P[[1, 2], :], P[[2, 3], :]]) + else + @test polyhedra_of_dim(PC, 1) == convex_hull.([f], [P[[2, 4], :], P[[1, 3], :], P[[2, 3], :], P[[1, 2], :]]) end + @test lineality_space(PCL) isa SubObjectIterator{RayVector{T}} + @test length(lineality_space(PCL)) == 1 + @test lineality_space(PCL) == [L[:]] + @test generator_matrix(lineality_space(PCL)) == matrix(QQ, L) + + @test lineality_dim(PCFL) == 1 + @test f_vector(PCL) == [0, 4, 4, 1] + # Since there is lineality, there are no rays or vertices + @test nrays(PCFL) == 0 + @test nvertices(PCFL) == 0 + @test npolyhedra(PCL) == 9 + @test codim(PCF) == 0 + @test is_embedded(PC) + + mfPCFLN = minimal_faces(PCFLN) + @test mfPCFLN.base_points == [P2[i, :] for i in 1:3] + rmlPCFLN = rays_modulo_lineality(PCFLN) + @test rmlPCFLN.rays_modulo_lineality == [P2[4, :]] + @test lineality_space(PCFLN) == [L[1, :]] + @test vertex_indices(maximal_polyhedra(PCFLN)) == I[:, 1:3] + @test ray_indices(maximal_polyhedra(PCFLN)) == I[:, 4:4] + @test vertex_and_ray_indices(maximal_polyhedra(PCFLN)) == I + @test IncidenceMatrix(maximal_polyhedra(PCFLN)) == I + @test maximal_polyhedra(IncidenceMatrix, PCFLN) == I + + end + end diff --git a/test/PolyhedralGeometry/polyhedral_fan.jl b/test/PolyhedralGeometry/polyhedral_fan.jl index f08d3b5e0b17..7f78b5e5dd8d 100644 --- a/test/PolyhedralGeometry/polyhedral_fan.jl +++ b/test/PolyhedralGeometry/polyhedral_fan.jl @@ -1,143 +1,136 @@ -Qx, x = QQ["x"] -K, (a1, a2) = embedded_number_field([x^2 - 2, x^3 - 5], [(0, 2), (0, 2)]) +@testset "PolyhedralFan{$T}" for (f, T) in _prepare_scalar_types() + C0 = cube(f, 2) + @test normal_fan(C0) isa PolyhedralFan{T} + NFsquare = normal_fan(C0) + R = [1 0 0; 0 0 1] + L = [0 1 0] + Cone4 = positive_hull(f, R) + Cone5 = positive_hull(f, [1 0 0; 0 1 0]) -for f in (QQ, K) + @test polyhedral_fan([Cone4, Cone5]) isa PolyhedralFan{T} + F0 = polyhedral_fan([Cone4, Cone5]) + I3 = [1 0 0; 0 1 0; 0 0 1] + incidence1 = IncidenceMatrix([[1,2],[2,3]]) + incidence2 = IncidenceMatrix([[1,2]]) + @test polyhedral_fan(f, I3, incidence1) isa PolyhedralFan{T} + F1 = polyhedral_fan(f, I3, incidence1) + F1NR = polyhedral_fan(f, I3, incidence1; non_redundant = true) + @test polyhedral_fan(f, I3, incidence1) isa PolyhedralFan{T} + F2 = polyhedral_fan(f, R, L, incidence2) + F2NR = polyhedral_fan(f, R, L, incidence2; non_redundant = true) - T = elem_type(f) - @testset "PolyhedralFan{$T}" begin - C0 = cube(f, 2) - @test normal_fan(C0) isa PolyhedralFan{T} - NFsquare = normal_fan(C0) - R = [1 0 0; 0 0 1] - L = [0 1 0] - Cone4 = positive_hull(f, R) - Cone5 = positive_hull(f, [1 0 0; 0 1 0]) - - @test polyhedral_fan([Cone4, Cone5]) isa PolyhedralFan{T} - F0 = polyhedral_fan([Cone4, Cone5]) - I3 = [1 0 0; 0 1 0; 0 0 1] - incidence1 = IncidenceMatrix([[1,2],[2,3]]) - incidence2 = IncidenceMatrix([[1,2]]) - @test polyhedral_fan(f, I3, incidence1) isa PolyhedralFan{T} - F1 = polyhedral_fan(f, I3, incidence1) - F1NR = polyhedral_fan(f, I3, incidence1; non_redundant = true) - @test polyhedral_fan(f, I3, incidence1) isa PolyhedralFan{T} - F2 = polyhedral_fan(f, R, L, incidence2) - F2NR = polyhedral_fan(f, R, L, incidence2; non_redundant = true) + @testset "core functionality" begin + if T == QQFieldElem + @test is_smooth(NFsquare) + end + @test vector_matrix(rays(NFsquare)) == matrix(f, [1 0; -1 0; 0 1; 0 -1]) + @test rays(NFsquare) isa SubObjectIterator{RayVector{T}} + @test length(rays(NFsquare)) == 4 + @test rays(NFsquare) == [[1, 0], [-1, 0], [0, 1], [0, -1]] + @test is_regular(NFsquare) + @test is_complete(NFsquare) + @test !is_complete(F0) + @test length(rays(F0)) == 3 + @test nrays(F1) == 3 + @test dim(F1) == 2 + @test ambient_dim(F1) == 3 + @test nrays(F2) == 0 + @test lineality_dim(F2) == 1 + RMLF2 = rays_modulo_lineality(F2) + @test length(RMLF2[:rays_modulo_lineality]) == 2 + @test maximal_cones(F1) isa SubObjectIterator{Cone{T}} + @test dim.(maximal_cones(F1)) == [2,2] + @test ray_indices(maximal_cones(F1)) == incidence1 + @test IncidenceMatrix(maximal_cones(F1)) == incidence1 + @test maximal_cones(IncidenceMatrix, F1) == incidence1 + @test n_maximal_cones(F1) == 2 + @test lineality_space(F2) isa SubObjectIterator{RayVector{T}} + @test generator_matrix(lineality_space(F2)) == matrix(f, L) + if T == QQFieldElem + @test matrix(QQ, lineality_space(F2)) == matrix(QQ, L) + end + @test length(lineality_space(F2)) == 1 + @test lineality_space(F2) == [L[:]] + @test cones(F2, 2) isa SubObjectIterator{Cone{T}} + @test size(cones(F2, 2)) == (2,) + @test lineality_space(cones(F2, 2)[1]) == [[0, 1, 0]] + @test rays.(cones(F2, 2)) == [[], []] + @test isnothing(cones(F2, 1)) + @test ray_indices(cones(F1, 2)) == incidence1 + @test IncidenceMatrix(cones(F1, 2)) == incidence1 + @test cones(IncidenceMatrix, F1, 2) == incidence1 - @testset "core functionality" begin - if T == QQFieldElem - @test is_smooth(NFsquare) - end - @test vector_matrix(rays(NFsquare)) == matrix(f, [1 0; -1 0; 0 1; 0 -1]) - @test rays(NFsquare) isa SubObjectIterator{RayVector{T}} - @test length(rays(NFsquare)) == 4 - @test rays(NFsquare) == [[1, 0], [-1, 0], [0, 1], [0, -1]] - @test is_regular(NFsquare) - @test is_complete(NFsquare) - @test !is_complete(F0) - @test length(rays(F0)) == 3 - @test nrays(F1) == 3 - @test dim(F1) == 2 - @test ambient_dim(F1) == 3 - @test nrays(F2) == 0 - @test lineality_dim(F2) == 1 - RMLF2 = rays_modulo_lineality(F2) - @test length(RMLF2[:rays_modulo_lineality]) == 2 - @test maximal_cones(F1) isa SubObjectIterator{Cone{T}} - @test dim.(maximal_cones(F1)) == [2,2] - @test ray_indices(maximal_cones(F1)) == incidence1 - @test IncidenceMatrix(maximal_cones(F1)) == incidence1 - @test maximal_cones(IncidenceMatrix, F1) == incidence1 - @test n_maximal_cones(F1) == 2 - @test lineality_space(F2) isa SubObjectIterator{RayVector{T}} - @test generator_matrix(lineality_space(F2)) == matrix(f, L) - if T == QQFieldElem - @test matrix(QQ, lineality_space(F2)) == matrix(QQ, L) - end - @test length(lineality_space(F2)) == 1 - @test lineality_space(F2) == [L[:]] - @test cones(F2, 2) isa SubObjectIterator{Cone{T}} - @test size(cones(F2, 2)) == (2,) - @test lineality_space(cones(F2, 2)[1]) == [[0, 1, 0]] - @test rays.(cones(F2, 2)) == [[], []] - @test isnothing(cones(F2, 1)) - @test ray_indices(cones(F1, 2)) == incidence1 - @test IncidenceMatrix(cones(F1, 2)) == incidence1 - @test cones(IncidenceMatrix, F1, 2) == incidence1 - - II = ray_indices(maximal_cones(NFsquare)) - NF0 = polyhedral_fan(rays(NFsquare), II) - @test nrays(NF0) == 4 - FF0 = face_fan(C0) - @test nrays(FF0) == 4 - if T == QQFieldElem - @test !is_smooth(FF0) - end - @test f_vector(NFsquare) == [4, 4] - @test rays(F1NR) == collect(eachrow(I3)) - @test ray_indices(maximal_cones(F1NR)) == incidence1 - @test IncidenceMatrix(maximal_cones(F1NR)) == incidence1 - @test nrays(F2NR) == 0 - @test lineality_dim(F2NR) == 1 - RMLF2NR = rays_modulo_lineality(F2NR) - @test length(RMLF2NR[:rays_modulo_lineality]) == 2 - @test RMLF2NR[:rays_modulo_lineality] == collect(eachrow(R)) - @test lineality_space(F2NR) == collect(eachrow(L)) - @test ray_indices(maximal_cones(F2NR)) == incidence2 - @test IncidenceMatrix(maximal_cones(F2NR)) == incidence2 - end - + II = ray_indices(maximal_cones(NFsquare)) + NF0 = polyhedral_fan(rays(NFsquare), II) + @test nrays(NF0) == 4 + FF0 = face_fan(C0) + @test nrays(FF0) == 4 + if T == QQFieldElem + @test !is_smooth(FF0) end + @test f_vector(NFsquare) == [4, 4] + @test rays(F1NR) == collect(eachrow(I3)) + @test ray_indices(maximal_cones(F1NR)) == incidence1 + @test IncidenceMatrix(maximal_cones(F1NR)) == incidence1 + @test nrays(F2NR) == 0 + @test lineality_dim(F2NR) == 1 + RMLF2NR = rays_modulo_lineality(F2NR) + @test length(RMLF2NR[:rays_modulo_lineality]) == 2 + @test RMLF2NR[:rays_modulo_lineality] == collect(eachrow(R)) + @test lineality_space(F2NR) == collect(eachrow(L)) + @test ray_indices(maximal_cones(F2NR)) == incidence2 + @test IncidenceMatrix(maximal_cones(F2NR)) == incidence2 + end + +end - @testset "Transform" begin - square = cube(f, 2) - nf_square = normal_fan(square) - m_good = matrix(f, [1 0; 0 1]) - m_bad = matrix(f, [1 1]) - nf_transformed = transform(nf_square, m_good) - @test nf_transformed isa PolyhedralFan{T} - @test nrays(nf_transformed) == 4 - @test n_maximal_cones(nf_transformed) == 4 - @test_throws ErrorException transform(nf_square, m_bad) - nf_unverified = transform(nf_square, m_good; check=false) - @test nf_unverified isa PolyhedralFan{T} - @test nrays(nf_unverified) == 4 - @test n_maximal_cones(nf_unverified) == 4 +@testset "Transform" for (f, T) in _prepare_scalar_types() + square = cube(f, 2) + nf_square = normal_fan(square) + m_good = matrix(f, [1 0; 0 1]) + m_bad = matrix(f, [1 1]) + nf_transformed = transform(nf_square, m_good) + @test nf_transformed isa PolyhedralFan{T} + @test nrays(nf_transformed) == 4 + @test n_maximal_cones(nf_transformed) == 4 + @test_throws ErrorException transform(nf_square, m_bad) + nf_unverified = transform(nf_square, m_good; check=false) + @test nf_unverified isa PolyhedralFan{T} + @test nrays(nf_unverified) == 4 + @test n_maximal_cones(nf_unverified) == 4 - cdeg = convex_hull(f, [1 0 0; 0 0 0]) - nflin = normal_fan(cdeg) - mm = matrix(f, [1 0 0; 0 1 0; 0 0 1]) - nflin_transformed = transform(nflin, mm) - @test nflin_transformed isa PolyhedralFan{T} - @test nrays(nflin_transformed) == 0 - @test n_maximal_cones(nflin_transformed) == 2 - @test lineality_dim(nflin_transformed) == 2 - end + cdeg = convex_hull(f, [1 0 0; 0 0 0]) + nflin = normal_fan(cdeg) + mm = matrix(f, [1 0 0; 0 1 0; 0 0 1]) + nflin_transformed = transform(nflin, mm) + @test nflin_transformed isa PolyhedralFan{T} + @test nrays(nflin_transformed) == 0 + @test n_maximal_cones(nflin_transformed) == 2 + @test lineality_dim(nflin_transformed) == 2 +end - @testset "Star Subdivision" begin - f = polyhedral_fan([1 0 0; 1 1 0; 1 1 1; 1 0 1], IncidenceMatrix([[1,2,3,4]])) - @test is_pure(f) - @test is_fulldimensional(f) - v0 = [1;0;0] - v1 = [2;1;0] - v2 = [2;1;1] - sf0 = star_subdivision(f, v0) - sf1 = star_subdivision(f, v1) - sf2 = star_subdivision(f, v2) - @test n_maximal_cones(sf0) == 2 - @test n_maximal_cones(sf1) == 3 - @test n_maximal_cones(sf2) == 4 +@testset "Star Subdivision" begin + f = polyhedral_fan([1 0 0; 1 1 0; 1 1 1; 1 0 1], IncidenceMatrix([[1,2,3,4]])) + @test is_pure(f) + @test is_fulldimensional(f) + v0 = [1;0;0] + v1 = [2;1;0] + v2 = [2;1;1] + sf0 = star_subdivision(f, v0) + sf1 = star_subdivision(f, v1) + sf2 = star_subdivision(f, v2) + @test n_maximal_cones(sf0) == 2 + @test n_maximal_cones(sf1) == 3 + @test n_maximal_cones(sf2) == 4 - ff = polyhedral_fan([1 0 0; -1 0 0; 0 1 0], IncidenceMatrix([[1],[2,3]])) - @test !is_pure(ff) - @test !is_fulldimensional(ff) - w0 = [1;0;0] - w1 = [-1;1;0] - sff0 = star_subdivision(ff, w0) - sff1 = star_subdivision(ff, w1) - @test n_maximal_cones(sff0) == 2 - @test n_maximal_cones(sff1) == 3 + ff = polyhedral_fan([1 0 0; -1 0 0; 0 1 0], IncidenceMatrix([[1],[2,3]])) + @test !is_pure(ff) + @test !is_fulldimensional(ff) + w0 = [1;0;0] + w1 = [-1;1;0] + sff0 = star_subdivision(ff, w0) + sff1 = star_subdivision(ff, w1) + @test n_maximal_cones(sff0) == 2 + @test n_maximal_cones(sff1) == 3 - end end diff --git a/test/PolyhedralGeometry/polyhedron.jl b/test/PolyhedralGeometry/polyhedron.jl index 381724888aed..2a684cd9b6b0 100644 --- a/test/PolyhedralGeometry/polyhedron.jl +++ b/test/PolyhedralGeometry/polyhedron.jl @@ -1,590 +1,580 @@ #TODO: include more examples with nontrivial lineality space -NF, sr2 = quadratic_field(2) -ENF, sre2 = Hecke.embedded_field(NF, real_embeddings(NF)[2]) -Qx, x = QQ["x"] -K, (a1, a2) = embedded_number_field([x^2 - 2, x^3 - 5], [(0, 2), (0, 2)]) - -for f in (QQ, ENF) - - T = elem_type(f) - - @testset "Polyhedron{$T}" begin - - pts = [1 0; 0 0; 0 1] - @test convex_hull(f, pts) isa Polyhedron{T} - Q0 = convex_hull(f, pts) - @test convex_hull(f, pts; non_redundant = true) == Q0 - Q1 = convex_hull(f, pts, [1 1]) - Q2 = convex_hull(f, pts, [1 1], [1 1]) - square = cube(f, 2) - CR = cube(f, 2, 0, 3//2) - Pos = polyhedron(f, [-1 0 0; 0 -1 0; 0 0 -1], [0,0,0]) - L = polyhedron(f, [-1 0 0; 0 -1 0], [0,0]) - point = convex_hull(f, [0 1 0]) - # this is to make sure the order of some matrices below doesn't change - Polymake.prefer("beneath_beyond") do - affine_hull(point) - end - s = simplex(f, 2) - R,x = polynomial_ring(QQ, "x") - v = T[f(1), f(1)] - - @testset "core functionality" begin - @test matrix(f, rays(Q1))*v == T[f(2)] - @test matrix(f, vertices(Q1))*v == T[f(1), f(0), f(1)] - @test issubset(Q0, Q1) - @test !issubset(Q1, Q0) - @test [1, 0] in Q0 - @test !([-1, -1] in Q0) - @test nvertices(Q0) == 3 - @test nvertices.(faces(Q0,1)) == [2,2,2] - if T == QQFieldElem - @test lattice_points(Q0) isa SubObjectIterator{PointVector{ZZRingElem}} - @test point_matrix(lattice_points(Q0)) == matrix(ZZ, [0 0; 0 1; 1 0]) - @test matrix(ZZ, lattice_points(Q0)) == matrix(ZZ, [0 0; 0 1; 1 0]) - @test length(lattice_points(Q0)) == 3 - @test lattice_points(Q0) == [[0, 0], [0, 1], [1, 0]] - @test interior_lattice_points(square) isa SubObjectIterator{PointVector{ZZRingElem}} - @test point_matrix(interior_lattice_points(square)) == matrix(ZZ, [0 0]) - @test matrix(ZZ, interior_lattice_points(square)) == matrix(ZZ,[0 0]) - @test length(interior_lattice_points(square)) == 1 - @test interior_lattice_points(square) == [[0, 0]] - @test boundary_lattice_points(square) isa SubObjectIterator{PointVector{ZZRingElem}} - @test point_matrix(boundary_lattice_points(square)) == matrix(ZZ, [-1 -1; -1 0; -1 1; 0 -1; 0 1; 1 -1; 1 0; 1 1]) - @test length(boundary_lattice_points(square)) == 8 - @test boundary_lattice_points(square) == [[-1, -1], [-1, 0], [-1, 1], [0, -1], [0, 1], [1, -1], [1, 0], [1, 1]] - @test is_smooth(Q0) - @test is_normal(Q0) - @test is_lattice_polytope(Q0) - @test is_very_ample(square) - @test is_smooth(square) - @test ehrhart_polynomial(R, square) == 4*x^2 + 4*x + 1 - @test h_star_polynomial(R, CR) == x^4 + 3*x^3 + 10*x^2 + 3*x + 1 - @test is_normal(square) - @test_throws ArgumentError ehrhart_polynomial(CR) - @test_throws ArgumentError is_normal(CR) - @test_throws ArgumentError is_smooth(Q1) - end - @test is_feasible(Q0) - @test is_bounded(Q0) - @test is_fulldimensional(Q0) - @test f_vector(Q0) == [3,3] - @test intersect(Q0, Q0) isa Polyhedron{T} - @test intersect(Q0, Q0) == Q0 - Ps = [Q0,Q0,Q0] - @test intersect(Ps) isa Polyhedron{T} - @test intersect(Ps...) isa Polyhedron{T} - @test intersect(Ps) == Q0 - @test intersect(Ps...) == Q0 - @test minkowski_sum(Q0, Q0) == convex_hull(f, 2 * pts) - @test Q0+Q0 == minkowski_sum(Q0, Q0) - @test f_vector(Pos) == [1,3,3] - @test f_vector(L) == [0, 1, 2] - @test codim(square) == 0 - @test codim(point) == 3 - @test !is_fulldimensional(point) - @test recession_cone(Pos) isa Cone{T} - @test nrays(recession_cone(Pos)) == 3 - @test vertices(PointVector{T}, point) isa SubObjectIterator{PointVector{T}} - @test vertices(PointVector, point) isa SubObjectIterator{PointVector{T}} - @test vertices(point) isa SubObjectIterator{PointVector{T}} - @test point_matrix(vertices(2*point)) == matrix(f, [0 2 0]) - @test point_matrix(vertices([0,1,0] + point)) == matrix(f, [0 2 0]) - @test rays(RayVector{T}, Pos) isa SubObjectIterator{RayVector{T}} - @test rays(RayVector, Pos) isa SubObjectIterator{RayVector{T}} - @test rays(Pos) isa SubObjectIterator{RayVector{T}} - @test length(rays(Pos)) == 3 - if T == QQFieldElem - @test vector_matrix(rays(Pos)) == matrix(QQ, [1 0 0; 0 1 0; 0 0 1]) - @test rays(Pos) == [[1, 0, 0], [0, 1, 0], [0, 0, 1]] - else - @test vector_matrix(rays(Pos)) == matrix(f, [0 1 0; 1 0 0; 0 0 1]) - @test rays(Pos) == [[0, 1, 0], [1, 0, 0], [0, 0, 1]] - end - @test lineality_space(L) isa SubObjectIterator{RayVector{T}} - @test generator_matrix(lineality_space(L)) == matrix(f, [0 0 1]) - if T == QQFieldElem - @test matrix(ZZ, lineality_space(L)) == matrix(ZZ, [0 0 1]) - end - @test length(lineality_space(L)) == 1 - @test lineality_space(L) == [[0, 0, 1]] - @test faces(square, 1) isa SubObjectIterator{Polyhedron{T}} - @test length(faces(square, 1)) == 4 - @test faces(square, 1) == convex_hull.([f], [[-1 -1; -1 1], [1 -1; 1 1], [-1 -1; 1 -1], [-1 1; 1 1]]) - @test vertex_indices(faces(square, 1)) == IncidenceMatrix([[1, 3], [2, 4], [1, 2], [3, 4]]) - @test ray_indices(faces(square, 1)) == IncidenceMatrix(4, 0) - @test vertex_and_ray_indices(faces(square, 1)) == IncidenceMatrix([[1, 3], [2, 4], [1, 2], [3, 4]]) - @test IncidenceMatrix(faces(square, 1)) == IncidenceMatrix([[1, 3], [2, 4], [1, 2], [3, 4]]) - @test faces(IncidenceMatrix, square, 1) == IncidenceMatrix([[1, 3], [2, 4], [1, 2], [3, 4]]) - @test facet_indices(vertices(square)) == IncidenceMatrix([[1, 3],[2, 3],[1, 4],[2, 4]]) - @test IncidenceMatrix(vertices(square)) == IncidenceMatrix([[1, 3], [2, 3], [1, 4], [2, 4]]) - @test vertices(IncidenceMatrix, square) == IncidenceMatrix([[1, 3], [2, 3], [1, 4], [2, 4]]) - @test faces(Pos, 1) isa SubObjectIterator{Polyhedron{T}} - @test length(faces(Pos, 1)) == 3 - if T == QQFieldElem - @test faces(Pos, 1) == convex_hull.(T, [[0 0 0]], [[1 0 0], [0 1 0] , [0 0 1]]) - else - @test faces(Pos, 1) == convex_hull.([f], [[0 0 0]], [[0 1 0], [1 0 0], [0 0 1]]) - end - @test vertex_indices(faces(Pos, 1)) == IncidenceMatrix([[1], [1], [1]]) - @test ray_indices(faces(Pos, 1)) == IncidenceMatrix([[1], [2], [3]]) - @test vertex_and_ray_indices(faces(Pos, 1)) == IncidenceMatrix([[1, 4], [2, 4], [3, 4]]) - @test IncidenceMatrix(faces(Pos, 1)) == IncidenceMatrix([[1, 4], [2, 4], [3, 4]]) - @test faces(IncidenceMatrix, Pos, 1) == IncidenceMatrix([[1, 4], [2, 4], [3, 4]]) - @test isnothing(faces(Q2, 0)) - v = vertices(minkowski_sum(Q0, square)) - @test length(v) == 5 - @test v == [f.([2, -1]), f.([2, 1]), f.([-1, -1]), f.([-1, 2]), f.([1, 2])] - @test point_matrix(v) == matrix(f, [2 -1; 2 1; -1 -1; -1 2; 1 2]) - for S in [AffineHalfspace{T}, - Pair{Matrix{T}, T}, - Polyhedron{T}] - @test facets(S, Pos) isa SubObjectIterator{S} - if S == Pair{Matrix{T}, T} - @test facets(S, Pos) == S.([f.([-1 0 0]), f.([0 -1 0]), f.([0 0 -1])], [f(0)]) - elseif S == AffineHalfspace{T} - @test facets(S, Pos) == affine_halfspace.([f], [[-1 0 0], [0 -1 0], [0 0 -1]], [0]) - end - @test length(facets(S, Pos)) == 3 - @test affine_inequality_matrix(facets(S, Pos)) == matrix(f, [0 -1 0 0; 0 0 -1 0; 0 0 0 -1]) - let hmp = halfspace_matrix_pair(facets(S, Pos)) - @test hmp isa NamedTuple{(:A, :b), Tuple{elem_type(matrix_space(f, 0, 0)), Vector{elem_type(f)}}} - @test hmp.A == matrix(f, [-1 0 0; 0 -1 0; 0 0 -1]) - @test hmp.b == f.([0, 0, 0]) - end - if T == QQFieldElem - @test ray_indices(facets(S, Pos)) == IncidenceMatrix([[2, 3], [1, 3], [1, 2]]) - @test vertex_and_ray_indices(facets(S, Pos)) == IncidenceMatrix([[2, 3, 4], [1, 3, 4], [1, 2, 4]]) - @test IncidenceMatrix(facets(S, Pos)) == IncidenceMatrix([[2, 3, 4], [1, 3, 4], [1, 2, 4]]) - else - @test ray_indices(facets(S, Pos)) == IncidenceMatrix([[1, 3], [2, 3], [1, 2]]) - @test vertex_and_ray_indices(facets(S, Pos)) == IncidenceMatrix([[1, 3, 4], [2, 3, 4], [1, 2, 4]]) - @test IncidenceMatrix(facets(S, Pos)) == IncidenceMatrix([[1, 3, 4], [2, 3, 4], [1, 2, 4]]) - end - @test vertex_indices(facets(S, Pos)) == IncidenceMatrix([[1], [1], [1]]) - end - @test facets(IncidenceMatrix, Pos) == IncidenceMatrix(T == QQFieldElem ? [[2, 3, 4], [1, 3, 4], [1, 2, 4]] : [[1, 3, 4], [2, 3, 4], [1, 2, 4]]) - @test facet_indices(vertices(Pos)) == IncidenceMatrix([[1,2,3]]) - @test IncidenceMatrix(vertices(Pos)) == IncidenceMatrix([[1, 2, 3]]) - @test vertices(IncidenceMatrix, Pos) == IncidenceMatrix([[1, 2, 3]]) - @test facet_indices(rays(Pos)) == ((T==QQFieldElem) ? IncidenceMatrix([[2, 3],[1, 3],[1, 2]]) : IncidenceMatrix([[1, 3],[2, 3],[1, 2]])) - @test IncidenceMatrix(rays(Pos)) == ((T==QQFieldElem) ? IncidenceMatrix([[2, 3],[1, 3],[1, 2]]) : IncidenceMatrix([[1, 3],[2, 3],[1, 2]])) - @test rays(IncidenceMatrix, Pos) == ((T==QQFieldElem) ? IncidenceMatrix([[2, 3],[1, 3],[1, 2]]) : IncidenceMatrix([[1, 3],[2, 3],[1, 2]])) - @test facets(Pair, Pos) isa SubObjectIterator{Pair{Matrix{T}, T}} - @test facets(Pos) isa SubObjectIterator{AffineHalfspace{T}} - @test facets(Halfspace, Pos) isa SubObjectIterator{AffineHalfspace{T}} - @test affine_hull(point) isa SubObjectIterator{AffineHyperplane{T}} - @test affine_equation_matrix(affine_hull(point)) == matrix(f, [0 1 0 0; -1 0 1 0; 0 0 0 1]) - @test Oscar.affine_matrix_for_polymake(affine_hull(point)) == [0 1 0 0; -1 0 1 0; 0 0 0 1] - @test length(affine_hull(point)) == 3 - # TODO: restrict comparison to same scalar? - @test affine_hull(point) == [hyperplane(f, [1 0 0], 0), hyperplane(f, [0 1 0], 1), hyperplane(f, [0 0 1], 0)] - @test nfacets(square) == 4 - @test lineality_dim(Q0) == 0 - @test nrays(Q1) == 1 - @test lineality_dim(Q2) == 1 - @test relative_interior_point(Q0) == [1//3, 1//3] - @test facet_sizes(Q0)[1] == 2 - @test sum(facet_sizes(Q1)) == 6 - @test facet_sizes(Q2)[1] == 1 - @test vertex_sizes(Q0)[1] == 2 - @test vertex_sizes(Q1)[1] == 2 - @test length(vertex_sizes(Q2)) == 0 - - end - - @testset "volume" begin - @test volume(square) isa T - @test normalized_volume(square) isa T - @test volume(square) == 4 - @test normalized_volume(square) == 8 - @test normalized_volume(s) == 1 - end - - @testset "standard_constructions" begin - @test convex_hull(f, pts, nothing, [1 1]) == Q2 - @test polyhedron(f, nothing, ([1 0 0; 0 1 0; 0 0 1], [0, 1, 0])) == point - nc = normal_cone(square, 1) - @test nc isa Cone{T} - @test rays(nc) == [[1, 0], [0, 1]] - let H = linear_halfspace(f, [1, 1, 0]) - @test polyhedron(H) isa Polyhedron{T} - @test polyhedron(H) == polyhedron(f, [1 1 0], 0) - end - let H = affine_halfspace(f, [1, 0, 1], 5) - @test polyhedron(H) isa Polyhedron{T} - @test polyhedron(H) == polyhedron(f, [1 0 1], 5) - end - let H = linear_hyperplane(f, [0, 1, 1]) - @test polyhedron(H) isa Polyhedron{T} - @test polyhedron(H) == polyhedron(f, (Polymake.Matrix{Polymake.Rational}(undef, 0, 3), Polymake.Rational[]), ([0 1 1], 0)) - end - let H = affine_hyperplane(f, [1, 1, 1], 7) - @test polyhedron(H) isa Polyhedron{T} - @test polyhedron(H) == polyhedron(f, (Polymake.Matrix{Polymake.Rational}(undef, 0, 3), Polymake.Rational[]), ([1 1 1], 7)) - end - if T == QQFieldElem - @test upper_bound_f_vector(4,8) == [8, 28, 40, 20] - @test upper_bound_g_vector(4,8) == [1, 3, 6] - @test upper_bound_h_vector(4,8) == [1, 4, 10, 4 ,1] - A = archimedean_solid("cuboctahedron") - @test count(F -> nvertices(F) == 3, faces(A, 2)) == 8 - # due to GLIBCXX issues with the outdated julia-shipped libstdc++ - # we run this only where recent CompilerSupportLibraries are available - if VERSION >= v"1.6" - C = catalan_solid("triakis_tetrahedron") - @test count(F -> nvertices(F) == 3, faces(C, 2)) == 12 - end - @test polyhedron(facets(A)) == A - b1 = birkhoff_polytope(3) - b2 = birkhoff_polytope(3, even = true) - @test nvertices(pyramid(b1)) + 1 == nvertices(bipyramid(b1)) - @test nvertices(b1) == nvertices(b2) * 2 - - GT = gelfand_tsetlin_polytope([3,2,1]) - @test ambient_dim(GT) == 6 - pGT = project_full(GT) - @test pGT isa Polyhedron{T} - @test volume(pGT) == 1 - - rsph = rand_spherical_polytope(3, 15) - @test rsph isa Polyhedron{T} - @test is_simplicial(rsph) - @test nvertices(rsph) == 15 - - rsph_r = rand_spherical_polytope(3, 10; distribution=:exact) - @test map(x->dot(x,x), vertices(rsph_r)) == ones(QQFieldElem,10) - @test is_simplicial(rsph_r) - @test nvertices(rsph_r) == 10 - - prec = 20 - rsph_prec = rand_spherical_polytope(3, 20; precision=prec) - @test rsph_prec isa Polyhedron{T} - @test is_simplicial(rsph_prec) - @test nvertices(rsph_prec) == 20 - @test all(map(v->abs(dot(v,v)-1), vertices(rsph_prec)) .< QQFieldElem(2)^-(prec-1)) - - @test_throws ArgumentError SIM_body_polytope([]) - @test_throws ArgumentError SIM_body_polytope([1,2,3]) - let sim = SIM_body_polytope([3,2,1]) - @test sim isa Polyhedron{T} - @test size(Oscar.pm_object(sim).INEQUALITIES,1) == 16 - end - - let a = associahedron(4) - @test a isa Polyhedron{T} - @test dim(a) == 4 - @test nfacets(a) == 14 - end - - let bmg = binary_markov_graph_polytope([0,1,0,0,1]) - @test bmg isa Polyhedron{T} - @test ambient_dim(bmg) == 2 - adj = Oscar.pm_object(bmg).SUM_PRODUCT_GRAPH.ADJACENCY - @test Polymake.nv(adj) == 12 - end - - @test_throws ArgumentError dwarfed_cube(1) - let dc = dwarfed_cube(3) - @test dc isa Polyhedron{T} - @test dim(dc) == 3 - @test nfacets(dc) == 7 - end - - @test_throws ArgumentError dwarfed_product_polygons(3,2) - @test_throws ArgumentError dwarfed_product_polygons(4,2) - let dpp = dwarfed_product_polygons(4,5) - @test dpp isa Polyhedron{T} - @test is_bounded(dpp) - end - - @test_throws ArgumentError lecture_hall_simplex(-1) - let lhs = lecture_hall_simplex(4) - @test lhs isa Polyhedron{T} - @test is_bounded(lhs) - @test nvertices(lhs) == 5 - end - - let ez = explicit_zonotope([1 2 3; 4 5 6]) - @test ez isa Polyhedron{T} - @test size(Oscar.pm_object(ez).POINTS,1) == 4 - end - - @test_throws ArgumentError cyclic_caratheodory_polytope(1,1) - @test_throws ArgumentError cyclic_caratheodory_polytope(2,1) - let ccp = cyclic_caratheodory_polytope(2,3) - @test ccp isa Polyhedron{T} - @test is_bounded(ccp) - @test nvertices(ccp) == 3 - end - - let fkp = fractional_knapsack_polytope([-1, -1, 2]) - @test fkp isa Polyhedron{T} - @test is_bounded(fkp) - @test size(Oscar.pm_object(fkp).INEQUALITIES,1) == 4 - end - - @test_throws ArgumentError hypersimplex(5,3) - let hs = hypersimplex(3,5) - @test hs isa Polyhedron{T} - @test is_bounded(hs) - @test nvertices(hs) == 10 - @test length(facets(hs)) == 10 - end - - @test zonotope([0 0 1; 2 2 2; 1 0 2]) isa Polyhedron{T} - - @test_throws ArgumentError goldfarb_cube(0,0,0) - @test_throws ArgumentError goldfarb_cube(3,1,0) - @test_throws ArgumentError goldfarb_cube(3,1//4,1//8) - let goldfarb = goldfarb_cube(3,1//4,0) # fuer zuweisungen - @test goldfarb isa Polyhedron{T} - @test ambient_dim(goldfarb) == 3 - @test size(Oscar.pm_object(goldfarb).INEQUALITIES,1) == 7 #nur falls oscar danach nicht fragen kann - end - - @test_throws ArgumentError goldfarb_sit_cube(0,0,0) - @test_throws ArgumentError goldfarb_sit_cube(3,1,0) - @test_throws ArgumentError goldfarb_sit_cube(3,1//4,5//8) - let gsc = goldfarb_sit_cube(3,1//4,0) - @test gsc isa Polyhedron{T} - @test ambient_dim(gsc) == 3 - @test size(Oscar.pm_object(gsc).INEQUALITIES,1) == 7 - end - - @test_throws ArgumentError hypertruncated_cube(3,5,0) - let htc = hypertruncated_cube(3,3//2, 3//4) - @test htc isa Polyhedron{T} - @test is_bounded(htc) - @test size(Oscar.pm_object(htc).INEQUALITIES,1) == 13 - end - - let kcp = k_cyclic_polytope(8,[1,2]) - @test kcp isa Polyhedron{T} - @test nvertices(kcp) == 8 - end - - @test_throws ArgumentError klee_minty_cube(0,0) - @test_throws ArgumentError klee_minty_cube(3,1) - let kmc = klee_minty_cube(4,1//32) - @test kmc isa Polyhedron{T} - @test is_bounded(kmc) - @test size(Oscar.pm_object(kmc).INEQUALITIES,1) == 9 - end - - @test_throws ArgumentError max_GC_rank_polytope(1) - @test_throws ArgumentError max_GC_rank_polytope(100000) - let gc = max_GC_rank_polytope(4) - @test gc isa Polyhedron{T} - @test ambient_dim(gc) == 4 - @test is_bounded(gc) - end - - @test_throws ArgumentError n_gon(2) - let gon = n_gon(4,r=2) - @test gon isa Polyhedron{T} - @test length(vertices(gon)[1]) == 2 - @test nvertices(gon) == 4 - end - - @test_throws ArgumentError permutahedron(-1) - let perm = permutahedron(3) - @test perm isa Polyhedron{T} - @test length(vertices(perm)[1])==4 - @test dim(perm) == 3 - end - - let pile = pile_polytope([2,2]) - @test pile isa Polyhedron{T} - @test ambient_dim(pile) == 3 - @test nvertices(pile) == 9 - end - - @test_throws ArgumentError pitman_stanley_polytope(Vector{Rational}([])) - let psp = pitman_stanley_polytope([2,4,2]) - @test psp isa Polyhedron{T} - @test ambient_dim(psp) == 3 - @test size(Oscar.pm_object(psp).INEQUALITIES,1) == 6 - end - - @test_throws ArgumentError pseudo_del_pezzo_polytope(0) - let pdp = pseudo_del_pezzo_polytope(2) - @test pdp isa Polyhedron{T} - @test is_bounded(pdp) - @test dim(pdp) == 2 - end - - @test_throws ArgumentError rand01_polytope(1,1) - @test rand01_polytope(2,4) isa Polyhedron{T} - let r_01_p = rand01_polytope(2,4; seed = 47) - @test r_01_p isa Polyhedron{T} - @test nvertices(r_01_p) == 4 - end - - @test_throws ArgumentError rand_box_polytope(1,0,1) - let rbox = rand_box_polytope(3,8,1) - @test rbox isa Polyhedron{T} - @test ambient_dim(rbox) == 3 - @test size(Oscar.pm_object(rbox).POINTS,1) == 8 - end - let rbox = rand_box_polytope(3,4,1; seed = 456) - @test rbox isa Polyhedron{T} - @test sum(Oscar.pm_object(rbox).POINTS)==6 - end - - let rmetric = rand_metric(3, seed = 213) - @test rmetric isa QQMatrix - end - - let rmetricint = rand_metric_int(3, 2, seed = 213) - @test rmetricint isa ZZMatrix - end - - let rnorm = rand_normal_polytope(3, 4, seed = 213) - @test rnorm isa Polyhedron{T} - @test isbounded(rnorm) - @test size(Oscar.pm_object(rnorm).POINTS, 1) == 4 - end - - @test_throws ArgumentError rand_cyclic_polytope(2,3) - @test rand_cyclic_polytope(2,4) isa Polyhedron{T} - let rcyc = p = rand_cyclic_polytope(3,8, seed = 4) - @test rcyc isa Polyhedron{T} - @test nvertices(rcyc) == 8 - end - - #3 more rand testset - - @test_throws ArgumentError rss_associahedron(1) - let rss = rss_associahedron(3) - @test rss isa Polyhedron{T} - @test typeof(facets(rss)[1]) == AffineHalfspace{T} - @test ambient_dim(rss) == 3 - end - - @test_throws ArgumentError signed_permutahedron(0) - @test_throws ArgumentError signed_permutahedron(100000) - let sph = signed_permutahedron(3) - @test sph isa Polyhedron{T} - @test nvertices(sph) == 48 - @test is_bounded(sph) - end - - let G = complete_graph(3) - ssp = stable_set_polytope(G) - @test ssp isa Polyhedron{T} - @test is_bounded(ssp) - @test size(Oscar.pm_object(ssp).INEQUALITIES,1) == 7 - end - - @test_throws ArgumentError transportation_polytope([2,3,1],[4,5,3]) - let tp = transportation_polytope([2,3,1],[4,0,2]) - @test tp isa Polyhedron{T} - @test ambient_dim(tp) == 9 - @test size(Oscar.pm_object(tp).EQUATIONS,1) == 6 - end - - @test sum(zonotope_vertices_fukuda_matrix([4 4 2; 2 4 1])) == 0 - - @test_throws ArgumentError vertex_figure(cube(3),10) - let vf = vertex_figure(platonic_solid("octahedron"),1) - @test vf isa Polyhedron{T} - @test ambient_dim(vf) == 3 - @test sum(facet_sizes(vf)) == 8 - end - end +@testset "Polyhedron{$T}" for (f, T) in _prepare_scalar_types() + + pts = [1 0; 0 0; 0 1] + @test convex_hull(f, pts) isa Polyhedron{T} + Q0 = convex_hull(f, pts) + @test convex_hull(f, pts; non_redundant = true) == Q0 + Q1 = convex_hull(f, pts, [1 1]) + Q2 = convex_hull(f, pts, [1 1], [1 1]) + square = cube(f, 2) + CR = cube(f, 2, 0, 3//2) + Pos = polyhedron(f, [-1 0 0; 0 -1 0; 0 0 -1], [0,0,0]) + L = polyhedron(f, [-1 0 0; 0 -1 0], [0,0]) + point = convex_hull(f, [0 1 0]) + # this is to make sure the order of some matrices below doesn't change + Polymake.prefer("beneath_beyond") do + affine_hull(point) + end + s = simplex(f, 2) + R,x = polynomial_ring(QQ, "x") + v = T[f(1), f(1)] + + @testset "core functionality" begin + @test matrix(f, rays(Q1))*v == T[f(2)] + @test matrix(f, vertices(Q1))*v == T[f(1), f(0), f(1)] + @test issubset(Q0, Q1) + @test !issubset(Q1, Q0) + @test [1, 0] in Q0 + @test !([-1, -1] in Q0) + @test nvertices(Q0) == 3 + @test nvertices.(faces(Q0,1)) == [2,2,2] + if T == QQFieldElem + @test lattice_points(Q0) isa SubObjectIterator{PointVector{ZZRingElem}} + @test point_matrix(lattice_points(Q0)) == matrix(ZZ, [0 0; 0 1; 1 0]) + @test matrix(ZZ, lattice_points(Q0)) == matrix(ZZ, [0 0; 0 1; 1 0]) + @test length(lattice_points(Q0)) == 3 + @test lattice_points(Q0) == [[0, 0], [0, 1], [1, 0]] + @test interior_lattice_points(square) isa SubObjectIterator{PointVector{ZZRingElem}} + @test point_matrix(interior_lattice_points(square)) == matrix(ZZ, [0 0]) + @test matrix(ZZ, interior_lattice_points(square)) == matrix(ZZ,[0 0]) + @test length(interior_lattice_points(square)) == 1 + @test interior_lattice_points(square) == [[0, 0]] + @test boundary_lattice_points(square) isa SubObjectIterator{PointVector{ZZRingElem}} + @test point_matrix(boundary_lattice_points(square)) == matrix(ZZ, [-1 -1; -1 0; -1 1; 0 -1; 0 1; 1 -1; 1 0; 1 1]) + @test length(boundary_lattice_points(square)) == 8 + @test boundary_lattice_points(square) == [[-1, -1], [-1, 0], [-1, 1], [0, -1], [0, 1], [1, -1], [1, 0], [1, 1]] + @test is_smooth(Q0) + @test is_normal(Q0) + @test is_lattice_polytope(Q0) + @test is_very_ample(square) + @test is_smooth(square) + @test ehrhart_polynomial(R, square) == 4*x^2 + 4*x + 1 + @test h_star_polynomial(R, CR) == x^4 + 3*x^3 + 10*x^2 + 3*x + 1 + @test is_normal(square) + @test_throws ArgumentError ehrhart_polynomial(CR) + @test_throws ArgumentError is_normal(CR) + @test_throws ArgumentError is_smooth(Q1) + end + @test is_feasible(Q0) + @test is_bounded(Q0) + @test is_fulldimensional(Q0) + @test f_vector(Q0) == [3,3] + @test intersect(Q0, Q0) isa Polyhedron{T} + @test intersect(Q0, Q0) == Q0 + Ps = [Q0,Q0,Q0] + @test intersect(Ps) isa Polyhedron{T} + @test intersect(Ps...) isa Polyhedron{T} + @test intersect(Ps) == Q0 + @test intersect(Ps...) == Q0 + @test minkowski_sum(Q0, Q0) == convex_hull(f, 2 * pts) + @test Q0+Q0 == minkowski_sum(Q0, Q0) + @test f_vector(Pos) == [1,3,3] + @test f_vector(L) == [0, 1, 2] + @test codim(square) == 0 + @test codim(point) == 3 + @test !is_fulldimensional(point) + @test recession_cone(Pos) isa Cone{T} + @test nrays(recession_cone(Pos)) == 3 + @test vertices(PointVector{T}, point) isa SubObjectIterator{PointVector{T}} + @test vertices(PointVector, point) isa SubObjectIterator{PointVector{T}} + @test vertices(point) isa SubObjectIterator{PointVector{T}} + @test point_matrix(vertices(2*point)) == matrix(f, [0 2 0]) + @test point_matrix(vertices([0,1,0] + point)) == matrix(f, [0 2 0]) + @test rays(RayVector{T}, Pos) isa SubObjectIterator{RayVector{T}} + @test rays(RayVector, Pos) isa SubObjectIterator{RayVector{T}} + @test rays(Pos) isa SubObjectIterator{RayVector{T}} + @test length(rays(Pos)) == 3 + if T == QQFieldElem + @test vector_matrix(rays(Pos)) == matrix(QQ, [1 0 0; 0 1 0; 0 0 1]) + @test rays(Pos) == [[1, 0, 0], [0, 1, 0], [0, 0, 1]] + else + @test vector_matrix(rays(Pos)) == matrix(f, [0 1 0; 1 0 0; 0 0 1]) + @test rays(Pos) == [[0, 1, 0], [1, 0, 0], [0, 0, 1]] + end + @test lineality_space(L) isa SubObjectIterator{RayVector{T}} + @test generator_matrix(lineality_space(L)) == matrix(f, [0 0 1]) + if T == QQFieldElem + @test matrix(ZZ, lineality_space(L)) == matrix(ZZ, [0 0 1]) + end + @test length(lineality_space(L)) == 1 + @test lineality_space(L) == [[0, 0, 1]] + @test faces(square, 1) isa SubObjectIterator{Polyhedron{T}} + @test length(faces(square, 1)) == 4 + @test faces(square, 1) == convex_hull.([f], [[-1 -1; -1 1], [1 -1; 1 1], [-1 -1; 1 -1], [-1 1; 1 1]]) + @test vertex_indices(faces(square, 1)) == IncidenceMatrix([[1, 3], [2, 4], [1, 2], [3, 4]]) + @test ray_indices(faces(square, 1)) == IncidenceMatrix(4, 0) + @test vertex_and_ray_indices(faces(square, 1)) == IncidenceMatrix([[1, 3], [2, 4], [1, 2], [3, 4]]) + @test IncidenceMatrix(faces(square, 1)) == IncidenceMatrix([[1, 3], [2, 4], [1, 2], [3, 4]]) + @test faces(IncidenceMatrix, square, 1) == IncidenceMatrix([[1, 3], [2, 4], [1, 2], [3, 4]]) + @test facet_indices(vertices(square)) == IncidenceMatrix([[1, 3],[2, 3],[1, 4],[2, 4]]) + @test IncidenceMatrix(vertices(square)) == IncidenceMatrix([[1, 3], [2, 3], [1, 4], [2, 4]]) + @test vertices(IncidenceMatrix, square) == IncidenceMatrix([[1, 3], [2, 3], [1, 4], [2, 4]]) + @test faces(Pos, 1) isa SubObjectIterator{Polyhedron{T}} + @test length(faces(Pos, 1)) == 3 + if T == QQFieldElem + @test faces(Pos, 1) == convex_hull.(T, [[0 0 0]], [[1 0 0], [0 1 0] , [0 0 1]]) + else + @test faces(Pos, 1) == convex_hull.([f], [[0 0 0]], [[0 1 0], [1 0 0], [0 0 1]]) + end + @test vertex_indices(faces(Pos, 1)) == IncidenceMatrix([[1], [1], [1]]) + @test ray_indices(faces(Pos, 1)) == IncidenceMatrix([[1], [2], [3]]) + @test vertex_and_ray_indices(faces(Pos, 1)) == IncidenceMatrix([[1, 4], [2, 4], [3, 4]]) + @test IncidenceMatrix(faces(Pos, 1)) == IncidenceMatrix([[1, 4], [2, 4], [3, 4]]) + @test faces(IncidenceMatrix, Pos, 1) == IncidenceMatrix([[1, 4], [2, 4], [3, 4]]) + @test isnothing(faces(Q2, 0)) + v = vertices(minkowski_sum(Q0, square)) + @test length(v) == 5 + @test v == [f.([2, -1]), f.([2, 1]), f.([-1, -1]), f.([-1, 2]), f.([1, 2])] + @test point_matrix(v) == matrix(f, [2 -1; 2 1; -1 -1; -1 2; 1 2]) + for S in [AffineHalfspace{T}, + Pair{Matrix{T}, T}, + Polyhedron{T}] + @test facets(S, Pos) isa SubObjectIterator{S} + if S == Pair{Matrix{T}, T} + @test facets(S, Pos) == S.([f.([-1 0 0]), f.([0 -1 0]), f.([0 0 -1])], [f(0)]) + elseif S == AffineHalfspace{T} + @test facets(S, Pos) == affine_halfspace.([f], [[-1 0 0], [0 -1 0], [0 0 -1]], [0]) + end + @test length(facets(S, Pos)) == 3 + @test affine_inequality_matrix(facets(S, Pos)) == matrix(f, [0 -1 0 0; 0 0 -1 0; 0 0 0 -1]) + let hmp = halfspace_matrix_pair(facets(S, Pos)) + @test hmp isa NamedTuple{(:A, :b), Tuple{elem_type(matrix_space(f, 0, 0)), Vector{elem_type(f)}}} + @test hmp.A == matrix(f, [-1 0 0; 0 -1 0; 0 0 -1]) + @test hmp.b == f.([0, 0, 0]) + end + if T == QQFieldElem + @test ray_indices(facets(S, Pos)) == IncidenceMatrix([[2, 3], [1, 3], [1, 2]]) + @test vertex_and_ray_indices(facets(S, Pos)) == IncidenceMatrix([[2, 3, 4], [1, 3, 4], [1, 2, 4]]) + @test IncidenceMatrix(facets(S, Pos)) == IncidenceMatrix([[2, 3, 4], [1, 3, 4], [1, 2, 4]]) + else + @test ray_indices(facets(S, Pos)) == IncidenceMatrix([[1, 3], [2, 3], [1, 2]]) + @test vertex_and_ray_indices(facets(S, Pos)) == IncidenceMatrix([[1, 3, 4], [2, 3, 4], [1, 2, 4]]) + @test IncidenceMatrix(facets(S, Pos)) == IncidenceMatrix([[1, 3, 4], [2, 3, 4], [1, 2, 4]]) + end + @test vertex_indices(facets(S, Pos)) == IncidenceMatrix([[1], [1], [1]]) + end + @test facets(IncidenceMatrix, Pos) == IncidenceMatrix(T == QQFieldElem ? [[2, 3, 4], [1, 3, 4], [1, 2, 4]] : [[1, 3, 4], [2, 3, 4], [1, 2, 4]]) + @test facet_indices(vertices(Pos)) == IncidenceMatrix([[1,2,3]]) + @test IncidenceMatrix(vertices(Pos)) == IncidenceMatrix([[1, 2, 3]]) + @test vertices(IncidenceMatrix, Pos) == IncidenceMatrix([[1, 2, 3]]) + @test facet_indices(rays(Pos)) == ((T==QQFieldElem) ? IncidenceMatrix([[2, 3],[1, 3],[1, 2]]) : IncidenceMatrix([[1, 3],[2, 3],[1, 2]])) + @test IncidenceMatrix(rays(Pos)) == ((T==QQFieldElem) ? IncidenceMatrix([[2, 3],[1, 3],[1, 2]]) : IncidenceMatrix([[1, 3],[2, 3],[1, 2]])) + @test rays(IncidenceMatrix, Pos) == ((T==QQFieldElem) ? IncidenceMatrix([[2, 3],[1, 3],[1, 2]]) : IncidenceMatrix([[1, 3],[2, 3],[1, 2]])) + @test facets(Pair, Pos) isa SubObjectIterator{Pair{Matrix{T}, T}} + @test facets(Pos) isa SubObjectIterator{AffineHalfspace{T}} + @test facets(Halfspace, Pos) isa SubObjectIterator{AffineHalfspace{T}} + @test affine_hull(point) isa SubObjectIterator{AffineHyperplane{T}} + @test affine_equation_matrix(affine_hull(point)) == matrix(f, [0 1 0 0; -1 0 1 0; 0 0 0 1]) + @test Oscar.affine_matrix_for_polymake(affine_hull(point)) == [0 1 0 0; -1 0 1 0; 0 0 0 1] + @test length(affine_hull(point)) == 3 + # TODO: restrict comparison to same scalar? + @test affine_hull(point) == [hyperplane(f, [1 0 0], 0), hyperplane(f, [0 1 0], 1), hyperplane(f, [0 0 1], 0)] + @test nfacets(square) == 4 + @test lineality_dim(Q0) == 0 + @test nrays(Q1) == 1 + @test lineality_dim(Q2) == 1 + @test relative_interior_point(Q0) == [1//3, 1//3] + @test facet_sizes(Q0)[1] == 2 + @test sum(facet_sizes(Q1)) == 6 + @test facet_sizes(Q2)[1] == 1 + @test vertex_sizes(Q0)[1] == 2 + @test vertex_sizes(Q1)[1] == 2 + @test length(vertex_sizes(Q2)) == 0 + + end + + @testset "volume" begin + @test volume(square) isa T + @test normalized_volume(square) isa T + @test volume(square) == 4 + @test normalized_volume(square) == 8 + @test normalized_volume(s) == 1 + end + + @testset "standard_constructions" begin + @test convex_hull(f, pts, nothing, [1 1]) == Q2 + @test polyhedron(f, nothing, ([1 0 0; 0 1 0; 0 0 1], [0, 1, 0])) == point + nc = normal_cone(square, 1) + @test nc isa Cone{T} + @test rays(nc) == [[1, 0], [0, 1]] + let H = linear_halfspace(f, [1, 1, 0]) + @test polyhedron(H) isa Polyhedron{T} + @test polyhedron(H) == polyhedron(f, [1 1 0], 0) + end + let H = affine_halfspace(f, [1, 0, 1], 5) + @test polyhedron(H) isa Polyhedron{T} + @test polyhedron(H) == polyhedron(f, [1 0 1], 5) + end + let H = linear_hyperplane(f, [0, 1, 1]) + @test polyhedron(H) isa Polyhedron{T} + @test polyhedron(H) == polyhedron(f, (Polymake.Matrix{Polymake.Rational}(undef, 0, 3), Polymake.Rational[]), ([0 1 1], 0)) + end + let H = affine_hyperplane(f, [1, 1, 1], 7) + @test polyhedron(H) isa Polyhedron{T} + @test polyhedron(H) == polyhedron(f, (Polymake.Matrix{Polymake.Rational}(undef, 0, 3), Polymake.Rational[]), ([1 1 1], 7)) + end + if T == QQFieldElem + @test upper_bound_f_vector(4,8) == [8, 28, 40, 20] + @test upper_bound_g_vector(4,8) == [1, 3, 6] + @test upper_bound_h_vector(4,8) == [1, 4, 10, 4 ,1] + A = archimedean_solid("cuboctahedron") + @test count(F -> nvertices(F) == 3, faces(A, 2)) == 8 + # due to GLIBCXX issues with the outdated julia-shipped libstdc++ + # we run this only where recent CompilerSupportLibraries are available + if VERSION >= v"1.6" + C = catalan_solid("triakis_tetrahedron") + @test count(F -> nvertices(F) == 3, faces(C, 2)) == 12 + end + @test polyhedron(facets(A)) == A + b1 = birkhoff_polytope(3) + b2 = birkhoff_polytope(3, even = true) + @test nvertices(pyramid(b1)) + 1 == nvertices(bipyramid(b1)) + @test nvertices(b1) == nvertices(b2) * 2 + + GT = gelfand_tsetlin_polytope([3,2,1]) + @test ambient_dim(GT) == 6 + pGT = project_full(GT) + @test pGT isa Polyhedron{T} + @test volume(pGT) == 1 + + rsph = rand_spherical_polytope(3, 15) + @test rsph isa Polyhedron{T} + @test is_simplicial(rsph) + @test nvertices(rsph) == 15 + + rsph_r = rand_spherical_polytope(3, 10; distribution=:exact) + @test map(x->dot(x,x), vertices(rsph_r)) == ones(QQFieldElem,10) + @test is_simplicial(rsph_r) + @test nvertices(rsph_r) == 10 + + prec = 20 + rsph_prec = rand_spherical_polytope(3, 20; precision=prec) + @test rsph_prec isa Polyhedron{T} + @test is_simplicial(rsph_prec) + @test nvertices(rsph_prec) == 20 + @test all(map(v->abs(dot(v,v)-1), vertices(rsph_prec)) .< QQFieldElem(2)^-(prec-1)) + + @test_throws ArgumentError SIM_body_polytope([]) + @test_throws ArgumentError SIM_body_polytope([1,2,3]) + let sim = SIM_body_polytope([3,2,1]) + @test sim isa Polyhedron{T} + @test size(Oscar.pm_object(sim).INEQUALITIES,1) == 16 + end + + let a = associahedron(4) + @test a isa Polyhedron{T} + @test dim(a) == 4 + @test nfacets(a) == 14 + end + + let bmg = binary_markov_graph_polytope([0,1,0,0,1]) + @test bmg isa Polyhedron{T} + @test ambient_dim(bmg) == 2 + adj = Oscar.pm_object(bmg).SUM_PRODUCT_GRAPH.ADJACENCY + @test Polymake.nv(adj) == 12 + end + + @test_throws ArgumentError dwarfed_cube(1) + let dc = dwarfed_cube(3) + @test dc isa Polyhedron{T} + @test dim(dc) == 3 + @test nfacets(dc) == 7 + end + + @test_throws ArgumentError dwarfed_product_polygons(3,2) + @test_throws ArgumentError dwarfed_product_polygons(4,2) + let dpp = dwarfed_product_polygons(4,5) + @test dpp isa Polyhedron{T} + @test is_bounded(dpp) + end + + @test_throws ArgumentError lecture_hall_simplex(-1) + let lhs = lecture_hall_simplex(4) + @test lhs isa Polyhedron{T} + @test is_bounded(lhs) + @test nvertices(lhs) == 5 + end + + let ez = explicit_zonotope([1 2 3; 4 5 6]) + @test ez isa Polyhedron{T} + @test size(Oscar.pm_object(ez).POINTS,1) == 4 + end + + @test_throws ArgumentError cyclic_caratheodory_polytope(1,1) + @test_throws ArgumentError cyclic_caratheodory_polytope(2,1) + let ccp = cyclic_caratheodory_polytope(2,3) + @test ccp isa Polyhedron{T} + @test is_bounded(ccp) + @test nvertices(ccp) == 3 + end + + let fkp = fractional_knapsack_polytope([-1, -1, 2]) + @test fkp isa Polyhedron{T} + @test is_bounded(fkp) + @test size(Oscar.pm_object(fkp).INEQUALITIES,1) == 4 + end + + @test_throws ArgumentError hypersimplex(5,3) + let hs = hypersimplex(3,5) + @test hs isa Polyhedron{T} + @test is_bounded(hs) + @test nvertices(hs) == 10 + @test length(facets(hs)) == 10 + end + + @test zonotope([0 0 1; 2 2 2; 1 0 2]) isa Polyhedron{T} + + @test_throws ArgumentError goldfarb_cube(0,0,0) + @test_throws ArgumentError goldfarb_cube(3,1,0) + @test_throws ArgumentError goldfarb_cube(3,1//4,1//8) + let goldfarb = goldfarb_cube(3,1//4,0) # fuer zuweisungen + @test goldfarb isa Polyhedron{T} + @test ambient_dim(goldfarb) == 3 + @test size(Oscar.pm_object(goldfarb).INEQUALITIES,1) == 7 #nur falls oscar danach nicht fragen kann + end + + @test_throws ArgumentError goldfarb_sit_cube(0,0,0) + @test_throws ArgumentError goldfarb_sit_cube(3,1,0) + @test_throws ArgumentError goldfarb_sit_cube(3,1//4,5//8) + let gsc = goldfarb_sit_cube(3,1//4,0) + @test gsc isa Polyhedron{T} + @test ambient_dim(gsc) == 3 + @test size(Oscar.pm_object(gsc).INEQUALITIES,1) == 7 + end + + @test_throws ArgumentError hypertruncated_cube(3,5,0) + let htc = hypertruncated_cube(3,3//2, 3//4) + @test htc isa Polyhedron{T} + @test is_bounded(htc) + @test size(Oscar.pm_object(htc).INEQUALITIES,1) == 13 + end + + let kcp = k_cyclic_polytope(8,[1,2]) + @test kcp isa Polyhedron{T} + @test nvertices(kcp) == 8 + end + + @test_throws ArgumentError klee_minty_cube(0,0) + @test_throws ArgumentError klee_minty_cube(3,1) + let kmc = klee_minty_cube(4,1//32) + @test kmc isa Polyhedron{T} + @test is_bounded(kmc) + @test size(Oscar.pm_object(kmc).INEQUALITIES,1) == 9 + end + + @test_throws ArgumentError max_GC_rank_polytope(1) + @test_throws ArgumentError max_GC_rank_polytope(100000) + let gc = max_GC_rank_polytope(4) + @test gc isa Polyhedron{T} + @test ambient_dim(gc) == 4 + @test is_bounded(gc) + end + + @test_throws ArgumentError n_gon(2) + let gon = n_gon(4,r=2) + @test gon isa Polyhedron{T} + @test length(vertices(gon)[1]) == 2 + @test nvertices(gon) == 4 + end + + @test_throws ArgumentError permutahedron(-1) + let perm = permutahedron(3) + @test perm isa Polyhedron{T} + @test length(vertices(perm)[1])==4 + @test dim(perm) == 3 + end + + let pile = pile_polytope([2,2]) + @test pile isa Polyhedron{T} + @test ambient_dim(pile) == 3 + @test nvertices(pile) == 9 + end + + @test_throws ArgumentError pitman_stanley_polytope(Vector{Rational}([])) + let psp = pitman_stanley_polytope([2,4,2]) + @test psp isa Polyhedron{T} + @test ambient_dim(psp) == 3 + @test size(Oscar.pm_object(psp).INEQUALITIES,1) == 6 + end + + @test_throws ArgumentError pseudo_del_pezzo_polytope(0) + let pdp = pseudo_del_pezzo_polytope(2) + @test pdp isa Polyhedron{T} + @test is_bounded(pdp) + @test dim(pdp) == 2 + end + + @test_throws ArgumentError rand01_polytope(1,1) + @test rand01_polytope(2,4) isa Polyhedron{T} + let r_01_p = rand01_polytope(2,4; seed = 47) + @test r_01_p isa Polyhedron{T} + @test nvertices(r_01_p) == 4 + end + + @test_throws ArgumentError rand_box_polytope(1,0,1) + let rbox = rand_box_polytope(3,8,1) + @test rbox isa Polyhedron{T} + @test ambient_dim(rbox) == 3 + @test size(Oscar.pm_object(rbox).POINTS,1) == 8 + end + let rbox = rand_box_polytope(3,4,1; seed = 456) + @test rbox isa Polyhedron{T} + @test sum(Oscar.pm_object(rbox).POINTS)==6 + end + + let rmetric = rand_metric(3, seed = 213) + @test rmetric isa QQMatrix + end + + let rmetricint = rand_metric_int(3, 2, seed = 213) + @test rmetricint isa ZZMatrix + end + + let rnorm = rand_normal_polytope(3, 4, seed = 213) + @test rnorm isa Polyhedron{T} + @test isbounded(rnorm) + @test size(Oscar.pm_object(rnorm).POINTS, 1) == 4 + end + + @test_throws ArgumentError rand_cyclic_polytope(2,3) + @test rand_cyclic_polytope(2,4) isa Polyhedron{T} + let rcyc = p = rand_cyclic_polytope(3,8, seed = 4) + @test rcyc isa Polyhedron{T} + @test nvertices(rcyc) == 8 + end + + #3 more rand testset + + @test_throws ArgumentError rss_associahedron(1) + let rss = rss_associahedron(3) + @test rss isa Polyhedron{T} + @test typeof(facets(rss)[1]) == AffineHalfspace{T} + @test ambient_dim(rss) == 3 + end + + @test_throws ArgumentError signed_permutahedron(0) + @test_throws ArgumentError signed_permutahedron(100000) + let sph = signed_permutahedron(3) + @test sph isa Polyhedron{T} + @test nvertices(sph) == 48 + @test is_bounded(sph) + end + + let G = complete_graph(3) + ssp = stable_set_polytope(G) + @test ssp isa Polyhedron{T} + @test is_bounded(ssp) + @test size(Oscar.pm_object(ssp).INEQUALITIES,1) == 7 + end + + @test_throws ArgumentError transportation_polytope([2,3,1],[4,5,3]) + let tp = transportation_polytope([2,3,1],[4,0,2]) + @test tp isa Polyhedron{T} + @test ambient_dim(tp) == 9 + @test size(Oscar.pm_object(tp).EQUATIONS,1) == 6 + end + + @test sum(zonotope_vertices_fukuda_matrix([4 4 2; 2 4 1])) == 0 + + @test_throws ArgumentError vertex_figure(cube(3),10) + let vf = vertex_figure(platonic_solid("octahedron"),1) + @test vf isa Polyhedron{T} + @test ambient_dim(vf) == 3 + @test sum(facet_sizes(vf)) == 8 + end + end + end + + if T == EmbeddedElem{nf_elem} + + @testset "Dodecahedron" begin + + D = polyhedron(Polymake.polytope.dodecahedron()) + R = coefficient_field(D) + NF = number_field(R) + let isq = Hecke.isquadratic_type(NF) + @test isq[1] + @test isq[2] == 5 + end + a = R(gens(NF)[]) + + V = [[1//2, a//4 + 3//4, 0], + [-1//2, a//4 + 3//4, 0], + [a//4 + 1//4, a//4 + 1//4, a//4 + 1//4], + [-a//4 - 1//4, a//4 + 1//4, a//4 + 1//4], + [a//4 + 1//4, a//4 + 1//4, -a//4 - 1//4], + [0, 1//2, a//4 + 3//4], + [-a//4 - 1//4, a//4 + 1//4, -a//4 - 1//4], + [0, 1//2, -a//4 - 3//4], + [a//4 + 3//4, 0, 1//2], + [a//4 + 3//4, 0, -1//2], + [-a//4 - 3//4, 0, 1//2], + [-a//4 - 3//4, 0, -1//2], + [0, -1//2, a//4 + 3//4], + [a//4 + 1//4, -a//4 - 1//4, a//4 + 1//4], + [0, -1//2, -a//4 - 3//4], + [-a//4 - 1//4, -a//4 - 1//4, a//4 + 1//4], + [a//4 + 1//4, -a//4 - 1//4, -a//4 - 1//4], + [-a//4 - 1//4, -a//4 - 1//4, -a//4 - 1//4], + [1//2, -a//4 - 3//4, 0], + [-1//2, -a//4 - 3//4, 0]] + + @test D isa Polyhedron{T} + + @test nvertices(D) == 20 + @test vertices(D) == V + + let A = [[a//2+1//2 1 0], [0 a//2+1//2 1], [0 a//2+1//2 -1], [-a//2-1//2 -1 0], [a//2-1//2 0 -1], [-a//2-1//2 1 0], [a//2-1//2 0 1], [-a//2+1//2 0 1], [0 -a//2-1//2 1], [-a//2+1//2 0 -1], [a//2+1//2 -1 0], [0 -a//2-1//2 -1]], b = [a//2 + 1, a//2 + 1, a//2 + 1, a//2 + 1, a//4 + 3//4, a//2 + 1, a//4 + 3//4, a//4 + 3//4, a//2 + 1, a//4 + 3//4, a//2 + 1, a//2 + 1] + + for S in [AffineHalfspace{T}, + Pair{Matrix{T}, T}, + Polyhedron{T}] + + @test facets(S, D) isa SubObjectIterator{S} + if S == Pair{Matrix{T}, T} + @test facets(S, D) == [Pair(A[i], b[i]) for i in 1:12] + elseif S == Polyhedron{T} + @test nvertices.(facets(S, D)) == repeat([5], 12) + else + @test facets(S, D) == [affine_halfspace(R, A[i], b[i]) for i in 1:12] + end + @test length(facets(S, D)) == 12 + @test affine_inequality_matrix(facets(S, D)) == matrix(R, hcat(-b, vcat(A...))) + @test halfspace_matrix_pair(facets(S, D)) == (A = matrix(R, vcat(A...)), b = b) + + @test ray_indices(facets(S, D)) == IncidenceMatrix(12, 0) + @test vertex_indices(facets(S, D)) == IncidenceMatrix([[1, 3, 5, 9, 10], [1, 2, 3, 4, 6], [1, 2, 5, 7, 8], [11, 12, 16, 18, 20], [5, 8, 10, 15, 17], [2, 4, 7, 11, 12], [3, 6, 9, 13, 14], [4, 6, 11, 13, 16], [13, 14, 16, 19, 20], [7, 8, 12, 15, 18], [9, 10, 14, 17, 19], [15, 17, 18, 19, 20]]) + @test vertex_and_ray_indices(facets(S, D)) == IncidenceMatrix([[1, 3, 5, 9, 10], [1, 2, 3, 4, 6], [1, 2, 5, 7, 8], [11, 12, 16, 18, 20], [5, 8, 10, 15, 17], [2, 4, 7, 11, 12], [3, 6, 9, 13, 14], [4, 6, 11, 13, 16], [13, 14, 16, 19, 20], [7, 8, 12, 15, 18], [9, 10, 14, 17, 19], [15, 17, 18, 19, 20]]) + @test IncidenceMatrix(facets(S, D)) == IncidenceMatrix([[1, 3, 5, 9, 10], [1, 2, 3, 4, 6], [1, 2, 5, 7, 8], [11, 12, 16, 18, 20], [5, 8, 10, 15, 17], [2, 4, 7, 11, 12], [3, 6, 9, 13, 14], [4, 6, 11, 13, 16], [13, 14, 16, 19, 20], [7, 8, 12, 15, 18], [9, 10, 14, 17, 19], [15, 17, 18, 19, 20]]) end - if T == EmbeddedElem{nf_elem} - - @testset "Dodecahedron" begin - - D = polyhedron(Polymake.polytope.dodecahedron()) - R = coefficient_field(D) - NF = number_field(R) - let isq = Hecke.isquadratic_type(NF) - @test isq[1] - @test isq[2] == 5 - end - a = R(gens(NF)[]) - - V = [[1//2, a//4 + 3//4, 0], - [-1//2, a//4 + 3//4, 0], - [a//4 + 1//4, a//4 + 1//4, a//4 + 1//4], - [-a//4 - 1//4, a//4 + 1//4, a//4 + 1//4], - [a//4 + 1//4, a//4 + 1//4, -a//4 - 1//4], - [0, 1//2, a//4 + 3//4], - [-a//4 - 1//4, a//4 + 1//4, -a//4 - 1//4], - [0, 1//2, -a//4 - 3//4], - [a//4 + 3//4, 0, 1//2], - [a//4 + 3//4, 0, -1//2], - [-a//4 - 3//4, 0, 1//2], - [-a//4 - 3//4, 0, -1//2], - [0, -1//2, a//4 + 3//4], - [a//4 + 1//4, -a//4 - 1//4, a//4 + 1//4], - [0, -1//2, -a//4 - 3//4], - [-a//4 - 1//4, -a//4 - 1//4, a//4 + 1//4], - [a//4 + 1//4, -a//4 - 1//4, -a//4 - 1//4], - [-a//4 - 1//4, -a//4 - 1//4, -a//4 - 1//4], - [1//2, -a//4 - 3//4, 0], - [-1//2, -a//4 - 3//4, 0]] - - @test D isa Polyhedron{T} - - @test nvertices(D) == 20 - @test vertices(D) == V - - let A = [[a//2+1//2 1 0], [0 a//2+1//2 1], [0 a//2+1//2 -1], [-a//2-1//2 -1 0], [a//2-1//2 0 -1], [-a//2-1//2 1 0], [a//2-1//2 0 1], [-a//2+1//2 0 1], [0 -a//2-1//2 1], [-a//2+1//2 0 -1], [a//2+1//2 -1 0], [0 -a//2-1//2 -1]], b = [a//2 + 1, a//2 + 1, a//2 + 1, a//2 + 1, a//4 + 3//4, a//2 + 1, a//4 + 3//4, a//4 + 3//4, a//2 + 1, a//4 + 3//4, a//2 + 1, a//2 + 1] - - for S in [AffineHalfspace{T}, - Pair{Matrix{T}, T}, - Polyhedron{T}] - - @test facets(S, D) isa SubObjectIterator{S} - if S == Pair{Matrix{T}, T} - @test facets(S, D) == [Pair(A[i], b[i]) for i in 1:12] - elseif S == Polyhedron{T} - @test nvertices.(facets(S, D)) == repeat([5], 12) - else - @test facets(S, D) == [affine_halfspace(R, A[i], b[i]) for i in 1:12] - end - @test length(facets(S, D)) == 12 - @test affine_inequality_matrix(facets(S, D)) == matrix(R, hcat(-b, vcat(A...))) - @test halfspace_matrix_pair(facets(S, D)) == (A = matrix(R, vcat(A...)), b = b) - - @test ray_indices(facets(S, D)) == IncidenceMatrix(12, 0) - @test vertex_indices(facets(S, D)) == IncidenceMatrix([[1, 3, 5, 9, 10], [1, 2, 3, 4, 6], [1, 2, 5, 7, 8], [11, 12, 16, 18, 20], [5, 8, 10, 15, 17], [2, 4, 7, 11, 12], [3, 6, 9, 13, 14], [4, 6, 11, 13, 16], [13, 14, 16, 19, 20], [7, 8, 12, 15, 18], [9, 10, 14, 17, 19], [15, 17, 18, 19, 20]]) - @test vertex_and_ray_indices(facets(S, D)) == IncidenceMatrix([[1, 3, 5, 9, 10], [1, 2, 3, 4, 6], [1, 2, 5, 7, 8], [11, 12, 16, 18, 20], [5, 8, 10, 15, 17], [2, 4, 7, 11, 12], [3, 6, 9, 13, 14], [4, 6, 11, 13, 16], [13, 14, 16, 19, 20], [7, 8, 12, 15, 18], [9, 10, 14, 17, 19], [15, 17, 18, 19, 20]]) - @test IncidenceMatrix(facets(S, D)) == IncidenceMatrix([[1, 3, 5, 9, 10], [1, 2, 3, 4, 6], [1, 2, 5, 7, 8], [11, 12, 16, 18, 20], [5, 8, 10, 15, 17], [2, 4, 7, 11, 12], [3, 6, 9, 13, 14], [4, 6, 11, 13, 16], [13, 14, 16, 19, 20], [7, 8, 12, 15, 18], [9, 10, 14, 17, 19], [15, 17, 18, 19, 20]]) - end - - end - - @test facets(IncidenceMatrix, D) == IncidenceMatrix([[1, 3, 5, 9, 10], [1, 2, 3, 4, 6], [1, 2, 5, 7, 8], [11, 12, 16, 18, 20], [5, 8, 10, 15, 17], [2, 4, 7, 11, 12], [3, 6, 9, 13, 14], [4, 6, 11, 13, 16], [13, 14, 16, 19, 20], [7, 8, 12, 15, 18], [9, 10, 14, 17, 19], [15, 17, 18, 19, 20]]) - @test facet_indices(rays(D))==IncidenceMatrix(0,12) - @test IncidenceMatrix(rays(D)) == IncidenceMatrix(0, 12) - @test rays(IncidenceMatrix, D) == IncidenceMatrix(0, 12) - @test facet_indices(vertices(D))==IncidenceMatrix([[1, 2, 3],[2, 3, 6],[1, 2, 7],[2, 6, 8],[1, 3, 5],[2, 7, 8],[3, 6, 10],[3, 5, 10],[1, 7, 11],[1, 5, 11],[4, 6, 8],[4, 6, 10],[7, 8, 9],[7, 9, 11],[5, 10, 12],[4, 8, 9],[5, 11, 12],[4, 10, 12],[9, 11, 12],[4, 9, 12]]) - @test IncidenceMatrix(vertices(D)) == IncidenceMatrix([[1, 2, 3],[2, 3, 6],[1, 2, 7],[2, 6, 8],[1, 3, 5],[2, 7, 8],[3, 6, 10],[3, 5, 10],[1, 7, 11],[1, 5, 11],[4, 6, 8],[4, 6, 10],[7, 8, 9],[7, 9, 11],[5, 10, 12],[4, 8, 9],[5, 11, 12],[4, 10, 12],[9, 11, 12],[4, 9, 12]]) - @test vertices(IncidenceMatrix, D) == IncidenceMatrix([[1, 2, 3],[2, 3, 6],[1, 2, 7],[2, 6, 8],[1, 3, 5],[2, 7, 8],[3, 6, 10],[3, 5, 10],[1, 7, 11],[1, 5, 11],[4, 6, 8],[4, 6, 10],[7, 8, 9],[7, 9, 11],[5, 10, 12],[4, 8, 9],[5, 11, 12],[4, 10, 12],[9, 11, 12],[4, 9, 12]]) - @test is_feasible(D) - @test is_bounded(D) - @test is_fulldimensional(D) - @test f_vector(D) == [20, 30, 12] - @test codim(D) == 0 - @test nrays(recession_cone(D)) == 0 - @test nrays(D) == 0 - @test isempty(rays(D)) - @test lineality_dim(D) == 0 - @test isempty(lineality_space(D)) - @test faces(D, 0) == convex_hull.(T, V) - @test isempty(affine_hull(D)) - @test relative_interior_point(D) == [0, 0, 0] - end + end + + @test facets(IncidenceMatrix, D) == IncidenceMatrix([[1, 3, 5, 9, 10], [1, 2, 3, 4, 6], [1, 2, 5, 7, 8], [11, 12, 16, 18, 20], [5, 8, 10, 15, 17], [2, 4, 7, 11, 12], [3, 6, 9, 13, 14], [4, 6, 11, 13, 16], [13, 14, 16, 19, 20], [7, 8, 12, 15, 18], [9, 10, 14, 17, 19], [15, 17, 18, 19, 20]]) + @test facet_indices(rays(D))==IncidenceMatrix(0,12) + @test IncidenceMatrix(rays(D)) == IncidenceMatrix(0, 12) + @test rays(IncidenceMatrix, D) == IncidenceMatrix(0, 12) + @test facet_indices(vertices(D))==IncidenceMatrix([[1, 2, 3],[2, 3, 6],[1, 2, 7],[2, 6, 8],[1, 3, 5],[2, 7, 8],[3, 6, 10],[3, 5, 10],[1, 7, 11],[1, 5, 11],[4, 6, 8],[4, 6, 10],[7, 8, 9],[7, 9, 11],[5, 10, 12],[4, 8, 9],[5, 11, 12],[4, 10, 12],[9, 11, 12],[4, 9, 12]]) + @test IncidenceMatrix(vertices(D)) == IncidenceMatrix([[1, 2, 3],[2, 3, 6],[1, 2, 7],[2, 6, 8],[1, 3, 5],[2, 7, 8],[3, 6, 10],[3, 5, 10],[1, 7, 11],[1, 5, 11],[4, 6, 8],[4, 6, 10],[7, 8, 9],[7, 9, 11],[5, 10, 12],[4, 8, 9],[5, 11, 12],[4, 10, 12],[9, 11, 12],[4, 9, 12]]) + @test vertices(IncidenceMatrix, D) == IncidenceMatrix([[1, 2, 3],[2, 3, 6],[1, 2, 7],[2, 6, 8],[1, 3, 5],[2, 7, 8],[3, 6, 10],[3, 5, 10],[1, 7, 11],[1, 5, 11],[4, 6, 8],[4, 6, 10],[7, 8, 9],[7, 9, 11],[5, 10, 12],[4, 8, 9],[5, 11, 12],[4, 10, 12],[9, 11, 12],[4, 9, 12]]) + @test is_feasible(D) + @test is_bounded(D) + @test is_fulldimensional(D) + @test f_vector(D) == [20, 30, 12] + @test codim(D) == 0 + @test nrays(recession_cone(D)) == 0 + @test nrays(D) == 0 + @test isempty(rays(D)) + @test lineality_dim(D) == 0 + @test isempty(lineality_space(D)) + @test faces(D, 0) == convex_hull.(T, V) + @test isempty(affine_hull(D)) + @test relative_interior_point(D) == [0, 0, 0] + end - end + end - end end diff --git a/test/PolyhedralGeometry/runtests.jl b/test/PolyhedralGeometry/runtests.jl deleted file mode 100644 index d0a3ce3f3acb..000000000000 --- a/test/PolyhedralGeometry/runtests.jl +++ /dev/null @@ -1,20 +0,0 @@ -using Oscar -using Test - -const pm = Polymake - -include("types.jl") -include("iterators.jl") -include("cone.jl") -include("group.jl") -include("polyhedron.jl") -include("linear_program.jl") -include("polyhedral_fan.jl") -include("polyhedral_complex.jl") -include("subdivision_of_points.jl") -include("extended.jl") -include("timing.jl") -include("solve_integrally.jl") -include("lineality.jl") -include("scalar_types.jl") -include("triangulations.jl") diff --git a/test/PolyhedralGeometry/setup_tests.jl b/test/PolyhedralGeometry/setup_tests.jl new file mode 100644 index 000000000000..08f35b1213a1 --- /dev/null +++ b/test/PolyhedralGeometry/setup_tests.jl @@ -0,0 +1,11 @@ +if !isdefined(Main, :_prepare_scalar_types) + + function _prepare_scalar_types() + NF, sr2 = quadratic_field(2) + Qx, x = QQ["x"] + K, a = Hecke.embedded_field(NF, real_embeddings(NF)[2]) + KK, (a1, a2) = embedded_number_field([x^2 - 2, x^3 - 5], [(0, 2), (0, 2)]) + return [(f, elem_type(f)) for f in (QQ, K, KK)] + end + +end diff --git a/test/PolyhedralGeometry/types.jl b/test/PolyhedralGeometry/types.jl index 3256888f9dfb..1c21bdc6ce3d 100644 --- a/test/PolyhedralGeometry/types.jl +++ b/test/PolyhedralGeometry/types.jl @@ -15,8 +15,7 @@ a = [1, 2, 3] b = [8, 6, 4] - NF, sr2 = quadratic_field(2) - ENF, sre2 = Hecke.embedded_field(NF, real_embeddings(NF)[2]) + (ENF, _) = _prepare_scalar_types()[2] @testset "$T" for (T, fun) in ((PointVector, point_vector), (RayVector, ray_vector)) @@ -132,7 +131,7 @@ end - for p in [QQ, NF] + for p in [QQ, ENF] U = elem_type(p) let A = linear_halfspace(p, a) @test invert(A) isa LinearHalfspace{U} diff --git a/test/Project.toml b/test/Project.toml index ef473db5904c..ad273f8bb499 100644 --- a/test/Project.toml +++ b/test/Project.toml @@ -3,7 +3,6 @@ Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595" Distributed = "8ba89e20-285c-5b6f-9357-94700520ee1b" Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4" PrettyTables = "08abe8d2-0d0c-5749-adfa-8a2ac140af0d" -Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7" Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" @@ -12,6 +11,5 @@ Aqua = "0.7" Distributed = "1.6" Documenter = "0.27, 1.0" PrettyTables = "2.2.7" -Printf = "1.6" Random = "1.6" Test = "1.6" diff --git a/test/Rings/runtests.jl b/test/Rings/runtests.jl deleted file mode 100644 index d6cc9d8dc30d..000000000000 --- a/test/Rings/runtests.jl +++ /dev/null @@ -1,43 +0,0 @@ -using Oscar -using Test - -include("integer.jl") -include("rational.jl") -include("mpoly.jl") -include("orderings.jl") -include("mpoly-graded.jl") -include("mpoly-local.jl") -include("mpoly-localizations.jl") -include("mpolyquo-localizations.jl") -include("integer-localizations.jl") -include("nmod-localizations.jl") -include("mpoly-nested.jl") -include("MPolyQuo.jl") -include("groebner.jl") -include("solving.jl") -include("FractionalIdeal.jl") -include("mpoly_affine_algebras.jl") -include("slpolys.jl") - -include("NumberField.jl") -include("FunctionField.jl") -include("AbelianClosure.jl") - -# FIXME: temporarily disable AlgClosureFp tests until we resolve -# issue https://github.com/oscar-system/Oscar.jl/issues/2691 -#include("AlgClosureFp.jl") -include("Laurent.jl") - -include("MPolyAnyMap/MPolyRing.jl") -include("MPolyAnyMap/MPolyQuo.jl") -include("MPolyAnyMap/AffineAlgebras.jl") -include("MPolyAnyMap/flattenings.jl") - -include("PBWAlgebra.jl") -include("PBWAlgebraQuo.jl") -include("FreeAssAlgIdeal.jl") - -include("binomial-ideals.jl") -include("hilbert.jl") - -include("ReesAlgebra.jl") diff --git a/test/Serialization/runtests.jl b/test/Serialization/runtests.jl deleted file mode 100644 index f97740458e85..000000000000 --- a/test/Serialization/runtests.jl +++ /dev/null @@ -1,19 +0,0 @@ -using Oscar -using Test - -isdefined(Main, :test_save_load_roundtrip) || - include(joinpath(Oscar.oscardir, "test", "Serialization", "test_save_load_roundtrip.jl")) - -include("IPC.jl") -include("session.jl") -include("basic_types.jl") -include("PolyhedralGeometry.jl") -include("containers.jl") -include("loading.jl") -include("ToricGeometry.jl") -include("Algebras.jl") -include("PolynomialsSeries.jl") -include("Matrices.jl") -include("Fields.jl") -include("TropicalGeometry.jl") -include("QuadForm.jl") diff --git a/test/Serialization/test_save_load_roundtrip.jl b/test/Serialization/setup_tests.jl similarity index 92% rename from test/Serialization/test_save_load_roundtrip.jl rename to test/Serialization/setup_tests.jl index f267de31999d..558e4401859e 100644 --- a/test/Serialization/test_save_load_roundtrip.jl +++ b/test/Serialization/setup_tests.jl @@ -1,6 +1,10 @@ # This code is needed for multiple test files that may end up on different workers. # Thus, this needs to be conditionally included in each of these test files. +# we only need to define this once + +if !isdefined(Main, :test_save_load_roundtrip) + function test_save_load_roundtrip(func, path, original::T; params=nothing) where {T} # save and load from a file filename = joinpath(path, "original.json") @@ -43,3 +47,5 @@ function test_save_load_roundtrip(func, path, original::T; params=nothing) where reset_global_serializer_state() loaded = load(filename; params=params) end + +end diff --git a/test/TropicalGeometry/runtests.jl b/test/TropicalGeometry/runtests.jl deleted file mode 100644 index c9ff623e039b..000000000000 --- a/test/TropicalGeometry/runtests.jl +++ /dev/null @@ -1,7 +0,0 @@ -using Oscar -using Test - -include("groebner_basis.jl") -include("groebner_fan.jl") -include("initial.jl") -include("hypersurface.jl") diff --git a/test/runtests.jl b/test/runtests.jl index 0103c779abf6..725f15fafe6e 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -37,6 +37,10 @@ end @everywhere using Oscar @everywhere Oscar.set_seed!($seed) @everywhere Oscar.randseed!($seed) +# setting the global julia seed does not work for distributed processes +# the RNG is task-local and each '@everywhere' runs in a separate task... +# to make sure we seed the main process we run this again +Oscar.randseed!(seed) if VERSION >= v"1.8.0" # Enable GC logging to help track down certain GC related issues. @@ -54,22 +58,16 @@ module SLPTest end # some helpers -@everywhere import Printf @everywhere import PrettyTables -# the current code for extracting the compile times does not work on earlier -# julia version -@everywhere const compiletimes = @static VERSION >= v"1.9.0-DEV" ? true : false -@everywhere const stats_dict = Dict{String,NamedTuple}() - -function print_stats(io::IO; fmt=PrettyTables.tf_unicode, max=50) +function print_stats(io::IO, stats_dict::Dict; fmt=PrettyTables.tf_unicode, max=50) sorted = sort(collect(stats_dict), by=x->x[2].time, rev=true) println(io, "### Stats per file") println(io) table = hcat(first.(sorted), permutedims(reduce(hcat, collect.(values.(last.(sorted)))))) formatters = nothing - @static if compiletimes + if haskey(first(values(stats_dict)), :ctime) header=[:Filename, Symbol("Runtime in s"), Symbol("+ Compilation"), Symbol("+ Recompilation"), Symbol("Allocations in MB")] #formatters = PrettyTables.ft_printf("%.2f%%", [3,4]) else @@ -78,94 +76,73 @@ function print_stats(io::IO; fmt=PrettyTables.tf_unicode, max=50) PrettyTables.pretty_table(io, table; tf=fmt, max_num_of_rows=max, header=header, formatters=formatters) end -# we only want to print stats for files that run tests and not those that just -# include other files -@everywhere const innermost = Ref(true) -# redefine include to print and collect some extra stats -@everywhere function include(str::String) - innermost[] = true - # we pass the identity to avoid recursing into this function again - @static if compiletimes - compile_elapsedtimes = Base.cumulative_compile_time_ns() - end - stats = @timed Base.include(identity, Main, str) - # skip files which just include other files and ignore - # files outside of the oscar folder - if innermost[] && !isabspath(str) - @static if compiletimes - compile_elapsedtimes = Base.cumulative_compile_time_ns() .- compile_elapsedtimes - compile_elapsedtimes = compile_elapsedtimes ./ 10^9 - end - path = Base.source_dir() - path = joinpath(relpath(path, joinpath(Oscar.oscardir,"test")), str) - rtime=NaN - @static if compiletimes - comptime = first(compile_elapsedtimes) - rcomptime = last(compile_elapsedtimes) - stats_dict[path] = (time=stats.time-comptime, ctime=comptime-rcomptime, rctime=rcomptime, alloc=stats.bytes/2^20) - Printf.@printf "-> Testing %s took: runtime %.3f seconds + compilation %.3f seconds + recompilation %.3f seconds, %.2f MB\n" path stats.time-comptime comptime-rcomptime rcomptime stats.bytes/2^20 - else - Printf.@printf "-> Testing %s took: %.3f seconds, %.2f MB\n" path stats.time stats.bytes/2^20 - stats_dict[path] = (time=stats.time, alloc=stats.bytes/2^20) - end - innermost[] = false + +testlist = Oscar._gather_tests("test") + +for exp in [Oscar.exppkgs; Oscar.oldexppkgs] + path = joinpath(Oscar.oscardir, "experimental", exp, "test") + if isdir(path) + append!(testlist, Oscar._gather_tests(path)) end end -@static if compiletimes - Base.cumulative_compile_timing(true) +# make sure we have the same list everywhere +sort!(testlist) +Random.shuffle!(Oscar.get_seeded_rng(), testlist) + +# tests with the highest number of allocations / runtime / compilation time +# more or less sorted by allocations +test_large = [ + "experimental/FTheoryTools/test/weierstrass.jl", + "test/PolyhedralGeometry/timing.jl", + "experimental/GITFans/test/runtests.jl", + "test/AlgebraicGeometry/ToricVarieties/toric_schemes.jl", + "test/AlgebraicGeometry/Schemes/WeilDivisor.jl", + "test/Rings/NumberField.jl", + "test/Serialization/PolynomialsSeries.jl", + "test/AlgebraicGeometry/Schemes/K3.jl", + "test/Groups/forms.jl", + "test/Modules/UngradedModules.jl", + "test/GAP/oscarinterface.jl", + "test/AlgebraicGeometry/Schemes/CoveredProjectiveSchemes.jl", + "test/AlgebraicGeometry/Schemes/MorphismFromRationalFunctions.jl", + "experimental/QuadFormAndIsom/test/runtests.jl", + "experimental/GModule/test/runtests.jl", + "test/Modules/ModulesGraded.jl", + "test/AlgebraicGeometry/Schemes/elliptic_surface.jl", + ] + +test_subset = get(ENV, "OSCAR_TEST_SUBSET", "") +if haskey(ENV, "JULIA_PKGEVAL") + test_subset = "short" end -testlist = [ - "Aqua.jl", - "printing.jl", - - "PolyhedralGeometry/runtests.jl", - "Combinatorics/runtests.jl", - "GAP/runtests.jl", - "Groups/runtests.jl", - "Rings/runtests.jl", - "NumberTheory/runtests.jl", - "Modules/runtests.jl", - "InvariantTheory/runtests.jl", - - "AlgebraicGeometry/Schemes/runtests.jl", - "AlgebraicGeometry/ToricVarieties/runtests.jl", - "AlgebraicGeometry/Surfaces/runtests.jl", - - "TropicalGeometry/runtests.jl", - - "Serialization/runtests.jl", - "Serialization/polymake/runtests.jl", - "Serialization/upgrades/runtests.jl", +if test_subset == "short" + filter!(x-> !in(relpath(x, Oscar.oscardir), test_large), testlist) +elseif test_subset == "long" + testlist = joinpath.(Oscar.oscardir, test_large) + filter!(isfile, testlist) +end - # Automatically include tests of all experimental packages following our - # guidelines. - "../experimental/runtests.jl", - "Data/runtests.jl", - "StraightLinePrograms/runtests.jl", -] +@everywhere testlist = $testlist # if many workers, distribute tasks across them # otherwise, is essentially a serial loop -pmap(include, testlist) +stats = merge(pmap(x -> Oscar.test_module(x; new=false, timed=true), testlist)...) -@static if compiletimes - Base.cumulative_compile_timing(false); +# this needs to run here to make sure it runs on the main process +# it is in the ignore list for the other tests +if numprocs == 1 && test_subset != "short" + push!(stats, Oscar._timed_include("Serialization/IPC.jl", Main)) end -#currently, print_stats will fail when running tests with external workers -#TODO: potentially rewrite include as well as print_stats -# to comply with parallel decisions -if numprocs == 1 - if haskey(ENV, "GITHUB_STEP_SUMMARY") && compiletimes - open(ENV["GITHUB_STEP_SUMMARY"], "a") do io - print_stats(io, fmt=PrettyTables.tf_markdown) - end - else - print_stats(stdout; max=10) +if haskey(ENV, "GITHUB_STEP_SUMMARY") + open(ENV["GITHUB_STEP_SUMMARY"], "a") do io + print_stats(io, stats; fmt=PrettyTables.tf_markdown) end +else + print_stats(stdout, stats; max=10) end cd(oldWorkingDirectory) From 866b277caff0124998163ba0bd47d4dc3bd2945c Mon Sep 17 00:00:00 2001 From: Max Horn Date: Sat, 21 Oct 2023 19:45:17 +0200 Subject: [PATCH 11/27] Revamp graded_polynomial_ring (#2940) It now accepts exactly the same variants for specifying variables as `polynomial_ring` (by passing them on unchanged). Moreover, the weight vector can now be passed as a keyword argument. At some point we could drop support for passing it as final argument. Finally, weight vectors can now be specified as `AbstractVector` instances, making them slightly more usable. So this is now valid: R, x, y = graded_polynomial_ring(QQ, :x => 1:3, :y => (1:2, 1:2); weights=1:7) --- src/Rings/MPolyQuo.jl | 1 - src/Rings/mpoly-graded.jl | 185 ++++++++++++++++---------------------- 2 files changed, 79 insertions(+), 107 deletions(-) diff --git a/src/Rings/MPolyQuo.jl b/src/Rings/MPolyQuo.jl index 0cae2fc41440..8b75cea52946 100644 --- a/src/Rings/MPolyQuo.jl +++ b/src/Rings/MPolyQuo.jl @@ -1565,7 +1565,6 @@ julia> HC = gens(L[1]); julia> EMB = L[2] Map defined by a julia-function with inverse from homogeneous component of Graded multivariate polynomial ring in 5 variables over QQ of degree Element of G with components [2 1] - to graded multivariate polynomial ring in 5 variables over QQ julia> for i in 1:length(HC) println(EMB(HC[i])) end diff --git a/src/Rings/mpoly-graded.jl b/src/Rings/mpoly-graded.jl index 79c0d15bed93..efc0b3a725cb 100644 --- a/src/Rings/mpoly-graded.jl +++ b/src/Rings/mpoly-graded.jl @@ -3,7 +3,7 @@ R::S D::GrpAbFinGen d::Vector{GrpAbFinGenElem} - lt + lt::Any function MPolyDecRing(R::S, d::Vector{GrpAbFinGenElem}) where {S} @assert length(d) == ngens(R) r = new{elem_type(base_ring(R)), S}() @@ -107,7 +107,7 @@ function decorate(R::MPolyRing) end @doc raw""" - grade(R::MPolyRing, W::Vector{<:IntegerUnion}) + grade(R::MPolyRing, W::AbstractVector{<:IntegerUnion}) Given a vector `W` of `ngens(R)` integers, create a free abelian group of type `GrpAbFinGen` given by one free generator, and convert the entries of `W` to elements of that group. Then @@ -132,7 +132,7 @@ julia> T, (x, y, z) = grade(R) (Graded multivariate polynomial ring in 3 variables over QQ, MPolyDecRingElem{QQFieldElem, QQMPolyRingElem}[x, y, z]) ``` """ -function grade(R::MPolyRing, W::Vector{<:IntegerUnion}) +function grade(R::MPolyRing, W::AbstractVector{<:IntegerUnion}) @assert length(W) == ngens(R) A = abelian_group([0]) set_attribute!(A, :show_elem => show_special_elem_grad) @@ -147,7 +147,7 @@ function grade(R::MPolyRing) end @doc raw""" - grade(R::MPolyRing, W::Vector{<:Vector{<:IntegerUnion}}) + grade(R::MPolyRing, W::AbstractVector{<:AbstractVector{<:IntegerUnion}}) Given a vector `W` of `ngens(R)` integer vectors of the same size `m`, say, create a free abelian group of type `GrpAbFinGen` given by `m` free generators, and convert the vectors in @@ -155,7 +155,7 @@ abelian group of type `GrpAbFinGen` given by `m` free generators, and convert th elements as weights to the variables of `R`, and return the new ring, together with the vector of variables. - grade(R::MPolyRing, W::Union{ZZMatrix, Matrix{<:IntegerUnion}}) + grade(R::MPolyRing, W::Union{ZZMatrix, AbstractMatrix{<:IntegerUnion}}) As above, converting the columns of `W`. @@ -173,7 +173,7 @@ julia> grade(R, W) (Graded multivariate polynomial ring in 5 variables over QQ, MPolyDecRingElem{QQFieldElem, QQMPolyRingElem}[x[1], x[2], y[1], y[2], y[3]]) ``` """ -function grade(R::MPolyRing, W::Vector{<:Vector{<:IntegerUnion}}) +function grade(R::MPolyRing, W::AbstractVector{<:AbstractVector{<:IntegerUnion}}) @assert length(W) == ngens(R) n = length(W[1]) @assert all(x->length(x) == n, W) @@ -184,7 +184,7 @@ function grade(R::MPolyRing, W::Vector{<:Vector{<:IntegerUnion}}) return S, map(S, gens(R)) end -function grade(R::MPolyRing, W::Union{ZZMatrix, Matrix{<:IntegerUnion}}) +function grade(R::MPolyRing, W::Union{ZZMatrix, AbstractMatrix{<:IntegerUnion}}) @assert size(W, 2) == ngens(R) A = abelian_group(zeros(Int, size(W, 1))) set_attribute!(A, :show_elem => show_special_elem_grad) @@ -202,12 +202,7 @@ Return `true` if `R` is standard $\mathbb Z$-graded, `false` otherwise. # Examples ```jldoctest -julia> R, (x, y, z) = polynomial_ring(QQ, ["x", "y", "z"]) -(Multivariate polynomial ring in 3 variables over QQ, QQMPolyRingElem[x, y, z]) - -julia> W = [1, 2, 3]; - -julia> S, (x, y, z) = grade(R, W) +julia> S, (x, y, z) = graded_polynomial_ring(QQ, ["x", "y", "z"]; weights = [1, 2, 3]) (Graded multivariate polynomial ring in 3 variables over QQ, MPolyDecRingElem{QQFieldElem, QQMPolyRingElem}[x, y, z]) julia> is_standard_graded(S) @@ -238,12 +233,7 @@ Return `true` if `R` is $\mathbb Z$-graded, `false` otherwise. # Examples ```jldoctest -julia> R, (x, y, z) = polynomial_ring(QQ, ["x", "y", "z"]) -(Multivariate polynomial ring in 3 variables over QQ, QQMPolyRingElem[x, y, z]) - -julia> W = [1, 2, 3]; - -julia> S, (x, y, z) = grade(R, W) +julia> S, (x, y, z) = graded_polynomial_ring(QQ, ["x", "y", "z"]; weights = [1, 2, 3]) (Graded multivariate polynomial ring in 3 variables over QQ, MPolyDecRingElem{QQFieldElem, QQMPolyRingElem}[x, y, z]) julia> is_z_graded(S) @@ -268,18 +258,13 @@ Return `true` if `R` is $\mathbb Z^m$-graded for some $m$, `false` otherwise. # Examples ```jldoctest -julia> R, x = polynomial_ring(QQ, "x" => 1:5) -(Multivariate polynomial ring in 5 variables over QQ, QQMPolyRingElem[x[1], x[2], x[3], x[4], x[5]]) - julia> G = abelian_group([0, 0, 2, 2]) (General) abelian group with relation matrix [0 0 0 0; 0 0 0 0; 0 0 2 0; 0 0 0 2] -julia> g = gens(G); - -julia> W = [g[1]+g[3]+g[4], g[2]+g[4], g[1]+g[3], g[2], g[1]+g[2]]; +julia> W = [G[1]+G[3]+G[4], G[2]+G[4], G[1]+G[3], G[2], G[1]+G[2]]; -julia> S, x = grade(R, W) +julia> S, x = graded_polynomial_ring(QQ, "x" => 1:5; weights=W) (Graded multivariate polynomial ring in 5 variables over QQ, MPolyDecRingElem{QQFieldElem, QQMPolyRingElem}[x[1], x[2], x[3], x[4], x[5]]) julia> is_zm_graded(S) @@ -320,21 +305,12 @@ Return `true` if `R` is positively graded, `false` otherwise. # Examples ```jldoctest -julia> R, (t, x, y) = polynomial_ring(QQ, ["t", "x", "y"]) -(Multivariate polynomial ring in 3 variables over QQ, QQMPolyRingElem[t, x, y]) - -julia> G = abelian_group([0]) -GrpAb: Z - -julia> S, (t, x, y) = grade(R, [-1, 1, 1]) +julia> S, (t, x, y) = graded_polynomial_ring(QQ, ["t", "x", "y"]; weights = [-1, 1, 1]) (Graded multivariate polynomial ring in 3 variables over QQ, MPolyDecRingElem{QQFieldElem, QQMPolyRingElem}[t, x, y]) julia> is_positively_graded(S) false -julia> R, (x, y) = polynomial_ring(QQ, ["x", "y"]) -(Multivariate polynomial ring in 2 variables over QQ, QQMPolyRingElem[x, y]) - julia> G = abelian_group([0, 2]) (General) abelian group with relation matrix [0 0; 0 2] @@ -344,7 +320,7 @@ julia> W = [gen(G, 1)+gen(G, 2), gen(G, 1)] Element of G with components [1 1] Element of G with components [1 0] -julia> S, (x, y) = grade(R, W) +julia> S, (x, y) = graded_polynomial_ring(QQ, ["x", "y"]; weights = W) (Graded multivariate polynomial ring in 2 variables over QQ, MPolyDecRingElem{QQFieldElem, QQMPolyRingElem}[x, y]) julia> is_positively_graded(S) @@ -377,18 +353,15 @@ end is_positively_graded(::MPolyRing) = false @doc raw""" - graded_polynomial_ring(C::Ring, V, W; ordering=:lex) - graded_polynomial_ring(C::Ring, n::Int, s::T, W; ordering=:lex) where T<:VarName + graded_polynomial_ring(C::Ring, args...; weights, kwargs...) Create a multivariate [`polynomial_ring`](@ref polynomial_ring(R, [:x])) with -coefficient ring `C` and variables which print according to the variable names -in `V` (respectively as "\$(s)1" up to "\$s\$n"), and [`grade`](@ref) this ring -according to the data provided by `W`. Return the graded ring as an object of -type `MPolyDecRing`, together with the vector of variables. - - graded_polynomial_ring(C::Ring, V; ordering=:lex) +coefficient ring `C` and variables as described by `args...` (using the exact +same syntax as `polynomial_ring`), and [`grade`](@ref) this ring +according to the data provided by the keyword argument `weights`. +Return the graded ring as an object of type `MPolyDecRing`, together with the variables. -As above, where the grading is the standard $\mathbb Z$-grading. +If `weights` is omitted the grading is the standard $\mathbb Z$-grading, i.e. all variables are graded with weight `1`. # Examples ```jldoctest @@ -399,31 +372,51 @@ julia> W = [[1, 0], [0, 1], [1, 0], [4, 1]] [1, 0] [4, 1] -julia> R, x = graded_polynomial_ring(QQ, 4, :x, W) +julia> R, x = graded_polynomial_ring(QQ, 4, :x; weights = W) (Graded multivariate polynomial ring in 4 variables over QQ, MPolyDecRingElem{QQFieldElem, QQMPolyRingElem}[x1, x2, x3, x4]) -julia> S, (x, y, z) = graded_polynomial_ring(QQ, [:x, :y, :z], [1, 2, 3]) +julia> S, (x, y, z) = graded_polynomial_ring(QQ, [:x, :y, :z]; weights = [1, 2, 3]) (Graded multivariate polynomial ring in 3 variables over QQ, MPolyDecRingElem{QQFieldElem, QQMPolyRingElem}[x, y, z]) -julia> T, (x, y, z) = graded_polynomial_ring(QQ, ["x", "y", "z"]) -(Graded multivariate polynomial ring in 3 variables over QQ, MPolyDecRingElem{QQFieldElem, QQMPolyRingElem}[x, y, z]) +julia> T, x = graded_polynomial_ring(QQ, :x => 1:3) +(Graded multivariate polynomial ring in 3 variables over QQ, MPolyDecRingElem{QQFieldElem, QQMPolyRingElem}[x[1], x[2], x[3]]) + +julia> T, x, y = graded_polynomial_ring(QQ, :x => 1:3, :y => (1:2, 1:2); weights=1:7) +(Graded multivariate polynomial ring in 7 variables over QQ, MPolyDecRingElem{QQFieldElem, QQMPolyRingElem}[x[1], x[2], x[3]], MPolyDecRingElem{QQFieldElem, QQMPolyRingElem}[y[1, 1] y[1, 2]; y[2, 1] y[2, 2]]) ``` """ -function graded_polynomial_ring(C::Ring, V::Union{Tuple{Vararg{T}}, AbstractVector{T}}, - W=ones(Int, length(V)); ordering=:lex, cached::Bool=true) where - T<:VarName - # HACK: we pass 'cached' only to 'polynomial_ring', but it really should - # also affect whether the MPolyDecRing gets cached... - return grade(polynomial_ring(C, V; ordering, cached)[1], W) -end +function graded_polynomial_ring(C::Ring, args...; weights=nothing, kwargs...) + if weights === nothing + # no weights kwarg given: for backwards compatibility also check if + # the last regular argument might be a weight vector and if so, use it. + if args[end] isa Union{Vector{<:IntegerUnion}, Vector{<:Vector{<:IntegerUnion}}, Matrix{<:IntegerUnion}, ZZMatrix, Vector{GrpAbFinGenElem}} + weights = args[end] + args = args[1:end-1] + end + end + + # pass all arguments (except possibly the last one if it contains weights) + # on to polynomial_ring + R, v... = polynomial_ring(C, args...; kwargs...) + + # if no weights were given as last argument or via the `weights` kwarg, + # then we now use a default value where we assign weight 1 to each variable + if weights === nothing + weights = ones(Int, nvars(R)) + end -function graded_polynomial_ring(C::Ring, n::Int, s::VarName, - W=ones(Int, n); ordering=:lex, cached::Bool=true) - # HACK: we pass 'cached' only to 'polynomial_ring', but it really should - # also affect whether the MPolyDecRing gets cached... - return grade(polynomial_ring(C, n, s; ordering, cached)[1], W) + # TODO: MPolyDecRing resp. `grade` should support `cached` kwarg + S, = grade(R, weights) + + # return a result of the same "shape" as that returned by polynomial_ring + return S, _map_recursive(S, v)... end +# helper for graded_polynomial_ring +_map_recursive(S::NCRing, x::NCRingElem) = S(x) +_map_recursive(S::NCRing, a::AbstractArray) = map(x -> _map_recursive(S, x), a) +_map_recursive(S::NCRing, a::Tuple) = map(x -> _map_recursive(S, x), a) + filtrate(R::MPolyRing) = decorate(R) function show_special_elem_grad(io::IO, a::GrpAbFinGenElem) @@ -522,20 +515,21 @@ julia> G = abelian_group([0, 0, 2, 2]) (General) abelian group with relation matrix [0 0 0 0; 0 0 0 0; 0 0 2 0; 0 0 0 2] -julia> g = gens(G) -4-element Vector{GrpAbFinGenElem}: - Element of G with components [1 0 0 0] - Element of G with components [0 1 0 0] - Element of G with components [0 0 1 0] - Element of G with components [0 0 0 1] +julia> g = gens(G); -julia> W = [g[1]+g[3]+g[4], g[2]+g[4], g[1]+g[3], g[2], g[1]+g[2]]; +julia> W = [g[1]+g[3]+g[4], g[2]+g[4], g[1]+g[3], g[2], g[1]+g[2]] +5-element Vector{GrpAbFinGenElem}: + Element of G with components [1 0 1 1] + Element of G with components [0 1 0 1] + Element of G with components [1 0 1 0] + Element of G with components [0 1 0 0] + Element of G with components [1 1 0 0] julia> S, x = grade(R, W) (Graded multivariate polynomial ring in 5 variables over QQ, MPolyDecRingElem{QQFieldElem, QQMPolyRingElem}[x[1], x[2], x[3], x[4], x[5]]) ``` """ -function grade(R::MPolyRing, v::Vector{GrpAbFinGenElem}) +function grade(R::MPolyRing, v::AbstractVector{GrpAbFinGenElem}) S = MPolyDecRing(R, v) return S, map(S, gens(R)) end @@ -665,7 +659,7 @@ end # ################################################################################ -function factor(x::Oscar.MPolyDecRingElem) +function factor(x::MPolyDecRingElem) R = parent(x) D = Dict{elem_type(R), Int64}() F = factor(forget_decoration(x)) @@ -680,12 +674,12 @@ function factor(x::Oscar.MPolyDecRingElem) #end end -function gcd(x::Oscar.MPolyDecRingElem, y::Oscar.MPolyDecRingElem) +function gcd(x::MPolyDecRingElem, y::MPolyDecRingElem) R = parent(x) return R(gcd(forget_decoration(x), forget_decoration(y))) end -function div(x::Oscar.MPolyDecRingElem, y::Oscar.MPolyDecRingElem) +function div(x::MPolyDecRingElem, y::MPolyDecRingElem) R = parent(x) return R(div(forget_decoration(x), forget_decoration(y))) end @@ -827,18 +821,13 @@ Given a homogeneous element `f` of a $\mathbb Z$-graded multivariate ring, retur # Examples ```jldoctest -julia> R, x = polynomial_ring(QQ, "x" => 1:5) -(Multivariate polynomial ring in 5 variables over QQ, QQMPolyRingElem[x[1], x[2], x[3], x[4], x[5]]) - julia> G = abelian_group([0, 0, 2, 2]) (General) abelian group with relation matrix [0 0 0 0; 0 0 0 0; 0 0 2 0; 0 0 0 2] -julia> g = gens(G); - -julia> W = [g[1]+g[3]+g[4], g[2]+g[4], g[1]+g[3], g[2], g[1]+g[2]]; +julia> W = [G[1]+G[3]+G[4], G[2]+G[4], G[1]+G[3], G[2], G[1]+G[2]]; -julia> S, x = grade(R, W) +julia> S, x = graded_polynomial_ring(QQ, "x" => 1:5; weights=W) (Graded multivariate polynomial ring in 5 variables over QQ, MPolyDecRingElem{QQFieldElem, QQMPolyRingElem}[x[1], x[2], x[3], x[4], x[5]]) julia> f = x[2]^2+2*x[4]^2 @@ -987,18 +976,13 @@ Dict{GrpAbFinGenElem, MPolyDecRingElem{QQFieldElem, QQMPolyRingElem}} with 2 ent [2] => x^2 + y [3] => z -julia> R, x = polynomial_ring(QQ, "x" => 1:5) -(Multivariate polynomial ring in 5 variables over QQ, QQMPolyRingElem[x[1], x[2], x[3], x[4], x[5]]) - julia> G = abelian_group([0, 0, 2, 2]) (General) abelian group with relation matrix [0 0 0 0; 0 0 0 0; 0 0 2 0; 0 0 0 2] -julia> g = gens(G); - -julia> W = [g[1]+g[3]+g[4], g[2]+g[4], g[1]+g[3], g[2], g[1]+g[2]]; +julia> W = [G[1]+G[3]+G[4], G[2]+G[4], G[1]+G[3], G[2], G[1]+G[2]]; -julia> S, x = grade(R, W) +julia> S, x = graded_polynomial_ring(QQ, "x" => 1:5; weights=W) (Graded multivariate polynomial ring in 5 variables over QQ, MPolyDecRingElem{QQFieldElem, QQMPolyRingElem}[x[1], x[2], x[3], x[4], x[5]]) julia> f = x[1]^2+x[3]^2+x[5]^2 @@ -1069,24 +1053,19 @@ homogeneous component of `f` whose degree is that element. # Examples ```jldoctest -julia> R, x = polynomial_ring(QQ, "x" => 1:5) -(Multivariate polynomial ring in 5 variables over QQ, QQMPolyRingElem[x[1], x[2], x[3], x[4], x[5]]) - julia> G = abelian_group([0, 0, 2, 2]) (General) abelian group with relation matrix [0 0 0 0; 0 0 0 0; 0 0 2 0; 0 0 0 2] -julia> g = gens(G); - -julia> W = [g[1]+g[3]+g[4], g[2]+g[4], g[1]+g[3], g[2], g[1]+g[2]]; +julia> W = [G[1]+G[3]+G[4], G[2]+G[4], G[1]+G[3], G[2], G[1]+G[2]]; -julia> S, x = grade(R, W) +julia> S, x = graded_polynomial_ring(QQ, "x" => 1:5; weights=W) (Graded multivariate polynomial ring in 5 variables over QQ, MPolyDecRingElem{QQFieldElem, QQMPolyRingElem}[x[1], x[2], x[3], x[4], x[5]]) julia> f = x[1]^2+x[3]^2+x[5]^2 x[1]^2 + x[3]^2 + x[5]^2 -julia> homogeneous_component(f, 2*g[1]) +julia> homogeneous_component(f, 2*G[1]) x[1]^2 + x[3]^2 julia> W = [[1, 0], [0, 1], [1, 0], [4, 1]] @@ -1096,7 +1075,7 @@ julia> W = [[1, 0], [0, 1], [1, 0], [4, 1]] [1, 0] [4, 1] -julia> R, x = graded_polynomial_ring(QQ, ["x[1]", "x[2]", "x[3]", "x[4]"], W) +julia> R, x = graded_polynomial_ring(QQ, :x => 1:4; weights=W) (Graded multivariate polynomial ring in 4 variables over QQ, MPolyDecRingElem{QQFieldElem, QQMPolyRingElem}[x[1], x[2], x[3], x[4]]) julia> f = x[1]^2*x[2]+x[4] @@ -1105,7 +1084,7 @@ x[1]^2*x[2] + x[4] julia> homogeneous_component(f, [2, 1]) x[1]^2*x[2] -julia> R, (x, y, z) = graded_polynomial_ring(QQ, ["x", "y", "z"], [1, 2, 3]) +julia> R, (x, y, z) = graded_polynomial_ring(QQ, ["x", "y", "z"]; weights=[1, 2, 3]) (Graded multivariate polynomial ring in 3 variables over QQ, MPolyDecRingElem{QQFieldElem, QQMPolyRingElem}[x, y, z]) julia> f = x^2+y+z @@ -1162,7 +1141,7 @@ function show_homo_comp(io::IO, M) if n !== nothing print(io, "$(n)_$(d.coeff) of dim $(dim(M))") else - println(io, "homogeneous component of $W of degree $d") + print(io, "homogeneous component of $W of degree $d") end end @@ -1271,14 +1250,12 @@ proceed as above. # Examples ```jldoctest -julia> R, x, y = polynomial_ring(QQ, "x" => 1:2, "y" => 1:3); - julia> W = [1 1 0 0 0; 0 0 1 1 1] 2×5 Matrix{Int64}: 1 1 0 0 0 0 0 1 1 1 -julia> S, _ = grade(R, W); +julia> S, _ = graded_polynomial_ring(QQ, "x" => 1:2, "y" => 1:3; weights = W); julia> G = grading_group(S) GrpAb: Z^2 @@ -1637,13 +1614,9 @@ function _homogenization(f::MPolyRingElem, W::ZZMatrix, var::VarName, pos::Int) insert!(A, pos-1+i, _make_variable(var, i)) end end - L, _ = polynomial_ring(base_ring(R), A) - Lgens = gens(L) - ###ff = evaluate(f, vcat(Lgens[1:pos-1], Lgens[pos + size(W, 1):end])) G = abelian_group(zeros(Int, size(W, 1))) WH = hcat(Matrix(W[:, 1:(pos-1)]), Matrix(identity_matrix(ZZ, size(W, 1))[:, 1:size(W, 1)]), Matrix(W[:, pos:l])) - S, _ = grade(L, [G(WH[:, i]) for i = 1:size(WH, 2)]) - ###return _homogenization(ff, S, pos) + S, _ = graded_polynomial_ring(base_ring(R), A; weights = [G(WH[:, i]) for i = 1:size(WH, 2)]) return _homogenization(f, S, pos) end From 3c8e0ed22a47d552759aa61ba8359d49a35c597c Mon Sep 17 00:00:00 2001 From: Max Horn Date: Mon, 23 Oct 2023 14:18:44 +0200 Subject: [PATCH 12/27] Fix show(io::IO, P::ProjSpc) (#2945) --- .../PlaneCurve/docs/src/elliptic_curves.md | 3 +-- .../PlaneCurve/docs/src/plane_curves.md | 3 +-- experimental/PlaneCurve/src/DivisorCurve.jl | 21 +++++++------------ experimental/PlaneCurve/src/ProjCurve.jl | 3 +-- .../PlaneCurve/src/ProjEllipticCurve.jl | 9 +++----- experimental/PlaneCurve/src/ProjPlaneCurve.jl | 9 +++----- src/AlgebraicGeometry/Miscellaneous/basics.jl | 4 ++-- 7 files changed, 18 insertions(+), 34 deletions(-) diff --git a/experimental/PlaneCurve/docs/src/elliptic_curves.md b/experimental/PlaneCurve/docs/src/elliptic_curves.md index 3f3ee68e3621..54b08251a8b4 100644 --- a/experimental/PlaneCurve/docs/src/elliptic_curves.md +++ b/experimental/PlaneCurve/docs/src/elliptic_curves.md @@ -127,8 +127,7 @@ julia> E = Oscar.ProjEllipticCurve(T(y^2*z - x^3 - 10*x*z^2 + 2*z^3)) Projective elliptic curve defined by 4452*x^3 + 4443*x*z^2 + y^2*z + 2*z^3 julia> PP = proj_space(A, 2) -(Projective space of dim 2 over Integers modulo 4453 -, MPolyDecRingElem{ZZModRingElem, AbstractAlgebra.Generic.MPoly{ZZModRingElem}}[x[0], x[1], x[2]]) +(Projective space of dim 2 over Integers modulo 4453, MPolyDecRingElem{ZZModRingElem, AbstractAlgebra.Generic.MPoly{ZZModRingElem}}[x[0], x[1], x[2]]) julia> Q = Oscar.Geometry.ProjSpcElem(PP[1], [A(1), A(3), A(1)]) (1 : 3 : 1) diff --git a/experimental/PlaneCurve/docs/src/plane_curves.md b/experimental/PlaneCurve/docs/src/plane_curves.md index 7eff7b0220b6..6bbd1854183f 100644 --- a/experimental/PlaneCurve/docs/src/plane_curves.md +++ b/experimental/PlaneCurve/docs/src/plane_curves.md @@ -77,8 +77,7 @@ julia> K = QQ Rational field julia> PP = proj_space(K, 2) -(Projective space of dim 2 over Rational field -, MPolyDecRingElem{QQFieldElem, QQMPolyRingElem}[x[0], x[1], x[2]]) +(Projective space of dim 2 over Rational field, MPolyDecRingElem{QQFieldElem, QQMPolyRingElem}[x[0], x[1], x[2]]) ``` diff --git a/experimental/PlaneCurve/src/DivisorCurve.jl b/experimental/PlaneCurve/src/DivisorCurve.jl index 1e64b631459e..cc60a05bd45e 100644 --- a/experimental/PlaneCurve/src/DivisorCurve.jl +++ b/experimental/PlaneCurve/src/DivisorCurve.jl @@ -90,8 +90,7 @@ julia> C = ProjPlaneCurve(T(y^2 + y*z + x^2)) Projective plane curve defined by x^2 + y^2 + y*z julia> PP = proj_space(QQ, 2) -(Projective space of dim 2 over Rational field -, MPolyDecRingElem{QQFieldElem, QQMPolyRingElem}[x[0], x[1], x[2]]) +(Projective space of dim 2 over Rational field, MPolyDecRingElem{QQFieldElem, QQMPolyRingElem}[x[0], x[1], x[2]]) julia> P = Oscar.Geometry.ProjSpcElem(PP[1], [QQ(0), QQ(0), QQ(1)]) (0 : 0 : 1) @@ -308,8 +307,7 @@ julia> C = ProjPlaneCurve(T(y^2 + y*z + x^2)) Projective plane curve defined by x^2 + y^2 + y*z julia> PP = proj_space(QQ, 2) -(Projective space of dim 2 over Rational field -, MPolyDecRingElem{QQFieldElem, QQMPolyRingElem}[x[0], x[1], x[2]]) +(Projective space of dim 2 over Rational field, MPolyDecRingElem{QQFieldElem, QQMPolyRingElem}[x[0], x[1], x[2]]) julia> P = Oscar.Geometry.ProjSpcElem(PP[1], [QQ(0), QQ(0), QQ(1)]) (0 : 0 : 1) @@ -452,8 +450,7 @@ julia> C = ProjPlaneCurve(T(y^2 + y*z + x^2)) Projective plane curve defined by x^2 + y^2 + y*z julia> PP = proj_space(QQ, 2) -(Projective space of dim 2 over Rational field -, MPolyDecRingElem{QQFieldElem, QQMPolyRingElem}[x[0], x[1], x[2]]) +(Projective space of dim 2 over Rational field, MPolyDecRingElem{QQFieldElem, QQMPolyRingElem}[x[0], x[1], x[2]]) julia> phi = T(x)//T(y) x//y @@ -597,8 +594,7 @@ julia> C = ProjPlaneCurve(T(y^2*z - x*(x-z)*(x+3*z))) Projective plane curve defined by -x^3 - 2*x^2*z + 3*x*z^2 + y^2*z julia> PP = proj_space(QQ, 2) -(Projective space of dim 2 over Rational field -, MPolyDecRingElem{QQFieldElem, QQMPolyRingElem}[x[0], x[1], x[2]]) +(Projective space of dim 2 over Rational field, MPolyDecRingElem{QQFieldElem, QQMPolyRingElem}[x[0], x[1], x[2]]) julia> P = Oscar.Geometry.ProjSpcElem(PP[1], [QQ(0), QQ(1), QQ(0)]) (0 : 1 : 0) @@ -693,8 +689,7 @@ julia> C = ProjPlaneCurve(T(y^2*z - x*(x-z)*(x+3*z))) Projective plane curve defined by -x^3 - 2*x^2*z + 3*x*z^2 + y^2*z julia> PP = proj_space(QQ, 2) -(Projective space of dim 2 over Rational field -, MPolyDecRingElem{QQFieldElem, QQMPolyRingElem}[x[0], x[1], x[2]]) +(Projective space of dim 2 over Rational field, MPolyDecRingElem{QQFieldElem, QQMPolyRingElem}[x[0], x[1], x[2]]) julia> P = Oscar.Geometry.ProjSpcElem(PP[1], [QQ(0), QQ(1), QQ(0)]) (0 : 1 : 0) @@ -734,8 +729,7 @@ julia> C = ProjPlaneCurve(T(y^2*z - x*(x-z)*(x+3*z))) Projective plane curve defined by -x^3 - 2*x^2*z + 3*x*z^2 + y^2*z julia> PP = proj_space(QQ, 2) -(Projective space of dim 2 over Rational field -, MPolyDecRingElem{QQFieldElem, QQMPolyRingElem}[x[0], x[1], x[2]]) +(Projective space of dim 2 over Rational field, MPolyDecRingElem{QQFieldElem, QQMPolyRingElem}[x[0], x[1], x[2]]) julia> P = Oscar.Geometry.ProjSpcElem(PP[1], [QQ(0), QQ(1), QQ(0)]) (0 : 1 : 0) @@ -773,8 +767,7 @@ julia> C = ProjPlaneCurve(T(y^2*z - x*(x-z)*(x+3*z))) Projective plane curve defined by -x^3 - 2*x^2*z + 3*x*z^2 + y^2*z julia> PP = proj_space(QQ, 2) -(Projective space of dim 2 over Rational field -, MPolyDecRingElem{QQFieldElem, QQMPolyRingElem}[x[0], x[1], x[2]]) +(Projective space of dim 2 over Rational field, MPolyDecRingElem{QQFieldElem, QQMPolyRingElem}[x[0], x[1], x[2]]) julia> P = Oscar.Geometry.ProjSpcElem(PP[1], [QQ(0), QQ(1), QQ(0)]) (0 : 1 : 0) diff --git a/experimental/PlaneCurve/src/ProjCurve.jl b/experimental/PlaneCurve/src/ProjCurve.jl index ee58d9a94f62..9f9dbd85b9f3 100644 --- a/experimental/PlaneCurve/src/ProjCurve.jl +++ b/experimental/PlaneCurve/src/ProjCurve.jl @@ -92,8 +92,7 @@ Projective curve defined by the ideal(x^2, y^2*z, z^2) julia> PP = proj_space(QQ, 3) -(Projective space of dim 3 over Rational field -, MPolyDecRingElem{QQFieldElem, QQMPolyRingElem}[x[0], x[1], x[2], x[3]]) +(Projective space of dim 3 over Rational field, MPolyDecRingElem{QQFieldElem, QQMPolyRingElem}[x[0], x[1], x[2], x[3]]) julia> P = Oscar.Geometry.ProjSpcElem(PP[1], [QQ(0), QQ(2), QQ(0), QQ(5)]) (0 : 2 : 0 : 5) diff --git a/experimental/PlaneCurve/src/ProjEllipticCurve.jl b/experimental/PlaneCurve/src/ProjEllipticCurve.jl index 7c36297756cf..e2446c4519f2 100644 --- a/experimental/PlaneCurve/src/ProjEllipticCurve.jl +++ b/experimental/PlaneCurve/src/ProjEllipticCurve.jl @@ -158,8 +158,7 @@ julia> F = T(-x^3 - 3*x^2*y - 3*x*y^2 - x*z^2 - y^3 + y^2*z - y*z^2 - 4*z^3) -x^3 - 3*x^2*y - 3*x*y^2 - x*z^2 - y^3 + y^2*z - y*z^2 - 4*z^3 julia> PP = proj_space(QQ, 2) -(Projective space of dim 2 over Rational field -, MPolyDecRingElem{QQFieldElem, QQMPolyRingElem}[x[0], x[1], x[2]]) +(Projective space of dim 2 over Rational field, MPolyDecRingElem{QQFieldElem, QQMPolyRingElem}[x[0], x[1], x[2]]) julia> P = Oscar.Geometry.ProjSpcElem(PP[1], [QQ(-1), QQ(1), QQ(0)]) (-1 : 1 : 0) @@ -274,8 +273,7 @@ julia> F = T(-x^3 - 3*x^2*y - 3*x*y^2 - x*z^2 - y^3 + y^2*z - y*z^2 - 4*z^3) -x^3 - 3*x^2*y - 3*x*y^2 - x*z^2 - y^3 + y^2*z - y*z^2 - 4*z^3 julia> PP = proj_space(QQ, 2) -(Projective space of dim 2 over Rational field -, MPolyDecRingElem{QQFieldElem, QQMPolyRingElem}[x[0], x[1], x[2]]) +(Projective space of dim 2 over Rational field, MPolyDecRingElem{QQFieldElem, QQMPolyRingElem}[x[0], x[1], x[2]]) julia> P = Oscar.Geometry.ProjSpcElem(PP[1], [QQ(-1), QQ(1), QQ(0)]) (-1 : 1 : 0) @@ -562,8 +560,7 @@ julia> T, _ = grade(S) (Graded multivariate polynomial ring in 3 variables over QQ, MPolyDecRingElem{QQFieldElem, QQMPolyRingElem}[x, y, z]) julia> PP = proj_space(QQ, 2) -(Projective space of dim 2 over Rational field -, MPolyDecRingElem{QQFieldElem, QQMPolyRingElem}[x[0], x[1], x[2]]) +(Projective space of dim 2 over Rational field, MPolyDecRingElem{QQFieldElem, QQMPolyRingElem}[x[0], x[1], x[2]]) julia> Q = Oscar.Geometry.ProjSpcElem(PP[1], [QQ(-1), QQ(1), QQ(0)]) (-1 : 1 : 0) diff --git a/experimental/PlaneCurve/src/ProjPlaneCurve.jl b/experimental/PlaneCurve/src/ProjPlaneCurve.jl index 03f06c7765ea..f46d72f9c2de 100644 --- a/experimental/PlaneCurve/src/ProjPlaneCurve.jl +++ b/experimental/PlaneCurve/src/ProjPlaneCurve.jl @@ -38,8 +38,7 @@ julia> C = ProjPlaneCurve(x^2*(x+y)*(y^3-x^2*z)) Projective plane curve defined by -x^5*z - x^4*y*z + x^3*y^3 + x^2*y^4 julia> PP = proj_space(QQ, 2) -(Projective space of dim 2 over Rational field -, MPolyDecRingElem{QQFieldElem, QQMPolyRingElem}[x[0], x[1], x[2]]) +(Projective space of dim 2 over Rational field, MPolyDecRingElem{QQFieldElem, QQMPolyRingElem}[x[0], x[1], x[2]]) julia> P = Oscar.Geometry.ProjSpcElem(PP[1], [QQ(0), QQ(0), QQ(1)]) (0 : 0 : 1) @@ -77,8 +76,7 @@ julia> T, _ = grade(S) (Graded multivariate polynomial ring in 3 variables over QQ, MPolyDecRingElem{QQFieldElem, QQMPolyRingElem}[x, y, z]) julia> PP = proj_space(QQ, 2) -(Projective space of dim 2 over Rational field -, MPolyDecRingElem{QQFieldElem, QQMPolyRingElem}[x[0], x[1], x[2]]) +(Projective space of dim 2 over Rational field, MPolyDecRingElem{QQFieldElem, QQMPolyRingElem}[x[0], x[1], x[2]]) julia> C = ProjPlaneCurve(x^2*(x+y)*(y^3-x^2*z)) Projective plane curve defined by -x^5*z - x^4*y*z + x^3*y^3 + x^2*y^4 @@ -155,8 +153,7 @@ julia> T, _ = grade(S) (Graded multivariate polynomial ring in 3 variables over QQ, MPolyDecRingElem{QQFieldElem, QQMPolyRingElem}[x, y, z]) julia> PP = proj_space(QQ, 2) -(Projective space of dim 2 over Rational field -, MPolyDecRingElem{QQFieldElem, QQMPolyRingElem}[x[0], x[1], x[2]]) +(Projective space of dim 2 over Rational field, MPolyDecRingElem{QQFieldElem, QQMPolyRingElem}[x[0], x[1], x[2]]) julia> C = ProjPlaneCurve(T(x+y+z)) Projective plane curve defined by x + y + z diff --git a/src/AlgebraicGeometry/Miscellaneous/basics.jl b/src/AlgebraicGeometry/Miscellaneous/basics.jl index 5c6d8dc02db0..224cc2978cb8 100644 --- a/src/AlgebraicGeometry/Miscellaneous/basics.jl +++ b/src/AlgebraicGeometry/Miscellaneous/basics.jl @@ -21,9 +21,9 @@ end function Base.show(io::IO, P::ProjSpc) w = weights(P) if all(isone, w) - print(io, "Projective space of dim $(P.n) over $(P.R)\n") + print(io, "Projective space of dim $(P.n) over $(P.R)") else - print(io, "Weighted projective space of dim $(P.n) over $(P.R) and weights $(w)\n") + print(io, "Weighted projective space of dim $(P.n) over $(P.R) and weights $(w)") end end From 5c0e24c53f221957a88118a64f171c3ca7cbe214 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Mon, 23 Oct 2023 14:21:32 +0200 Subject: [PATCH 13/27] Fix test failures caused by `is_welldefined(M3_to_M1)` (#2946) The test being edited produces random modules and random morphisms. If by bad look things are aligned badly, then the resulting morphism may be not well-defined, If that happens, just skip to the next test case. --- test/Modules/UngradedModules.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Modules/UngradedModules.jl b/test/Modules/UngradedModules.jl index 077ec5d21b18..7c6fe9c20f7d 100644 --- a/test/Modules/UngradedModules.jl +++ b/test/Modules/UngradedModules.jl @@ -693,7 +693,7 @@ end N,pure_N = tensor_product(M3,F4, task=:map) M3_to_M1 = SubQuoHom(M3,M1, matrix([randpoly(R,0:2,2,2) for i=1:ngens(M3), j=1:ngens(M1)])) - @assert is_welldefined(M3_to_M1) + is_welldefined(M3_to_M1) || continue F4_to_M2 = FreeModuleHom(F4,M2, matrix([randpoly(R,0:2,2,2) for i=1:ngens(F4), j=1:ngens(M2)])) phi = hom_tensor(N,M,[M3_to_M1,F4_to_M2]) From 3d23939bd0ab75d2a4789c8ca92a7694e5146dc8 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Mon, 23 Oct 2023 14:28:18 +0200 Subject: [PATCH 14/27] Use graded_polynomial_ring in yet more places (#2924) --- experimental/GITFans/test/runtests.jl | 3 +- experimental/IntersectionTheory/src/Bott.jl | 2 +- experimental/IntersectionTheory/src/Main.jl | 20 +-- .../PlaneCurve/docs/src/elliptic_curves.md | 14 +- .../PlaneCurve/src/AffinePlaneCurve.jl | 6 +- experimental/PlaneCurve/src/DivisorCurve.jl | 35 +--- experimental/PlaneCurve/src/ProjPlaneCurve.jl | 26 +-- experimental/PlaneCurve/test/runtests.jl | 115 +++++------- .../Schemes/CoveredProjectiveSchemes.jl | 2 +- .../src/homogeneous_polynomial_actions.jl | 4 +- .../src/representations.jl | 2 +- .../src/symmetric_grassmannians.jl | 6 +- .../SymmetricIntersections/test/runtests.jl | 5 +- src/AlgebraicGeometry/Miscellaneous/basics.jl | 10 +- src/InvariantTheory/affine_algebra.jl | 3 +- src/InvariantTheory/types.jl | 2 +- src/Modules/hilbert.jl | 4 +- src/Rings/MPolyQuo.jl | 13 +- src/Rings/mpoly-graded.jl | 6 +- .../Schemes/FunctionFields.jl | 3 +- .../AlgebraicGeometry/Schemes/IdealSheaves.jl | 3 +- .../Schemes/ProjectiveAlgebraicSet.jl | 3 +- .../Schemes/ProjectiveSchemes.jl | 9 +- .../Schemes/ProjectiveVarieties.jl | 3 +- test/AlgebraicGeometry/Schemes/WeilDivisor.jl | 3 +- test/AlgebraicGeometry/Schemes/transforms.jl | 3 +- test/Modules/ModulesGraded.jl | 167 ++++++------------ test/Modules/hilbert.jl | 4 +- test/Rings/MPolyQuo.jl | 2 +- test/Rings/mpoly-graded.jl | 2 +- 30 files changed, 171 insertions(+), 309 deletions(-) diff --git a/experimental/GITFans/test/runtests.jl b/experimental/GITFans/test/runtests.jl index 101cb3e4cf59..9ff3eb6156ab 100644 --- a/experimental/GITFans/test/runtests.jl +++ b/experimental/GITFans/test/runtests.jl @@ -17,10 +17,9 @@ ] n = nrows(Q) - Qt, T = polynomial_ring(QQ, :T => 1:n) D = free_abelian_group(ncols(Q)) w = [D(Q[i, :]) for i = 1:n] - R, T = grade(Qt, w) + R, T = graded_polynomial_ring(QQ, :T => 1:n, w) a = ideal([ T[5]*T[10] - T[6]*T[9] + T[7]*T[8], T[1]*T[9] - T[2]*T[7] + T[4]*T[5], diff --git a/experimental/IntersectionTheory/src/Bott.jl b/experimental/IntersectionTheory/src/Bott.jl index f4c6250dec7a..d703c72460fa 100644 --- a/experimental/IntersectionTheory/src/Bott.jl +++ b/experimental/IntersectionTheory/src/Bott.jl @@ -125,7 +125,7 @@ Base.show(io::IO, c::TnBundleChern) = print(io, "Chern class $(c.c) of $(c.F)") function _get_ring(F::TnBundle) if get_attribute(F, :R) === nothing r = min(F.parent.dim, F.rank) - R, _ = grade(polynomial_ring(QQ, _parse_symbol("c", 1:r))[1], collect(1:r)) + R, _ = graded_polynomial_ring(QQ, _parse_symbol("c", 1:r), collect(1:r)) set_attribute!(R, :abstract_variety_dim => F.parent.dim) set_attribute!(F, :R => R) end diff --git a/experimental/IntersectionTheory/src/Main.jl b/experimental/IntersectionTheory/src/Main.jl index c5d68c7a7989..199f099ce51b 100644 --- a/experimental/IntersectionTheory/src/Main.jl +++ b/experimental/IntersectionTheory/src/Main.jl @@ -210,7 +210,7 @@ Return the abstract variety and the list of classes. """ function abstract_variety(n::Int, symbols::Vector{String}, degs::Vector{Int}; base::Ring=QQ) @assert length(symbols) > 0 - R, x = grade(polynomial_ring(base, symbols)[1], degs) + R, x = graded_polynomial_ring(base, symbols, degs) return AbstractVariety(n, R), x end @@ -533,7 +533,7 @@ function *(X::AbstractVariety, Y::AbstractVariety) A, B = X.ring, Y.ring symsA, symsB = string.(gens(A)), string.(gens(B)) a = length(symsA) - R, x = grade(polynomial_ring(base, vcat(symsA, symsB))[1], vcat(gradings(A), gradings(B))) + R, x = graded_polynomial_ring(base, vcat(symsA, symsB), vcat(gradings(A), gradings(B))) # TODO: fails with check = true AtoR = hom(A, R, x[1:a], check = false) BtoR = hom(B, R, x[a+1:end], check = false) @@ -860,7 +860,7 @@ function _genus(x::MPolyDecRingOrQuoElem, taylor::Vector{}) R = parent(x) iszero(x) && return R(1) n = get_attribute(R, :abstract_variety_dim) - R, (t,) = grade(polynomial_ring(QQ, ["t"])[1]) + R, (t,) = graded_polynomial_ring(QQ, ["t"]) set_attribute!(R, :abstract_variety_dim, n) lg = _logg(R(sum(taylor[i+1] * t^i for i in 0:n))) comps = lg[1:n] @@ -896,7 +896,7 @@ for (g,s) in [:a_hat_genus=>"p", :l_genus=>"p", :todd_class=>"c"] _g = Symbol("_", g) @eval function $g(n::Int) n == 0 && return QQ(1) - R, p = grade(polynomial_ring(QQ, _parse_symbol($s, 1:n))[1], collect(1:n)) + R, p = graded_polynomial_ring(QQ, _parse_symbol($s, 1:n), collect(1:n)) set_attribute!(R, :abstract_variety_dim, n) $_g(_logg(R(1+sum(p))))[n] end @@ -1014,7 +1014,7 @@ end Construct a point as an abstract abstract_variety. """ function point(; base::Ring=QQ) - R, (p,) = grade(polynomial_ring(base, ["p"])[1]) + R, (p,) = graded_polynomial_ring(base, ["p"]) I = ideal([p]) pt = AbstractVariety(0, quo(R, I)[1]) pt.point = pt(1) @@ -1032,7 +1032,7 @@ Construct an abstract projective space of dimension $n$, parametrizing 1-dimensional *subspaces* of a vector space of dimension $n+1$. """ function abstract_projective_space(n::Int; base::Ring=QQ, symbol::String="h") - R, (h,) = grade(polynomial_ring(base, [symbol])[1]) + R, (h,) = graded_polynomial_ring(base, [symbol]) I = ideal([h^(n+1)]) AP = quo(R, I)[1] P = AbstractVariety(n, AP) @@ -1068,7 +1068,7 @@ function abstract_projective_bundle(F::AbstractBundle; symbol::String="h") # ord = ordering_dp(1) * R.R.ord # construct the ring w = vcat([1], gradings(R)) - R1, (h,) = grade(polynomial_ring(X.base, syms)[1], w) + R1, (h,) = graded_polynomial_ring(X.base, syms, w) # TODO: why does this fail with check = true pback = hom(R, R1, gens(R1)[2:end], check = false) pfwd = hom(R1, R, pushfirst!(gens(R), R())) @@ -1115,7 +1115,7 @@ function abs_grassmannian(k::Int, n::Int; base::Ring=QQ, symbol::String="c") @assert k < n d = k*(n-k) - R, c = grade(polynomial_ring(base, _parse_symbol(symbol, 1:k))[1], collect(1:k)) + R, c = graded_polynomial_ring(base, _parse_symbol(symbol, 1:k), collect(1:k)) inv_c = sum((-sum(c))^i for i in 1:n) # this is c(Q) since c(S)⋅c(Q) = 1 # Q is of rank n-k: the vanishing of Chern classes in higher degrees provides all the relations for the Chow ring AGr = quo(R, ideal(inv_c[n-k+1:n]))[1] @@ -1164,7 +1164,7 @@ function abs_flag(dims::Vector{Int}; base::Ring=QQ, symbol::String="c") syms = vcat([_parse_symbol(symbol, i, 1:r) for (i,r) in enumerate(ranks)]...) # FIXME ordering # ord = prod(ordering_dp(r) for r in ranks) - R = grade(polynomial_ring(base, syms)[1], vcat([collect(1:r) for r in ranks]...))[1] + R = graded_polynomial_ring(base, syms, vcat([collect(1:r) for r in ranks]...))[1] c = pushfirst!([1+sum(gens(R)[dims[i]+1:dims[i+1]]) for i in 1:l-1], 1+sum(gens(R)[1:dims[1]])) gi = prod(c)[0:n] # XXX cannot mod using graded ring element @@ -1218,7 +1218,7 @@ function abstract_flag_variety(F::AbstractBundle, dims::Vector{Int}; symbol::Str syms = vcat([_parse_symbol(symbol, i, 1:r) for (i,r) in enumerate(ranks)]..., string.(gens(R.R))) # ord = prod(ordering_dp(r) for r in ranks) * ordering(X.ring.R.R) w = vcat([collect(1:r) for r in ranks]..., gradings(R)) - R1 = grade(polynomial_ring(X.base, syms)[1], w)[1] + R1 = graded_polynomial_ring(X.base, syms, w)[1] pback = hom(R, R1, gens(R1)[n+1:end]) pfwd = hom(R1, R, vcat(repeat([R()], n), gens(R))) diff --git a/experimental/PlaneCurve/docs/src/elliptic_curves.md b/experimental/PlaneCurve/docs/src/elliptic_curves.md index 54b08251a8b4..e58c2213d76e 100644 --- a/experimental/PlaneCurve/docs/src/elliptic_curves.md +++ b/experimental/PlaneCurve/docs/src/elliptic_curves.md @@ -44,13 +44,10 @@ Addition and multiplication by an integer of a point on an elliptic curve can be #### Example ```jldoctest -julia> S, (x, y, z) = polynomial_ring(QQ, ["x", "y", "z"]) -(Multivariate polynomial ring in 3 variables over QQ, QQMPolyRingElem[x, y, z]) - -julia> T, _ = grade(S) +julia> T, (x, y, z) = graded_polynomial_ring(QQ, ["x", "y", "z"]) (Graded multivariate polynomial ring in 3 variables over QQ, MPolyDecRingElem{QQFieldElem, QQMPolyRingElem}[x, y, z]) -julia> E = Oscar.ProjEllipticCurve(T(y^2*z - x^3 + 2*x*z^2)) +julia> E = Oscar.ProjEllipticCurve(y^2*z - x^3 + 2*x*z^2) Projective elliptic curve defined by -x^3 + 2*x*z^2 + y^2*z julia> PP = Oscar.proj_space(E) @@ -117,13 +114,10 @@ julia> n = 4453 julia> A = residue_ring(ZZ, ZZ(n)) Integers modulo 4453 -julia> S, (x,y,z) = polynomial_ring(A, ["x", "y", "z"]) -(Multivariate polynomial ring in 3 variables over ZZ/(4453), AbstractAlgebra.Generic.MPoly{ZZModRingElem}[x, y, z]) - -julia> T, _ = grade(S) +julia> T, (x,y,z) = graded_polynomial_ring(A, ["x", "y", "z"]) (Graded multivariate polynomial ring in 3 variables over ZZ/(4453), MPolyDecRingElem{ZZModRingElem, AbstractAlgebra.Generic.MPoly{ZZModRingElem}}[x, y, z]) -julia> E = Oscar.ProjEllipticCurve(T(y^2*z - x^3 - 10*x*z^2 + 2*z^3)) +julia> E = Oscar.ProjEllipticCurve(y^2*z - x^3 - 10*x*z^2 + 2*z^3) Projective elliptic curve defined by 4452*x^3 + 4443*x*z^2 + y^2*z + 2*z^3 julia> PP = proj_space(A, 2) diff --git a/experimental/PlaneCurve/src/AffinePlaneCurve.jl b/experimental/PlaneCurve/src/AffinePlaneCurve.jl index f9ce00932a4c..80935f7b1730 100644 --- a/experimental/PlaneCurve/src/AffinePlaneCurve.jl +++ b/experimental/PlaneCurve/src/AffinePlaneCurve.jl @@ -520,8 +520,7 @@ Return the arithmetic genus of the projective closure of `C`. function arithmetic_genus(C::AffinePlaneCurve) F = defining_equation(C) K = base_ring(parent(F)) - R, (x, y, z) = polynomial_ring(K, ["x", "y", "z"]) - T, _ = grade(R) + T, _ = graded_polynomial_ring(K, ["x", "y", "z"]) G = homogenization(F, T; pos=3) D = ProjPlaneCurve(G) return arithmetic_genus(D) @@ -549,8 +548,7 @@ julia> geometric_genus(C) function geometric_genus(C::AffinePlaneCurve) F = defining_equation(C) K = base_ring(parent(F)) - R, (x, y, z) = polynomial_ring(K, ["x", "y", "z"]) - T, _ = grade(R) + T, _ = graded_polynomial_ring(K, ["x", "y", "z"]) G = homogenization(F, T; pos=3) D = ProjPlaneCurve(G) return geometric_genus(D) diff --git a/experimental/PlaneCurve/src/DivisorCurve.jl b/experimental/PlaneCurve/src/DivisorCurve.jl index cc60a05bd45e..24872c1afa68 100644 --- a/experimental/PlaneCurve/src/DivisorCurve.jl +++ b/experimental/PlaneCurve/src/DivisorCurve.jl @@ -80,10 +80,7 @@ Given a curve `C` which is assumed to be smooth and irreducible, return the divi # Examples ```jldoctest -julia> S, (x,y,z) = polynomial_ring(QQ, ["x", "y", "z"]) -(Multivariate polynomial ring in 3 variables over QQ, QQMPolyRingElem[x, y, z]) - -julia> T, _ = grade(S) +julia> T, (x,y,z) = graded_polynomial_ring(QQ, ["x", "y", "z"]) (Graded multivariate polynomial ring in 3 variables over QQ, MPolyDecRingElem{QQFieldElem, QQMPolyRingElem}[x, y, z]) julia> C = ProjPlaneCurve(T(y^2 + y*z + x^2)) @@ -297,10 +294,7 @@ Return the multiplicity of the rational function `phi` on the curve `C` at the p # Examples ```jldoctest -julia> S, (x,y,z) = polynomial_ring(QQ, ["x", "y", "z"]) -(Multivariate polynomial ring in 3 variables over QQ, QQMPolyRingElem[x, y, z]) - -julia> T, _ = grade(S) +julia> T, (x,y,z) = graded_polynomial_ring(QQ, ["x", "y", "z"]) (Graded multivariate polynomial ring in 3 variables over QQ, MPolyDecRingElem{QQFieldElem, QQMPolyRingElem}[x, y, z]) julia> C = ProjPlaneCurve(T(y^2 + y*z + x^2)) @@ -440,10 +434,7 @@ Return the divisor defined by the rational function `phi` on the curve `C`. # Examples ```jldoctest -julia> S, (x,y,z) = polynomial_ring(QQ, ["x", "y", "z"]) -(Multivariate polynomial ring in 3 variables over QQ, QQMPolyRingElem[x, y, z]) - -julia> T, _ = grade(S) +julia> T, (x,y,z) = graded_polynomial_ring(QQ, ["x", "y", "z"]) (Graded multivariate polynomial ring in 3 variables over QQ, MPolyDecRingElem{QQFieldElem, QQMPolyRingElem}[x, y, z]) julia> C = ProjPlaneCurve(T(y^2 + y*z + x^2)) @@ -584,10 +575,7 @@ Return a set of generators of the global sections of the sheaf associated to the # Examples ```jldoctest -julia> S, (x, y, z) = polynomial_ring(QQ, ["x", "y", "z"]) -(Multivariate polynomial ring in 3 variables over QQ, QQMPolyRingElem[x, y, z]) - -julia> T, _ = grade(S) +julia> T, (x,y,z) = graded_polynomial_ring(QQ, ["x", "y", "z"]) (Graded multivariate polynomial ring in 3 variables over QQ, MPolyDecRingElem{QQFieldElem, QQMPolyRingElem}[x, y, z]) julia> C = ProjPlaneCurve(T(y^2*z - x*(x-z)*(x+3*z))) @@ -679,10 +667,7 @@ otherwise # Examples ```jldoctest -julia> S, (x, y, z) = polynomial_ring(QQ, ["x", "y", "z"]) -(Multivariate polynomial ring in 3 variables over QQ, QQMPolyRingElem[x, y, z]) - -julia> T, _ = grade(S) +julia> T, (x,y,z) = graded_polynomial_ring(QQ, ["x", "y", "z"]) (Graded multivariate polynomial ring in 3 variables over QQ, MPolyDecRingElem{QQFieldElem, QQMPolyRingElem}[x, y, z]) julia> C = ProjPlaneCurve(T(y^2*z - x*(x-z)*(x+3*z))) @@ -719,10 +704,7 @@ Return `true` if the divisor `D` is principal, and `false` otherwise # Examples ```jldoctest -julia> S, (x, y, z) = polynomial_ring(QQ, ["x", "y", "z"]) -(Multivariate polynomial ring in 3 variables over QQ, QQMPolyRingElem[x, y, z]) - -julia> T, _ = grade(S) +julia> T, (x,y,z) = graded_polynomial_ring(QQ, ["x", "y", "z"]) (Graded multivariate polynomial ring in 3 variables over QQ, MPolyDecRingElem{QQFieldElem, QQMPolyRingElem}[x, y, z]) julia> C = ProjPlaneCurve(T(y^2*z - x*(x-z)*(x+3*z))) @@ -757,10 +739,7 @@ is linearly equivalent to the divisor defined by `phi`. # Examples ```jldoctest -julia> S, (x, y, z) = polynomial_ring(QQ, ["x", "y", "z"]) -(Multivariate polynomial ring in 3 variables over QQ, QQMPolyRingElem[x, y, z]) - -julia> T, _ = grade(S) +julia> T, (x,y,z) = graded_polynomial_ring(QQ, ["x", "y", "z"]) (Graded multivariate polynomial ring in 3 variables over QQ, MPolyDecRingElem{QQFieldElem, QQMPolyRingElem}[x, y, z]) julia> C = ProjPlaneCurve(T(y^2*z - x*(x-z)*(x+3*z))) diff --git a/experimental/PlaneCurve/src/ProjPlaneCurve.jl b/experimental/PlaneCurve/src/ProjPlaneCurve.jl index f46d72f9c2de..642b86931b52 100644 --- a/experimental/PlaneCurve/src/ProjPlaneCurve.jl +++ b/experimental/PlaneCurve/src/ProjPlaneCurve.jl @@ -28,10 +28,7 @@ Throw an error if `P` is not a point of `C`, return `false` if `P` is a singular # Examples ```jldoctest -julia> S, (x, y, z) = polynomial_ring(QQ, ["x", "y", "z"]) -(Multivariate polynomial ring in 3 variables over QQ, QQMPolyRingElem[x, y, z]) - -julia> T, _ = grade(S) +julia> T, (x, y, z) = graded_polynomial_ring(QQ, ["x", "y", "z"]) (Graded multivariate polynomial ring in 3 variables over QQ, MPolyDecRingElem{QQFieldElem, QQMPolyRingElem}[x, y, z]) julia> C = ProjPlaneCurve(x^2*(x+y)*(y^3-x^2*z)) @@ -69,10 +66,7 @@ Return the tangent of `C` at `P` when `P` is a smooth point of `C`, and throw an # Examples ```jldoctest -julia> S, (x, y, z) = polynomial_ring(QQ, ["x", "y","z"]) -(Multivariate polynomial ring in 3 variables over QQ, QQMPolyRingElem[x, y, z]) - -julia> T, _ = grade(S) +julia> T, (x, y, z) = graded_polynomial_ring(QQ, ["x", "y", "z"]) (Graded multivariate polynomial ring in 3 variables over QQ, MPolyDecRingElem{QQFieldElem, QQMPolyRingElem}[x, y, z]) julia> PP = proj_space(QQ, 2) @@ -146,19 +140,16 @@ Return a list whose first element is the projective plane curve defined by the g # Examples ```jldoctest -julia> S, (x, y, z) = polynomial_ring(QQ, ["x", "y","z"]) -(Multivariate polynomial ring in 3 variables over QQ, QQMPolyRingElem[x, y, z]) - -julia> T, _ = grade(S) +julia> T, (x, y, z) = graded_polynomial_ring(QQ, ["x", "y", "z"]) (Graded multivariate polynomial ring in 3 variables over QQ, MPolyDecRingElem{QQFieldElem, QQMPolyRingElem}[x, y, z]) julia> PP = proj_space(QQ, 2) (Projective space of dim 2 over Rational field, MPolyDecRingElem{QQFieldElem, QQMPolyRingElem}[x[0], x[1], x[2]]) -julia> C = ProjPlaneCurve(T(x+y+z)) +julia> C = ProjPlaneCurve(x+y+z) Projective plane curve defined by x + y + z -julia> D = ProjPlaneCurve(T(z)) +julia> D = ProjPlaneCurve(z) Projective plane curve defined by z julia> curve_intersect(PP[1], C, D) @@ -448,13 +439,10 @@ Return the arithmetic genus of `C`. # Examples ```jldoctest -julia> S, (x, y, z) = polynomial_ring(QQ, ["x", "y", "z"]) -(Multivariate polynomial ring in 3 variables over QQ, QQMPolyRingElem[x, y, z]) - -julia> T, _ = grade(S) +julia> T, (x, y, z) = graded_polynomial_ring(QQ, ["x", "y", "z"]) (Graded multivariate polynomial ring in 3 variables over QQ, MPolyDecRingElem{QQFieldElem, QQMPolyRingElem}[x, y, z]) -julia> C = ProjPlaneCurve(T(y^2 * z - x^3 - x * z^2)) +julia> C = ProjPlaneCurve(y^2 * z - x^3 - x * z^2) Projective plane curve defined by -x^3 - x*z^2 + y^2*z julia> Oscar.PlaneCurveModule.arithmetic_genus(C) diff --git a/experimental/PlaneCurve/test/runtests.jl b/experimental/PlaneCurve/test/runtests.jl index 6d71638f3ec9..2f0e7d13eeae 100644 --- a/experimental/PlaneCurve/test/runtests.jl +++ b/experimental/PlaneCurve/test/runtests.jl @@ -114,9 +114,8 @@ end end @testset "ProjPlaneCurve constructors" begin - R, (x, y, z) = polynomial_ring(QQ, ["x", "y", "z"]) - T, _ = grade(R) - F = T(y^3 * x^6 - y^6 * x^2 * z) + T, (x, y, z) = graded_polynomial_ring(QQ, ["x", "y", "z"]) + F = y^3 * x^6 - y^6 * x^2 * z C = ProjPlaneCurve(F) @test Oscar.defining_equation(C) == F.f @@ -134,35 +133,33 @@ end end @testset "ProjPlaneCurve reducible functions" begin - R, (x, y, z) = polynomial_ring(QQ, ["x", "y", "z"]) - T, _ = grade(R) - F = ProjPlaneCurve(T(x^2 + y^2)) + T, (x, y, z) = graded_polynomial_ring(QQ, ["x", "y", "z"]) + F = ProjPlaneCurve(x^2 + y^2) P = Point([QQ(0), QQ(0), QQ(1)]) @test Oscar.is_irreducible(F) @test Oscar.is_reduced(F) @test Oscar.reduction(F) == F - G = ProjPlaneCurve(T(y^2)) + G = ProjPlaneCurve(y^2) @test !Oscar.is_irreducible(G) @test !Oscar.is_reduced(G) - @test Oscar.reduction(G) == ProjPlaneCurve(T(y)) + @test Oscar.reduction(G) == ProjPlaneCurve(y) - H = ProjPlaneCurve(T(x * y)) + H = ProjPlaneCurve(x * y) @test !Oscar.is_irreducible(H) @test Oscar.is_reduced(H) @test Oscar.reduction(H) == H - @test Oscar.union(G, H) == ProjPlaneCurve(T(x * y^3)) + @test Oscar.union(G, H) == ProjPlaneCurve(x * y^3) end @testset "ProjPlaneCurve intersection functions" begin - R, (x, y, z) = polynomial_ring(QQ, ["x", "y", "z"]) - T, _ = grade(R) - F = ProjPlaneCurve(T(x * (x + y))) - G = ProjPlaneCurve(T(x * z + y^2 + z^2)) - H = ProjPlaneCurve(T(x * (x + y) * y)) + T, (x, y, z) = graded_polynomial_ring(QQ, ["x", "y", "z"]) + F = ProjPlaneCurve(x * (x + y)) + G = ProjPlaneCurve(x * z + y^2 + z^2) + H = ProjPlaneCurve(x * (x + y) * y) M = ProjPlaneCurve((x - y) * (x - 2 * z)) PP = proj_space(QQ, 2) @@ -172,14 +169,14 @@ end Z = Oscar.Geometry.ProjSpcElem(PP[1], [QQ(1), QQ(-1), QQ(0)]) @test common_components(F, G) == [] - @test common_components(F, H) == [ProjPlaneCurve(T(x * (x + y)))] + @test common_components(F, H) == [ProjPlaneCurve(x * (x + y))] @test curve_intersect(PP[1], F, G) == [[], []] - @test curve_intersect(PP[1], F, H) == [[ProjPlaneCurve(T(x * (x + y)))], []] + @test curve_intersect(PP[1], F, H) == [[ProjPlaneCurve(x * (x + y))], []] @test curve_intersect( PP[1], - ProjPlaneCurve(T(x + y + z)), - ProjPlaneCurve(T(z)), + ProjPlaneCurve(x + y + z), + ProjPlaneCurve(z), ) == [[], [Z]] L = curve_intersect(PP[1], F, M) @@ -196,8 +193,7 @@ end end @testset "ProjPlaneCurve int_multiplicity functions" begin - R, (x, y, z) = polynomial_ring(QQ, ["x", "y", "z"]) - T, _ = grade(R) + T, (x, y, z) = graded_polynomial_ring(QQ, ["x", "y", "z"]) F = ProjPlaneCurve(T((x^2 + y^2) * (x^2 + y^2 + 2 * y * z))) G = ProjPlaneCurve(T((x^2 + y^2) * (y^3 * x^6 - y^6 * x^2 * z))) PP = proj_space(QQ, 2) @@ -216,8 +212,7 @@ end end @testset "ProjPlaneCurve singularity functions" begin - R, (x, y, z) = polynomial_ring(QQ, ["x", "y", "z"]) - T, _ = grade(R) + T, (x, y, z) = graded_polynomial_ring(QQ, ["x", "y", "z"]) PP = proj_space(QQ, 2) F = ProjPlaneCurve(T(x * z + y^2)) P = Oscar.Geometry.ProjSpcElem(PP[1], [QQ(1), QQ(0), QQ(0)]) @@ -270,8 +265,7 @@ end end @testset "ProjCurveDivisor basic functions" begin - S, (x, y, z) = polynomial_ring(QQ, ["x", "y", "z"]) - T, _ = grade(S) + T, (x, y, z) = graded_polynomial_ring(QQ, ["x", "y", "z"]) C = ProjPlaneCurve(T(y^2 + y * z + x^2)) PP = proj_space(QQ, 2) P = Oscar.Geometry.ProjSpcElem(PP[1], [QQ(0), QQ(0), QQ(1)]) @@ -316,27 +310,23 @@ end end @testset "Weierstrass form" begin - S, (x, y, z) = polynomial_ring(QQ, ["x", "y", "z"]) - T, _ = grade(S) + T, (x, y, z) = graded_polynomial_ring(QQ, ["x", "y", "z"]) PP = proj_space(QQ, 2) P = Oscar.Geometry.ProjSpcElem(PP[1], [QQ(0), QQ(1), QQ(0)]) Q = Oscar.Geometry.ProjSpcElem(PP[1], [QQ(-1), QQ(1), QQ(0)]) - C = ProjPlaneCurve(T(y^2 * z - x^3 - x * z^2)) + C = ProjPlaneCurve(y^2 * z - x^3 - x * z^2) D = ProjPlaneCurve( - T( -x^3 - 3 * x^2 * y + 2 * x^2 * z - 3 * x * y^2 + 3 * x * y * z - 4 * x * z^2 - y^3 - y * z^2 + 6 * z^3, - ), ) @test Oscar.iselliptic(C) - @test Oscar.toweierstrass(C, P) == T(y^2 * z - x^3 - x * z^2) + @test Oscar.toweierstrass(C, P) == y^2 * z - x^3 - x * z^2 @test Oscar.toweierstrass(D, Q) == - T(y^2 * z + x * y * z + 3 * y * z^2 - x^3 - 2 * x^2 * z - 4 * x * z^2 - 6 * z^3) + y^2 * z + x * y * z + 3 * y * z^2 - x^3 - 2 * x^2 * z - 4 * x * z^2 - 6 * z^3 end @testset "genus" begin - S, (x, y, z) = polynomial_ring(QQ, ["x", "y", "z"]) - T, _ = grade(S) - C = ProjPlaneCurve(T(y^2 * z - x^3 - x * z^2)) + T, (x, y, z) = graded_polynomial_ring(QQ, ["x", "y", "z"]) + C = ProjPlaneCurve(y^2 * z - x^3 - x * z^2) @test (Oscar.PlaneCurveModule.arithmetic_genus(C)) == ZZ(1) @test (geometric_genus(C)) == ZZ(1) R, (a, b) = polynomial_ring(GF(7), ["a", "b"]) @@ -346,22 +336,20 @@ end end @testset "ProjEllipticCurve" begin - S, (x, y, z) = polynomial_ring(QQ, ["x", "y", "z"]) - T, _ = grade(S) - F = T(y^2 * z - x^3 - x * z^2) + T, (x, y, z) = graded_polynomial_ring(QQ, ["x", "y", "z"]) + F = y^2 * z - x^3 - x * z^2 E = Oscar.ProjEllipticCurve(F) @test Oscar.discriminant(E) == -64 @test Oscar.j_invariant(E) == 1728 end @testset "Point addition" begin - S, (x, y, z) = polynomial_ring(QQ, ["x", "y", "z"]) - T, _ = grade(S) - F = T(-x^3 - 3 * x^2 * y - 3 * x * y^2 - x * z^2 - y^3 + y^2 * z - y * z^2 - 4 * z^3) + T, (x, y, z) = graded_polynomial_ring(QQ, ["x", "y", "z"]) + F = -x^3 - 3 * x^2 * y - 3 * x * y^2 - x * z^2 - y^3 + y^2 * z - y * z^2 - 4 * z^3 PP = proj_space(QQ, 2) P1 = Oscar.Geometry.ProjSpcElem(PP[1], [QQ(-1), QQ(1), QQ(0)]) E = Oscar.ProjEllipticCurve(F, P1) - @test Oscar.weierstrass_form(E) == T(-x^3 - x * z^2 + y^2 * z - 4 * z^3) + @test Oscar.weierstrass_form(E) == -x^3 - x * z^2 + y^2 * z - 4 * z^3 Q1 = Oscar.Point_EllCurve(E, P1) P2 = Oscar.Geometry.ProjSpcElem(PP[1], [QQ(-2), QQ(2), QQ(1)]) Q2 = Oscar.Point_EllCurve(E, P2) @@ -371,9 +359,8 @@ end @testset "Counting Points on Elliptic Curves" begin K = GF(5, 7) - S, (x, y, z) = polynomial_ring(K, ["x", "y", "z"]) - T, _ = grade(S) - F = T(-x^3 - 3 * x^2 * y - 3 * x * y^2 - x * z^2 - y^3 + y^2 * z - y * z^2 - 4 * z^3) + T, (x, y, z) = graded_polynomial_ring(K, ["x", "y", "z"]) + F = -x^3 - 3 * x^2 * y - 3 * x * y^2 - x * z^2 - y^3 + y^2 * z - y * z^2 - 4 * z^3 PP = proj_space(K, 2) P1 = Oscar.Geometry.ProjSpcElem(PP[1], [K(-1), K(1), K(0)]) E = Oscar.ProjEllipticCurve(F, P1) @@ -381,9 +368,8 @@ end end @testset "Torsion points on elliptic curves" begin - S, (x, y, z) = polynomial_ring(QQ, ["x", "y", "z"]) - T, _ = grade(S) - F = T(-x^3 - 3 * x^2 * y - 3 * x * y^2 - x * z^2 - y^3 + y^2 * z - y * z^2 - 4 * z^3) + T, (x, y, z) = graded_polynomial_ring(QQ, ["x", "y", "z"]) + F = -x^3 - 3 * x^2 * y - 3 * x * y^2 - x * z^2 - y^3 + y^2 * z - y * z^2 - 4 * z^3 PP = proj_space(QQ, 2) P1 = Oscar.Geometry.ProjSpcElem(PP[1], [QQ(-1), QQ(1), QQ(0)]) E = Oscar.ProjEllipticCurve(F, P1) @@ -403,9 +389,8 @@ end @test gcd(n, ZZ(4453)) == n A = residue_ring(ZZ, ZZ(4453)) - S, (x, y, z) = polynomial_ring(A, ["x", "y", "z"]) - T, _ = grade(S) - F = T(y^2 * z - x^3 - 10 * x * z^2 + 2 * z^3) + T, (x, y, z) = graded_polynomial_ring(A, ["x", "y", "z"]) + F = y^2 * z - x^3 - 10 * x * z^2 + 2 * z^3 E = Oscar.ProjEllipticCurve(F) PP = proj_space(A, 2) P = Oscar.Point_EllCurve(E, Oscar.Geometry.ProjSpcElem(PP[1], [A(1), A(3), A(1)])) @@ -423,23 +408,22 @@ end end @testset "ParaPlaneCurve" begin - S, (x, y, z) = polynomial_ring(QQ, ["x", "y", "z"]) - T, _ = grade(S) - C1 = ProjPlaneCurve(T(1//2*x^5+x^2*y*z^2+x^3*y*z+1//2*x*y^2*z^2-2*x*y^3*z+y^5)) + T, (x, y, z) = graded_polynomial_ring(QQ, ["x", "y", "z"]) + C1 = ProjPlaneCurve(1//2*x^5+x^2*y*z^2+x^3*y*z+1//2*x*y^2*z^2-2*x*y^3*z+y^5) I1 = Oscar.parametrization_plane_curve(C1) I2 = Oscar.adjoint_ideal(C1) R1 = parent(I1[1]) s, t = gens(R1) @test I1 == [-4*s^4*t + 2*s^3*t^2, 2*s^2*t^3 - s*t^4, 4*s^5 - t^5] - @test gens(I2) == [T(-x*y*z + y^3), T(-x^2*z + x*y^2), T(x^2*y + y^2*z), T(x^3 + x*y*z)] - C2 = ProjPlaneCurve(T(y^2 - x*z)) + @test gens(I2) == [-x*y*z + y^3, -x^2*z + x*y^2, x^2*y + y^2*z, x^3 + x*y*z] + C2 = ProjPlaneCurve(y^2 - x*z) P = Oscar.rational_point_conic(C2) I3 = Oscar.parametrization_conic(C2) R2 = parent(I3[1]) s1, t1 = gens(R2) @test iszero(evaluate(C2.eq, P)) @test I3 == [s1^2, s1*t1, t1^2] - C3 = ProjPlaneCurve(T(y^8-x^3*(z+x)^5)) + C3 = ProjPlaneCurve(y^8-x^3*(z+x)^5) D = Oscar.map_to_rational_normal_curve(C3) I4 = Oscar.rat_normal_curve_anticanonical_map(D) Y = gens(parent(I4[1])) @@ -448,17 +432,17 @@ end R3 = parent(C4[2].eq) U = gens(R3) @test C4[2] == ProjPlaneCurve(-U[1]*U[3] + U[2]^2) - C5 = ProjPlaneCurve(T(-x^7-10*x^5*y^2-10*x^4*y^3-3*x^3*y^4+8*x^2*y^5+ + C5 = ProjPlaneCurve(-x^7-10*x^5*y^2-10*x^4*y^3-3*x^3*y^4+8*x^2*y^5+ 7*x*y^6+11*y^7+3*x^6*z+10*x^5*y*z+30*x^4*y^2*z+26*x^3*y^3*z-13*x^2*y^4*z- 29*x*y^5*z-33*y^6*z-3*x^5*z^2-20*x^4*y*z^2-33*x^3*y^2*z^2-8*x^2*y^3*z^2+ 37*x*y^4*z^2+33*y^5*z^2+x^4*z^3+10*x^3*y*z^3+13*x^2*y^2*z^3-15*x*y^3*z^3- - 11*y^4*z^3)) + 11*y^4*z^3) D2 = Oscar.map_to_rational_normal_curve(C5) I5 = Oscar.rat_normal_curve_It_Proj_Odd(D2) R4 = parent(I5[1]) V = gens(R4) @test I5 == [121*V[3] + 77*V[4], -11*V[5] - 7*V[6]] - C6 = ProjPlaneCurve(T(y^8 - x^3*(z+x)^5)) + C6 = ProjPlaneCurve(y^8 - x^3*(z+x)^5) I = Oscar.adjoint_ideal(C6) BM = Oscar.invert_birational_map(gens(I), C6) R5 = parent(BM["image"][1]) @@ -473,8 +457,7 @@ end end @testset "NonPlaneCurve" begin - S, (x, y, z, t) = polynomial_ring(QQ, ["x", "y", "z", "t"]) - T, _ = grade(S) + T, (x, y, z, t) = graded_polynomial_ring(QQ, ["x", "y", "z", "t"]) I = ideal(T, [x^2, y^2*z, z^2]) C = Oscar.ProjCurve(I) PP = proj_space(QQ, 3) @@ -484,10 +467,10 @@ end J = Oscar.jacobi_ideal(C) L = gens(J) @test length(L) == 4 - @test length(findall(a -> a == T(4*x*y*z), L)) == 1 - @test length(findall(a -> a == T(2*x*y^2), L)) == 1 - @test length(findall(a -> a == T(4*x*z), L)) == 1 - @test length(findall(a -> a == T(4*y*z^2), L)) == 1 + @test length(findall(a -> a == 4*x*y*z, L)) == 1 + @test length(findall(a -> a == 2*x*y^2, L)) == 1 + @test length(findall(a -> a == 4*x*z, L)) == 1 + @test length(findall(a -> a == 4*y*z^2, L)) == 1 C2 = Oscar.reduction(C) I2 = Oscar.defining_ideal(C2) @test I2 == ideal(T, [x, z]) diff --git a/experimental/Schemes/CoveredProjectiveSchemes.jl b/experimental/Schemes/CoveredProjectiveSchemes.jl index 1d9544c453d9..4f147e974d17 100644 --- a/experimental/Schemes/CoveredProjectiveSchemes.jl +++ b/experimental/Schemes/CoveredProjectiveSchemes.jl @@ -469,7 +469,7 @@ function blow_up_chart(W::AbsSpec{<:Field, <:RingType}, I::Ideal; # It follows the generic Proj construction R = OO(W) T, (t,) = polynomial_ring(R, ["t"]) - S, s = grade(polynomial_ring(R, [Symbol(var_name, i-1) for i in 1:ngens(I)])[1]) + S, s = graded_polynomial_ring(R, [Symbol(var_name, i-1) for i in 1:ngens(I)]) phi = hom(S, T, [t*g for g in gens(I)], check=false) K = kernel(phi) K = ideal(S, [g for g in gens(K) if !iszero(g)]) # clean up superfluous generators diff --git a/experimental/SymmetricIntersections/src/homogeneous_polynomial_actions.jl b/experimental/SymmetricIntersections/src/homogeneous_polynomial_actions.jl index db74d99580d6..ed8e16ef516a 100644 --- a/experimental/SymmetricIntersections/src/homogeneous_polynomial_actions.jl +++ b/experimental/SymmetricIntersections/src/homogeneous_polynomial_actions.jl @@ -199,7 +199,7 @@ function symmetric_intersections(prep::ProjRep, d::Int, t::Int; j = nothing, che RR = representation_ring_linear_lift(prep) F = base_field(RR) if j === nothing - S, _ = grade(polynomial_ring(F, "x" => 0:dimension_representation(prep)-1)[1]) + S, _ = graded_polynomial_ring(F, "x" => 0:dimension_representation(prep)-1) _, j = homogeneous_component(S, d) elseif check V = domain(j) @@ -251,7 +251,7 @@ function symmetric_intersections(G::Oscar.GAPGroup, n::Int, d::Int, t::Int) res = Tuple{ProjRep, Vector{SymInter}}[] is_empty(pfr) && return res F = base_field(representation_ring_linear_lift(pfr[1])) - S, _ = grade(polynomial_ring(F, "x" => 0:n-1)[1]) + S, _ = graded_polynomial_ring(F, "x" => 0:n-1) _, j = homogeneous_component(S, d) for prep in pfr D = symmetric_intersections(prep, d, t, j = j, check = false) diff --git a/experimental/SymmetricIntersections/src/representations.jl b/experimental/SymmetricIntersections/src/representations.jl index 8b8662209915..7e586aa7d8ba 100644 --- a/experimental/SymmetricIntersections/src/representations.jl +++ b/experimental/SymmetricIntersections/src/representations.jl @@ -888,7 +888,7 @@ space `V`, return an induced action on Sym^d V. function _action_symmetric_power(mr::Vector{AbstractAlgebra.Generic.MatSpaceElem{S}}, d::Int) where S n = ncols(mr[1]) F = base_ring(mr[1]) - R, _ = grade(polynomial_ring(F, "x"=>1:n, cached=false)[1]) + R, _ = graded_polynomial_ring(F, "x"=>1:n, cached=false) R1, R1toR = homogeneous_component(R, 1) Rd, RdtoR = homogeneous_component(R, d) bsp = reverse(RdtoR.(gens(Rd))) diff --git a/experimental/SymmetricIntersections/src/symmetric_grassmannians.jl b/experimental/SymmetricIntersections/src/symmetric_grassmannians.jl index c89ab72cac9b..cff56d9c69b0 100644 --- a/experimental/SymmetricIntersections/src/symmetric_grassmannians.jl +++ b/experimental/SymmetricIntersections/src/symmetric_grassmannians.jl @@ -499,7 +499,7 @@ function _intersection_with_grassmannian(V::Vector{T}, n::Int, t::Int; S = nothi F = base_ring(V[1]) if S === nothing - S, _ = grade(polynomial_ring(F, "x" => 0:binomial(n, t)-1)[1]) + S, _ = graded_polynomial_ring(F, "x" => 0:binomial(n, t)-1) end X = ProjectiveScheme(S) @@ -532,7 +532,7 @@ function _defining_ideal_determinant_grassmannian(r::LinRep, chi::Oscar.GAPGroup rt = t == 1 ? r : exterior_power_representation(r, t) F = base_field(representation_ring(r)) k = dimension_representation(rt) - S, _ = grade(polynomial_ring(F, "x" => 0:k-1)[1]) + S, _ = graded_polynomial_ring(F, "x" => 0:k-1) bas = basis_isotypical_component(rt, chi) if length(bas) == 0 return ideal(S, [S(1)]) @@ -546,7 +546,7 @@ function _defining_ideal_invariant_grassmannian(r::LinRep, t::Int) cds = character_decomposition(rt) chis = [cd[2] for cd in cds if Int(degree(cd[2])) == 1] k = dimension_representation(rt) - S, _ = grade(polynomial_ring(F, "x" => 0:k-1)[1]) + S, _ = graded_polynomial_ring(F, "x" => 0:k-1) irre = ideal(S, gens(S)) I = ideal(S, [S(1)]) for chi in chis diff --git a/experimental/SymmetricIntersections/test/runtests.jl b/experimental/SymmetricIntersections/test/runtests.jl index 33a7eb0cd8e1..83d70a2e672e 100644 --- a/experimental/SymmetricIntersections/test/runtests.jl +++ b/experimental/SymmetricIntersections/test/runtests.jl @@ -2,9 +2,8 @@ using Test using Oscar @testset "Elevators" begin - R, _ = polynomial_ring(QQ, 10, cached=false) W = sort(rand(1:5, 10)) - S, x = grade(R, W) + S, x = graded_polynomial_ring(QQ, 10, W; cached=false) function weight(p) return degree(p).coeff[1] @@ -18,7 +17,7 @@ using Oscar @test Set([prod(x[l]) for l in el]) == Set(SitoS.(gens(Si))) end - S, x = grade(R) + S, x = graded_polynomial_ring(QQ, 10; cached=false) el = Oscar.elevator(x, weight, 5, lbs=[2,0,0,0,0,0,0,0,0, 0]) @test Oscar.number_of_elevations(el) == binomial(12, 3) @test Oscar.underlying_list(el) === x diff --git a/src/AlgebraicGeometry/Miscellaneous/basics.jl b/src/AlgebraicGeometry/Miscellaneous/basics.jl index 224cc2978cb8..f526d2933bdb 100644 --- a/src/AlgebraicGeometry/Miscellaneous/basics.jl +++ b/src/AlgebraicGeometry/Miscellaneous/basics.jl @@ -28,15 +28,13 @@ function Base.show(io::IO, P::ProjSpc) end function proj_space(R::AbstractAlgebra.Ring, n::Int, name::Symbol=:x) - Sx = polynomial_ring(R, name => 0:n)[1] - Rx = grade(Sx, [1 for i=0:n])[1] - return ProjSpc(R, n, Rx), gens(Rx) + Rx, x = graded_polynomial_ring(R, name => 0:n) + return ProjSpc(R, n, Rx), x end function proj_space(R::AbstractAlgebra.Ring, n::Vector{<:Integer}, name::Symbol = :x) - Sx = polynomial_ring(R, name => 0:length(n)-1)[1] - Rx = grade(Sx, n)[1] - return ProjSpc(R, length(n)-1, Rx), gens(Rx) + Rx, x = graded_polynomial_ring(R, name => 0:length(n)-1, n) + return ProjSpc(R, length(n)-1, Rx), x end function coordinate_ring(P::ProjSpc) diff --git a/src/InvariantTheory/affine_algebra.jl b/src/InvariantTheory/affine_algebra.jl index e6afb368a67e..fe718f46b639 100644 --- a/src/InvariantTheory/affine_algebra.jl +++ b/src/InvariantTheory/affine_algebra.jl @@ -137,7 +137,8 @@ function relations_primary_and_irreducible_secondary(RG::InvRing) np = length(p_invars) - S, t = grade(polynomial_ring(K, "t" => 1:(np + length(is_invars)))[1], append!([ total_degree(f) for f in p_invars ], [ total_degree(f) for f in is_invars ])) + w = append!([ total_degree(f) for f in p_invars ], [ total_degree(f) for f in is_invars ]) + S, t = graded_polynomial_ring(K, "t" => 1:(np + length(is_invars)), w) if isempty(is_invars) I = ideal(S, elem_type(S)[]) diff --git a/src/InvariantTheory/types.jl b/src/InvariantTheory/types.jl index d0d59d1576af..610eac30252a 100644 --- a/src/InvariantTheory/types.jl +++ b/src/InvariantTheory/types.jl @@ -72,7 +72,7 @@ mutable struct InvRing{FldT, GrpT, PolyRingElemT, PolyRingT, ActionT} n = degree(G) # We want to use divrem w.r.t. degrevlex e.g. for the computation of # secondary invariants and fundamental invariants - R, = grade(polynomial_ring(K, "x" => 1:n, cached = false, ordering = :degrevlex)[1], ones(Int, n)) + R, = graded_polynomial_ring(K, "x" => 1:n, cached = false, ordering = :degrevlex) return InvRing(K, G, action, R) end diff --git a/src/Modules/hilbert.jl b/src/Modules/hilbert.jl index a09c419a85b4..ded9486e2609 100644 --- a/src/Modules/hilbert.jl +++ b/src/Modules/hilbert.jl @@ -61,9 +61,7 @@ If the kwarg `parent` is supplied `N` and `D` are computed in the ring `parent`. # Examples ```jldoctest -julia> R, _ = polynomial_ring(QQ, ["x", "y", "z"]); - -julia> Rg, (x, y, z) = grade(R, [4,3,2]); +julia> Rg, (x, y, z) = graded_polynomial_ring(QQ, ["x", "y", "z"], [4,3,2]); julia> F = graded_free_module(Rg, 1); diff --git a/src/Rings/MPolyQuo.jl b/src/Rings/MPolyQuo.jl index 8b75cea52946..9d9c58897e24 100644 --- a/src/Rings/MPolyQuo.jl +++ b/src/Rings/MPolyQuo.jl @@ -1544,19 +1544,12 @@ w^2 ``` ```jldoctest -julia> R, x, y = polynomial_ring(QQ, "x" => 1:2, "y" => 1:3); - julia> G = abelian_group([0, 0]) GrpAb: Z^2 -julia> g = gens(G) -2-element Vector{GrpAbFinGenElem}: - Element of G with components [1 0] - Element of G with components [0 1] - -julia> W = [g[1], g[1], g[2], g[2], g[2]]; +julia> W = [G[1], G[1], G[2], G[2], G[2]]; -julia> S, _ = grade(R, W); +julia> S, x, y = graded_polynomial_ring(QQ, "x" => 1:2, "y" => 1:3; weights = W); julia> L = homogeneous_component(S, [2,1]); @@ -1564,7 +1557,7 @@ julia> HC = gens(L[1]); julia> EMB = L[2] Map defined by a julia-function with inverse - from homogeneous component of Graded multivariate polynomial ring in 5 variables over QQ of degree Element of G with components [2 1] + from homogeneous component of graded multivariate polynomial ring in 5 variables over QQ of degree [2 1] to graded multivariate polynomial ring in 5 variables over QQ julia> for i in 1:length(HC) println(EMB(HC[i])) end diff --git a/src/Rings/mpoly-graded.jl b/src/Rings/mpoly-graded.jl index efc0b3a725cb..f9eb4ae15617 100644 --- a/src/Rings/mpoly-graded.jl +++ b/src/Rings/mpoly-graded.jl @@ -1141,7 +1141,9 @@ function show_homo_comp(io::IO, M) if n !== nothing print(io, "$(n)_$(d.coeff) of dim $(dim(M))") else - print(io, "homogeneous component of $W of degree $d") + io = pretty(io) + print(io, "homogeneous component of ", Lowercase(), W, " of degree ") + print(IOContext(io, :compact => true), d) end end @@ -1263,7 +1265,7 @@ GrpAb: Z^2 julia> L = homogeneous_component(S, [1, 1]); julia> L[1] -homogeneous component of Graded multivariate polynomial ring in 5 variables over QQ of degree [1 1] +homogeneous component of graded multivariate polynomial ring in 5 variables over QQ of degree [1 1] julia> FG = gens(L[1]); diff --git a/test/AlgebraicGeometry/Schemes/FunctionFields.jl b/test/AlgebraicGeometry/Schemes/FunctionFields.jl index c968fa55a3f1..24565930fa5e 100644 --- a/test/AlgebraicGeometry/Schemes/FunctionFields.jl +++ b/test/AlgebraicGeometry/Schemes/FunctionFields.jl @@ -25,8 +25,7 @@ end kk = GF(29) # Set up the base ℙ¹ with coordinates s and t - R, (s,t) = polynomial_ring(kk, ["s", "t"]) - S, _ = grade(R, [1, 1]) + S, _ = graded_polynomial_ring(kk, ["s", "t"]) base_P1 = ProjectiveScheme(S) diff --git a/test/AlgebraicGeometry/Schemes/IdealSheaves.jl b/test/AlgebraicGeometry/Schemes/IdealSheaves.jl index a6361508fa63..19e47094d341 100644 --- a/test/AlgebraicGeometry/Schemes/IdealSheaves.jl +++ b/test/AlgebraicGeometry/Schemes/IdealSheaves.jl @@ -2,8 +2,7 @@ kk = GF(29) # Set up the base ℙ¹ with coordinates s and t - R, (s,t) = polynomial_ring(kk, ["s", "t"]) - S, _ = grade(R, [1, 1]) + S, _ = graded_polynomial_ring(kk, ["s", "t"]) base_P1 = ProjectiveScheme(S) diff --git a/test/AlgebraicGeometry/Schemes/ProjectiveAlgebraicSet.jl b/test/AlgebraicGeometry/Schemes/ProjectiveAlgebraicSet.jl index 590b1d431334..55dc2a2ab4fd 100644 --- a/test/AlgebraicGeometry/Schemes/ProjectiveAlgebraicSet.jl +++ b/test/AlgebraicGeometry/Schemes/ProjectiveAlgebraicSet.jl @@ -1,6 +1,5 @@ @testset "Projective Algebraic Set" begin - P,_ = polynomial_ring(QQ, [:x, :y, :z]) - G, (x,y,z) = grade(P) + G, (x,y,z) = graded_polynomial_ring(QQ, [:x, :y, :z]) A = algebraic_set(x^2 - y^2) @test is_reduced(A) diff --git a/test/AlgebraicGeometry/Schemes/ProjectiveSchemes.jl b/test/AlgebraicGeometry/Schemes/ProjectiveSchemes.jl index 9e2d05374567..ff274cf4c27f 100644 --- a/test/AlgebraicGeometry/Schemes/ProjectiveSchemes.jl +++ b/test/AlgebraicGeometry/Schemes/ProjectiveSchemes.jl @@ -1,8 +1,7 @@ @testset "projective_schemes_1" begin # test for relative projective space over a polynomial ring R, (x,y) = QQ["x", "y"] - R_ext, _ = polynomial_ring(R, ["u", "v"]) - S, (u,v) = grade(R_ext, [1,1]) + S, (u,v) = graded_polynomial_ring(R, ["u", "v"]) I = ideal(S, [x*v - y*u]) X = ProjectiveScheme(S, I) @@ -17,8 +16,7 @@ #@test is_well_defined(phi) # deprecated # test for projective space over a field - R_ext, _ = polynomial_ring(QQ, ["u", "v"]) - S, (u,v) = grade(R_ext, [1,1]) + S, (u,v) = graded_polynomial_ring(QQ, ["u", "v"]) I = ideal(S, [u]) X = ProjectiveScheme(S, I) @@ -35,8 +33,7 @@ # test for relative projective space over MPolyQuoLocalizedRings Y = Spec(R) Q = OO(Y) - R_ext, _ = polynomial_ring(Q, ["u", "v"]) - S, (u,v) = grade(R_ext, [1,1]) + S, (u,v) = graded_polynomial_ring(Q, ["u", "v"]) X = ProjectiveScheme(S) phi = ProjectiveSchemeMor(X, X, [u^2, v^2]) diff --git a/test/AlgebraicGeometry/Schemes/ProjectiveVarieties.jl b/test/AlgebraicGeometry/Schemes/ProjectiveVarieties.jl index b119c46b62bd..07303eec38e2 100644 --- a/test/AlgebraicGeometry/Schemes/ProjectiveVarieties.jl +++ b/test/AlgebraicGeometry/Schemes/ProjectiveVarieties.jl @@ -1,6 +1,5 @@ @testset "Projective Varieties" begin - P,_ = polynomial_ring(QQ, [:x, :y, :z]) - G, (x, y, z) = grade(P) + G, (x, y, z) = graded_polynomial_ring(QQ, [:x, :y, :z]) p = x^2 + y^2 + z^2 X = variety(p) @test_throws ErrorException variety(p^2) diff --git a/test/AlgebraicGeometry/Schemes/WeilDivisor.jl b/test/AlgebraicGeometry/Schemes/WeilDivisor.jl index 70f6f7abdc88..bb0496f79705 100644 --- a/test/AlgebraicGeometry/Schemes/WeilDivisor.jl +++ b/test/AlgebraicGeometry/Schemes/WeilDivisor.jl @@ -2,8 +2,7 @@ kk = GF(29) # Set up the base ℙ¹ with coordinates s and t - R, (s,t) = polynomial_ring(kk, ["s", "t"]) - S, _ = grade(R, [1, 1]) + S, = graded_polynomial_ring(kk, ["s", "t"]) base_P1 = ProjectiveScheme(S) diff --git a/test/AlgebraicGeometry/Schemes/transforms.jl b/test/AlgebraicGeometry/Schemes/transforms.jl index 852e750ce23e..da8256722d9d 100644 --- a/test/AlgebraicGeometry/Schemes/transforms.jl +++ b/test/AlgebraicGeometry/Schemes/transforms.jl @@ -36,8 +36,7 @@ end @testset "associated_points" begin # set up standard P2 - R, (x,y,z) = polynomial_ring(QQ,["x","y","z"]) - S,_=grade(R,[1,1,1]) + S, _ = graded_polynomial_ring(QQ,["x","y","z"]) P2 = ProjectiveScheme(S) X = covered_scheme(P2) diff --git a/test/Modules/ModulesGraded.jl b/test/Modules/ModulesGraded.jl index 64798663d69e..0f5949ea51bf 100644 --- a/test/Modules/ModulesGraded.jl +++ b/test/Modules/ModulesGraded.jl @@ -23,9 +23,7 @@ RNG = Random.MersenneTwister(42) end @testset "Graded free modules hom constructor" begin - R, _= polynomial_ring(QQ, ["x", "y", "z"]) - Z = abelian_group(0) - Rg, (x, y, z) = grade(R,[Z[1], Z[1], Z[1]]) + Rg, (x, y, z) = graded_polynomial_ring(QQ, ["x", "y", "z"]) F = graded_free_module(Rg, 3) G = graded_free_module(Rg, 2) V = [y*G[1], (x+y)*G[1]+y*G[2], z*G[2]] @@ -43,9 +41,7 @@ end end @testset "Kernel and image free modules hom" begin - R, _= polynomial_ring(QQ, ["x", "y", "z"]) - Z = abelian_group(0) - Rg, (x, y, z) = grade(R,[Z[1], Z[1], Z[1]]) + Rg, (x, y, z) = graded_polynomial_ring(QQ, ["x", "y", "z"]) F = graded_free_module(Rg, 3) G = graded_free_module(Rg, 2) V = [y*G[1], (x+y)*G[1]+y*G[2], z*G[2]] @@ -61,9 +57,8 @@ end end @testset "Presentations 1" begin - R, _= polynomial_ring(QQ, ["x", "y", "z"]) - Z = abelian_group(0) - Rg, (x, y, z) = grade(R,[Z[1], Z[1], Z[1]]) + Rg, (x, y, z) = graded_polynomial_ring(QQ, ["x", "y", "z"]) + Z = grading_group(Rg) F = graded_free_module(Rg, 3) G = graded_free_module(Rg, 2) V = [y*G[1], (x+y)*G[1]+y*G[2], z*G[2]] @@ -80,9 +75,8 @@ end end @testset "Degrees of free module homomorphisms" begin - R, _= polynomial_ring(QQ, ["x", "y", "z"]) - Z = abelian_group(0) - Rg, (x, y, z) = grade(R,[Z[1], Z[1], Z[1]]) + Rg, (x, y, z) = graded_polynomial_ring(QQ, ["x", "y", "z"]) + Z = grading_group(Rg) F = graded_free_module(Rg, 3) G = graded_free_module(Rg, 2) V = [y*G[1], (x+y)*G[1]+y*G[2], z*G[2]] @@ -99,9 +93,8 @@ end end @testset "Subquotient constructors" begin - R, _= polynomial_ring(QQ, ["x", "y", "z"]) - Z = abelian_group(0) - Rg, (x, y, z) = grade(R,[Z[1], Z[1], Z[1]]) + Rg, (x, y, z) = graded_polynomial_ring(QQ, ["x", "y", "z"]) + Z = grading_group(Rg) F = graded_free_module(Rg, [1,1,1]) G = graded_free_module(Rg, [0,0]) B = Rg[y 0; x y; 0 z] @@ -136,9 +129,8 @@ end end @testset "Graded modules from matrices constructors" begin - R, _= polynomial_ring(QQ, ["x", "y", "z"]) - Z = abelian_group(0) - Rg, (x, y, z) = grade(R,[Z[1], Z[1], Z[1]]) + Rg, (x, y, z) = graded_polynomial_ring(QQ, ["x", "y", "z"]) + Z = grading_group(Rg) F2 = graded_free_module(Rg,[8,8]) A1 = Rg[x y; 2*x^2 3*y^2] @@ -157,9 +149,8 @@ end end @testset "Graded morphisms from matrix constructor" begin - R, _= polynomial_ring(QQ, ["x", "y", "z"]) - Z = abelian_group(0) - Rg, (x, y, z) = grade(R,[Z[1], Z[1], Z[1]]) + Rg, (x, y, z) = graded_polynomial_ring(QQ, ["x", "y", "z"]) + Z = grading_group(Rg) F = graded_free_module(Rg,[1,2, 3]) A2 = Rg[x^3 x^2 x; (2*x^2+x*y)*x^2 (2*y^2+x^2)*x x^2] @@ -169,9 +160,8 @@ end end @testset "Graded morphisms of subquotients constructor" begin - R, _= polynomial_ring(QQ, ["x", "y", "z"]) - Z = abelian_group(0) - Rg, (x, y, z) = grade(R,[Z[1], Z[1], Z[1]]) + Rg, (x, y, z) = graded_polynomial_ring(QQ, ["x", "y", "z"]) + Z = grading_group(Rg) F = graded_free_module(Rg, 1); A = Rg[x; y] B = Rg[x^2; y^3; z^4] @@ -184,9 +174,7 @@ end end @testset "Graded morphisms of subquotients and kernel" begin - R, _= polynomial_ring(QQ, ["x", "y", "z"]) - Z = abelian_group(0) - Rg, (x, y, z) = grade(R,[Z[1], Z[1], Z[1]]) + Rg, (x, y, z) = graded_polynomial_ring(QQ, ["x", "y", "z"]) F = graded_free_module(Rg, 1); A = Rg[x; y] B = Rg[x^2; y^3; z^4] @@ -200,9 +188,7 @@ end end @testset "Is isomorphic for graded free modules" begin - R, _= polynomial_ring(QQ, ["x", "y", "z"]) - Z = abelian_group(0) - Rg, (x, y, z)=grade(R,[Z[1], Z[1], Z[1]]) + Rg, (x, y, z) = graded_polynomial_ring(QQ, ["x", "y", "z"]) F = graded_free_module(Rg, [1,1,3,2]) G = graded_free_module(Rg, [1,1,2,3]) @test is_isomorphic(F, G) @@ -212,9 +198,7 @@ end end @testset "Canonical isomorphism between graded subquotients" begin - R, _= polynomial_ring(QQ, ["x", "y", "z"]) - Z = abelian_group(0) - Rg, (x, y, z) = grade(R,[Z[1], Z[1], Z[1]]) + Rg, (x, y, z) = graded_polynomial_ring(QQ, ["x", "y", "z"]) F1 = graded_free_module(Rg,[2,3, 4]) A2 = Rg[x^3 x^2 x; (2*x^2+x*y)*x^2 (2*y^2+x^2)*x x^2] @@ -229,9 +213,7 @@ end end @testset "Being a subset and equality for graded subquotients" begin - R, _= polynomial_ring(QQ, ["x", "y", "z"]) - Z = abelian_group(0) - Rg, (x, y, z) = grade(R,[Z[1], Z[1], Z[1]]) + Rg, (x, y, z) = graded_polynomial_ring(QQ, ["x", "y", "z"]) F = graded_free_module(Rg,2) O1 = [x*F[1]+y*F[2],y*F[2]] O1a = [x*F[1],y*F[2]] @@ -247,9 +229,7 @@ end end @testset "Sum of graded subquotients" begin - R0, _ = polynomial_ring(QQ, ["x", "y", "z"]) - Z = abelian_group(0) - Rg, (x, y, z) = grade(R0, [Z[1],Z[1],Z[1]]) + Rg, (x, y, z) = graded_polynomial_ring(QQ, ["x", "y", "z"]) F = graded_free_module(Rg, 1) AM = Rg[x;] BM = Rg[x^2; y^3; z^4] @@ -267,9 +247,7 @@ end @testset "Being well defined and equality for graded morphisms of subquotients" begin - R0, _ = polynomial_ring(QQ, ["x", "y", "z"]) - Z = abelian_group(0) - Rg, (x, y, z) = grade(R0, [Z[1],Z[1],Z[1]]) + Rg, (x, y, z) = graded_polynomial_ring(QQ, ["x", "y", "z"]) F = graded_free_module(Rg, 1) A = Rg[x; y] B = Rg[x^2; y^3; z^4] @@ -290,9 +268,7 @@ end end @testset "Being zero for elements of graded subquotients" begin - R0, _ = polynomial_ring(QQ, ["x", "y", "z"]) - Z = abelian_group(0) - Rg, (x, y, z) = grade(R0, [Z[1],Z[1],Z[1]]) + Rg, (x, y, z) = graded_polynomial_ring(QQ, ["x", "y", "z"]) F = free_module(Rg, 1) A = Rg[x; y] B = Rg[x^2; y^3; z^4] @@ -302,9 +278,8 @@ end end @testset "Hom module of graded free modules" begin - R0, _ = polynomial_ring(QQ, ["x", "y", "z"]) - Z = abelian_group(0) - Rg, (x, y, z) = grade(R0, [Z[1],Z[1],Z[1]]) + Rg, (x, y, z) = graded_polynomial_ring(QQ, ["x", "y", "z"]) + Z = grading_group(Rg) F1 = graded_free_module(Rg, [1,2,2]) F2 = graded_free_module(Rg, [3,5]) V, f = hom(F1, F2) @@ -319,9 +294,8 @@ end end @testset "Presentations 2" begin - R0, _ = polynomial_ring(QQ, ["x", "y", "z"]) - Z = abelian_group(0) - Rg, (x, y, z) = grade(R0, [Z[1],Z[1],Z[1]]) + Rg, (x, y, z) = graded_polynomial_ring(QQ, ["x", "y", "z"]) + Z = grading_group(Rg) F = graded_free_module(Rg, [1,2,2]); p = presentation(F) @test rank(p[-2]) == 0 @@ -364,9 +338,7 @@ end @testset "Equality morphism for subquotients" begin - R0, _ = polynomial_ring(QQ, ["x", "y", "z"]) - Z = abelian_group(0) - Rg, (x, y, z) = grade(R0, [Z[1],Z[1],Z[1]]) + Rg, (x, y, z) = graded_polynomial_ring(QQ, ["x", "y", "z"]) F = graded_free_module(Rg, 1); A = Rg[x-y; x+y]; B = Rg[x^2; y^3; z^4]; @@ -382,9 +354,8 @@ end end @testset "Free resolutions" begin - R0, _ = polynomial_ring(QQ, ["x", "y", "z"]) - Z = abelian_group(0) - Rg, (x, y, z) = grade(R0, [Z[1],Z[1],Z[1]]) + Rg, (x, y, z) = graded_polynomial_ring(QQ, ["x", "y", "z"]) + Z = grading_group(Rg) F = graded_free_module(Rg, 3) rs = free_resolution(F) @test is_graded(rs) @@ -403,9 +374,8 @@ end end @testset "Hom module of graded subquotient modules" begin - R, _ = polynomial_ring(QQ, ["x", "y"]); - Z = abelian_group(0) - Rg, (x,y) = grade(R,[Z[1], Z[1]]) + Rg, (x, y) = graded_polynomial_ring(QQ, ["x", "y"]) + Z = grading_group(Rg) F = graded_free_module(Rg, 2); V = [x*F[1], y^2*F[2]]; M = quo(F, V)[1] @@ -425,9 +395,8 @@ end end @testset "Dual and double dual" begin - R, _ = polynomial_ring(QQ, ["x", "y", "z"]); - Z = abelian_group(0) - Rg, (x,y) = grade(R,[Z[1], Z[1], Z[1]]) + Rg, (x, y, z) = graded_polynomial_ring(QQ, ["x", "y", "z"]) + Z = grading_group(Rg) F1 = graded_free_module(Rg, 1) F2 = graded_free_module(Rg, 2) F2v, ev = dual(F2, cod=F1) @@ -467,9 +436,7 @@ end end @testset "Hom module element morphism conversion" begin - R0, _ = polynomial_ring(QQ, ["x", "y"]) - Z = abelian_group(0) - Rg, (x, y) = grade(R0, [Z[1],Z[1]]) + Rg, (x, y) = graded_polynomial_ring(QQ, ["x", "y"]) A1 = Rg[x^2+y^2 x*y; x^2+y^2 x*y] B1 = Rg[x*y^3+x^4+y^2*x^2 x^4; y^4-3*x^4 x*y^3-x^4] F = graded_free_module(Rg, 2) @@ -484,9 +451,7 @@ end end @testset "Multiplication morphism" begin - R0, _ = polynomial_ring(QQ, ["x", "y"]) - Z = abelian_group(0) - Rg, (x, y) = grade(R0, [Z[1],Z[1]]) + Rg, (x, y) = graded_polynomial_ring(QQ, ["x", "y"]) A1 = Rg[x^2+y^2 x*y; x^2+y^2 x*y] B1 = Rg[x*y^3+x^4+y^2*x^2 x^4; y^4-3*x^4 x*y^3-x^4] F = graded_free_module(Rg, 2) @@ -499,9 +464,8 @@ end end @testset "Graded tensor product of graded free modules" begin - R0, _ = polynomial_ring(QQ, ["x", "y"]) - Z = abelian_group(0) - Rg, (x, y) = grade(R0, [Z[1],Z[1]]) + Rg, (x, y) = graded_polynomial_ring(QQ, ["x", "y"]) + Z = grading_group(Rg) F1 = graded_free_module(Rg, [1,2]); F2 = graded_free_module(Rg, [3]); F3 = graded_free_module(Rg, [5,6]); @@ -513,9 +477,8 @@ end end @testset "Graded tensor product of graded subquotients" begin - R0, _ = polynomial_ring(QQ, ["x", "y"]) - Z = abelian_group(0) - Rg, (x, y) = grade(R0, [Z[1],Z[1]]) + Rg, (x, y) = graded_polynomial_ring(QQ, ["x", "y"]) + Z = grading_group(Rg) A1 = Rg[x^2+y^2 x*y; x^2+y^2 x*y] B1 = Rg[x*y^3+x^4+y^2*x^2 x^4; y^4-3*x^4 x*y^3-x^4] F = graded_free_module(Rg, 2) @@ -532,9 +495,7 @@ end end @testset "Betti tables 1" begin - R0, _ = polynomial_ring(QQ, ["x", "y", "z"]) - Z = abelian_group(0) - Rg, (x, y, z) = grade(R0, [Z[1],Z[1],Z[1]]) + Rg, (x, y, z) = graded_polynomial_ring(QQ, ["x", "y", "z"]) F = graded_free_module(Rg, 1) A = Rg[x; y] B = Rg[x^2; x*y; y^2; z^4] @@ -548,9 +509,8 @@ end end @testset "Betti tables 2" begin - R0, _ = polynomial_ring(QQ, ["x", "y", "z"]) - Z = abelian_group(0) - Rg, (x, y, z) = grade(R0, [Z[1],Z[1],Z[1]]) + Rg, (x, y, z) = graded_polynomial_ring(QQ, ["x", "y", "z"]) + Z = grading_group(Rg) A = Rg[x; y] B = Rg[x^2; x*y; y^2; z^4] F = graded_free_module(Rg, 1) @@ -612,9 +572,7 @@ end end @testset "Tensor module resolution" begin - R0, _ = polynomial_ring(QQ, ["x", "y", "z"]) - Z = abelian_group(0) - Rg, (x, y, z) = grade(R0, [Z[1],Z[1],Z[1]]) + Rg, (x, y, z) = graded_polynomial_ring(QQ, ["x", "y", "z"]) F = graded_free_module(Rg, 1) A = Rg[x; y] B = Rg[x^2; x*y; y^2; z^4] @@ -637,9 +595,7 @@ end end @testset "Tensor resolution module" begin - R0, _ = polynomial_ring(QQ, ["x", "y", "z"]) - Z = abelian_group(0) - Rg, (x, y, z) = grade(R0, [Z[1],Z[1],Z[1]]) + Rg, (x, y, z) = graded_polynomial_ring(QQ, ["x", "y", "z"]) F = graded_free_module(Rg, 1) A = Rg[x; y] B = Rg[x^2; x*y; y^2; z^4] @@ -662,9 +618,7 @@ end end @testset "Hom module resolution" begin - R0, _ = polynomial_ring(QQ, ["x", "y", "z"]) - Z = abelian_group(0) - Rg, (x, y, z) = grade(R0, [Z[1],Z[1],Z[1]]) + Rg, (x, y, z) = graded_polynomial_ring(QQ, ["x", "y", "z"]) F = graded_free_module(Rg, 1) A = Rg[x; y] B = Rg[x^2; x*y; y^2; z^4] @@ -699,9 +653,7 @@ end end @testset "Hom resolution module" begin - R0, _ = polynomial_ring(QQ, ["x", "y", "z"]) - Z = abelian_group(0) - Rg, (x, y, z) = grade(R0, [Z[1],Z[1],Z[1]]) + Rg, (x, y, z) = graded_polynomial_ring(QQ, ["x", "y", "z"]) F = graded_free_module(Rg, 1) A = Rg[x; y] B = Rg[x^2; x*y; y^2; z^4] @@ -738,9 +690,7 @@ end end @testset "Tor and Ext" begin - R0, _ = polynomial_ring(QQ, ["x", "y", "z"]) - Z = abelian_group(0) - Rg, (x, y, z) = grade(R0, [Z[1],Z[1],Z[1]]) + Rg, (x, y, z) = graded_polynomial_ring(QQ, ["x", "y", "z"]) A = Rg[x; y] B = Rg[x^2; x*y; y^2; z^4] F = graded_free_module(Rg, 1) @@ -783,9 +733,7 @@ end end @testset "Groebner bases graded" begin - R0, _ = polynomial_ring(QQ, ["x", "y", "z"]) - Z = abelian_group(0) - Rg, (x, y, z) = grade(R0, [Z[1],Z[1],Z[1]]) + Rg, (x, y, z) = graded_polynomial_ring(QQ, ["x", "y", "z"]) F = graded_free_module(Rg, 1) J = SubquoModule(F, [x*F[1], (x^2)*F[1], (x+y)*F[1]]) @test leading_module(J) == SubquoModule(F, [x*F[1], y*F[1]]) @@ -803,9 +751,7 @@ end J = SubquoModule(F, [(x[1]+x[2])*F[1], (x[1]+x[2]+2*x[3]+2*x[4])*F[1],(x[1]+x[2]+x[3]+x[4])*F[1]]) @test reduced_groebner_basis(J, lp).O == Oscar.ModuleGens([(x[3]+x[4])*F[1], (x[1]+x[2])*F[1]], F).O @test haskey(J.groebner_basis, lp) - R0, _ = polynomial_ring(QQ, ["x", "y", "z"]) - Z = abelian_group(0) - Rg, (x, y, z) = grade(R0, [Z[1],Z[1],Z[1]]) + Rg, (x, y, z) = graded_polynomial_ring(QQ, ["x", "y", "z"]) F = graded_free_module(Rg, 1) lp = lex(gens(base_ring(F)))*lex(gens(F)) I = SubquoModule(F, [(x-y)*F[1], (y^2-z^2)*F[1]]) @@ -824,9 +770,7 @@ end end @testset "Tensor product of morphisms graded" begin - R0, _ = polynomial_ring(QQ, ["x", "y", "z"]) - Z = abelian_group(0) - Rg, (x, y, z) = grade(R0, [Z[1],Z[1],Z[1]]) + Rg, (x, y, z) = graded_polynomial_ring(QQ, ["x", "y", "z"]) F2 = graded_free_module(Rg,2) F3 = graded_free_module(Rg,3) F4 = graded_free_module(Rg,4) @@ -859,9 +803,8 @@ end end @testset "direct product graded" begin - R0, _ = polynomial_ring(QQ, ["x", "y", "z"]) - Z = abelian_group(0) - Rg, (x, y, z) = grade(R0, [Z[1],Z[1],Z[1]]) + Rg, (x, y, z) = graded_polynomial_ring(QQ, ["x", "y", "z"]) + Z = grading_group(Rg) F2 = graded_free_module(Rg, 2) F3 = graded_free_module(Rg, 3) A1 = Rg[6*x*y^2*z^2 + 4*y*z^4 + 12*y^2*z^3 6*x^2*y^2*z + 11*x^2*z^3; x y; y*z 3*x*z + 3*x*y + 5*y*z] @@ -1030,8 +973,7 @@ function randpoly(R::Oscar.Ring,coeffs=0:9,max_exp=4,max_terms=8) end @testset "Basic degree and homogeneity tests for free modules" begin - Qx, x = polynomial_ring(QQ, 3) - R, x = grade(Qx) + R, x = graded_polynomial_ring(QQ, 3) F = FreeMod_dec(R, 3) #standard grading @test degree(F[1]) == decoration(R)[0] @@ -1089,9 +1031,8 @@ end end @testset "Hom module for decorated free modules" begin - Z = abelian_group(0) - Qx, x = polynomial_ring(QQ, 3) - R, x = grade(Qx, [Z[1] for _ in 1:3]) + R, x = graded_polynomial_ring(QQ, 3, "x") + Z = grading_group(R) F = FreeMod_dec(R, [Z[1], 2*Z[1]]) G = FreeMod_dec(R, [Z[1], 2*Z[1], 3*Z[1]]) diff --git a/test/Modules/hilbert.jl b/test/Modules/hilbert.jl index 70fdc0011d50..f958b2704498 100644 --- a/test/Modules/hilbert.jl +++ b/test/Modules/hilbert.jl @@ -1,7 +1,5 @@ @testset "Hilbert series and free resolution" begin - R, _ = polynomial_ring(QQ, ["x", "y", "z"]); - Z = abelian_group(0); - Rg, (x, y, z) = grade(R, [3*Z[1],Z[1],Z[1]]); + Rg, (x, y, z) = graded_polynomial_ring(QQ, ["x", "y", "z"]; weights = [3,1,1]); F = graded_free_module(Rg, 1); A = Rg[x; y]; B = Rg[x^2+y^6; y^7; z^4]; diff --git a/test/Rings/MPolyQuo.jl b/test/Rings/MPolyQuo.jl index a69c7e82b8c2..c8a43cda326a 100644 --- a/test/Rings/MPolyQuo.jl +++ b/test/Rings/MPolyQuo.jl @@ -131,7 +131,7 @@ end @test intersect(I,J,K) == ideal(Q, [y+1, x]) @test intersect(I,J,K) == intersect([I,J,K]) - R, (x, y) = grade(polynomial_ring(QQ, [ "x", "y"])[1], [ 1, 2 ]) + R, (x, y) = graded_polynomial_ring(QQ, [ "x", "y" ], [ 1, 2 ]) I = ideal(R, [ x*y ]) Q, RtoQ = quo(R, I) J = ideal(Q, [ x^3 + x*y, y, x^2 + y ]) diff --git a/test/Rings/mpoly-graded.jl b/test/Rings/mpoly-graded.jl index 69bede808e34..991bd1c94fa4 100644 --- a/test/Rings/mpoly-graded.jl +++ b/test/Rings/mpoly-graded.jl @@ -208,7 +208,7 @@ end end @testset "Minimal generating set" begin - R, (x, y) = grade(polynomial_ring(QQ, [ "x", "y"])[1], [ 1, 2 ]) + R, (x, y) = graded_polynomial_ring(QQ, [ "x", "y"], [ 1, 2 ]) I = ideal(R, [ x^2, y, x^2 + y ]) @test minimal_generating_set(I) == [ y, x^2 ] @test !isempty(I.gb) From c4933722f7f55d33e43da78c13ba1be0e3c7511a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20G=C3=B6ttgens?= Date: Mon, 23 Oct 2023 16:28:48 +0200 Subject: [PATCH 15/27] Make LieAlgebras compatible with new testing routine (#2943) --- .../LieAlgebras/test/LieAlgebra-test.jl | 110 --------- .../LieAlgebras/test/LieAlgebraModule-test.jl | 106 --------- experimental/LieAlgebras/test/runtests.jl | 10 - experimental/LieAlgebras/test/setup_tests.jl | 214 ++++++++++++++++++ 4 files changed, 214 insertions(+), 226 deletions(-) delete mode 100644 experimental/LieAlgebras/test/runtests.jl create mode 100644 experimental/LieAlgebras/test/setup_tests.jl diff --git a/experimental/LieAlgebras/test/LieAlgebra-test.jl b/experimental/LieAlgebras/test/LieAlgebra-test.jl index 8e8eb23c72bc..121d73446ccb 100644 --- a/experimental/LieAlgebras/test/LieAlgebra-test.jl +++ b/experimental/LieAlgebras/test/LieAlgebra-test.jl @@ -1,113 +1,3 @@ - -function lie_algebra_conformance_test( - L::LieAlgebra{C}, parentT::DataType, elemT::DataType; num_random_tests::Int=10 -) where {C<:FieldElem} - @testset "basic manipulation" begin - x = L(rand(-10:10, dim(L))) - - @test parentT <: LieAlgebra{C} - @test elemT <: LieAlgebraElem{C} - @test L isa parentT - @test x isa elemT - - @test parent_type(elemT) == parentT - @test elem_type(parentT) == elemT - - @test parent(x) === L - - @test coefficient_ring(x) === coefficient_ring(L) - @test elem_type(coefficient_ring(L)) == C - - @test characteristic(L) == characteristic(coefficient_ring(L)) - - # this block stays only as long as `ngens` and `gens` are not specialized for Lie algebras - @test dim(L) == ngens(L) - @test basis(L) == gens(L) - @test all(i -> basis(L, i) == gen(L, i), 1:dim(L)) - - @test dim(L) == length(basis(L)) - @test all(i -> basis(L, i) == basis(L)[i], 1:dim(L)) - - @test dim(L) == length(symbols(L)) - - @test iszero(zero(L)) - - @test coefficients(x) == [coeff(x, i) for i in 1:dim(L)] - @test all(i -> coeff(x, i) == x[i], 1:dim(L)) - @test sum(x[i] * basis(L, i) for i in 1:dim(L); init=zero(L)) == x - - @test x == x - @test deepcopy(x) == x - @test hash(deepcopy(x)) == hash(x) - end - - @testset "parent object call overload" begin - @test L() == zero(L) == L(zeros(coefficient_ring(L), dim(L))) - - for _ in 1:num_random_tests - coeffs = rand(-10:10, dim(L)) - x1 = L(coeffs) - x2 = L(coefficient_ring(L).(coeffs)) - x3 = L(matrix(coefficient_ring(L), 1, dim(L), coeffs)) - x4 = L(sparse_row(matrix(coefficient_ring(L), 1, dim(L), coeffs))) - x5 = L(x1) - @test x1 == x2 - @test x1 == x3 - @test x1 == x4 - @test x1 == x5 - end - end - - @testset "vector space axioms" begin - for _ in 1:num_random_tests - x = L(rand(-10:10, dim(L))) - y = L(rand(-10:10, dim(L))) - z = L(rand(-10:10, dim(L))) - - @test x + y == y + x - @test x + (y + z) == (x + y) + z - - @test x + zero(L) == x - @test zero(L) + x == x - - @test -x + x == zero(L) - @test x + (-x) == zero(L) - - @test x - y == x + (-y) - - @test x * 0 == zero(L) - @test 0 * x == zero(L) - - @test 2 * x == x + x - @test x * 2 == x + x - @test coefficient_ring(L)(2) * x == x + x - @test x * coefficient_ring(L)(2) == x + x - end - end - - @testset "Lie algebra axioms" begin - for _ in 1:num_random_tests - x = L(rand(-10:10, dim(L))) - y = L(rand(-10:10, dim(L))) - z = L(rand(-10:10, dim(L))) - - @test x * y == bracket(x, y) - - @test (x + y) * z == x * z + y * z - @test x * (y + z) == x * y + x * z - - @test x * x == zero(L) - @test x * y == -(y * x) - - @test (x * (y * z)) + (y * (z * x)) + (z * (x * y)) == zero(L) - end - end -end - -include("AbstractLieAlgebra-test.jl") -include("LinearLieAlgebra-test.jl") -include("simple_lie_algebra-test.jl") - @testset "LieAlgebras.LieAlgebra" begin @testset "universal_enveloping_algebra" begin L = special_linear_lie_algebra(QQ, 2) diff --git a/experimental/LieAlgebras/test/LieAlgebraModule-test.jl b/experimental/LieAlgebras/test/LieAlgebraModule-test.jl index 0c050c7a1588..b8e5ee796c4f 100644 --- a/experimental/LieAlgebras/test/LieAlgebraModule-test.jl +++ b/experimental/LieAlgebras/test/LieAlgebraModule-test.jl @@ -1,110 +1,4 @@ -function lie_algebra_module_conformance_test( - L::LieAlgebra{C}, - V::LieAlgebraModule{C}, - parentT::DataType=LieAlgebraModule{C}, - elemT::DataType=LieAlgebraModuleElem{C}; - num_random_tests::Int=10, -) where {C<:FieldElem} - @testset "basic manipulation" begin - v = V(rand(-10:10, dim(V))) - - # @test parentT <: LieAlgebraModule{C} - # @test elemT <: LieAlgebraModuleElem{C} - @test V isa parentT - @test v isa elemT - - @test parent_type(elemT) == parentT - @test elem_type(parentT) == elemT - - @test parent(v) === V - - @test coefficient_ring(v) === coefficient_ring(V) - @test elem_type(coefficient_ring(V)) == C - - @test base_lie_algebra(V) === L - - # this block stays only as long as `ngens` and `gens` are not specialized for Lie algebra modules - @test dim(V) == ngens(V) - @test basis(V) == gens(V) - @test all(i -> basis(V, i) == gen(V, i), 1:dim(V)) - - @test dim(V) == length(basis(V)) - @test all(i -> basis(V, i) == basis(V)[i], 1:dim(V)) - - @test iszero(zero(V)) - - @test coefficients(v) == [coeff(v, i) for i in 1:dim(V)] - @test all(i -> coeff(v, i) == v[i], 1:dim(V)) - @test sum(v[i] * basis(V, i) for i in 1:dim(V); init=zero(V)) == v - - @test v == v - @test deepcopy(v) == v - @test hash(deepcopy(v)) == hash(v) - end - - @testset "parent object call overload" begin - @test V() == zero(V) == V(zeros(coefficient_ring(V), dim(V))) - - for _ in 1:num_random_tests - coeffs = rand(-10:10, dim(V)) - v1 = V(coeffs) - v2 = V(coefficient_ring(V).(coeffs)) - v3 = V(matrix(coefficient_ring(V), 1, dim(V), coeffs)) - v4 = V(sparse_row(matrix(coefficient_ring(V), 1, dim(V), coeffs))) - v5 = V(v1) - @test v1 == v2 - @test v1 == v3 - @test v1 == v4 - @test v1 == v5 - end - end - - @testset "vector space axioms" begin - for _ in 1:num_random_tests - v = V(rand(-10:10, dim(V))) - w = V(rand(-10:10, dim(V))) - w2 = V(rand(-10:10, dim(V))) - - @test v + w == w + v - @test v + (w + w2) == (v + w) + w2 - - @test v + zero(V) == v - @test zero(V) + v == v - - @test -v + v == zero(V) - @test v + (-v) == zero(V) - - @test v - w == v + (-w) - - @test v * 0 == zero(V) - @test 0 * v == zero(V) - - @test 2 * v == v + v - @test v * 2 == v + v - @test coefficient_ring(V)(2) * v == v + v - @test v * coefficient_ring(V)(2) == v + v - end - end - - @testset "Lie algebra action axioms" begin - for _ in 1:num_random_tests - x = L(rand(-10:10, dim(L))) - y = L(rand(-10:10, dim(L))) - v = V(rand(-10:10, dim(V))) - w = V(rand(-10:10, dim(V))) - - @test (x * v) isa elemT - @test parent(x * v) == parent(v) - - @test (x + y) * v == x * v + y * v - @test x * (v + w) == x * v + x * w - - @test (x * y) * v == x * (y * v) - y * (x * v) - end - end -end - @testset "LieAlgebras.LieAlgebraModule" begin sc = Matrix{SRow{elem_type(QQ)}}(undef, 3, 2) sc[1, 1] = sparse_row(QQ, [1, 2], [0, 0]) diff --git a/experimental/LieAlgebras/test/runtests.jl b/experimental/LieAlgebras/test/runtests.jl deleted file mode 100644 index f6216cc2fb20..000000000000 --- a/experimental/LieAlgebras/test/runtests.jl +++ /dev/null @@ -1,10 +0,0 @@ -include("Combinatorics-test.jl") -include("iso_oscar_gap-test.jl") -include("iso_gap_oscar-test.jl") -include("LieAlgebra-test.jl") -include("LieSubalgebra-test.jl") -include("LieAlgebraIdeal-test.jl") -include("LieAlgebraHom-test.jl") -include("LieAlgebraModule-test.jl") -include("LieAlgebraModuleHom-test.jl") -include("root_systems-test.jl") diff --git a/experimental/LieAlgebras/test/setup_tests.jl b/experimental/LieAlgebras/test/setup_tests.jl new file mode 100644 index 000000000000..fe0d6fb87829 --- /dev/null +++ b/experimental/LieAlgebras/test/setup_tests.jl @@ -0,0 +1,214 @@ +if !isdefined(Main, :lie_algebra_conformance_test) + function lie_algebra_conformance_test( + L::LieAlgebra{C}, parentT::DataType, elemT::DataType; num_random_tests::Int=10 + ) where {C<:FieldElem} + @testset "basic manipulation" begin + x = L(rand(-10:10, dim(L))) + + @test parentT <: LieAlgebra{C} + @test elemT <: LieAlgebraElem{C} + @test L isa parentT + @test x isa elemT + + @test parent_type(elemT) == parentT + @test elem_type(parentT) == elemT + + @test parent(x) === L + + @test coefficient_ring(x) === coefficient_ring(L) + @test elem_type(coefficient_ring(L)) == C + + @test characteristic(L) == characteristic(coefficient_ring(L)) + + # this block stays only as long as `ngens` and `gens` are not specialized for Lie algebras + @test dim(L) == ngens(L) + @test basis(L) == gens(L) + @test all(i -> basis(L, i) == gen(L, i), 1:dim(L)) + + @test dim(L) == length(basis(L)) + @test all(i -> basis(L, i) == basis(L)[i], 1:dim(L)) + + @test dim(L) == length(symbols(L)) + + @test iszero(zero(L)) + + @test coefficients(x) == [coeff(x, i) for i in 1:dim(L)] + @test all(i -> coeff(x, i) == x[i], 1:dim(L)) + @test sum(x[i] * basis(L, i) for i in 1:dim(L); init=zero(L)) == x + + @test x == x + @test deepcopy(x) == x + @test hash(deepcopy(x)) == hash(x) + end + + @testset "parent object call overload" begin + @test L() == zero(L) == L(zeros(coefficient_ring(L), dim(L))) + + for _ in 1:num_random_tests + coeffs = rand(-10:10, dim(L)) + x1 = L(coeffs) + x2 = L(coefficient_ring(L).(coeffs)) + x3 = L(matrix(coefficient_ring(L), 1, dim(L), coeffs)) + x4 = L(sparse_row(matrix(coefficient_ring(L), 1, dim(L), coeffs))) + x5 = L(x1) + @test x1 == x2 + @test x1 == x3 + @test x1 == x4 + @test x1 == x5 + end + end + + @testset "vector space axioms" begin + for _ in 1:num_random_tests + x = L(rand(-10:10, dim(L))) + y = L(rand(-10:10, dim(L))) + z = L(rand(-10:10, dim(L))) + + @test x + y == y + x + @test x + (y + z) == (x + y) + z + + @test x + zero(L) == x + @test zero(L) + x == x + + @test -x + x == zero(L) + @test x + (-x) == zero(L) + + @test x - y == x + (-y) + + @test x * 0 == zero(L) + @test 0 * x == zero(L) + + @test 2 * x == x + x + @test x * 2 == x + x + @test coefficient_ring(L)(2) * x == x + x + @test x * coefficient_ring(L)(2) == x + x + end + end + + @testset "Lie algebra axioms" begin + for _ in 1:num_random_tests + x = L(rand(-10:10, dim(L))) + y = L(rand(-10:10, dim(L))) + z = L(rand(-10:10, dim(L))) + + @test x * y == bracket(x, y) + + @test (x + y) * z == x * z + y * z + @test x * (y + z) == x * y + x * z + + @test x * x == zero(L) + @test x * y == -(y * x) + + @test (x * (y * z)) + (y * (z * x)) + (z * (x * y)) == zero(L) + end + end + end +end + +if !isdefined(Main, :lie_algebra_module_conformance_test) + function lie_algebra_module_conformance_test( + L::LieAlgebra{C}, + V::LieAlgebraModule{C}, + parentT::DataType=LieAlgebraModule{C}, + elemT::DataType=LieAlgebraModuleElem{C}; + num_random_tests::Int=10, + ) where {C<:FieldElem} + @testset "basic manipulation" begin + v = V(rand(-10:10, dim(V))) + + # @test parentT <: LieAlgebraModule{C} + # @test elemT <: LieAlgebraModuleElem{C} + @test V isa parentT + @test v isa elemT + + @test parent_type(elemT) == parentT + @test elem_type(parentT) == elemT + + @test parent(v) === V + + @test coefficient_ring(v) === coefficient_ring(V) + @test elem_type(coefficient_ring(V)) == C + + @test base_lie_algebra(V) === L + + # this block stays only as long as `ngens` and `gens` are not specialized for Lie algebra modules + @test dim(V) == ngens(V) + @test basis(V) == gens(V) + @test all(i -> basis(V, i) == gen(V, i), 1:dim(V)) + + @test dim(V) == length(basis(V)) + @test all(i -> basis(V, i) == basis(V)[i], 1:dim(V)) + + @test iszero(zero(V)) + + @test coefficients(v) == [coeff(v, i) for i in 1:dim(V)] + @test all(i -> coeff(v, i) == v[i], 1:dim(V)) + @test sum(v[i] * basis(V, i) for i in 1:dim(V); init=zero(V)) == v + + @test v == v + @test deepcopy(v) == v + @test hash(deepcopy(v)) == hash(v) + end + + @testset "parent object call overload" begin + @test V() == zero(V) == V(zeros(coefficient_ring(V), dim(V))) + + for _ in 1:num_random_tests + coeffs = rand(-10:10, dim(V)) + v1 = V(coeffs) + v2 = V(coefficient_ring(V).(coeffs)) + v3 = V(matrix(coefficient_ring(V), 1, dim(V), coeffs)) + v4 = V(sparse_row(matrix(coefficient_ring(V), 1, dim(V), coeffs))) + v5 = V(v1) + @test v1 == v2 + @test v1 == v3 + @test v1 == v4 + @test v1 == v5 + end + end + + @testset "vector space axioms" begin + for _ in 1:num_random_tests + v = V(rand(-10:10, dim(V))) + w = V(rand(-10:10, dim(V))) + w2 = V(rand(-10:10, dim(V))) + + @test v + w == w + v + @test v + (w + w2) == (v + w) + w2 + + @test v + zero(V) == v + @test zero(V) + v == v + + @test -v + v == zero(V) + @test v + (-v) == zero(V) + + @test v - w == v + (-w) + + @test v * 0 == zero(V) + @test 0 * v == zero(V) + + @test 2 * v == v + v + @test v * 2 == v + v + @test coefficient_ring(V)(2) * v == v + v + @test v * coefficient_ring(V)(2) == v + v + end + end + + @testset "Lie algebra action axioms" begin + for _ in 1:num_random_tests + x = L(rand(-10:10, dim(L))) + y = L(rand(-10:10, dim(L))) + v = V(rand(-10:10, dim(V))) + w = V(rand(-10:10, dim(V))) + + @test (x * v) isa elemT + @test parent(x * v) == parent(v) + + @test (x + y) * v == x * v + y * v + @test x * (v + w) == x * v + x * w + + @test (x * y) * v == x * (y * v) - y * (x * v) + end + end + end +end From d5e7b73ab465a73a7f93034c13dd42e565b54146 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Mon, 23 Oct 2023 18:37:56 +0200 Subject: [PATCH 16/27] Clean up PlaneCurve tests (#2948) --- experimental/PlaneCurve/test/runtests.jl | 32 ++++++++++++------------ 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/experimental/PlaneCurve/test/runtests.jl b/experimental/PlaneCurve/test/runtests.jl index 2f0e7d13eeae..ec02b44b2779 100644 --- a/experimental/PlaneCurve/test/runtests.jl +++ b/experimental/PlaneCurve/test/runtests.jl @@ -124,9 +124,9 @@ end @test degree(C) == 9 @test Oscar.curve_components(C) == Dict{ProjPlaneCurve{QQFieldElem},Int64}( - ProjPlaneCurve(T(x)) => 2, - ProjPlaneCurve(T(y)) => 3, - ProjPlaneCurve(T(x^4 - y^3 * z)) => 1, + ProjPlaneCurve(x) => 2, + ProjPlaneCurve(y) => 3, + ProjPlaneCurve(x^4 - y^3 * z) => 1, ) @test C == ProjPlaneCurve(2 * F) @@ -194,15 +194,15 @@ end @testset "ProjPlaneCurve int_multiplicity functions" begin T, (x, y, z) = graded_polynomial_ring(QQ, ["x", "y", "z"]) - F = ProjPlaneCurve(T((x^2 + y^2) * (x^2 + y^2 + 2 * y * z))) - G = ProjPlaneCurve(T((x^2 + y^2) * (y^3 * x^6 - y^6 * x^2 * z))) + F = ProjPlaneCurve((x^2 + y^2) * (x^2 + y^2 + 2 * y * z)) + G = ProjPlaneCurve((x^2 + y^2) * (y^3 * x^6 - y^6 * x^2 * z)) PP = proj_space(QQ, 2) L = curve_intersect(PP[1], F, G) P = Oscar.Geometry.ProjSpcElem(PP[1], [QQ(0), QQ(0), QQ(1)]) Q = Oscar.Geometry.ProjSpcElem(PP[1], [QQ(0), QQ(-2), QQ(1)]) - @test L[1] == [ProjPlaneCurve(T(x^2 + y^2))] + @test L[1] == [ProjPlaneCurve(x^2 + y^2)] @test length(L[2]) == 2 @test length(findall(x -> x == P, L[2])) == 1 @test length(findall(x -> x == Q, L[2])) == 1 @@ -214,14 +214,14 @@ end @testset "ProjPlaneCurve singularity functions" begin T, (x, y, z) = graded_polynomial_ring(QQ, ["x", "y", "z"]) PP = proj_space(QQ, 2) - F = ProjPlaneCurve(T(x * z + y^2)) + F = ProjPlaneCurve(x * z + y^2) P = Oscar.Geometry.ProjSpcElem(PP[1], [QQ(1), QQ(0), QQ(0)]) @test curve_singular_locus(F) == [[], []] @test is_smooth_curve(F) @test multiplicity(F, P) == 1 - H = ProjPlaneCurve(T(x * y * (x + y))) + H = ProjPlaneCurve(x * y * (x + y)) @test !is_smooth_curve(H) G = ProjPlaneCurve(x^2 * (x + y) * (y^3 - x^2 * z)) @@ -231,17 +231,17 @@ end P3 = Oscar.Geometry.ProjSpcElem(PP[1], [QQ(2), QQ(-2), QQ(1)]) P4 = Oscar.Geometry.ProjSpcElem(PP[1], [QQ(1), QQ(2), QQ(1)]) - @test S[1] == [ProjPlaneCurve(T(x))] + @test S[1] == [ProjPlaneCurve(x)] @test length(S[2]) == 2 @test length(findall(x -> x == P1, S[2])) == 1 @test length(findall(x -> x == P2, S[2])) == 1 @test !is_smooth(G, P1) @test is_smooth(G, P3) - @test tangent(G, P3) == ProjPlaneCurve(T(x + y)) + @test tangent(G, P3) == ProjPlaneCurve(x + y) @test tangent_lines(G, P1) == Dict{ProjPlaneCurve{QQFieldElem},Int64}( - ProjPlaneCurve(T(x)) => 4, - ProjPlaneCurve(T(x + y)) => 1, + ProjPlaneCurve(x) => 4, + ProjPlaneCurve(x + y) => 1, ) @test multiplicity(G, P1) == 5 @@ -266,7 +266,7 @@ end @testset "ProjCurveDivisor basic functions" begin T, (x, y, z) = graded_polynomial_ring(QQ, ["x", "y", "z"]) - C = ProjPlaneCurve(T(y^2 + y * z + x^2)) + C = ProjPlaneCurve(y^2 + y * z + x^2) PP = proj_space(QQ, 2) P = Oscar.Geometry.ProjSpcElem(PP[1], [QQ(0), QQ(0), QQ(1)]) Q = Oscar.Geometry.ProjSpcElem(PP[1], [QQ(0), QQ(-1), QQ(1)]) @@ -275,8 +275,8 @@ end @test -2 * D == Oscar.ProjCurveDivisor(C, Dict(P => -6, Q => 4)) @test !Oscar.is_effective(D) @test Oscar.is_effective(Oscar.ProjCurveDivisor(C, P, 3)) - F = T(x) - phi = T(x) // T(y) + F = x + phi = x // y @test multiplicity(C, F, P) == 1 @test multiplicity(C, phi, P) == -1 @test Oscar.divisor(PP[1], C, F) == Oscar.ProjCurveDivisor(C, Dict(P => 1, Q => 1)) @@ -286,7 +286,7 @@ end @testset "ProjCurveDivisor global sections" begin S, (x, y, z) = polynomial_ring(QQ, ["x", "y", "z"]) T, _ = grade(S) - C = ProjPlaneCurve(T(y^2 * z - x * (x - z) * (x + 3 * z))) + C = ProjPlaneCurve(y^2 * z - x * (x - z) * (x + 3 * z)) PP = proj_space(QQ, 2) P = Oscar.Geometry.ProjSpcElem(PP[1], [QQ(0), QQ(1), QQ(0)]) R = Oscar.Geometry.ProjSpcElem(PP[1], [QQ(0), QQ(0), QQ(1)]) From 4918a7a4fd5026e1b5bb673fe82ebc429e66944b Mon Sep 17 00:00:00 2001 From: Benjamin Lorenz Date: Wed, 25 Oct 2023 09:54:44 +0200 Subject: [PATCH 17/27] PolyhedralFan: fix for trivial fans (#2951) --- .../PolyhedralFan/constructors.jl | 17 +++++++++++------ test/PolyhedralGeometry/polyhedral_fan.jl | 11 +++++++++++ 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/src/PolyhedralGeometry/PolyhedralFan/constructors.jl b/src/PolyhedralGeometry/PolyhedralFan/constructors.jl index 0b6a16df06d5..a18c72621699 100644 --- a/src/PolyhedralGeometry/PolyhedralFan/constructors.jl +++ b/src/PolyhedralGeometry/PolyhedralFan/constructors.jl @@ -101,7 +101,16 @@ Get the underlying polymake object, which can be used via Polymake.jl. """ pm_object(PF::PolyhedralFan) = PF.pm_fan -polyhedral_fan(itr::AbstractVector{Cone{T}}) where T<:scalar_types = PolyhedralFan{T}(Polymake.fan.check_fan_objects(pm_object.(itr)...), coefficient_field(iterate(itr)[1])) +function polyhedral_fan(itr::AbstractVector{Cone{T}}) where T<:scalar_types + @req length(itr) > 0 "list of cones must be non-empty" + pmfan = Polymake.fan.check_fan_objects(pm_object.(itr)...) + if pmfan.N_MAXIMAL_CONES == 0 + # if check fan returns no cones then the rays are empty and we have just one trivial cone (maybe with lineality) + C = itr[1] + return polyhedral_fan(coefficient_field(C), rays(C), lineality_space(C), IncidenceMatrix(1,0); non_redundant=true) + end + return PolyhedralFan{T}(pmfan, coefficient_field(iterate(itr)[1])) +end #Same construction for when the user gives Matrix{Bool} as incidence matrix polyhedral_fan(f::scalar_type_or_field, Rays::AbstractCollection[RayVector], LS::AbstractCollection[RayVector], Incidence::Matrix{Bool}) = @@ -109,11 +118,7 @@ polyhedral_fan(f::scalar_type_or_field, Rays::AbstractCollection[RayVector], LS: polyhedral_fan(f::scalar_type_or_field, Rays::AbstractCollection[RayVector], Incidence::Matrix{Bool}) = polyhedral_fan(f, Rays, IncidenceMatrix(Polymake.IncidenceMatrix(Incidence))) - -function polyhedral_fan(C::Cone{T}) where T<:scalar_types - pmfan = Polymake.fan.check_fan_objects(pm_object(C)) - return PolyhedralFan{T}(pmfan, coefficient_field(C)) -end +polyhedral_fan(C::Cone{T}) where T<:scalar_types = polyhedral_fan([C]) ############################################################################### ############################################################################### diff --git a/test/PolyhedralGeometry/polyhedral_fan.jl b/test/PolyhedralGeometry/polyhedral_fan.jl index 7f78b5e5dd8d..e5a5edd18ff8 100644 --- a/test/PolyhedralGeometry/polyhedral_fan.jl +++ b/test/PolyhedralGeometry/polyhedral_fan.jl @@ -80,6 +80,17 @@ @test lineality_space(F2NR) == collect(eachrow(L)) @test ray_indices(maximal_cones(F2NR)) == incidence2 @test IncidenceMatrix(maximal_cones(F2NR)) == incidence2 + + C = positive_hull(f, identity_matrix(ZZ, 0)) + pf = polyhedral_fan(C) + @test n_maximal_cones(pf) == 1 + @test dim(pf) == 0 + pfc = polyhedral_fan(maximal_cones(pf)) + @test n_maximal_cones(pfc) == 1 + + C = positive_hull(f, vcat(identity_matrix(ZZ, 4), -identity_matrix(ZZ,4))) + pf = polyhedral_fan(C) + @test n_maximal_cones(pf) == 1 end end From 4eec6b588ef667a458dcbc90a69bdde405eded43 Mon Sep 17 00:00:00 2001 From: Matthias Zach <85350711+HechtiDerLachs@users.noreply.github.com> Date: Wed, 25 Oct 2023 11:58:10 +0200 Subject: [PATCH 18/27] Implement flattenings of graded polynomial rings (#2906) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Implement flattenings of graded polynomial rings over various coefficient rings. * Implement free graded resolutions via flattenings. --------- Co-authored-by: Anne Frühbis-Krüger <77079696+afkafkafk13@users.noreply.github.com> --- .../ProjectiveSchemes/Objects/Attributes.jl | 4 +- src/Modules/Modules.jl | 1 + src/Modules/ModulesGraded.jl | 40 ++++ src/Modules/flattenings.jl | 100 +++++++++ src/Rings/MPolyMap/AffineAlgebras.jl | 7 +- src/Rings/MPolyMap/flattenings.jl | 189 +++++++++++++++- src/Rings/mpoly-localizations.jl | 21 ++ src/Rings/mpoly.jl | 3 + src/Rings/mpolyquo-localizations.jl | 19 ++ test/Rings/MPolyAnyMap/AffineAlgebras.jl | 9 + test/Rings/MPolyAnyMap/flattenings.jl | 211 +++++++++++++++++- 11 files changed, 582 insertions(+), 22 deletions(-) create mode 100644 src/Modules/flattenings.jl diff --git a/src/AlgebraicGeometry/Schemes/ProjectiveSchemes/Objects/Attributes.jl b/src/AlgebraicGeometry/Schemes/ProjectiveSchemes/Objects/Attributes.jl index 17777bab3248..b98adbedecb8 100644 --- a/src/AlgebraicGeometry/Schemes/ProjectiveSchemes/Objects/Attributes.jl +++ b/src/AlgebraicGeometry/Schemes/ProjectiveSchemes/Objects/Attributes.jl @@ -399,13 +399,13 @@ Projective space of dimension 2 with homogeneous coordinates [x, y, z] julia> homogeneous_coordinates_on_affine_cone(P) -3-element Vector{MPolyQuoRingElem{QQMPolyRingElem}}: +3-element Vector{MPolyQuoRingElem{MPolyDecRingElem{QQFieldElem, QQMPolyRingElem}}}: x y z julia> gens(OO(affine_cone(P)[1])) # all coordinates on the affine cone -5-element Vector{MPolyQuoRingElem{QQMPolyRingElem}}: +5-element Vector{MPolyQuoRingElem{MPolyDecRingElem{QQFieldElem, QQMPolyRingElem}}}: x y z diff --git a/src/Modules/Modules.jl b/src/Modules/Modules.jl index f83dc77e3cb3..68bf74e76909 100644 --- a/src/Modules/Modules.jl +++ b/src/Modules/Modules.jl @@ -8,6 +8,7 @@ include("ModulesGraded.jl") include("module-localizations.jl") include("local_rings.jl") include("mpolyquo.jl") +include("flattenings.jl") include("ExteriorPowers/ExteriorPowers.jl") #include("Iterators.jl") # inclusion postponed to src/InvariantTheory/InvariantTheory.jl due to dependencies diff --git a/src/Modules/ModulesGraded.jl b/src/Modules/ModulesGraded.jl index 357e58fb7f2c..35379d847c0b 100644 --- a/src/Modules/ModulesGraded.jl +++ b/src/Modules/ModulesGraded.jl @@ -2657,3 +2657,43 @@ function twist(M::ModuleFP{T}, d::IntegerUnion) where {T<:MPolyDecRingElem} @assert is_z_graded(R) return twist(M, grading_group(R)([d])) end + +# TODO: implement further base changes. But for this we need more functionality +# for potential change of grading groups. See the open pr #2677. +function change_base_ring( + f::RingFlattening{DomType, CodType}, F::FreeMod + ) where {DomType<:MPolyDecRing, CodType<:Ring} + domain(f) === base_ring(F) || error("ring map not compatible with the module") + S = codomain(f) + r = ngens(F) + FS = grade(FreeMod(S, F.S), degree.(gens(F))) + map = hom(F, FS, gens(FS), f) + return FS, map +end + +function change_base_ring(f::RingFlattening{DomType, CodType}, M::SubquoModule) where {DomType<:MPolyDecRing, CodType<:Ring} + domain(f) == base_ring(M) || error("ring map not compatible with the module") + S = codomain(f) + F = ambient_free_module(M) + R = base_ring(M) + FS, mapF, iso_inv = f(F) # Makes sure ambient modules are preserved due to caching in flattenings + g = ambient_representatives_generators(M) + rels = relations(M) + MS = SubquoModule(FS, mapF.(g), mapF.(rels)) + map = SubQuoHom(M, MS, gens(MS), f) + return MS, map +end + +function _regularity_bound(M::SubquoModule) + @assert is_graded(M) "module must be graded" + S = base_ring(M) + G = grading_group(S) + @assert is_free(G) && isone(rank(G)) "base ring must be ZZ-graded" + @assert all(x->degree(x)[1] >= 0, gens(S)) "base ring variables must be non-negatively graded" + res = free_resolution(M) + result = maximum((x->degree(x)[1]).(gens(res[0]))) + for i in 0:first(chain_range(res)) + result = maximum(push!((x->degree(x)[1]-i).(gens(res[i])), result)) + end + return result +end diff --git a/src/Modules/flattenings.jl b/src/Modules/flattenings.jl new file mode 100644 index 000000000000..6dc4516bc2ee --- /dev/null +++ b/src/Modules/flattenings.jl @@ -0,0 +1,100 @@ +### Flattenings of (graded) modules + +function flatten(F::ModuleFP) + return flatten(base_ring(F))(F) +end + +function (flat_map::RingFlattening)(F::ModuleFP{T}) where {T <: MPolyRingElem{<:Union{MPolyRingElem, MPolyQuoRingElem, + MPolyQuoLocRingElem, MPolyLocRingElem}}} + if !haskey(flat_counterparts(flat_map), F) + F_flat, iso = change_base_ring(flat_map, F) + iso_inv = hom(F_flat, F, gens(F), inverse(flat_map)) + set_attribute!(iso, :inverse, iso_inv) + set_attribute!(iso_inv, :inverse, iso) + flat_counterparts(flat_map)[F] = (F_flat, iso, iso_inv) + end + + F_flat, iso, iso_inv = flat_counterparts(flat_map)[F]::Tuple{<:ModuleFP, <:ModuleFPHom, <:ModuleFPHom} + return F_flat, iso, iso_inv +end + +function flatten( + a::FreeModElem{T} + ) where {T <: MPolyRingElem{<:Union{MPolyRingElem, MPolyQuoRingElem, + MPolyQuoLocRingElem, MPolyLocRingElem}}} + F = parent(a) + R = base_ring(F) + flat_map = flatten(R) + return flat_map(a) +end + +function (flat::RingFlattening)(a::FreeModElem) + if !haskey(flat_counterparts(flat), a) + F = parent(a) + F_flat, iso, iso_inv = flat(F) + a_flat = iso(a) + flat_counterparts(flat)[a] = a_flat + end + return flat_counterparts(flat)[a]::FreeModElem +end + + +function Base.in( + a::FreeModElem{T}, M::SubquoModule{T} + ) where {T <: MPolyRingElem{<:Union{MPolyRingElem, MPolyQuoRingElem, + MPolyQuoLocRingElem, MPolyLocRingElem}}} + flat = flatten(base_ring(parent(a))) + return flat(a) in flat(M)[1] +end + +function coordinates( + a::FreeModElem{T}, M::SubquoModule{T} + ) where {T <: MPolyRingElem{<:Union{MPolyRingElem, MPolyQuoRingElem, + MPolyQuoLocRingElem, MPolyLocRingElem}}} + + flat = flatten(base_ring(parent(a))) + c = coordinates(flat(a), flat(M)[1]) + return map_entries(inverse(flat), c) +end + +function free_resolution( + M::SubquoModule{T} + ) where {T <: MPolyRingElem{<:Union{MPolyRingElem, MPolyQuoRingElem, + MPolyQuoLocRingElem, MPolyLocRingElem}}} + flat = flatten(base_ring(M)) + M_flat, iso_M, iso_M_inv = flat(M) + comp = free_resolution(M_flat) # assuming that this is potentially cached + if !haskey(flat_counterparts(flat), comp) + res_obj = ModuleFP[] + isos = ModuleFPHom[] + push!(res_obj, M) + push!(isos, iso_M_inv) + res_maps = Map[] + for i in 0:first(chain_range(comp)) + F_flat = comp[i] + @assert F_flat === domain(map(comp, i)) + @assert domain(last(isos)) === codomain(map(comp, i)) + F, iso_F_inv = _change_base_ring_and_preserve_gradings(inverse(flat), F_flat) + iso_F = hom(F, F_flat, gens(F_flat), flat) + push!(res_maps, hom(F, last(res_obj), last(isos).(map(comp, i).(iso_F.(gens(F)))))) + push!(res_obj, F) + push!(isos, iso_F_inv) + end + comp_up = ComplexOfMorphisms(ModuleFP, reverse(res_maps), typ=:chain, seed=-1, check=false) + comp_up.complete = true + result = FreeResolution(comp_up) + flat_counterparts(flat)[comp] = result + end + return flat_counterparts(flat)[comp]::FreeResolution +end + +# TODO: We need this special routine, because we can not write a generic +# base change method for morphisms of graded rings. See pr #2677 +function _change_base_ring_and_preserve_gradings(phi::Map{<:Ring, <:Ring}, F::FreeMod) + R = domain(phi) + S = codomain(phi) + FS = (is_graded(F) ? graded_free_module(S, degree.(gens(F))) : FreeMod(S, ngens(F))) + FS.S = F.S + return FS, hom(F, FS, gens(FS), phi) +end + diff --git a/src/Rings/MPolyMap/AffineAlgebras.jl b/src/Rings/MPolyMap/AffineAlgebras.jl index e8a5e978ed49..859d07732825 100644 --- a/src/Rings/MPolyMap/AffineAlgebras.jl +++ b/src/Rings/MPolyMap/AffineAlgebras.jl @@ -5,9 +5,10 @@ ################################################################################ const AffAlgHom = MPolyAnyMap{DT, CT, Nothing} where {T <: FieldElem, - U <: MPolyRingElem{T}, - DT <: Union{MPolyRing{T}, MPolyQuoRing{U}}, - CT <: Union{MPolyRing{T}, MPolyQuoRing{U}}} + U1 <: MPolyRingElem{T}, + U2 <: MPolyRingElem{T}, # types in domain an codomain might differ: one might be decorated, the other not. + DT <: Union{MPolyRing{T}, MPolyQuoRing{U1}}, + CT <: Union{MPolyRing{T}, MPolyQuoRing{U2}}} affine_algebra_morphism_type(::Type{T}) where {T <: Union{MPolyRing, MPolyQuoRing}} = morphism_type(T, T) diff --git a/src/Rings/MPolyMap/flattenings.jl b/src/Rings/MPolyMap/flattenings.jl index 3f25dee9d3bd..f2327c2fc888 100644 --- a/src/Rings/MPolyMap/flattenings.jl +++ b/src/Rings/MPolyMap/flattenings.jl @@ -20,6 +20,8 @@ flat_to_orig::Map{FlatRingType, TowerRingType} base_ring_to_flat::Map{CoeffRingType, FlatRingType} + flat_counterparts::AbstractAlgebra.WeakKeyIdDict{Any, Any} + function RingFlattening( S::MPolyRing{RingElemType} ) where {RingElemType <: MPolyRingElem} @@ -35,6 +37,30 @@ ) end + function RingFlattening( + S::MPolyDecRing{RingElemType} + ) where {RingElemType <: MPolyRingElem} + R = base_ring(S) + kk = coefficient_ring(R) + G = grading_group(S) + w = degree.(gens(S)) + new_w = vcat(w, [zero(G) for i in 1:ngens(R)]) + S_flat, _ = graded_polynomial_ring(kk, vcat(symbols(S), symbols(R)), new_w) + set_default_ordering!(S_flat, + matrix_ordering(S_flat, + block_diagonal_matrix( + [canonical_matrix(default_ordering(S)), + canonical_matrix(default_ordering(R))] + ))) + R_to_S_flat = hom(R, S_flat, gens(S_flat)[ngens(S)+1:end], check=false) + S_to_S_flat = hom(S, S_flat, R_to_S_flat, gens(S_flat)[1:ngens(S)], check=false) + S_flat_to_S = hom(S_flat, S, vcat(gens(S), S.(gens(R))), check=false) + return new{typeof(S), typeof(S_flat), typeof(R)}(S, S_flat, R, + S_to_S_flat, S_flat_to_S, + R_to_S_flat + ) + end + function RingFlattening( S::MPolyRing{RingElemType} ) where {RingElemType <: MPolyQuoRingElem} @@ -62,6 +88,42 @@ ) end + function RingFlattening( + S::MPolyDecRing{RingElemType} + ) where {RingElemType <: MPolyQuoRingElem} + A = base_ring(S)::MPolyQuoRing + R = base_ring(A)::MPolyRing + I = modulus(A)::MPolyIdeal + kk = coefficient_ring(R)::Field + G = grading_group(S) + w = degree.(gens(S)) + new_w = vcat(w, [zero(G) for i in 1:ngens(R)]) + + # Before building S_flat, we have to create a polynomial + # ring T_flat from which we can pass to the quotient. + T_flat, _ = graded_polynomial_ring(kk, vcat(symbols(S), symbols(R)), new_w) + set_default_ordering!(T_flat, + matrix_ordering(T_flat, + block_diagonal_matrix( + [canonical_matrix(default_ordering(S)), + canonical_matrix(default_ordering(R))] + ))) + R_to_T_flat = hom(R, T_flat, gens(T_flat)[ngens(S)+1:end], check=false) + + I_flat = ideal(T_flat, R_to_T_flat.(gens(I))) + S_flat, pr = quo(T_flat, I_flat) + + A_to_S_flat = hom(A, S_flat, gens(S_flat)[ngens(S)+1:end], check=false) + + S_to_S_flat = hom(S, S_flat, A_to_S_flat, gens(S_flat)[1:ngens(S)], check=false) + S_flat_to_S = hom(S_flat, S, vcat(gens(S), S.(gens(A))), check=false) + + return new{typeof(S), typeof(S_flat), typeof(A)}(S, S_flat, A, + S_to_S_flat, S_flat_to_S, + A_to_S_flat + ) + end + function RingFlattening( S::MPolyRing{RingElemType} ) where {RingElemType <: MPolyQuoLocRingElem} @@ -95,6 +157,49 @@ ) end + function RingFlattening( + S::MPolyDecRing{RingElemType} + ) where {RingElemType <: MPolyQuoLocRingElem} + Q = base_ring(S)::MPolyQuoLocRing + R = base_ring(Q)::MPolyRing + L = localized_ring(Q)::MPolyLocRing + A = underlying_quotient(Q)::MPolyQuoRing + U = inverted_set(Q)::AbsMultSet + I = modulus(Q)::MPolyLocalizedIdeal + kk = coefficient_ring(R)::Field + + G = grading_group(S) + w = degree.(gens(S)) + new_w = vcat(w, [zero(G) for i in 1:ngens(R)]) + + # Before building S_flat, we have to create a polynomial + # ring T_flat from which we can pass to the localized quotient. + T_flat, _ = graded_polynomial_ring(kk, vcat(symbols(S), symbols(R)), new_w) + set_default_ordering!(T_flat, + matrix_ordering(T_flat, + block_diagonal_matrix( + [canonical_matrix(default_ordering(S)), + canonical_matrix(default_ordering(R))] + ))) + R_to_T_flat = hom(R, T_flat, gens(T_flat)[ngens(S)+1:end], check=false) + + T_flat_loc, _ = localization(T_flat, R_to_T_flat(U)) # Will throw if multiplicative set can not be transferred. + L_to_T_flat_loc = hom(L, T_flat_loc, gens(T_flat_loc)[ngens(S)+1:end], check=false) + + I_flat = ideal(T_flat_loc, L_to_T_flat_loc.(gens(I))) + S_flat, pr = quo(T_flat_loc, I_flat) + + Q_to_S_flat = hom(Q, S_flat, gens(S_flat)[ngens(S)+1:end], check=false) + + S_to_S_flat = hom(S, S_flat, Q_to_S_flat, gens(S_flat)[1:ngens(S)], check=false) + S_flat_to_S = hom(S_flat, S, vcat(gens(S), S.(gens(Q))), check=false) + + return new{typeof(S), typeof(S_flat), typeof(Q)}(S, S_flat, Q, + S_to_S_flat, S_flat_to_S, + Q_to_S_flat + ) + end + function RingFlattening( S::MPolyRing{RingElemType} ) where {RingElemType <: MPolyLocRingElem} @@ -121,6 +226,44 @@ L_to_S_flat ) end + + function RingFlattening( + S::MPolyDecRing{RingElemType} + ) where {RingElemType <: MPolyLocRingElem} + L = base_ring(S)::MPolyLocRing + R = base_ring(L)::MPolyRing + U = inverted_set(L)::AbsMultSet + kk = coefficient_ring(R)::Field + + G = grading_group(S) + w = degree.(gens(S)) + new_w = vcat(w, [zero(G) for i in 1:ngens(R)]) + + # Before building S_flat, we have to create a polynomial + # ring T_flat from which we can pass to the localized quotient. + T_flat, _ = graded_polynomial_ring(kk, vcat(symbols(S), symbols(R)), new_w) + set_default_ordering!(T_flat, + matrix_ordering(T_flat, + block_diagonal_matrix( + [canonical_matrix(default_ordering(S)), + canonical_matrix(default_ordering(R))] + ))) + R_to_T_flat = hom(R, T_flat, gens(T_flat)[ngens(S)+1:end], check=false) + + S_flat, _ = localization(T_flat, R_to_T_flat(U)) # Will throw if multiplicative set can not be transferred. + L_to_S_flat = hom(L, S_flat, gens(S_flat)[ngens(S)+1:end], check=false) + + R_to_S_flat = hom(R, S_flat, gens(S_flat)[ngens(S)+1:end], check=false) + + S_to_S_flat = hom(S, S_flat, L_to_S_flat, gens(S_flat)[1:ngens(S)], check=false) + S_flat_to_S = hom(S_flat, S, vcat(gens(S), S.(gens(R))), check=false) + + return new{typeof(S), typeof(S_flat), typeof(L)}(S, S_flat, L, + S_to_S_flat, S_flat_to_S, + L_to_S_flat + ) + end + # Flattenings of quotient rings of the form (𝕜[x][u])/J → 𝕜[x, u]/J' function RingFlattening( @@ -244,7 +387,12 @@ end ### Getters function (phi::RingFlattening)(x::RingElem) - return phi.orig_to_flat(x) + if !haskey(flat_counterparts(phi), x) + result = phi.orig_to_flat(x) + flat_counterparts(phi)[x] = result + return result + end + return flat_counterparts(phi)[x]::elem_type(codomain(phi)) end function inverse(phi::RingFlattening) @@ -263,6 +411,30 @@ function map_from_coefficient_ring_to_flattening(phi::RingFlattening) return phi.base_ring_to_flat end +### flat counterparts of algebraic objects defined over the domain +# Given a `RingFlattening` `phi` from `R` to `S` and an algebraic object +# `M` on R, one wishes to be able to use `phi` to deflect questions +# on `M` to questions about its flattening `N` over `S`. +# +# The common syntax should be to call `phi(M)` to get `N` and then +# proceed. Clearly, `N` should be cached. We could cache it in `M`, +# but then it is not clear how two different ring flattenings could +# distinguish which one of the attributes `N` is theirs. Also, `M` +# might not even be an object that supports attribute storage. +# +# To solve this problem, we add a dictionary here in which we can +# store the flat counterparts to any object `M` as above. Any call +# of the form `phi(M)` should then first look up whether a flat +# counterpart for `M` has already been stored, using `M` itself as +# a key. Note that, to prevent memory flooding, this dictionary +# has weak keys. +function flat_counterparts(phi::RingFlattening) + if !isdefined(phi, :flat_counterparts) + phi.flat_counterparts = AbstractAlgebra.WeakKeyIdDict{Any, Any}() + end + return phi.flat_counterparts +end + ### Some basic functionality @attr RingFlattening function flatten(R::MPolyRing) return RingFlattening(R) @@ -273,12 +445,12 @@ end end function (phi::RingFlattening)(I::MPolyIdeal) - if !has_attribute(I, :flat_counterpart) - I_flat = ideal(codomain(phi), elem_type(codomain(phi))[phi(g) for g in gens(I)]) - set_attribute!(I, :flat_counterpart, I_flat) - return I_flat + if haskey(flat_counterparts(phi), I) + return flat_counterparts(phi)[I][1] end - return get_attribute(I, :flat_counterpart) + I_flat = ideal(codomain(phi), elem_type(codomain(phi))[phi(g) for g in gens(I)]) + flat_counterparts(phi)[I] = (I_flat, phi) + return I_flat end function preimage(phi::RingFlattening, x::RingElem) @@ -371,7 +543,7 @@ function kernel( K_flat = kernel(f_flat) phi = flatten(domain(f)) K = ideal(domain(f), inverse(phi).(gens(K_flat))) - set_attribute!(K, :flat_counterpart, K_flat) # TODO: Support attribute storage? + flat_counterparts(phi)[K] = (K_flat, phi) return K end @@ -387,7 +559,7 @@ function kernel( f_flat = hom(codomain(phi), codomain(f), f.(inverse(phi).(gens(codomain(phi)))), check=false) K_flat = kernel(f_flat) K = ideal(domain(f), inverse(phi).(gens(K_flat))) - set_attribute!(K, :flat_counterpart, K_flat) # TODO: Support attribute storage? + flat_counterparts(phi)[K] = (K_flat, phi) return K end @@ -451,3 +623,4 @@ HasGroebnerAlgorithmTrait(::Type{T}) where {T <: MPolyQuoRing{<:MPolyRingElem{<: HasGroebnerAlgorithmTrait(::Type{T}) where {T <: MPolyLocRing{<:Field, <:FieldElem, <:MPolyRing, <:MPolyRingElem, <:MPolyPowersOfElement}} = HasRingFlattening() HasGroebnerAlgorithmTrait(::Type{T}) where {T <: MPolyQuoLocRing{<:Field, <:FieldElem, <:MPolyRing, <:MPolyRingElem, <:MPolyPowersOfElement}} = HasRingFlattening() + diff --git a/src/Rings/mpoly-localizations.jl b/src/Rings/mpoly-localizations.jl index ba1bc2f5c80b..d68041107f28 100644 --- a/src/Rings/mpoly-localizations.jl +++ b/src/Rings/mpoly-localizations.jl @@ -3193,3 +3193,24 @@ end dim(R::MPolyLocRing{<:Field, <:FieldElem, <:MPolyRing, <:MPolyRingElem, <:MPolyComplementOfPrimeIdeal}) = nvars(base_ring(R)) - dim(prime_ideal(inverted_set(R))) +######################################################################## +# Localizations of graded rings # +######################################################################## +function is_graded(L::MPolyLocRing{<:Ring, <:RingElem, <:MPolyDecRing}) + return true +end + +function grading_group(L::MPolyLocRing{<:Ring, <:RingElem, <:MPolyDecRing}) + return grading_group(base_ring(L)) +end + +function degree(a::MPolyLocRingElem{<:Ring, <:RingElem, <:MPolyDecRing}) + return degree(numerator(a)) - degree(denominator(a)) +end + +function is_homogeneous(a::MPolyLocRingElem{<:Ring, <:RingElem, <:MPolyDecRing}) + return is_homogeneous(numerator(a)) && is_homogeneous(denominator(a)) +end + + + diff --git a/src/Rings/mpoly.jl b/src/Rings/mpoly.jl index ecc8c7955589..8fab08934230 100644 --- a/src/Rings/mpoly.jl +++ b/src/Rings/mpoly.jl @@ -1311,3 +1311,6 @@ end hessian(f::MPolyRingElem) = det(hessian_matrix(f)) +function set_default_ordering!(S::MPolyRing, ord::MonomialOrdering) + set_attribute!(S, :default_ordering, ord) +end diff --git a/src/Rings/mpolyquo-localizations.jl b/src/Rings/mpolyquo-localizations.jl index 2426e217a461..2bd1fd4bc0b5 100644 --- a/src/Rings/mpolyquo-localizations.jl +++ b/src/Rings/mpolyquo-localizations.jl @@ -2247,3 +2247,22 @@ end dim(R::MPolyQuoLocRing{<:Field, <:FieldElem, <:MPolyRing, <:MPolyRingElem, <:MPolyComplementOfPrimeIdeal}) = dim(saturated_ideal(modulus(R))) - dim(prime_ideal(inverted_set(R))) +######################################################################## +# Localizations of graded rings # +######################################################################## +function is_graded(L::MPolyQuoLocRing{<:Ring, <:RingElem, <:MPolyDecRing}) + return true +end + +function grading_group(L::MPolyQuoLocRing{<:Ring, <:RingElem, <:MPolyDecRing}) + return grading_group(base_ring(L)) +end + +function degree(a::MPolyQuoLocRingElem{<:Ring, <:RingElem, <:MPolyDecRing}) + return degree(numerator(a)) - degree(denominator(a)) +end + +function is_homogeneous(a::MPolyQuoLocRingElem{<:Ring, <:RingElem, <:MPolyDecRing}) + return is_homogeneous(numerator(a)) && is_homogeneous(denominator(a)) +end + diff --git a/test/Rings/MPolyAnyMap/AffineAlgebras.jl b/test/Rings/MPolyAnyMap/AffineAlgebras.jl index 676ead2cb0db..ad3ed3d8a2d7 100644 --- a/test/Rings/MPolyAnyMap/AffineAlgebras.jl +++ b/test/Rings/MPolyAnyMap/AffineAlgebras.jl @@ -66,3 +66,12 @@ @test f(x) == x end end + +@testset "cross-type kernels" begin + R, (x, y) = QQ[:x, :y] + S, _ = grade(R) + A, _ = quo(R, ideal(R, zero(R))) + Q, _ = quo(S, ideal(S, zero(S))) + phi = hom(Q, A, gens(A)) + @test iszero(kernel(phi)) +end diff --git a/test/Rings/MPolyAnyMap/flattenings.jl b/test/Rings/MPolyAnyMap/flattenings.jl index 24c72d698d16..ecc5e41a2272 100644 --- a/test/Rings/MPolyAnyMap/flattenings.jl +++ b/test/Rings/MPolyAnyMap/flattenings.jl @@ -1,7 +1,6 @@ @testset "kernels via flattenings" begin - R, (x,y,z) = QQ["x", "y", "z"] - - S, _ = polynomial_ring(R, ["s", "t"]) + R, (x,y,z) = polynomial_ring(QQ, ["x", "y", "z"], cached=false) + S, _ = polynomial_ring(R, ["s", "t"], cached=false) phi = Oscar.flatten(S) @test vcat(phi.(gens(S)), Oscar.map_from_coefficient_ring_to_flattening(phi).(gens(coefficient_ring(S)))) == gens(codomain(phi)) @test gens(S) == inverse(phi).(phi.(gens(S))) @@ -66,10 +65,9 @@ end @testset "cross kernel computations" begin - R, (x,y,z) = QQ["x", "y", "z"] - - S, (s, t) = polynomial_ring(R, ["s", "t"]) - + R, (x,y,z) = polynomial_ring(QQ, ["x", "y", "z"], cached=false) + S, (s, t) = polynomial_ring(R, ["s", "t"], cached=false) + f = hom(R, S, [s, s, t]) @test x-y in kernel(f) @@ -82,9 +80,9 @@ end end @testset "flattenings of quotient rings" begin - R, (x,y,z) = QQ["x", "y", "z"] + R, (x,y,z) = polynomial_ring(QQ, ["x", "y", "z"], cached=false) - S, _ = polynomial_ring(R, ["s", "t"]) + S, _ = polynomial_ring(R, ["s", "t"], cached=false) Q, _ = quo(S, ideal(S, S[1])) phi = Oscar.flatten(Q) @test vcat(phi.(gens(Q)), Oscar.map_from_coefficient_ring_to_flattening(phi).(gens(coefficient_ring(Q)))) == gens(codomain(phi)) @@ -117,3 +115,198 @@ end @test Oscar.map_from_coefficient_ring_to_flattening(phi).(gens(R)) == phi.(Q.(S.(gens(R)))) end +@testset "flattenings of graded rings" begin + # towers of polynomial rings + R, (x, y) = polynomial_ring(QQ, [:x, :y], cached=false) + S, (u, v) = grade(polynomial_ring(R, [:u, :v], cached=false)[1]) + + flat = Oscar.flatten(S) + S_flat = codomain(flat) + + @test is_graded(S_flat) + G = grading_group(S_flat) + + @test degree.(gens(S_flat)) == [G[1], G[1], zero(G), zero(G)] + @test default_ordering(S_flat) == degrevlex(gens(S_flat)[1:2])*degrevlex(gens(S_flat)[3:4]) + + I = ideal(S, [u-v]) + I_flat = flat(I) + @test is_graded(I_flat) + @test !(u in I) + @test u-v in I + + # graded rings over quotient rings + A, _ = quo(R, [x-y]) + S, (u, v) = grade(A[:u, :v][1]) + + flat = Oscar.flatten(S) + + S_flat = codomain(flat) + S_poly = base_ring(S_flat) + + @test default_ordering(S_flat) == degrevlex(gens(S_poly)[1:2])*degrevlex(gens(S_poly)[3:4]) + + I = ideal(S, [u*x]) + I_flat = flat(I) + @test !(u in I) + @test u*y in I + + # graded rings over localizations of quotient rings + U = powers_of_element(x^2 + y^2) + W, _ = localization(A, U) + S, (u, v) = graded_polynomial_ring(W, [:u, :v]) + + flat = Oscar.flatten(S) + + S_flat = codomain(flat) + S_poly = base_ring(S_flat) + + @test default_ordering(S_poly) == degrevlex(gens(S_poly)[1:2])*degrevlex(gens(S_poly)[3:4]) + + I = ideal(S, [u*x]) + I_flat = flat(I) + @test u in I + @test !(v in I) + + # graded rings over localizations of polynomial rings + L, _ = localization(R, U) + S, (u, v) = graded_polynomial_ring(L, [:u, :v]) + + flat = Oscar.flatten(S) + + S_flat = codomain(flat) + S_poly = base_ring(S_flat) + + @test default_ordering(S_poly) == degrevlex(gens(S_poly)[1:2])*degrevlex(gens(S_poly)[3:4]) + + I = ideal(S, [u*(x^2 + y^2)]) + I_flat = flat(I) + @test u in I + @test !(v in I) +end + +@testset "flattenings of modules" begin + R, (x, y) = polynomial_ring(QQ, [:x, :y], cached=false) + S, (u, v) = grade(polynomial_ring(R, [:u, :v], cached=false)[1]) + + flat = Oscar.flatten(S) + + S_flat = codomain(flat) + + F = graded_free_module(S, [-2, 1]) + F_flat, iso, iso_inv = Oscar.flatten(F) + + M, _ = sub(F, [F[1]]) + M_flat, iso_M, iso_M_inv = Oscar.flatten(M) + @test is_graded(M_flat) + @test ambient_free_module(M_flat) === F_flat + @test F[1] in M + @test coordinates(u*F[1], M)[1] == u + + @test is_graded(F_flat) + + @test iso_inv(iso(F[1])) == F[1] + @test F_flat === Oscar.flatten(F)[1] + + A, _ = quo(R, [x-y]) + + S, (u, v) = grade(A[:u, :v][1]) + + flat = Oscar.flatten(S) + + S_flat = codomain(flat) + + F = graded_free_module(S, [-2, 1]) + F_flat, iso, iso_inv = Oscar.flatten(F) + + M, _ = sub(F, [F[1]]) + M_flat, iso_M, iso_M_inv = Oscar.flatten(M) + @test is_graded(M_flat) + @test ambient_free_module(M_flat) === F_flat + @test F[1] in M + @test coordinates(u*F[1], M)[1] == u + + @test iso_inv(iso(F[1])) == F[1] + @test F_flat === Oscar.flatten(F)[1] + @test is_graded(F_flat) + + U = powers_of_element(y) + L, _ = localization(R, U) + S, (u, v) = grade(L[:u, :v][1]) + + flat = Oscar.flatten(S) + S_flat = codomain(flat) + U, V, X, Y = gens(S_flat) + + @test degree(U) == degree(u) + @test iszero(degree(X)) + + F = graded_free_module(S, [-2, 1]) + F_flat, iso, iso_inv = Oscar.flatten(F) + + M, _ = sub(F, [F[1]]) + M_flat, iso_M, iso_M_inv = Oscar.flatten(M) + @test is_graded(M_flat) + @test ambient_free_module(M_flat) === F_flat + @test F[1] in M + @test coordinates(u*F[1], M)[1] == u + + @test iso_inv(iso(F[1])) == F[1] + @test F_flat === Oscar.flatten(F)[1] + @test is_graded(F_flat) + + U = powers_of_element(y) + W, _ = localization(A, U) + S, (u, v) = grade(W[:u, :v][1]) + + flat = Oscar.flatten(S) + S_flat = codomain(flat) + U, V, X, Y = gens(S_flat) + + @test degree(U) == degree(u) + @test iszero(degree(X)) + + F = graded_free_module(S, [-2, 1]) + F_flat, iso, iso_inv = Oscar.flatten(F) + + M, _ = sub(F, [F[1]]) + M_flat, iso_M, iso_M_inv = Oscar.flatten(M) + @test is_graded(M_flat) + @test ambient_free_module(M_flat) === F_flat + @test F[1] in M + @test coordinates(u*F[1], M)[1] == u + + @test iso_inv(iso(F[1])) == F[1] + @test F_flat === Oscar.flatten(F)[1] + @test is_graded(F_flat) +end + +@testset "free (graded) resolutions" begin + R, (x, y) = polynomial_ring(QQ, [:x, :y], cached=false) + S, (u, v) = grade(polynomial_ring(R, [:u, :v], cached=false)[1]) + + flat = Oscar.flatten(S) + + S_flat = codomain(flat) + + F = graded_free_module(S, [-2, 1]) + F_flat, iso, iso_inv = Oscar.flatten(F) + + M, _ = quo(F, [u^5*F[1], v*F[1]]) + M_flat, iso, iso_inv = Oscar.flatten(M) + res = free_resolution(M) + @test Oscar._regularity_bound(M) == 2 +end + +@testset "garbage collection" begin + R, (x,y,z) = polynomial_ring(QQ, ["x", "y", "z"], cached=false) + S, _ = polynomial_ring(R, ["s", "t"], cached=false) + phi = Oscar.flatten(S) + a = x^2 + y^2 + b = phi(a) + @test phi(a) === b + a = 5 + GC.gc() + @test isempty(keys(Oscar.flat_counterparts(phi))) +end + From 05f4f461b6435ebdb65777520af37919b8ea1a8d Mon Sep 17 00:00:00 2001 From: Matthias Zach <85350711+HechtiDerLachs@users.noreply.github.com> Date: Wed, 25 Oct 2023 12:46:48 +0200 Subject: [PATCH 19/27] Amend changes suggested from review. (#2084) --- docs/src/DeveloperDocumentation/styleguide.md | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/docs/src/DeveloperDocumentation/styleguide.md b/docs/src/DeveloperDocumentation/styleguide.md index e42526827a68..636b3c68d64e 100644 --- a/docs/src/DeveloperDocumentation/styleguide.md +++ b/docs/src/DeveloperDocumentation/styleguide.md @@ -194,6 +194,63 @@ end However, as always, rules sometimes should be broken. +## Optional arguments for parents of return values + +Several objects in OSCAR have `parent`s, e.g. polynomials, group elements, ... +Whenever a function creates such objects from an input which does not involve +the output's parent, we strongly recommend that +the user should have the possibility to pass on this +parent as a keyword argument under the name `parent`. +Beyond that you can make more entry points for such parents available for +the user's convenience. + +Let's see an example. Say, you want to implement the characteristic +polynomial of a matrix. You could do it as follows: +```julia + function characteristic_polynomial(A::MatrixElem) + kk = base_ring(A) + P, x = kk["x"] + AP = change_base_ring(P, A) + return det(AP - x*one(AP)) + end +``` +You can see that the polynomial ring `P`, i.e. the parent of the output, +is newly created in the body of the function. In particular, calling this +function two times on two different matrices `A` and `B` might produce +incompatible polynomials `p = det(A - x*one(A))` and `q = det(B - x*one(B))` +with different parents. Calling `p + q` will result in an error. + +To solve this, we should have implemented the function differently: +```julia + # Implementation of the recommended keyword argument signature: + function characteristic_polynomial( + A::MatrixElem; + parent::AbstractAlgebra.Ring=polynomial_ring(base_ring(A), :t)[1] + ) + AP = change_base_ring(parent, A) + x = first(gens(ring)) + return det(AP - x*one(AP)) + end + + # Optional second signature to also allow for the specification of the + # output's parent as the first argument: + function characteristic_polynomial( + P::PolyRing, + A::MatrixElem + ) + coefficient_ring(P) === base_ring(A) || error("coefficient rings incompatible") + return characteristic_polynomial(A, parent=P) + end +``` +In fact this now allows for two different entry points for the parent ring `P` +of the output: First as the required `parent` keyword argument and second +as the first argument of a method of `characteristic_polynomial` with +an extended signature. Note that within the scope of the first method's body +the OSCAR function `parent` is necessarily overwritten by the name of the +keyword argument. Hence to call the actual parent of any other object, you +must then use `Oscar.parent`. E.g. to get the `MatrixSpace` of the +matrix `A`, write `Oscar.parent(A)`. + ## Documentation From b6c8dc88b116a60a34f10417692c84baa0b3777f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20G=C3=B6ttgens?= Date: Wed, 25 Oct 2023 16:45:54 +0200 Subject: [PATCH 20/27] Failing tests on master fail job (#2954) --- .github/workflows/CI.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 356b3e4439a8..969da3664933 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -18,7 +18,6 @@ jobs: test: runs-on: ${{ matrix.os }} timeout-minutes: 150 - continue-on-error: ${{ matrix.julia-version == 'nightly' }} strategy: fail-fast: false matrix: @@ -73,7 +72,6 @@ jobs: doctest: runs-on: ${{ matrix.os }} timeout-minutes: 150 - continue-on-error: ${{ matrix.julia-version == 'nightly' }} strategy: fail-fast: false matrix: From acd5903ef3d51768d630a30693a8ceb0648fd3bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20G=C3=B6ttgens?= Date: Thu, 26 Oct 2023 09:50:10 +0200 Subject: [PATCH 21/27] Rename `mul` to `*` (#2913) --- Project.toml | 2 +- src/Groups/GAPGroups.jl | 2 -- src/Modules/Posur.jl | 18 +++++++-------- src/Modules/UngradedModules.jl | 2 +- src/Modules/mpoly-localizations.jl | 2 +- src/Modules/mpolyquo-localizations.jl | 8 +++---- src/Rings/mpoly-localizations.jl | 33 +++++++++++++-------------- src/deprecations.jl | 1 + src/exports.jl | 1 - test/Groups/operations.jl | 1 - test/Modules/module-localizations.jl | 2 +- 11 files changed, 34 insertions(+), 38 deletions(-) diff --git a/Project.toml b/Project.toml index 159468312cdb..e372728da03e 100644 --- a/Project.toml +++ b/Project.toml @@ -31,7 +31,7 @@ AlgebraicSolving = "0.3.6" Distributed = "1.6" DocStringExtensions = "0.8, 0.9" GAP = "0.10.0" -Hecke = "0.22.3" +Hecke = "0.22.4" JSON = "^0.20, ^0.21" LazyArtifacts = "1.6" Nemo = "0.37.1" diff --git a/src/Groups/GAPGroups.jl b/src/Groups/GAPGroups.jl index da291a44dd89..32ada4c6abdb 100644 --- a/src/Groups/GAPGroups.jl +++ b/src/Groups/GAPGroups.jl @@ -349,12 +349,10 @@ Base.:/(x::GAPGroupElem, y::GAPGroupElem) = group_element(parent(x), (x.X / y.X) Base.:\(x::GAPGroupElem, y::GAPGroupElem) = group_element(parent(x), (x.X \ y.X)::GapObj) - # Compatibility with GroupsCore interface one!(x::GAPGroupElem) = one(parent(x)) inv!(out::GAPGroupElem, x::GAPGroupElem) = inv(x) #if needed later -mul(x::GAPGroupElem, y::GAPGroupElem) = x*y mul!(out::GAPGroupElem, x::GAPGroupElem, y::GAPGroupElem) = x*y div_right(x::GAPGroupElem, y::GAPGroupElem) = x / y diff --git a/src/Modules/Posur.jl b/src/Modules/Posur.jl index c78c2961b8e9..d38661f25a9f 100644 --- a/src/Modules/Posur.jl +++ b/src/Modules/Posur.jl @@ -105,7 +105,7 @@ free modules given by ``A``. function syz(A::MatrixElem{<:AbsLocalizedRingElem}) B, D = clear_denominators(A) L = syz(B) - return transpose(mul(transpose(D), transpose(L))) + return transpose(transpose(D) * transpose(L)) end # The annihilator of b as an element of a free module modulo the cokernel of A @@ -188,7 +188,7 @@ function has_solution( # We have B = D⋅A and c = u ⋅ b as matrices. # Now y⋅B = v⋅c ⇔ y⋅D ⋅A = v ⋅ u ⋅ b ⇔ v⁻¹ ⋅ u⁻¹ ⋅ y ⋅ D ⋅ A = b. # Take v⁻¹ ⋅ u⁻¹ ⋅ y ⋅ D to be the solution x of x ⋅ A = b. - return (success, S(one(R), v*u[1,1])*change_base_ring(S, transpose(mul(transpose(D), transpose(y))))) + return (success, S(one(R), v*u[1,1])*change_base_ring(S, transpose(transpose(D) * transpose(y)))) end # This second version solves over the base ring and checks compatibility with @@ -432,7 +432,7 @@ function kernel( fb = hom(Fb, Gb, B) Kb, incb = kernel(fb) Cb = representing_matrix(incb) - C = change_base_ring(S, transpose(mul(transpose(D), transpose(Cb)))) + C = change_base_ring(S, transpose(transpose(D) * transpose(Cb))) #C = change_base_ring(S, Cb*D) K, inc = sub(domain(f), C) return K, inc @@ -475,7 +475,7 @@ function coordinates(u::FreeModElem{T}, M::SubquoModule{T}) where {T<:AbsLocaliz # # generator_matrix(M). # result = S(one(R), d_u)*(yc*Tr) # return sparse_row(result) - return S(one(R), d_u, check=false)*mul(change_base_ring(S, coordinates(u_clear, Mb)), + return S(one(R), d_u, check=false)*(change_base_ring(S, coordinates(u_clear, Mb)) * pre_saturation_data_gens(M)) end @@ -515,12 +515,12 @@ function coordinates(u::FreeModElem{T}, M::SubquoModule{T}) where {T<:AbsLocaliz # need to extend this matrix by one more row given by d_v ⋅ y. set_attribute!(M, :pre_saturation_data_gens, #vcat(Tr, d_v*y) - push!(Tr, sparse_row(mul(change_base_ring(base_ring(y), d_v), y))) + push!(Tr, sparse_row(change_base_ring(base_ring(y), d_v) * y)) ) Tr = pre_saturation_data_rels(M) set_attribute!(M, :pre_saturation_data_rels, #vcat(Tr, d_w*z) - push!(Tr, sparse_row(mul(change_base_ring(base_ring(z), d_w), z))) + push!(Tr, sparse_row(change_base_ring(base_ring(z), d_w) * z)) ) set_attribute!(M, :pre_saturated_module, Mbext) # finally, return the computed coordinates @@ -603,12 +603,12 @@ function represents_element(u::FreeModElem{T}, M::SubquoModule{T}) where {T<:Abs # need to extend this matrix by one more row given by d_v ⋅ y. set_attribute!(M, :pre_saturation_data_gens, #vcat(Tr, d_v*y) - push!(Tr, sparse_row(mul(change_base_ring(base_ring(M), d_v), y))) + push!(Tr, sparse_row(change_base_ring(base_ring(M), d_v) * y)) ) Tr = pre_saturation_data_rels(M) set_attribute!(M, :pre_saturation_data_rels, #vcat(Tr, d_w*z) - push!(Tr, sparse_row(mul(change_base_ring(base_ring(M), d_w), z))) + push!(Tr, sparse_row(change_base_ring(base_ring(M), d_w) * z)) ) set_attribute!(M, :pre_saturated_module, Mbext) @@ -764,7 +764,7 @@ function coordinates( # # generator_matrix(M). # result = S(one(R), d_u)*(yc*Tr) # return sparse_row(result) - return S(one(R), d_u)*mul(change_base_ring(S, coordinates(u_clear, Mb)), + return S(one(R), d_u)*(change_base_ring(S, coordinates(u_clear, Mb)) * pre_saturation_data_gens(M)) end diff --git a/src/Modules/UngradedModules.jl b/src/Modules/UngradedModules.jl index 127f52afe00c..be33ffba7659 100644 --- a/src/Modules/UngradedModules.jl +++ b/src/Modules/UngradedModules.jl @@ -5084,7 +5084,7 @@ function coordinates_via_transform(a::FreeModElem{T}, generators::ModuleGens{T}) Rx = base_ring(generators) coords_wrt_groebner_basis = sparse_row(Rx, s[1], 1:ngens(generators)) - return mul(coords_wrt_groebner_basis,sparse_matrix(A)) + return coords_wrt_groebner_basis * sparse_matrix(A) end @doc raw""" diff --git a/src/Modules/mpoly-localizations.jl b/src/Modules/mpoly-localizations.jl index 3b837fdbe4f6..e6246c189079 100644 --- a/src/Modules/mpoly-localizations.jl +++ b/src/Modules/mpoly-localizations.jl @@ -75,7 +75,7 @@ function has_nonempty_intersection(U::MPolyProductOfMultSets, I::MPolyIdeal; che return false, zero(R), zero_matrix(R, 1, ngens(I)) end T = pre_saturation_data(Iloc) - Bext = transpose(mul(T, transpose(B))) + Bext = transpose(T * transpose(A)) #Bext = A*T u = lcm(vec(denominator.(Bext))) B = map_entries(x->preimage(map_from_base_ring(Iloc), x), u*Bext) diff --git a/src/Modules/mpolyquo-localizations.jl b/src/Modules/mpolyquo-localizations.jl index 85824248f75c..5f4c3bf3fac3 100644 --- a/src/Modules/mpolyquo-localizations.jl +++ b/src/Modules/mpolyquo-localizations.jl @@ -36,7 +36,7 @@ end function syz(A::MatrixElem{<:MPolyQuoLocRingElem}) B, D = clear_denominators(A) L = syz(vcat(B, modulus_matrix(base_ring(A), ncols(B)))) - return map_entries(base_ring(A), transpose(mul(transpose(D), transpose(L[:,1:nrows(D)])))) + return map_entries(base_ring(A), transpose(transpose(D) * transpose(L[:,1:nrows(D)]))) end function ann(b::MatrixType, A::MatrixType) where {T<:MPolyQuoLocRingElem, MatrixType<:MatrixElem{T}} @@ -65,7 +65,7 @@ function has_solution(A::MatrixType, b::MatrixType) where {T<:MPolyQuoLocRingEle # Now [y z]⋅B = v⋅c ⇔ [y z]⋅D ⋅Aext = v ⋅ u ⋅ b ⇔ v⁻¹ ⋅ u⁻¹ ⋅ [y z] ⋅ D ⋅ Aext = b. # Take v⁻¹ ⋅ u⁻¹ ⋅ [y z] ⋅ D to be the solution x of x ⋅ Aext = b. # Then for the first m components x' of x we have x' ⋅ A ≡ b mod I - x = S(one(R), v*u[1,1])*map_entries(S, transpose(mul(transpose(D), transpose(y)))) + x = S(one(R), v*u[1,1])*map_entries(S, transpose(transpose(D) * transpose(y))) #x = S(one(R), v*u[1,1])*map_entries(S, y*D) xpart = zero_matrix(S, 1, nrows(A)) for i in 1:nrows(A) @@ -118,8 +118,8 @@ function kernel( ffb = compose(fb, p) Kb, incb = kernel(ffb) Cb = representing_matrix(incb) - C = change_base_ring(S, transpose(mul(transpose(D), transpose(Cb)))) - C = change_base_ring(S, transpose(mul(transpose(D), transpose(Cb)))) + C = change_base_ring(S, transpose(transpose(D) * transpose(Cb))) + C = change_base_ring(S, transpose(transpose(D) * transpose(Cb))) #C = change_base_ring(S, Cb*D) K, inc = sub(domain(f), C) return K, inc diff --git a/src/Rings/mpoly-localizations.jl b/src/Rings/mpoly-localizations.jl index d68041107f28..145de76f4563 100644 --- a/src/Rings/mpoly-localizations.jl +++ b/src/Rings/mpoly-localizations.jl @@ -1778,13 +1778,13 @@ function coordinates(a::RingElem, I::MPolyLocalizedIdeal; check::Bool=true) # caching has been done during the call of `in`, so the following will work x = coordinates(p, pre_saturated_ideal(I)) # multiplications sparse*dense have to be carried out this way round. - return transpose(mul(pre_saturation_data(I), transpose(L(one(q), q, check=false)*change_base_ring(L, x)))) + return transpose(pre_saturation_data(I) * transpose(L(one(q), q, check=false)*change_base_ring(L, x))) else (success, x, u) = has_solution(generator_matrix(J), matrix(R, 1, 1, [p]), inverted_set(L), check=false) !success && error("check for membership was disabled, but element is not in the ideal") # cache the intermediate result #result = L(one(R), u*denominator(a), check=false)*change_base_ring(L, x)*pre_saturation_data(I) - result = transpose(mul(pre_saturation_data(I), transpose(L(one(R), u*denominator(a), check=false)*change_base_ring(L, x)))) + result = transpose(pre_saturation_data(I) * transpose(L(one(R), u*denominator(a), check=false)*change_base_ring(L, x))) extend_pre_saturated_ideal!(I, p, x, u, check=false) return result end @@ -1800,8 +1800,7 @@ function coordinates( if b in pre_saturated_ideal(I) x = coordinates(b, pre_saturated_ideal(I)) q = denominator(a) - # multiplications sparse*dense have to be carried out this way round. - return transpose(mul(pre_saturation_data(I), transpose(L(one(q), q, check=false)*change_base_ring(L, x)))) + return transpose(pre_saturation_data(I) * transpose(L(one(q), q, check=false)*change_base_ring(L, x))) end @check a in I "the given element is not in the ideal" @@ -1811,7 +1810,7 @@ function coordinates( p = numerator(a) x = coordinates(p, J) q = denominator(a) - return transpose(mul(pre_saturation_data(I), transpose(L(one(q), q, check=false)*change_base_ring(L, x)))) + return transpose(pre_saturation_data(I) * transpose(L(one(q), q, check=false)*change_base_ring(L, x))) end generator_matrix(J::MPolyIdeal) = matrix(base_ring(J), ngens(J), 1, gens(J)) @@ -1911,7 +1910,7 @@ function extend_pre_saturated_ideal!( @check u*f == dot(x, gens(J)) "input is not coherent" J_ext = ideal(R, vcat(gens(J), [f])) T = pre_saturation_data(I) - y = mul(T, transpose(L(one(u), u, check=false)*change_base_ring(L, x))) + y = T * transpose(L(one(u), u, check=false)*change_base_ring(L, x)) T_ext = zero_matrix(SMat, L, 0, ncols(T)+1) for i in 1:length(y) push!(T_ext, T[i] + sparse_row(L, [(ncols(T) + 1, y[i, 1])])) @@ -1943,7 +1942,7 @@ function extend_pre_saturated_ideal!( # change_base_ring(L, x)*T # ) #y = T * transpose(L(one(u), u, check=false)*change_base_ring(L, x)) - y = mul(T, transpose(change_base_ring(L, x))) + y = T * transpose(change_base_ring(L, x)) for i in 1:ncols(y) for j in 1:n y[i, j] = y[i, j]*L(one(u[i]), u[i], check=false) @@ -2124,7 +2123,7 @@ function _replace_pre_saturated_ideal( cols = Vector() for i in 1:length(cache) (g, a, dttk) = cache[i] - push!(cols, mul(pre_saturation_data(I), transpose(L(one(dttk), dttk, check=false)*change_base_ring(L, a)))) + push!(cols, pre_saturation_data(I) * transpose(L(one(dttk), dttk, check=false)*change_base_ring(L, a))) end A = zero_matrix(SMat, L, 0, length(cache)) for i in 1:ngens(I) @@ -2396,7 +2395,7 @@ function coordinates( o = negdegrevlex(gens(R)) x, u = Oscar.lift(p, J, o) T = pre_saturation_data(I) - return transpose(mul(T, transpose(L(one(base_ring(L)), tfihs(u)*denominator(a), check=false)*change_base_ring(L, map_entries(tfihs,x))))) + return transpose(T * transpose(L(one(base_ring(L)), tfihs(u)*denominator(a), check=false)*change_base_ring(L, map_entries(tfihs,x)))) #return L(one(base_ring(L)), tfihs(u)*denominator(a), check=false)*change_base_ring(L, map_entries(tfihs,x))*T end @@ -2434,12 +2433,12 @@ function coordinates( set_attribute!(I, :popped_ideal, popped_ideal) end popped_ideal = get_attribute(I, :popped_ideal) - return transpose(mul(pre_saturation_data(I), transpose(L(one(R), denominator(a), check=false)*map_entries(x->L(x, check=false), coordinates(numerator(a), popped_ideal))))) + return transpose(pre_saturation_data(I) * transpose(L(one(R), denominator(a), check=false)*map_entries(x->L(x, check=false), coordinates(numerator(a), popped_ideal)))) #return L(one(R), denominator(a), check=false)*map_entries(x->L(x, check=false), coordinates(numerator(a), popped_ideal))*pre_saturation_data(I) end if numerator(a) in pre_saturated_ideal(I) - return transpose(mul(T, transpose(L(one(R), denominator(a), check=false)*map_entries(L, coordinates(numerator(a), pre_saturated_ideal(I)))))) + return transpose(T * transpose(L(one(R), denominator(a), check=false)*map_entries(L, coordinates(numerator(a), pre_saturated_ideal(I))))) end i = findfirst(x->(typeof(x)<:MPolyPowersOfElement), U) @@ -2457,8 +2456,8 @@ function coordinates( popped_ideal = get_attribute(I, :popped_ideal) next_ideal = get_attribute(I, :next_ideal) y = coordinates(numerator(a), next_ideal) - x = transpose(mul(map_entries(x->L(x, check=false), pre_saturation_data(popped_ideal)), - transpose(map_entries(x->L(x, check=false), y)))) + x = transpose(map_entries(x->L(x, check=false), pre_saturation_data(popped_ideal)) * + transpose(map_entries(x->L(x, check=false), y))) #x = map_entries(x->L(x, check=false), y)*map_entries(x->L(x, check=false), pre_saturation_data(popped_ideal)) return L(one(R), denominator(a), check=false)*x else @@ -2475,8 +2474,8 @@ function coordinates( popped_ideal = get_attribute(I, :popped_ideal) next_ideal = get_attribute(I, :next_ideal) y = coordinates(numerator(a), next_ideal) - x = transpose(mul(map_entries(x->L(x, check=false), pre_saturation_data(popped_ideal)), - transpose(map_entries(x->L(x, check=false), y)))) + x = transpose(map_entries(x->L(x, check=false), pre_saturation_data(popped_ideal)) * + transpose(map_entries(x->L(x, check=false), y))) #x = map_entries(x->L(x, check=false), y)*map_entries(x->L(x, check=false), pre_saturation_data(popped_ideal)) return L(one(R), denominator(a), check=false)*x end @@ -2564,8 +2563,8 @@ function coordinates( o = ordering(inverted_set(parent(a))) x, u = Oscar.lift(p, J, o) T = pre_saturation_data(I) - return transpose(mul(T, transpose(L(one(base_ring(L)), u*denominator(a), check=false)* - change_base_ring(L, x)))) + return transpose(T * transpose(L(one(base_ring(L)), u*denominator(a), check=false)* + change_base_ring(L, x))) end @doc raw""" diff --git a/src/deprecations.jl b/src/deprecations.jl index 3b490a34ea44..99128487d580 100644 --- a/src/deprecations.jl +++ b/src/deprecations.jl @@ -410,6 +410,7 @@ end @deprecate dual_cone(v::AffineNormalToricVariety) weight_cone(v) @deprecate cohomology_index(tvs::ToricVanishingSet) cohomology_indices(tvs) +@deprecate mul(x::GAPGroupElem, y::GAPGroupElem) x*y # see https://github.com/oscar-system/Oscar.jl/pull/2908 diff --git a/src/exports.jl b/src/exports.jl index 2ec90f620678..044a5567643c 100644 --- a/src/exports.jl +++ b/src/exports.jl @@ -1015,7 +1015,6 @@ export mpoly_dec_ring_type export mpoly_dec_type export mpoly_ring_type export mpoly_type -export mul export mul! export mult_set_type export multi_hilbert_function diff --git a/test/Groups/operations.jl b/test/Groups/operations.jl index 597ec40a756b..cd47b2ad9c52 100644 --- a/test/Groups/operations.jl +++ b/test/Groups/operations.jl @@ -18,7 +18,6 @@ @test x isa PermGroupElem @test ox isa ZZRingElem @test inv(x) in G - @test mul(x,y) == x*y @test mul!(x,x,y) == x*y @test inv(x)==x^-1 @test inv!(x,x) == x^-1 diff --git a/test/Modules/module-localizations.jl b/test/Modules/module-localizations.jl index d3c53439d4e5..a179a2ca4558 100644 --- a/test/Modules/module-localizations.jl +++ b/test/Modules/module-localizations.jl @@ -34,7 +34,7 @@ end Fb = base_ring_module(F) A = S[x//(x+y); y//(x+y)^2] B, D = Oscar.clear_denominators(A) - @test mul(change_base_ring(S, D), A) == B + @test change_base_ring(S, D) * A == B b = matrix(S, 1, 1, [(x+y)*x + 5*y//(x+y)^10]) (success, v) = Oscar.has_solution(A, b) From 3c9a74237cb53ea1421ed43fc3e5659d4082eedc Mon Sep 17 00:00:00 2001 From: Stevell Muller <78619134+StevellM@users.noreply.github.com> Date: Thu, 26 Oct 2023 19:02:45 +0200 Subject: [PATCH 22/27] Minor fixes for `QuadFormWithIsom` (#2957) --- .../QuadFormAndIsom/src/embeddings.jl | 9 +++- .../QuadFormAndIsom/src/serialization.jl | 6 +-- experimental/QuadFormAndIsom/test/runtests.jl | 49 ++++++++++++++++++- 3 files changed, 57 insertions(+), 7 deletions(-) diff --git a/experimental/QuadFormAndIsom/src/embeddings.jl b/experimental/QuadFormAndIsom/src/embeddings.jl index b6f6fbaa8dc8..048b3f141caa 100644 --- a/experimental/QuadFormAndIsom/src/embeddings.jl +++ b/experimental/QuadFormAndIsom/src/embeddings.jl @@ -424,7 +424,7 @@ function _subgroups_orbit_representatives_and_stabilizers_elementary(Vinq::TorQu GVtoMGp = hom(GV, MGp, MGp.(act_GV); check = false) GtoMGp = compose(GtoGV, GVtoMGp) - @hassert :ZZLatWithIsom g-ngens(snf(abelian_group(H0))[1]) < dim(Qp) + g-ngens(snf(abelian_group(H0))[1]) >= dim(Qp) && return res F = base_ring(Qp) # K is H0 but seen a subvector space of Vp (which is V) @@ -738,13 +738,18 @@ function primitive_extensions(M::ZZLat, N::ZZLat; x::Union{IntegerUnion, Nothing if !isnothing(x) !is_divisible_by(numerator(gcd(det(M), det(N))), x) && return results if !isnothing(q) + @req modulus_quadratic_form(q) == 2 "q does not define the discriminant form of an even lattice" @req x^2*order(q) == det(M)*det(N) "Wrong requirements: the square of the index `x` should be equal to (det(M)*det(N)/order(q))" + aM, _, bM = signature_tuple(M) + aN, _, bN = signature_tuple(N) + !is_genus(q, (aM+aN, bM+bN)) && return results + G = genus(q, (aM+aN, bM+bN)) end elseif !isnothing(q) + @req modulus_quadratic_form(q) == 2 "q does not define the discriminant form of an even lattice" aM, _, bM = signature_tuple(M) aN, _, bN = signature_tuple(N) !is_genus(q, (aM+aN, bM+bN)) && return results - @req modulus_quadratic_form(q) == 2 "q does not define the discriminant form of an even lattice" G = genus(q, (aM+aN, bM+bN)) ok, x = divides(numerator(det(M)*det(N)), order(q)) !ok && return results diff --git a/experimental/QuadFormAndIsom/src/serialization.jl b/experimental/QuadFormAndIsom/src/serialization.jl index fd44fffa1c5c..609139869c57 100644 --- a/experimental/QuadFormAndIsom/src/serialization.jl +++ b/experimental/QuadFormAndIsom/src/serialization.jl @@ -1,7 +1,7 @@ ## TODO # it might be beneficial to eventually implement a save_type_params / load_type_params # especially if one wants to serialize vectors of these objects -# also ZZLatWithIsom currently always serialized with ambient space, this may not alwyas be +# also ZZLatWithIsom currently always serialized with ambient space, this may not always be # desired @register_serialization_type QuadSpaceWithIsom @@ -30,6 +30,7 @@ end @register_serialization_type ZZLatWithIsom +# This should be changed by saving only the basis matrix of `L` function save_object(s::SerializerState, L::ZZLatWithIsom) save_data_dict(s) do save_typed_object(s, ambient_space(L), :ambient_space) @@ -40,6 +41,5 @@ end function load_object(s::DeserializerState, ::Type{ZZLatWithIsom}, dict::Dict) quad_space = load_typed_object(s, dict[:ambient_space]) lat = load_typed_object(s, dict[:lattice]) - - return ZZLatWithIsom(quad_space, lat, isometry(quad_space), order_of_isometry(quad_space)) + return lattice(quad_space, basis_matrix(lat); check = false) end diff --git a/experimental/QuadFormAndIsom/test/runtests.jl b/experimental/QuadFormAndIsom/test/runtests.jl index 593e1934ca23..ef3c8d239a91 100644 --- a/experimental/QuadFormAndIsom/test/runtests.jl +++ b/experimental/QuadFormAndIsom/test/runtests.jl @@ -164,8 +164,9 @@ end Lf = integer_lattice_with_isometry(L, f); mktempdir() do path - test_save_load_roundtrip(path, Lf) do loaded - @test Lf == loaded + C = coinvariant_lattice(Lf) + test_save_load_roundtrip(path, C) do loaded + @test C == loaded end end @@ -312,4 +313,48 @@ end reps = @inferred primitive_extensions(lattice(F), lattice(C); q = discriminant_group(L), classification = :emb) @test length(reps) == 1 @test reps[1] == (L, lattice(F), lattice(C)) + + C = integer_lattice(; gram = QQ[-4 -2 -2 0 2 -2 -1 -3 -2 -1 -3 -2 -4 0 -2 -1; + -2 -4 -1 -3 1 -1 1 -3 -1 -5 -3 2 -1 2 -2 -1; + -2 -1 -4 0 2 -2 -1 -3 -2 -2 -3 -3 -4 0 -2 0; + 0 -3 0 -8 0 -2 4 -2 0 -7 -1 4 1 2 1 0; + 2 1 2 0 -4 0 0 2 2 1 1 2 3 0 1 0; + -2 -1 -2 -2 0 -4 0 -4 -1 -2 -2 -2 -2 0 0 -1; + -1 1 -1 4 0 0 -4 0 -1 3 -1 -3 -2 -1 -3 -1; + -3 -3 -3 -2 2 -4 0 -8 -2 -4 -3 -2 -2 1 -1 -3; + -2 -1 -2 0 2 -1 -1 -2 -4 -2 -3 -3 -4 -1 -3 -1; + -1 -5 -2 -7 1 -2 3 -4 -2 -10 -4 3 -1 2 -2 -1; + -3 -3 -3 -1 1 -2 -1 -3 -3 -4 -6 -1 -4 1 -5 -1; + -2 2 -3 4 2 -2 -3 -2 -3 3 -1 -8 -5 -3 -1 -1; + -4 -1 -4 1 3 -2 -2 -2 -4 -1 -4 -5 -8 -2 -4 0; + 0 2 0 2 0 0 -1 1 -1 2 1 -3 -2 -4 0 -1; + -2 -2 -2 1 1 0 -3 -1 -3 -2 -5 -1 -4 0 -8 -2; + -1 -1 0 0 0 -1 -1 -3 -1 -1 -1 -1 0 -1 -2 -4]) + + L = integer_lattice(; gram = QQ[0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0; + 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0; + 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0; + 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0; + 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0; + 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0; + 0 0 0 0 0 0 -2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0; + 0 0 0 0 0 0 1 -2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0; + 0 0 0 0 0 0 0 1 -2 1 0 0 0 1 0 0 0 0 0 0 0 0 0; + 0 0 0 0 0 0 0 0 1 -2 1 0 0 0 0 0 0 0 0 0 0 0 0; + 0 0 0 0 0 0 0 0 0 1 -2 1 0 0 0 0 0 0 0 0 0 0 0; + 0 0 0 0 0 0 0 0 0 0 1 -2 1 0 0 0 0 0 0 0 0 0 0; + 0 0 0 0 0 0 0 0 0 0 0 1 -2 0 0 0 0 0 0 0 0 0 0; + 0 0 0 0 0 0 0 0 1 0 0 0 0 -2 0 0 0 0 0 0 0 0 0; + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -2 1 0 0 0 0 0 0 0; + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 -2 1 0 0 0 0 0 0; + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 -2 1 0 0 0 1 0; + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 -2 1 0 0 0 0; + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 -2 1 0 0 0; + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 -2 1 0 0; + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 -2 0 0; + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 -2 0; + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -4]) + + ok, reps = primitive_embeddings(L, C; check = false) + @test length(reps) == 1 end From 821055d0016621d901a856fc6c83e2cccbbcd584 Mon Sep 17 00:00:00 2001 From: Benjamin Lorenz Date: Fri, 27 Oct 2023 11:26:18 +0200 Subject: [PATCH 23/27] Polyhedral: add hash method for Cone + Polyhedron (#2955) --- docs/src/PolyhedralGeometry/linear_programs.md | 1 + .../mixed_integer_linear_programs.md | 2 ++ src/PolyhedralGeometry/Cone/constructors.jl | 15 ++++++++++----- src/PolyhedralGeometry/Polyhedron/constructors.jl | 10 ++++++++++ src/PolyhedralGeometry/linear_program.jl | 7 +++++++ .../mixed_integer_linear_program.jl | 7 +++++++ test/PolyhedralGeometry/cone.jl | 3 +++ test/PolyhedralGeometry/linear_program.jl | 4 ++++ test/PolyhedralGeometry/polyhedron.jl | 11 +++++------ 9 files changed, 49 insertions(+), 11 deletions(-) diff --git a/docs/src/PolyhedralGeometry/linear_programs.md b/docs/src/PolyhedralGeometry/linear_programs.md index 7ec8e216b901..0c70acec22ca 100644 --- a/docs/src/PolyhedralGeometry/linear_programs.md +++ b/docs/src/PolyhedralGeometry/linear_programs.md @@ -101,6 +101,7 @@ julia> V = optimal_vertex(LP) ```@docs feasible_region(lp::LinearProgram) +ambient_dim(lp::LinearProgram) objective_function(lp::LinearProgram{T}; as::Symbol = :pair) where T<:scalar_types solve_lp(LP::LinearProgram) optimal_value(lp::LinearProgram{T}) where T<:scalar_types diff --git a/docs/src/PolyhedralGeometry/mixed_integer_linear_programs.md b/docs/src/PolyhedralGeometry/mixed_integer_linear_programs.md index d3a100c55cb6..3c9e022f20c8 100644 --- a/docs/src/PolyhedralGeometry/mixed_integer_linear_programs.md +++ b/docs/src/PolyhedralGeometry/mixed_integer_linear_programs.md @@ -28,6 +28,8 @@ mixed_integer_linear_program ## Functions ```@docs +feasible_region(milp::MixedIntegerLinearProgram) +ambient_dim(milp::MixedIntegerLinearProgram) optimal_value(milp::MixedIntegerLinearProgram{T}) where T<:scalar_types optimal_solution solve_milp diff --git a/src/PolyhedralGeometry/Cone/constructors.jl b/src/PolyhedralGeometry/Cone/constructors.jl index 31b0d06d989a..4ca23cb04a0a 100644 --- a/src/PolyhedralGeometry/Cone/constructors.jl +++ b/src/PolyhedralGeometry/Cone/constructors.jl @@ -84,13 +84,18 @@ cone(f::scalar_type_or_field, x...) = positive_hull(f, x...) function ==(C0::Cone{T}, C1::Cone{T}) where T<:scalar_types - # TODO: Remove the following 3 lines, see #758 - for pair in Iterators.product([C0, C1], ["RAYS", "FACETS"]) - Polymake.give(pm_object(pair[1]),pair[2]) - end - return Polymake.polytope.equal_polyhedra(pm_object(C0), pm_object(C1)) + return Polymake.polytope.equal_polyhedra(pm_object(C0), pm_object(C1))::Bool end +# For a proper hash function for cones we should use a "normal form", +# which would require a potentially expensive convex hull computation +# (and even that is not enough). But hash methods should be fast, so we +# just consider the ambient dimension and the precise type of the cone. +function Base.hash(x::T, h::UInt) where {T <: Cone} + h = hash(ambient_dim(x), h) + h = hash(T, h) + return h +end @doc raw""" cone_from_inequalities([::Union{Type{T}, Field} = QQFieldElem,] I::AbstractCollection[LinearHalfspace] [, E::AbstractCollection[LinearHyperplane]]; non_redundant::Bool = false) diff --git a/src/PolyhedralGeometry/Polyhedron/constructors.jl b/src/PolyhedralGeometry/Polyhedron/constructors.jl index d5347eeb6780..9bb2ac4e2a53 100644 --- a/src/PolyhedralGeometry/Polyhedron/constructors.jl +++ b/src/PolyhedralGeometry/Polyhedron/constructors.jl @@ -137,6 +137,16 @@ function ==(P0::Polyhedron{T}, P1::Polyhedron{T}) where T<:scalar_types Polymake.polytope.equal_polyhedra(pm_object(P0), pm_object(P1)) end +# For a proper hash function for cones we should use a "normal form", +# which would require a potentially expensive convex hull computation +# (and even that is not enough). But hash methods should be fast, so we +# just consider the ambient dimension and the precise type of the polyhedron. +function Base.hash(x::T, h::UInt) where {T <: Polyhedron} + h = hash(ambient_dim(x), h) + h = hash(T, h) + return h +end + ### Construct polyhedron from V-data, as the convex hull of points, rays and lineality. @doc raw""" convex_hull([::Union{Type{T}, Field} = QQFieldElem,] V [, R [, L]]; non_redundant::Bool = false) diff --git a/src/PolyhedralGeometry/linear_program.jl b/src/PolyhedralGeometry/linear_program.jl index dc604856fe7b..5a7a9a8c5ec1 100644 --- a/src/PolyhedralGeometry/linear_program.jl +++ b/src/PolyhedralGeometry/linear_program.jl @@ -207,3 +207,10 @@ Return a pair `(m,v)` where the optimal value `m` of the objective `nothing`. """ solve_lp(lp::LinearProgram) = optimal_value(lp), optimal_vertex(lp) + +@doc raw""" + ambient_dim(LP::LinearProgram) + +Return the ambient dimension of the feasible reagion of `LP`. +""" +ambient_dim(lp::LinearProgram) = ambient_dim(feasible_region(lp)) diff --git a/src/PolyhedralGeometry/mixed_integer_linear_program.jl b/src/PolyhedralGeometry/mixed_integer_linear_program.jl index a0176ef04d95..a678e00fefa1 100644 --- a/src/PolyhedralGeometry/mixed_integer_linear_program.jl +++ b/src/PolyhedralGeometry/mixed_integer_linear_program.jl @@ -248,3 +248,10 @@ julia> solve_milp(milp) ``` """ solve_milp(milp::MixedIntegerLinearProgram) = optimal_value(milp), optimal_solution(milp) + +@doc raw""" + ambient_dim(MILP::MixedIntegerLinearProgram) + +Return the ambient dimension of the feasible reagion of `MILP`. +""" +ambient_dim(milp::MixedIntegerLinearProgram) = ambient_dim(feasible_region(milp)) diff --git a/test/PolyhedralGeometry/cone.jl b/test/PolyhedralGeometry/cone.jl index f40d2d69b558..48bc3ce9ce21 100644 --- a/test/PolyhedralGeometry/cone.jl +++ b/test/PolyhedralGeometry/cone.jl @@ -78,6 +78,9 @@ @test is_fulldimensional(Cone2) @test Cone2 == Cone3 @test Cone4 != Cone2 + + @test length(unique([Cone2, Cone3, Cone4])) == 2 + @test dim(Cone4) == 2 @test dim(Cone2) == 3 @test ambient_dim(Cone2) == 3 diff --git a/test/PolyhedralGeometry/linear_program.jl b/test/PolyhedralGeometry/linear_program.jl index a148d8472cf6..0b638d591816 100644 --- a/test/PolyhedralGeometry/linear_program.jl +++ b/test/PolyhedralGeometry/linear_program.jl @@ -24,6 +24,8 @@ @test LP2 isa LinearProgram{T} @test LP3 isa LinearProgram{T} + @test ambient_dim(LP1) == 2 + @test solve_lp(LP1)==(4,[1,1]) @test solve_lp(LP2)==(-1,[-1,-1]) if T == QQFieldElem @@ -43,6 +45,8 @@ @test MILP2 isa MixedIntegerLinearProgram{T} @test MILP3 isa MixedIntegerLinearProgram{T} + @test ambient_dim(MILP3) == 3 + @test solve_milp(MILP1)==(11//2,[1,3//2]) @test solve_milp(MILP2)==(-1,[-1,-1]) @test string(solve_milp(MILP3))==string("(inf, nothing)") diff --git a/test/PolyhedralGeometry/polyhedron.jl b/test/PolyhedralGeometry/polyhedron.jl index 2a684cd9b6b0..d968984f506b 100644 --- a/test/PolyhedralGeometry/polyhedron.jl +++ b/test/PolyhedralGeometry/polyhedron.jl @@ -183,6 +183,7 @@ @test vertex_sizes(Q1)[1] == 2 @test length(vertex_sizes(Q2)) == 0 + @test length(unique([cube(2), cube(2), simplex(2), simplex(2)])) == 2 end @testset "volume" begin @@ -221,12 +222,10 @@ @test upper_bound_h_vector(4,8) == [1, 4, 10, 4 ,1] A = archimedean_solid("cuboctahedron") @test count(F -> nvertices(F) == 3, faces(A, 2)) == 8 - # due to GLIBCXX issues with the outdated julia-shipped libstdc++ - # we run this only where recent CompilerSupportLibraries are available - if VERSION >= v"1.6" - C = catalan_solid("triakis_tetrahedron") - @test count(F -> nvertices(F) == 3, faces(C, 2)) == 12 - end + + C = catalan_solid("triakis_tetrahedron") + @test count(F -> nvertices(F) == 3, faces(C, 2)) == 12 + @test polyhedron(facets(A)) == A b1 = birkhoff_polytope(3) b2 = birkhoff_polytope(3, even = true) From 8a53dde78db5ac10dda07b9facb79938fa193291 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20G=C3=B6ttgens?= Date: Fri, 27 Oct 2023 11:27:50 +0200 Subject: [PATCH 24/27] Add a single ci job per group with depwarn=error (#2956) --- .github/workflows/CI.yml | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 969da3664933..d13f5a4e4809 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -29,7 +29,17 @@ jobs: group: [ 'short', 'long' ] os: - ubuntu-latest + depwarn: [ '' ] include: + # Add a single job per group with deprecation errors on the most recent stable julia version + - julia-version: '1.9' + os: ubuntu-latest + group: 'short' + depwarn: 'depwarn=error' + - julia-version: '1.9' + os: ubuntu-latest + group: 'long' + depwarn: 'depwarn=error' # Add a few macOS jobs (not too many, the number we can run in parallel is limited) - julia-version: 'nightly' os: macOS-latest @@ -58,14 +68,14 @@ jobs: with: annotate: ${{ matrix.julia-version == '1.9' }} coverage: ${{ matrix.julia-version == '1.9' }} - depwarn: error + depwarn: ${{ matrix.depwarn == 'depwarn=error' && 'error' || 'no' }} - name: "Process code coverage" - if: matrix.julia-version == '1.9' + if: matrix.julia-version == '1.9' && matrix.depwarn != 'depwarn=error' uses: julia-actions/julia-processcoverage@v1 with: directories: src,experimental - name: "Upload coverage data to Codecov" - if: matrix.julia-version == '1.9' + if: matrix.julia-version == '1.9' && matrix.depwarn != 'depwarn=error' continue-on-error: true uses: codecov/codecov-action@v3 @@ -81,7 +91,12 @@ jobs: - 'nightly' os: - ubuntu-latest + depwarn: [ '' ] include: + # Add a single job with deprecation errors on the most recent stable julia version + - julia-version: '1.9' + os: ubuntu-latest + depwarn: 'depwarn=error' # Add macOS jobs (not too many, the number we can run in parallel is limited) - julia-version: '1.9' os: macOS-latest @@ -110,7 +125,7 @@ jobs: with: annotate: ${{ matrix.julia-version == '1.9' }} coverage: ${{ matrix.julia-version == '1.9' }} - depwarn: error + depwarn: ${{ matrix.depwarn == 'depwarn=error' && 'error' || 'no' }} - name: "Setup package" run: | julia --project=docs --color=yes -e ' @@ -120,18 +135,18 @@ jobs: - name: "Run doctests" run: | julia ${{ matrix.julia-version == '1.9' && '--code-coverage' || '' }} \ - --project=docs --depwarn=error --color=yes -e' + --project=docs --depwarn=${{ matrix.depwarn == 'depwarn=error' && 'error' || 'no' }} --color=yes -e' using Documenter include("docs/documenter_helpers.jl") using Oscar DocMeta.setdocmeta!(Oscar, :DocTestSetup, Oscar.doctestsetup(); recursive = true) doctest(Oscar)' - name: "Process code coverage" - if: matrix.julia-version == '1.9' + if: matrix.julia-version == '1.9' && matrix.depwarn != 'depwarn=error' uses: julia-actions/julia-processcoverage@v1 with: directories: src,experimental - name: "Upload coverage data to Codecov" - if: matrix.julia-version == '1.9' + if: matrix.julia-version == '1.9' && matrix.depwarn != 'depwarn=error' continue-on-error: true uses: codecov/codecov-action@v3 From c75f03efc47aa576ad6e71d46a4a0f26d7e13e1d Mon Sep 17 00:00:00 2001 From: Max Horn Date: Sat, 21 Oct 2023 20:56:15 +0200 Subject: [PATCH 25/27] Change ideal_of_linear_relations to use a graded ring --- .../ToricVarieties/NormalToricVarieties/attributes.jl | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/AlgebraicGeometry/ToricVarieties/NormalToricVarieties/attributes.jl b/src/AlgebraicGeometry/ToricVarieties/NormalToricVarieties/attributes.jl index d4060a261fe7..133280f7c8a8 100644 --- a/src/AlgebraicGeometry/ToricVarieties/NormalToricVarieties/attributes.jl +++ b/src/AlgebraicGeometry/ToricVarieties/NormalToricVarieties/attributes.jl @@ -412,9 +412,7 @@ julia> ngens(ideal_of_linear_relations(p2)) ``` """ @attr MPolyIdeal function ideal_of_linear_relations(v::NormalToricVarietyType) - R, _ = polynomial_ring(coefficient_ring(v), coordinate_names(v)) - weights = [1 for i in 1:ngens(R)] - grade(R, weights) + R, _ = graded_polynomial_ring(coefficient_ring(v), coordinate_names(v), cached = false) return ideal_of_linear_relations(R, v) end From a0262ff90a1a582858cba8310887ba662fad2970 Mon Sep 17 00:00:00 2001 From: Andrew Patrick Turner Date: Thu, 26 Oct 2023 12:32:20 -0400 Subject: [PATCH 26/27] Minimal fix --- experimental/FTheoryTools/src/auxiliary.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/experimental/FTheoryTools/src/auxiliary.jl b/experimental/FTheoryTools/src/auxiliary.jl index 589db5b97736..b60544121674 100644 --- a/experimental/FTheoryTools/src/auxiliary.jl +++ b/experimental/FTheoryTools/src/auxiliary.jl @@ -278,7 +278,7 @@ end # 8: Blowups ################################################################ -function _blowup_global(id::MPolyIdeal{QQMPolyRingElem}, center::MPolyIdeal{QQMPolyRingElem}, irr::MPolyIdeal{QQMPolyRingElem}, sri::MPolyIdeal{QQMPolyRingElem}, lin::MPolyIdeal{QQMPolyRingElem}; index::Integer = 1) +function _blowup_global(id::MPolyIdeal{QQMPolyRingElem}, center::MPolyIdeal{QQMPolyRingElem}, irr::MPolyIdeal{QQMPolyRingElem}, sri::MPolyIdeal{QQMPolyRingElem}, lin::MPolyIdeal{<:MPolyRingElem}; index::Integer = 1) # @warn "The function _blowup_global is experimental; absence of bugs and proper results are not guaranteed" R = base_ring(id) @@ -319,10 +319,10 @@ function _blowup_global(id::MPolyIdeal{QQMPolyRingElem}, center::MPolyIdeal{QQMP return total_transform, strict_transform, exceptional_ideal, crepant, new_irr, new_sri, new_lin, S, S_gens, ring_map end -_blowup_global(id::T, center::T, irr::T, sri::T, lin::MPolyIdeal{QQMPolyRingElem}; index::Integer = 1) where {T<:MPolyIdeal{<:MPolyRingElem}} = _blowup_global(ideal(map(g -> g.f, gens(id))), ideal(map(g -> g.f, gens(center))), ideal(map(g -> g.f, gens(irr))), ideal(map(g -> g.f, gens(sri))), lin, index = index) +_blowup_global(id::T, center::T, irr::T, sri::T, lin::T; index::Integer = 1) where {T<:MPolyIdeal{<:MPolyRingElem}} = _blowup_global(ideal(map(g -> g.f, gens(id))), ideal(map(g -> g.f, gens(center))), ideal(map(g -> g.f, gens(irr))), ideal(map(g -> g.f, gens(sri))), lin, index = index) -function _blowup_global_sequence(id::MPolyIdeal{QQMPolyRingElem}, centers::Vector{<:Vector{<:Integer}}, irr::MPolyIdeal{QQMPolyRingElem}, sri::MPolyIdeal{QQMPolyRingElem}, lin::MPolyIdeal{QQMPolyRingElem}; index::Integer = 1) +function _blowup_global_sequence(id::MPolyIdeal{QQMPolyRingElem}, centers::Vector{<:Vector{<:Integer}}, irr::MPolyIdeal{QQMPolyRingElem}, sri::MPolyIdeal{QQMPolyRingElem}, lin::MPolyIdeal{<:MPolyRingElem}; index::Integer = 1) # @warn "The function _blowup_global_sequence is experimental; absence of bugs and proper results are not guaranteed" (cur_strict_transform, cur_irr, cur_sri, cur_lin, cur_S, cur_S_gens, cur_index) = (id, irr, sri, lin, base_ring(id), gens(base_ring((id))), index) @@ -347,7 +347,7 @@ function _blowup_global_sequence(id::MPolyIdeal{QQMPolyRingElem}, centers::Vecto return cur_strict_transform, exceptionals, crepant, cur_irr, cur_sri, cur_lin, cur_S, cur_S_gens, ring_map end -_blowup_global_sequence(id::T, centers::Vector{<:Vector{<:Integer}}, irr::T, sri::T, lin::MPolyIdeal{QQMPolyRingElem}; index::Integer = 1) where {T<:MPolyIdeal{<:MPolyRingElem}} = _blowup_global_sequence(ideal(map(g -> g.f, gens(id))), centers, ideal(map(g -> g.f, gens(irr))), ideal(map(g -> g.f, gens(sri))), lin, index = index) +_blowup_global_sequence(id::T, centers::Vector{<:Vector{<:Integer}}, irr::T, sri::T, lin::T; index::Integer = 1) where {T<:MPolyIdeal{<:MPolyRingElem}} = _blowup_global_sequence(ideal(map(g -> g.f, gens(id))), centers, ideal(map(g -> g.f, gens(irr))), ideal(map(g -> g.f, gens(sri))), lin, index = index) ########################################################################### From 103262f9a2932cdc68b23470bbc69a7df41cae3e Mon Sep 17 00:00:00 2001 From: Martin Bies Date: Fri, 20 Oct 2023 14:50:38 +0200 Subject: [PATCH 27/27] [ToricVarieties] Catch more edge cases --- .../NormalToricVarieties/standard_constructions.jl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/AlgebraicGeometry/ToricVarieties/NormalToricVarieties/standard_constructions.jl b/src/AlgebraicGeometry/ToricVarieties/NormalToricVarieties/standard_constructions.jl index e1d398123394..57cb35846ff4 100644 --- a/src/AlgebraicGeometry/ToricVarieties/NormalToricVarieties/standard_constructions.jl +++ b/src/AlgebraicGeometry/ToricVarieties/NormalToricVarieties/standard_constructions.jl @@ -10,6 +10,7 @@ Normal toric variety ``` """ function affine_space(::Type{NormalToricVariety}, d::Int) + @req d >= 0 "Dimension must be non-negative" C = positive_hull(identity_matrix(ZZ, d)) variety = normal_toric_variety(C) return variety @@ -28,6 +29,7 @@ Normal toric variety ``` """ function projective_space(::Type{NormalToricVariety}, d::Int) + @req d >= 0 "Dimension must be non-negative" f = normal_fan(Oscar.simplex(d)) pm_object = Polymake.fulton.NormalToricVariety(Oscar.pm_object(f)) variety = NormalToricVariety(pm_object) @@ -51,6 +53,7 @@ Normal toric variety ``` """ function weighted_projective_space(::Type{NormalToricVariety}, w::Vector{T}) where {T <: IntegerUnion} + @req length(w) > 0 "At least one weight must be specified" if all(a -> isone(a), w) return projective_space(NormalToricVariety, length(w)-1) end