Skip to content

Commit

Permalink
Polyhedral: add hash method for Cone + Polyhedron (#2955)
Browse files Browse the repository at this point in the history
  • Loading branch information
benlorenz authored Oct 27, 2023
1 parent 3c9a742 commit 821055d
Show file tree
Hide file tree
Showing 9 changed files with 49 additions and 11 deletions.
1 change: 1 addition & 0 deletions docs/src/PolyhedralGeometry/linear_programs.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions docs/src/PolyhedralGeometry/mixed_integer_linear_programs.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
15 changes: 10 additions & 5 deletions src/PolyhedralGeometry/Cone/constructors.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
10 changes: 10 additions & 0 deletions src/PolyhedralGeometry/Polyhedron/constructors.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
7 changes: 7 additions & 0 deletions src/PolyhedralGeometry/linear_program.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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))
7 changes: 7 additions & 0 deletions src/PolyhedralGeometry/mixed_integer_linear_program.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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))
3 changes: 3 additions & 0 deletions test/PolyhedralGeometry/cone.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 4 additions & 0 deletions test/PolyhedralGeometry/linear_program.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)")
Expand Down
11 changes: 5 additions & 6 deletions test/PolyhedralGeometry/polyhedron.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down

0 comments on commit 821055d

Please sign in to comment.