diff --git a/docs/src/PolyhedralGeometry/linear_programs.md b/docs/src/PolyhedralGeometry/linear_programs.md index 7ec8e216b901..0c70acec22ca 100644 --- a/docs/src/PolyhedralGeometry/linear_programs.md +++ b/docs/src/PolyhedralGeometry/linear_programs.md @@ -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 diff --git a/docs/src/PolyhedralGeometry/mixed_integer_linear_programs.md b/docs/src/PolyhedralGeometry/mixed_integer_linear_programs.md index d3a100c55cb6..3c9e022f20c8 100644 --- a/docs/src/PolyhedralGeometry/mixed_integer_linear_programs.md +++ b/docs/src/PolyhedralGeometry/mixed_integer_linear_programs.md @@ -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 diff --git a/src/PolyhedralGeometry/Cone/constructors.jl b/src/PolyhedralGeometry/Cone/constructors.jl index 31b0d06d989a..4ca23cb04a0a 100644 --- a/src/PolyhedralGeometry/Cone/constructors.jl +++ b/src/PolyhedralGeometry/Cone/constructors.jl @@ -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) diff --git a/src/PolyhedralGeometry/Polyhedron/constructors.jl b/src/PolyhedralGeometry/Polyhedron/constructors.jl index d5347eeb6780..9bb2ac4e2a53 100644 --- a/src/PolyhedralGeometry/Polyhedron/constructors.jl +++ b/src/PolyhedralGeometry/Polyhedron/constructors.jl @@ -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) diff --git a/src/PolyhedralGeometry/linear_program.jl b/src/PolyhedralGeometry/linear_program.jl index dc604856fe7b..5a7a9a8c5ec1 100644 --- a/src/PolyhedralGeometry/linear_program.jl +++ b/src/PolyhedralGeometry/linear_program.jl @@ -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)) diff --git a/src/PolyhedralGeometry/mixed_integer_linear_program.jl b/src/PolyhedralGeometry/mixed_integer_linear_program.jl index a0176ef04d95..a678e00fefa1 100644 --- a/src/PolyhedralGeometry/mixed_integer_linear_program.jl +++ b/src/PolyhedralGeometry/mixed_integer_linear_program.jl @@ -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)) diff --git a/test/PolyhedralGeometry/cone.jl b/test/PolyhedralGeometry/cone.jl index f40d2d69b558..48bc3ce9ce21 100644 --- a/test/PolyhedralGeometry/cone.jl +++ b/test/PolyhedralGeometry/cone.jl @@ -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 diff --git a/test/PolyhedralGeometry/linear_program.jl b/test/PolyhedralGeometry/linear_program.jl index a148d8472cf6..0b638d591816 100644 --- a/test/PolyhedralGeometry/linear_program.jl +++ b/test/PolyhedralGeometry/linear_program.jl @@ -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 @@ -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)") diff --git a/test/PolyhedralGeometry/polyhedron.jl b/test/PolyhedralGeometry/polyhedron.jl index 2a684cd9b6b0..d968984f506b 100644 --- a/test/PolyhedralGeometry/polyhedron.jl +++ b/test/PolyhedralGeometry/polyhedron.jl @@ -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 @@ -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)