diff --git a/src/TropicalGeometry/TropicalGeometry.jl b/src/TropicalGeometry/TropicalGeometry.jl index 2fae5858027c..3ce5a308bb27 100644 --- a/src/TropicalGeometry/TropicalGeometry.jl +++ b/src/TropicalGeometry/TropicalGeometry.jl @@ -20,6 +20,6 @@ include("variety_binomial.jl") include("variety_principal.jl") include("variety_affine_linear.jl") include("variety_zerodimensional.jl") -include("variety_equidimensional.jl") +include("variety_prime.jl") include("intersection.jl") include("groebner_fan.jl") diff --git a/src/TropicalGeometry/variety.jl b/src/TropicalGeometry/variety.jl index ca7b0a9471bf..f4f78b0837bc 100644 --- a/src/TropicalGeometry/variety.jl +++ b/src/TropicalGeometry/variety.jl @@ -24,10 +24,10 @@ end # ################################################################################ -function Base.show(io::IO, tv::TropicalVariety{typeof(min), true}) +function Base.show(io::IO, ::TropicalVariety{typeof(min), true}) print(io, "Min tropical variety") end -function Base.show(io::IO, tv::TropicalVariety{typeof(max), true}) +function Base.show(io::IO, ::TropicalVariety{typeof(max), true}) print(io, "Max tropical variety") end @@ -40,7 +40,7 @@ end ################################################################################ @doc raw""" - tropical_variety(Sigma::PolyhedralComplex, mult, minOrMax::Union{typeof(min),typeof(max)}=min) + tropical_variety(Sigma::PolyhedralComplex, mult::Vector{ZZRingElem}, minOrMax::Union{typeof(min),typeof(max)}=min) Return the `TropicalVariety` whose polyhedral complex is `Sigma` with multiplicities `mult` and convention `minOrMax`. Here, `mult` is optional can be specified as a `Vector{ZZRingElem}` which represents a list of multiplicities on the maximal polyhedra in the order of `maximal_polyhedra(Sigma)`. If `mult` is unspecified, then all multiplicities are set to one. @@ -133,21 +133,37 @@ If `nu==nothing`, will compute with respect to the trivial valuation and min con If `weighted_polyhedral_complex_only==true`, will not cache any additional information. !!! warning - Assumes that `I` is equi-dimensional. Only special cases supported: - - any valuation: `I` principal, binomial, affine linear - - trivial and p-adic valuation only: `I` general + Experimental feature, only special cases supported: + - any coefficient field and any valuation: `I` principal, binomial, or affine linear + - QQ and trivial / p-adic valuation only: `I` prime # Examples ```jldoctest -julia> R,(x,y) = QQ["x","y"]; +julia> R,(x,y,z) = QQ["x","y","z"]; -julia> I = ideal([(x^2+y)*(x+y^2)*(x+y)]); +julia> nu_2 = tropical_semiring_map(QQ,2) +Map into Min tropical semiring encoding the 2-adic valuation on Rational field -julia> tropical_variety(I) -3-element Vector{TropicalVariety}: - Min tropical variety - Min tropical variety - Min tropical variety +julia> f1 = 8*x^2 + x*y + x*z + x + 8*y^2 + y*z + y + 8*z^2 + z + 8; + +julia> f2 = x + 1; + +julia> I = ideal([f1,f2]); + +julia> TropI_0 = tropical_variety(I) +Min tropical variety + +julia> vertices(TropI_0) +1-element SubObjectIterator{PointVector{QQFieldElem}}: + [0, 0, 0] + +julia> TropI_2 = tropical_variety(I,nu_2) +Min tropical variety + +julia> vertices(TropI_2) +2-element SubObjectIterator{PointVector{QQFieldElem}}: + [0, -3, 3] + [0, 3, -3] ``` """ @@ -171,7 +187,7 @@ function tropical_variety(I::MPolyIdeal, nu::Union{TropicalSemiringMap,Nothing}= end # I general - return tropical_variety_equidimensional(I,nu,weighted_polyhedral_complex_only=weighted_polyhedral_complex_only) + return tropical_variety_prime(I,nu,weighted_polyhedral_complex_only=weighted_polyhedral_complex_only) end @@ -206,13 +222,14 @@ function homogenize_pre_tropicalization(I::MPolyIdeal) end -function dehomogenize_post_tropicalization(Sigma::PolyhedralComplex) - @req lineality_dim(Sigma)>0 "dehomogenizing polyhedral complex without lineality" +function dehomogenize_post_tropicalization(TropV::TropicalVarietySupertype) + + @req lineality_dim(TropV)>0 "dehomogenizing polyhedral complex without lineality" ### # Construct hyperplane {first coord = 0} ### - n = ambient_dim(Sigma) + n = ambient_dim(TropV) zerothUnitRowVector = zeros(Int,1,n) zerothUnitRowVector[1,1] = 1 dehomogenisingHyperplane = polyhedron((zeros(Int,0,n),zeros(Int,0)), (zerothUnitRowVector,[0])) @@ -224,7 +241,7 @@ function dehomogenize_post_tropicalization(Sigma::PolyhedralComplex) dehomogenizedVertices = Vector{QQFieldElem}[] incidenceMatrixRays = Vector{Int}[] dehomogenizedRays = Vector{QQFieldElem}[] - for sigma in maximal_polyhedra(Sigma) + for sigma in maximal_polyhedra(TropV) sigmaDehomogenized = intersect(sigma,dehomogenisingHyperplane) incidenceVectorVertices = Int[] V,_ = minimal_faces(sigmaDehomogenized) @@ -267,12 +284,17 @@ function dehomogenize_post_tropicalization(Sigma::PolyhedralComplex) ### # Dehomogenize lineality space ### - sigma = first(maximal_polyhedra(Sigma)) + sigma = first(maximal_polyhedra(TropV)) sigmaDehomogenized = intersect(sigma,dehomogenisingHyperplane) dehomogenizedLineality = [linealityVector[2:end] for linealityVector in lineality_space(sigmaDehomogenized)] - return polyhedral_complex(incidenceMatrixVerticesAndRays, - dehomogenizedVerticesAndRays, - collect(length(dehomogenizedVertices)+1:length(dehomogenizedVertices)+length(dehomogenizedRays)), - dehomogenizedLineality) + SigmaDehom = polyhedral_complex(incidenceMatrixVerticesAndRays, + dehomogenizedVerticesAndRays, + collect(length(dehomogenizedVertices)+1:length(dehomogenizedVertices)+length(dehomogenizedRays)), + dehomogenizedLineality) + + TropVDehom = tropical_variety(SigmaDehom,multiplicities(TropV),convention(TropV)) + # TropVDehom.__attrs = deepcopy(TropV.__attrs) # TODO: not working, how to copy all attributes? + return TropVDehom + end diff --git a/src/TropicalGeometry/variety_affine_linear.jl b/src/TropicalGeometry/variety_affine_linear.jl index 7a84aacc1a5b..f8b6516cd842 100644 --- a/src/TropicalGeometry/variety_affine_linear.jl +++ b/src/TropicalGeometry/variety_affine_linear.jl @@ -7,32 +7,16 @@ ################################################################################ function tropical_variety_affine_linear(I::MPolyIdeal,nu::TropicalSemiringMap; weighted_polyhedral_complex_only::Bool=false) - ### - # Compute reduced Groebner basis (usually already cached), - # and check whether the linear polynomials have a constant term - ### - R = base_ring(I) + # compute a reduced GB to check whether I is homogeneous G = groebner_basis(I,complete_reduction=true) - if min(total_degree.(Iterators.flatten(collect.(terms.(G))))...)==1 - # input homogneeous, construct TropicalVariety via TropicalLinearSpace - TropV = tropical_variety(tropical_linear_space(I,nu,weighted_polyhedral_complex_only=weighted_polyhedral_complex_only)) - if !weighted_polyhedral_complex_only - set_attribute!(TropV,:algebraic_ideal,I) - set_attribute!(TropV,:tropical_semiring_map,nu) - end - return TropV - else - # input inhomogeneous, homogenise first - Ih = homogenize_pre_tropicalization(I) - TropLh = tropical_linear_space(Ih,nu,weighted_polyhedral_complex_only=true) - Sigma = dehomogenize_post_tropicalization(polyhedral_complex(TropLh)) - multiplicities = ones(ZZRingElem, n_maximal_polyhedra(Sigma)) - TropV = tropical_variety(Sigma,multiplicities) - if !weighted_polyhedral_complex_only - set_attribute!(TropV,:algebraic_ideal,I) - set_attribute!(TropV,:tropical_semiring_map,nu) - end - return TropV + if all(Oscar._is_homogeneous.(G)) + # input homogneeous, construct TropicalVariety via TropicalLinearSpace + return tropical_variety(tropical_linear_space(I,nu,weighted_polyhedral_complex_only=weighted_polyhedral_complex_only)) end + + # input inhomogeneous, homogenise first + Ih = homogenize_pre_tropicalization(I) + TropLh = tropical_linear_space(Ih,nu,weighted_polyhedral_complex_only=true) + return dehomogenize_post_tropicalization(TropLh) end diff --git a/src/TropicalGeometry/variety_equidimensional.jl b/src/TropicalGeometry/variety_prime.jl similarity index 71% rename from src/TropicalGeometry/variety_equidimensional.jl rename to src/TropicalGeometry/variety_prime.jl index 12a1a2842f51..541501e0672d 100644 --- a/src/TropicalGeometry/variety_equidimensional.jl +++ b/src/TropicalGeometry/variety_prime.jl @@ -1,17 +1,26 @@ ################################################################################ # -# Tropicalization of equi-dimensional ideals +# Tropicalization of prime ideals # -# WARNING: assumes without test that `I` is equi-dimensional +# WARNING: assumes without test that `I` is prime # ################################################################################ -function tropical_variety_equidimensional(I::MPolyIdeal, nu::TropicalSemiringMap{QQField,Nothing,<:Union{typeof(min),typeof(max)}}; weighted_polyhedral_complex_only::Bool=false) - return tropical_variety_equidimensional_singular(I,nu; weighted_polyhedral_complex_only=weighted_polyhedral_complex_only) +function tropical_variety_prime(I::MPolyIdeal, nu::TropicalSemiringMap; weighted_polyhedral_complex_only::Bool=false) + # compute a reduced GB to check whether I is homogeneous + G = groebner_basis(I,complete_reduction=true) + + if all(Oscar._is_homogeneous.(G)) + return tropical_variety_prime_singular(I,nu; weighted_polyhedral_complex_only=weighted_polyhedral_complex_only) + end + + Ih = homogenize_pre_tropicalization(I) + TropIh = tropical_variety_prime_singular(Ih,nu,weighted_polyhedral_complex_only=weighted_polyhedral_complex_only) + return dehomogenize_post_tropicalization(TropIh) end -# trivial valuation case -function tropical_variety_equidimensional_singular(I::MPolyIdeal, nu::TropicalSemiringMap{QQField,Nothing,<:Union{typeof(min),typeof(max)}}; weighted_polyhedral_complex_only::Bool=false) +# trivial valuation +function tropical_variety_prime_singular(I::MPolyIdeal, nu::TropicalSemiringMap{QQField,Nothing,<:Union{typeof(min),typeof(max)}}; weighted_polyhedral_complex_only::Bool=false) R = base_ring(I) singularCommand = join(["ring r=0,("*join(string.(symbols(R)),",")*"),dp;", "ideal I = "*join(string.(gens(I)), ",")*";", @@ -29,7 +38,8 @@ function tropical_variety_equidimensional_singular(I::MPolyIdeal, nu::TropicalSe return TropI end -function tropical_variety_equidimensional_singular(I::MPolyIdeal, nu::TropicalSemiringMap{QQField,ZZRingElem,<:Union{typeof(min),typeof(max)}}; weighted_polyhedral_complex_only::Bool=false) +# p-adic valuation +function tropical_variety_prime_singular(I::MPolyIdeal, nu::TropicalSemiringMap{QQField,ZZRingElem,<:Union{typeof(min),typeof(max)}}; weighted_polyhedral_complex_only::Bool=false) R = base_ring(I) singularCommand = join(["ring r=0,("*join(string.(symbols(R)),",")*"),dp;", "ideal I = "*join(string.(gens(I)), ",")*";", @@ -53,6 +63,9 @@ end # if dehomogenizeFan==true, the gfan fan is a homogenized polyhedral complex, and we need to dehomogenize it function gfan_fan_string_to_oscar_complex(input_string::String, negateFan::Bool=false, dehomogenizeFan::Bool=false) + # Extracting AMBIENT_DIM + ambientDim = parse(Int, match(r"AMBIENT_DIM\n(\d+)", input_string).captures[1]) + # Extracting the RAYS, LINEALITY_SPACE and MAXIMAL_CONES sections stringsParsed = Vector{SubString{String}}[] for regexp in [r"RAYS\n([\s\S]*?)\nN_RAYS", r"LINEALITY_SPACE\n([\s\S]*?)\nORTH_LINEALITY_SPACE", r"MAXIMAL_CONES\n([\s\S]*)"] @@ -64,14 +77,29 @@ function gfan_fan_string_to_oscar_complex(input_string::String, negateFan::Bool= # Convert Rays and ORTH_LINEALITY_SPACE to matrices # and negate if necessary - rayGenerators = matrix(QQ,[parse.(Int, split(line)) for line in stringsParsed[1]]) - linealityGenerators = matrix(QQ,[parse.(Int, split(line)) for line in stringsParsed[2]]) + rayGenerators = [parse.(Int, split(line)) for line in stringsParsed[1]] + if isempty(rayGenerators) + rayGenerators = zero_matrix(QQ,0,ambientDim) + else + rayGenerators = matrix(QQ,rayGenerators) + end if negateFan rayGenerators *= -1 end + linealityGenerators = [parse.(Int, split(line)) for line in stringsParsed[2]] + if isempty(linealityGenerators) + linealityGenerators = zero_matrix(QQ,0,ambientDim) + else + linealityGenerators = matrix(QQ,linealityGenerators) + end + # Convert MAXIMAL_CONES to a Vector{Vector{Int}} - coneIncidences = [parse.(Int, split(replace(line, r"[{}]" => ""), r"\s+")) .+ 1 for line in stringsParsed[3]] + if length(stringsParsed[3])==1 && first(stringsParsed[3])=="{}" + coneIncidences = [Int[]] + else + coneIncidences = [parse.(Int, split(replace(line, r"[{}]" => ""), r"\s+")) .+ 1 for line in stringsParsed[3]] + end if dehomogenizeFan # if the singular fan is a homogenized polyhedral complex, diff --git a/test/TropicalGeometry/variety.jl b/test/TropicalGeometry/variety.jl index a7d3a5776d4a..bfe139340aff 100644 --- a/test/TropicalGeometry/variety.jl +++ b/test/TropicalGeometry/variety.jl @@ -19,11 +19,11 @@ R,(x,y,z,w) = QQ["x","y","z","w"] I = ideal(R,[x+2*y,z+4*w]) nu = tropical_semiring_map(QQ,2) - TropV = first(tropical_variety(I,nu)) + TropV = tropical_variety(I,nu) TropL = tropical_linear_space(I,nu) @test issetequal(maximal_polyhedra(TropV),maximal_polyhedra(TropL)) nu = tropical_semiring_map(QQ,2,max) - TropV = first(tropical_variety(I,nu)) + TropV = tropical_variety(I,nu) TropL = tropical_linear_space(I,nu) @test issetequal(maximal_polyhedra(TropV),maximal_polyhedra(TropL)) end @@ -33,12 +33,36 @@ f = x*y*z+2 nu = tropical_semiring_map(QQ,2) TropH = tropical_hypersurface(f,nu) - TropV = first(tropical_variety(ideal(R,f),nu)) + TropV = tropical_variety(ideal(R,f),nu) @test issetequal(maximal_polyhedra(TropH),maximal_polyhedra(TropV)) nu = tropical_semiring_map(QQ,2,max) - TropV = first(tropical_variety(ideal(R,f),nu)) + TropV = tropical_variety(ideal(R,f),nu) TropH = tropical_hypersurface(f,nu) @test issetequal(maximal_polyhedra(TropH),maximal_polyhedra(TropV)) end + # running tropical_variety and all its subroutines + @testset "testing tropical_variety" begin + + # principal ideals + R,(x,y,z) = QQ["x","y","z"] + f = x^2+y^2+z^2+1 + TropV = tropical_variety(ideal(R,f)) + @test f_vector(TropV) == [1,4,6] + + # binomial ideals + f = x^2+1 + g = y^2+1 + TropV = tropical_variety(ideal(R,[f,g])) + @test f_vector(TropV) == [0,1] + + # affine linear ideals + f = x+z+1 + g = y+z+1 + TropV = tropical_variety(ideal(R,[f,g])) + @test f_vector(TropV) == [1,3] + + # general ideals, see doctests + + end end