Skip to content

Commit

Permalink
updates related to polymake 4.12 (#3819)
Browse files Browse the repository at this point in the history
* Polymake: support graphmaps and decorations in serialization

* Combinatorics: small fix for graph iterators

* Combinatorics: graph iterator test

* floor+ceil

* require new polymake.jl

* Polyhedron: allow lattice_points for non-rational polytopes

* Test: serialization of face lattice in oscarnumber polytopes

* fix qqbar-polyhedron test

* more conversions, require upcoming polymake.jl
  • Loading branch information
benlorenz authored Jul 22, 2024
1 parent 46e414e commit e548b0d
Show file tree
Hide file tree
Showing 9 changed files with 68 additions and 18 deletions.
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ LazyArtifacts = "1.6"
Markdown = "1.6"
Nemo = "0.45.5"
Pkg = "1.6"
Polymake = "0.11.14"
Polymake = "0.11.19"
Random = "1.6"
RandomExtensions = "0.4.3"
Serialization = "1.6"
Expand Down
5 changes: 3 additions & 2 deletions src/Combinatorics/Graphs/functions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -342,22 +342,23 @@ function reverse(e::Edge)
end


struct EdgeIterator
mutable struct EdgeIterator
pm_itr::Polymake.GraphEdgeIterator{T} where {T <: Union{Directed, Undirected}}
l::Int64
end
Base.length(eitr::EdgeIterator) = eitr.l
Base.eltype(::Type{EdgeIterator}) = Edge

function Base.iterate(eitr::EdgeIterator, index = 1)
if index > eitr.l
if eitr.l == 0 || Polymake.isdone(eitr.pm_itr)
return nothing
else
e = Polymake.get_element(eitr.pm_itr)
s = Polymake.first(e)
t = Polymake.last(e)
edge = Edge(s+1, t+1)
Polymake.increment(eitr.pm_itr)
eitr.l -= 1
return (edge, index+1)
end
end
Expand Down
18 changes: 9 additions & 9 deletions src/PolyhedralGeometry/Polyhedron/properties.jl
Original file line number Diff line number Diff line change
Expand Up @@ -731,7 +731,7 @@ julia> dim(P)
dim(P::Polyhedron) = Polymake.polytope.dim(pm_object(P))::Int

@doc raw"""
lattice_points(P::Polyhedron{QQFieldElem})
lattice_points(P::Polyhedron)
Return the integer points contained in the bounded polyhedron `P`.
Expand All @@ -757,15 +757,15 @@ julia> matrix(ZZ, lattice_points(S))
[2 0]
```
"""
function lattice_points(P::Polyhedron{QQFieldElem})
function lattice_points(P::Polyhedron)
@req pm_object(P).BOUNDED "Polyhedron not bounded"
return SubObjectIterator{PointVector{ZZRingElem}}(
P, _lattice_point, size(pm_object(P).LATTICE_POINTS_GENERATORS[1], 1)
)
end

_lattice_point(
T::Type{PointVector{ZZRingElem}}, P::Polyhedron{QQFieldElem}, i::Base.Integer
T::Type{PointVector{ZZRingElem}}, P::Polyhedron, i::Base.Integer
) = point_vector(ZZ, @view pm_object(P).LATTICE_POINTS_GENERATORS[1][i, 2:end])::T

_point_matrix(::Val{_lattice_point}, P::Polyhedron; homogenized=false) =
Expand All @@ -774,7 +774,7 @@ _point_matrix(::Val{_lattice_point}, P::Polyhedron; homogenized=false) =
_matrix_for_polymake(::Val{_lattice_point}) = _point_matrix

@doc raw"""
interior_lattice_points(P::Polyhedron{QQFieldElem})
interior_lattice_points(P::Polyhedron)
Return the integer points contained in the interior of the bounded polyhedron
`P`.
Expand All @@ -792,15 +792,15 @@ julia> matrix(ZZ, interior_lattice_points(c))
[0 0 0]
```
"""
function interior_lattice_points(P::Polyhedron{QQFieldElem})
function interior_lattice_points(P::Polyhedron)
@req pm_object(P).BOUNDED "Polyhedron not bounded"
return SubObjectIterator{PointVector{ZZRingElem}}(
P, _interior_lattice_point, size(pm_object(P).INTERIOR_LATTICE_POINTS, 1)
)
end

_interior_lattice_point(
T::Type{PointVector{ZZRingElem}}, P::Polyhedron{QQFieldElem}, i::Base.Integer
T::Type{PointVector{ZZRingElem}}, P::Polyhedron, i::Base.Integer
) = point_vector(ZZ, @view pm_object(P).INTERIOR_LATTICE_POINTS[i, 2:end])::T

_point_matrix(::Val{_interior_lattice_point}, P::Polyhedron; homogenized=false) =
Expand All @@ -813,7 +813,7 @@ _point_matrix(::Val{_interior_lattice_point}, P::Polyhedron; homogenized=false)
_matrix_for_polymake(::Val{_interior_lattice_point}) = _point_matrix

@doc raw"""
boundary_lattice_points(P::Polyhedron{QQFieldElem})
boundary_lattice_points(P::Polyhedron)
Return the integer points contained in the boundary of the bounded polyhedron
`P`.
Expand Down Expand Up @@ -841,15 +841,15 @@ julia> matrix(ZZ, boundary_lattice_points(c))
[ 1 0 0]
```
"""
function boundary_lattice_points(P::Polyhedron{QQFieldElem})
function boundary_lattice_points(P::Polyhedron)
@req pm_object(P).BOUNDED "Polyhedron not bounded"
return SubObjectIterator{PointVector{ZZRingElem}}(
P, _boundary_lattice_point, size(pm_object(P).BOUNDARY_LATTICE_POINTS, 1)
)
end

_boundary_lattice_point(
T::Type{PointVector{ZZRingElem}}, P::Polyhedron{QQFieldElem}, i::Base.Integer
T::Type{PointVector{ZZRingElem}}, P::Polyhedron, i::Base.Integer
) = point_vector(ZZ, @view pm_object(P).BOUNDARY_LATTICE_POINTS[i, 2:end])::T

_point_matrix(::Val{_boundary_lattice_point}, P::Polyhedron; homogenized=false) =
Expand Down
8 changes: 8 additions & 0 deletions src/PolyhedralGeometry/helpers.jl
Original file line number Diff line number Diff line change
Expand Up @@ -676,6 +676,14 @@ end

# oscarnumber helpers

function Polymake._fieldelem_to_floor(e::Union{EmbeddedNumFieldElem,QQBarFieldElem})
return BigInt(floor(ZZRingElem, e))
end

function Polymake._fieldelem_to_ceil(e::Union{EmbeddedNumFieldElem,QQBarFieldElem})
return BigInt(ceil(ZZRingElem, e))
end

function Polymake._fieldelem_to_rational(e::EmbeddedNumFieldElem)
return Rational{BigInt}(QQ(e))
end
Expand Down
21 changes: 20 additions & 1 deletion src/Serialization/polymake.jl
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,9 @@ _pmdata_for_oscar(v::Polymake.Vector{<:Polymake.Rational}, coeff::Field) = colle

_pmdata_for_oscar(v::Polymake.SparseVector, coeff::Field) = _pmdata_for_oscar(Polymake.common.dense(v), coeff)

_pmdata_for_oscar(nm::Polymake.NodeMap, coeff::Field) = _pmdata_for_oscar(Polymake.Array(nm), coeff)
_pmdata_for_oscar(bd::Polymake.BasicDecoration, coeff::Field) = (_pmdata_for_oscar(Polymake.decoration_face(bd), coeff), _pmdata_for_oscar(Polymake.decoration_rank(bd), coeff))

_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)
Expand All @@ -106,6 +109,8 @@ _pmdata_for_oscar(s::Polymake.TropicalNumber{A}, coeff::Field) where A = tropica
_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]
_pmdata_for_oscar(a::Polymake.Array{T}, coeff::Field) where T <: Union{Polymake.Matrix, Polymake.Vector} = Tuple(_pmdata_for_oscar.(a, Ref(coeff)))

