Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TropicalGeometry: add and improve polymake conversions #3426

Merged
merged 3 commits into from
Feb 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 12 additions & 7 deletions src/PolyhedralGeometry/helpers.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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)
Expand All @@ -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])
Expand All @@ -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
Expand Down Expand Up @@ -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)

Expand Down
4 changes: 4 additions & 0 deletions src/Serialization/polymake.jl
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,10 @@
_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)

Check warning on line 102 in src/Serialization/polymake.jl

View check run for this annotation

Codecov / codecov/patch

src/Serialization/polymake.jl#L100-L102

Added lines #L100 - L102 were not covered by tests

_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]
Expand Down
30 changes: 5 additions & 25 deletions src/TropicalGeometry/hypersurface.jl
Original file line number Diff line number Diff line change
Expand Up @@ -51,30 +51,11 @@
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

Expand Down Expand Up @@ -175,9 +156,8 @@
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)

Check warning on line 160 in src/TropicalGeometry/hypersurface.jl

View check run for this annotation

Codecov / codecov/patch

src/TropicalGeometry/hypersurface.jl#L159-L160

Added lines #L159 - L160 were not covered by tests
pmhypproj = Polymake.tropical.Hypersurface{minOrMax}(MONOMIALS=exps, COEFFICIENTS=coeffs)
pmhyp = Polymake.tropical.affine_chart(pmhypproj)

Expand Down
19 changes: 19 additions & 0 deletions src/TropicalGeometry/semiring.jl
Original file line number Diff line number Diff line change
Expand Up @@ -408,3 +408,22 @@

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))

Check warning on line 428 in src/TropicalGeometry/semiring.jl

View check run for this annotation

Codecov / codecov/patch

src/TropicalGeometry/semiring.jl#L426-L428

Added lines #L426 - L428 were not covered by tests
end
Loading