diff --git a/src/PolyhedralGeometry/helpers.jl b/src/PolyhedralGeometry/helpers.jl index 061e45191959..1bfc934c9286 100644 --- a/src/PolyhedralGeometry/helpers.jl +++ b/src/PolyhedralGeometry/helpers.jl @@ -75,12 +75,15 @@ Set{Int64} with 1 element: """ column(i::IncidenceMatrix, n::Int) = convert(Set{Int}, Polymake.col(i, n)) +const _polymake_scalars = Union{Polymake.Integer, Polymake.Rational, Polymake.QuadraticExtension, Polymake.OscarNumber, Float64, Polymake.TropicalNumber} +const _polymake_compatible_scalars = Union{QQFieldElem, ZZRingElem, Base.Integer, Base.Rational, _polymake_scalars} + function assure_matrix_polymake(m::Union{AbstractMatrix{Any}, AbstractMatrix{FieldElem}}) a, b = size(m) if a > 0 i = findfirst(_cannot_convert_to_fmpq, m) t = i === nothing ? QQFieldElem : typeof(m[i]) - if t <: Union{Polymake.Rational, Polymake.QuadraticExtension{Polymake.Rational}, Polymake.OscarNumber, Float64} + if t <: _polymake_scalars m = Polymake.Matrix{Polymake.convert_to_pm_type(t)}(m) else m = Polymake.Matrix{_scalar_type_to_polymake(t)}(m) @@ -95,9 +98,9 @@ assure_matrix_polymake(m::AbstractMatrix{<:FieldElem}) = Polymake.Matrix{Polymak assure_matrix_polymake(m::MatElem) = Polymake.Matrix{_scalar_type_to_polymake(eltype(m))}(m) -assure_matrix_polymake(m::Union{Oscar.ZZMatrix, Oscar.QQMatrix, AbstractMatrix{<:Union{QQFieldElem, ZZRingElem, Base.Integer, Base.Rational, Polymake.Rational, Polymake.QuadraticExtension, Polymake.OscarNumber, Float64}}}) = m +assure_matrix_polymake(m::Union{Oscar.ZZMatrix, Oscar.QQMatrix, AbstractMatrix{<:_polymake_compatible_scalars}}) = m -assure_matrix_polymake(m::SubArray{T, 2, U, V, W}) where {T<:Union{Polymake.Rational, Polymake.QuadraticExtension, Float64}, U, V, W} = Polymake.Matrix{T}(m) +assure_matrix_polymake(m::SubArray{T, 2, U, V, W}) where {T<:Union{_polymake_scalars}, U, V, W} = Polymake.Matrix{T}(m) function assure_vector_polymake(v::Union{AbstractVector{Any}, AbstractVector{FieldElem}}) i = findfirst(_cannot_convert_to_fmpq, v) @@ -107,7 +110,7 @@ end assure_vector_polymake(v::AbstractVector{<:FieldElem}) = Polymake.Vector{Polymake.OscarNumber}(v) -assure_vector_polymake(v::AbstractVector{<:Union{QQFieldElem, ZZRingElem, Base.Integer, Base.Rational, Polymake.Rational, Polymake.QuadraticExtension, Polymake.OscarNumber, Float64}}) = v +assure_vector_polymake(v::AbstractVector{<:_polymake_compatible_scalars}) = v affine_matrix_for_polymake(x::Tuple{<:AnyVecOrMat, <:AbstractVector}) = augment(unhomogenized_matrix(x[1]), -Vector(assure_vector_polymake(x[2]))) affine_matrix_for_polymake(x::Tuple{<:AnyVecOrMat, <:Any}) = homogenized_matrix(x[1], -x[2]) @@ -125,7 +128,7 @@ number_of_rows(x::SubArray{T, 2, U, V, W}) where {T, U, V, W} = size(x, 1) _isempty_halfspace(x::Pair{<:Union{Oscar.MatElem, AbstractMatrix}, Any}) = isempty(x[1]) _isempty_halfspace(x) = isempty(x) -function Polymake.Matrix{T}(x::Union{MatElem,AbstractMatrix{<:FieldElem}}) where T<:Union{Float64, Polymake.Rational, Polymake.Integer, Polymake.OscarNumber} +function Polymake.Matrix{T}(x::Union{MatElem,AbstractMatrix{<:FieldElem}}) where T<:_polymake_scalars res = Polymake.Matrix{T}(size(x)...) return res .= x end @@ -188,14 +191,16 @@ end (F::Field)(x::Polymake.Rational) = F(QQ(x)) (F::Field)(x::Polymake.OscarNumber) = F(Polymake.unwrap(x)) +Polymake.convert_to_pm_type(::Type{typeof(min)}) = Polymake.Min +Polymake.convert_to_pm_type(::Type{typeof(max)}) = Polymake.Max + Polymake.convert_to_pm_type(::Type{ZZMatrix}) = Polymake.Matrix{Polymake.Integer} Polymake.convert_to_pm_type(::Type{QQMatrix}) = Polymake.Matrix{Polymake.Rational} Polymake.convert_to_pm_type(::Type{ZZRingElem}) = Polymake.Integer Polymake.convert_to_pm_type(::Type{QQFieldElem}) = Polymake.Rational Polymake.convert_to_pm_type(::Type{T}) where T<:FieldElem = Polymake.OscarNumber -Polymake.convert_to_pm_type(::Type{<:Oscar.MatElem}) = Polymake.Matrix{Polymake.OscarNumber} +Polymake.convert_to_pm_type(::Type{<:MatElem{T}}) where T = Polymake.Matrix{Polymake.convert_to_pm_type(T)} Polymake.convert_to_pm_type(::Type{<:Graph{T}}) where T<:Union{Directed,Undirected} = Polymake.Graph{T} -Polymake.convert_to_pm_type(::Type{<:MatElem{Float64}}) = Polymake.Matrix{Float64} Base.convert(::Type{<:Polymake.Graph{T}}, g::Graph{T}) where T<:Union{Directed,Undirected} = Oscar.pm_object(g) diff --git a/src/Serialization/polymake.jl b/src/Serialization/polymake.jl index 4b876581d5e3..1ba57c2aa897 100644 --- a/src/Serialization/polymake.jl +++ b/src/Serialization/polymake.jl @@ -97,6 +97,10 @@ _pmdata_for_oscar(s::Polymake.Integer, coeff::Field) = ZZ(s) _pmdata_for_oscar(s::Polymake.Rational, coeff::Field) = QQ(s) _pmdata_for_oscar(s::Polymake.OscarNumber, coeff::Field) = coeff(s) +_convert_pm_minormax(::Type{Polymake.Max}) = typeof(max) +_convert_pm_minormax(::Type{Polymake.Min}) = typeof(min) +_pmdata_for_oscar(s::Polymake.TropicalNumber{A}, coeff::Field) where A = tropical_semiring(_convert_pm_minormax(A))(s) + _pmdata_for_oscar(s::Polymake.CxxWrap.StdString, coeff::Field) = String(s) _pmdata_for_oscar(a::Polymake.Array, coeff::Field) = [_pmdata_for_oscar(e, coeff) for e in a] diff --git a/src/TropicalGeometry/hypersurface.jl b/src/TropicalGeometry/hypersurface.jl index d7ca5a50d099..091b9f44002a 100644 --- a/src/TropicalGeometry/hypersurface.jl +++ b/src/TropicalGeometry/hypersurface.jl @@ -51,30 +51,11 @@ function tropical_hypersurface(TropV::TropicalVarietySupertype{minOrMax,true}) w return tropical_hypersurface(polyhedral_complex(TropV),multiplicities(TropV),convention(TropV)) end -# Decompose a tropical polynomial into parts that Polymake can eat. -# First function deals with the coefficients, -# Second function then deals with the entire polynomial. -function homogenize_and_convert_to_pm(t::TropicalSemiringElem{minOrMax}) where {minOrMax<:Union{typeof(max), typeof(min)}} - Add = (minOrMax==typeof(max)) ? Polymake.Max : Polymake.Min - if isinf(t) - return Polymake.TropicalNumber{Add}() - else - return Polymake.TropicalNumber{Add}(Polymake.new_rational_from_fmpq(data(t))) - end -end - +# Decompose and homogenize a tropical polynomial into parts that Polymake can eat. function homogenize_and_convert_to_pm(f::Oscar.MPolyRingElem{TropicalSemiringElem{minOrMax}}) where {minOrMax<:Union{typeof(max), typeof(min)}} - Add = (minOrMax==typeof(max)) ? Polymake.Max : Polymake.Min - coeffs = Polymake.TropicalNumber{Add}[] td = total_degree(f) - exps = Vector{Int}[] - for (c,alpha) in zip(coefficients(f),exponents(f)) - push!(coeffs, homogenize_and_convert_to_pm(c)) - prepend!(alpha, td-sum(alpha)) - push!(exps, alpha) - end - exps = matrix(ZZ, exps) - coeffs = Polymake.Vector{Polymake.TropicalNumber{Add, Polymake.Rational}}(coeffs) + exps = matrix(ZZ, collect([td-sum(alpha); alpha] for alpha in exponents(f))) + coeffs = collect(coefficients(f)) return coeffs, exps end @@ -175,9 +156,8 @@ julia> # tropical_hypersurface(Delta) # issue 2628 function tropical_hypersurface(Delta::SubdivisionOfPoints, minOrMax::Union{typeof(min),typeof(max)}=min; weighted_polyhedral_complex_only::Bool=false) - PMinOrMax = (minOrMax==typeof(min)) ? Polymake.Min : Polymake.Max - coeffs = Polymake.TropicalNumber{PMinOrMax}.(Polymake.new_integer_from_fmpz.(min_weights(Delta))) - exps = ZZ.(matrix(QQ,points(Delta))) + coeffs = min_weights(Delta) + exps = points(Delta) pmhypproj = Polymake.tropical.Hypersurface{minOrMax}(MONOMIALS=exps, COEFFICIENTS=coeffs) pmhyp = Polymake.tropical.affine_chart(pmhypproj) diff --git a/src/TropicalGeometry/semiring.jl b/src/TropicalGeometry/semiring.jl index 277a0aa3e99f..bda0454c1db5 100644 --- a/src/TropicalGeometry/semiring.jl +++ b/src/TropicalGeometry/semiring.jl @@ -408,3 +408,22 @@ end Oscar.mul!(x::TropicalSemiringElem, y::TropicalSemiringElem, z::TropicalSemiringElem) = y * z Oscar.addeq!(y::TropicalSemiringElem, z::TropicalSemiringElem) = y + z + + +################################################################################ +# +# helpers for polymake conversion +# +################################################################################ + +Polymake.convert_to_pm_type(::Type{<:TropicalSemiringElem{A}}) where A = Polymake.TropicalNumber{Polymake.convert_to_pm_type(A),Polymake.Rational} + +function Base.convert(::Type{<:Polymake.TropicalNumber{PA}}, t::TropicalSemiringElem{A}) where {A <: Union{typeof(min),typeof(max)}, PA <: Union{Polymake.Min, Polymake.Max}} + @req PA == Polymake.convert_to_pm_type(A) "cannot convert between different tropical conventions" + isinf(t) ? Polymake.TropicalNumber{PA}() : Polymake.TropicalNumber{PA}(convert(Polymake.Rational, data(t))) +end + +function (T::TropicalSemiring{A})(t::Polymake.TropicalNumber{PA}) where {A <: Union{typeof(min),typeof(max)}, PA <: Union{Polymake.Min, Polymake.Max}} + @req PA == Polymake.convert_to_pm_type(A) "cannot convert between different tropical conventions" + t == Polymake.zero(t) ? zero(T) : T(Polymake.scalar(t)) +end