_pmdata_for_oscar(s::Polymake.Set, coeff::Field) = Set(_pmdata_for_oscar(e, coeff) for e in s)


Expand Down Expand Up @@ -145,16 +150,30 @@ function _polyhedral_object_as_dict(x::Oscar.PolyhedralObjectUnion)
end

function _load_bigobject_from_dict!(obj::Polymake.BigObject, dict::Dict, parent_key::String="")
delay_loading = Tuple{String,Any}[]
for (k, v) in dict
key_str = parent_key == "" ? k : parent_key * "." * k
first(k) == '_' && continue

if v isa Dict
_load_bigobject_from_dict!(obj, v, key_str)
else
Polymake.take(obj, key_str, convert(Polymake.PolymakeType, v))
pmv = convert(Polymake.PolymakeType, v)
bot = Polymake.bigobject_type(obj)
# NodeMaps need extra treatment since the constructor doesn't accept polymake c++ arrays
# and we can't create a nodemap from scratch without the graph
# so we convert it to a pure perl array and delay loading until the end of this level
if pmv isa Polymake.Array && Polymake.bigobject_prop_type(bot, key_str) in ["NodeMap", "EdgeMap"]
pmv = Polymake.as_perl_array_of_array(pmv)
push!(delay_loading, (key_str, pmv))
else
Polymake.take(obj, key_str, pmv)
end
end
end
for (k, v) in delay_loading
Polymake.take(obj, k, v)
end
if haskey(dict, "_description")
Polymake.setdescription!(obj, dict["_description"])
end
Expand Down
10 changes: 10 additions & 0 deletions test/Combinatorics/Graph.jl
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,16 @@
@test n_vertices(G2) == 13
@test n_edges(G2) == 5

ei = edges(G2)
@test length(ei) == 5

ee = collect(ei)
@test length(ei) == 0
@test collect(ei) == Edge[]

GG2 = graph_from_edges(Undirected, ee, 13)
@test is_isomorphic(G2, GG2)

end

@testset "adjacency_matrix laplacian_matrix" begin
Expand Down
2 changes: 1 addition & 1 deletion test/PolyhedralGeometry/polyhedron.jl
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@
@test !([-1, -1] in Q0)
@test n_vertices(Q0) == 3
@test n_vertices.(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])
Expand All @@ -63,6 +62,7 @@
@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]]
if T == QQFieldElem
@test is_smooth(Q0)
@test is_normal(Q0)
@test is_lattice_polytope(Q0)
Expand Down
5 changes: 5 additions & 0 deletions test/PolyhedralGeometry/scalar_types.jl
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@
@test _edge_length_for_test.(faces(sd, 1)) == repeat([4], 18)
# scaling the Polyhedron by 3 yields edge lengths of 6
@test _edge_length_for_test.(faces(3 * sd, 1)) == repeat([36], 18)
# there are 11 lattice points
@test length(lattice_points(sd)) == 11

let pc = polyhedral_complex(
E, IncidenceMatrix(facets(sd)), vertices(sd); non_redundant=true
)
Expand All @@ -62,6 +65,8 @@
@test number_of_vertices(qp) == 3
@test number_of_facets(qp) == 3

@test length(lattice_points(qp)) == 1

@testset "Scalar detection" begin
let j = johnson_solid(12)
@test j isa Polyhedron{QQFieldElem}
Expand Down
15 changes: 11 additions & 4 deletions test/Serialization/PolyhedralGeometry.jl
Original file line number Diff line number Diff line change
Expand Up @@ -49,23 +49,30 @@ using Oscar: _integer_variables

@testset "Polyhedron" begin
square = cube(2)
f_vector(square)
test_save_load_roundtrip(path, square) do loaded
@test n_vertices(square) == n_vertices(loaded)
@test dim(square) == dim(loaded)
@test square == loaded
@test Polymake.exists(Oscar.pm_object(loaded), "HASSE_DIAGRAM.DECORATION")
end

n2 = (QQBarField()(5))^(QQ(4//5))
c = cube(QQBarField(), 3, -1, n2)
test_save_load_roundtrip(path, square) do loaded
@test n_vertices(square) == n_vertices(loaded)
@test dim(square) == dim(loaded)
@test square == loaded
f_vector(c)
lattice_points(c)
test_save_load_roundtrip(path, c) do loaded
@test n_vertices(c) == n_vertices(loaded)
@test dim(c) == dim(loaded)
@test c == loaded
@test Polymake.exists(Oscar.pm_object(loaded), "HASSE_DIAGRAM.DECORATION")
end

d_hedron = dodecahedron()
facets(d_hedron)
vertices(d_hedron)
f_vector(d_hedron)
lattice_points(d_hedron)

dict_ps = Dict{String, Any}(
"unprecise" => polyhedron(
Expand Down

0 comments on commit e548b0d

Please sign in to comment.