From f7cd13ada3127f1829b5bb188b73f2dc16ca42a3 Mon Sep 17 00:00:00 2001 From: Zoe Geiselmann Date: Wed, 13 Sep 2023 16:22:59 +0200 Subject: [PATCH 01/14] facet_sizes, vertex_sizes, vertex_figure --- src/PolyhedralGeometry/Cone/properties.jl | 3 + .../Polyhedron/properties.jl | 62 +++++++++++++++++++ .../Polyhedron/standard_constructions.jl | 53 ++++++++++++++++ src/exports.jl | 4 ++ 4 files changed, 122 insertions(+) diff --git a/src/PolyhedralGeometry/Cone/properties.jl b/src/PolyhedralGeometry/Cone/properties.jl index e599aafaf91c..4dd00b1c4134 100644 --- a/src/PolyhedralGeometry/Cone/properties.jl +++ b/src/PolyhedralGeometry/Cone/properties.jl @@ -329,6 +329,9 @@ julia> lineality_dim(C1) """ lineality_dim(C::Cone) = pm_object(C).LINEALITY_DIM::Int +function facet_degrees(C::Cone) + return Vector{Int}(pm_object(C).FACET_DEGREES) +end ############################################################################### diff --git a/src/PolyhedralGeometry/Polyhedron/properties.jl b/src/PolyhedralGeometry/Polyhedron/properties.jl index 2994d5bd101f..881fa56231a5 100644 --- a/src/PolyhedralGeometry/Polyhedron/properties.jl +++ b/src/PolyhedralGeometry/Polyhedron/properties.jl @@ -731,6 +731,68 @@ julia> codim(P) """ codim(P::Polyhedron) = ambient_dim(P)-dim(P) +@doc raw""" + facet_sizes(P::Polyhedron{T}) + +Number of vertices in each facet. + +#Example +```jldoctest +julia> p = johnson_solid(3) +Polyhedron in ambient dimension 3 with EmbeddedElem{nf_elem} type coefficients + +julia> facet_sizes(p) +8-element Vector{Int64}: + 3 + 4 + 3 + 3 + 4 + 6 + 3 + 4 +``` +""" +function facet_sizes(P::Polyhedron{T}) where T<:scalar_types + is_bounded(P) && return Vector{Int}(pm_object(P).FACET_SIZES) #shortcut, rest of the code works as well + im = IncidenceMatrix(pm_object(P).VERTICES_IN_FACETS) #incidence matrix with pm info with oscar indices + nrows = size(im)[1] + #get the vertices that are really vertices + ff = convert(Set{Int}, Polymake.to_one_based_indexing(P.pm_polytope.FAR_FACE)) #indices of vertices that are really rays (or higher dimensional faces) + #get the facets that are really facets + i = _facet_at_infinity(pm_object(P)) + rows = Vector{Int}(1:nrows) + i <= nrows && deleteat!(rows,i) #the face at infinity is not always a facet, so does not always need to be removed + #sum the vertices in facets that are really vertices in facets + return [length(Base.setdiff(row(im,i), ff)) for i in 1:length(rows)] +end + +@doc raw""" + vertex_sizes(P::Polyhedron{T}) + +Number of incident facets for each vertex + +#Example +```jldoctest +julia> vertex_sizes(bipyramid(simplex(2))) +5-element Vector{Int64}: + 4 + 4 + 4 + 3 + 3 +``` +""" +function vertex_sizes(P::Polyhedron{T}) where T<:scalar_types + res = Vector{Int}(pm_object(P).VERTEX_SIZES) + fai = [i+1 for i in Vector{Int}(pm_object(P).FAR_FACE)] #indices of vertices that are really rays (or higher dimensional faces) +# ff = convert(Set{Int}, Polymake.to_one_based_indexing(P.pm_polytope.FAR_FACE)) +# vf = Base.setdiff(Set(1:pm_object(P).N_VERTICES),ff) +# I don't think the set version is beneficiary here, bc the nvertices come as a vector and we want a vector back, so i still use symdiff + vertices = symdiff(Vector{Int}(1:pm_object(P).N_VERTICES),fai) + return keepat!(res,vertices) +end + ############################################################################### ## Points properties ############################################################################### diff --git a/src/PolyhedralGeometry/Polyhedron/standard_constructions.jl b/src/PolyhedralGeometry/Polyhedron/standard_constructions.jl index 51261481df81..a2abbf5aa47f 100644 --- a/src/PolyhedralGeometry/Polyhedron/standard_constructions.jl +++ b/src/PolyhedralGeometry/Polyhedron/standard_constructions.jl @@ -2312,3 +2312,56 @@ function zonotope_vertices_fukuda_matrix(M::Union{MatElem,AbstractMatrix}) Polymake.polytope.zonotope_vertices_fukuda(Oscar.homogenized_matrix(A, 1)) ) end + +@doc raw""" + vertex_figure(P::Polyhedron, n::Int; cutoff::Rational=1/2) + +Construct the vertex figure of the vertex `n` of a polyhedron. The vertex figure is dual to a facet of the dual polytope. + +# Optional Arguments +-`cutoff::Number`: controls the exact location of the cutting hyperplane. It should lie in the open Interval $(0,1)$. +Value $0$ would let the hyperplane go through the chosen vertex, thus degenerating the vertex figure to a single point. +Value $1$ would let the hyperplane touch the nearest neighbor vertex of a polyhedron. Default value is $\fraction{1}{2}$. +-`no_coordinates::Bool`: Skip the coordinates computation, producing a pure combinatorial description. +-`no_labels::Bool`: Do not copy `VERTEX_LABELS` from the underlying `pm_object` of the original polytope (`true`), +default: do copy them (`false`). + +#Example +To produce a triangular vertex figure of a $3$-dimensional cube in the positive orthant, do: +```jldoctest +julia> T = vertex_figure(cube(3), 8) +Polyhedron in ambient dimension 3 + +julia> vertices(T) +3-element SubObjectIterator{PointVector{QQFieldElem}}: + [1, 1, 0] + [1, 0, 1] + [0, 1, 1] + +julia> T = vertex_figure(cube(3), 8, cutoff = 1/4) +Polyhedron in ambient dimension 3 + +julia> vertices(T) +3-element SubObjectIterator{PointVector{QQFieldElem}}: + [1, 1, 1//2] + [1, 1//2, 1] + [1//2, 1, 1] +``` + +""" +function vertex_figure(P::Polyhedron{T}, n::Int; cutoff=nothing, no_coordinates=nothing, no_labels=nothing) where {T<:scalar_types} + (n<=0 || n > nvertices(P)) && throw(ArgumentError("vertex_figure: There is no vertex "*string(n)*" in this polyhedron")) + opts = Dict{Symbol,Any}() + if !isnothing(cutoff) + (cutoff <= 0 || cutoff >=1) && throw(ArgumentError("vertex_figure: cutoff factor must be within (0,1)")) + !isnothing(no_coordinates) && throw(ArgumentError("vertex_figure: cannot specify cutoff and no_coordinates options simultaneously")) + opts[:cutoff] = convert(Number, cutoff) + end + if !isnothing(no_coordinates) + opts[:no_coordinates] = convert(Bool, no_coordinates) + end + if !isnothing(no_labels) + opts[:no_labels] = convert(Bool, no_labels) + end + return Polyhedron{T}(Polymake.polytope.vertex_figure(pm_object(P),n-1; opts...)) +end diff --git a/src/exports.jl b/src/exports.jl index 80219825d03c..d43e083bc078 100644 --- a/src/exports.jl +++ b/src/exports.jl @@ -510,8 +510,10 @@ export exterior_power export f_vector export face_fan export faces +export facet_degrees export facet_indices export facet_points +export facet_sizes export facets export factor_of_direct_product export factorisations @@ -1442,7 +1444,9 @@ export vector_matrix export vector_space_basis export vector_space_dimension export vertex_and_ray_indices +export vertex_figure export vertex_indices +export vertex_sizes export vertexindices export vertical_connectivity export vertices From 093a3e873e5f031387f010cc41f4e4b6757322fe Mon Sep 17 00:00:00 2001 From: Zoe Geiselmann Date: Thu, 14 Sep 2023 13:34:18 +0200 Subject: [PATCH 02/14] facet_degrees, ray_degrees --- src/PolyhedralGeometry/Cone/properties.jl | 63 ++++++++++++++++++++++- src/exports.jl | 1 + 2 files changed, 63 insertions(+), 1 deletion(-) diff --git a/src/PolyhedralGeometry/Cone/properties.jl b/src/PolyhedralGeometry/Cone/properties.jl index 4dd00b1c4134..05fae0cbd25c 100644 --- a/src/PolyhedralGeometry/Cone/properties.jl +++ b/src/PolyhedralGeometry/Cone/properties.jl @@ -329,10 +329,71 @@ julia> lineality_dim(C1) """ lineality_dim(C::Cone) = pm_object(C).LINEALITY_DIM::Int +@doc raw""" + facet_degrees(C::Cone) + +Facet degrees of the cone. The degree of a facet is the number of adjacent facets. +In particular a general $2$-dimensional cone has two facets (rays) that meet at the origin. + +#Example +Produce the facet degrees of a cone over a square and a cone over a square pyramid. +```jldoctest +julia> c = positive_hull([1 1 0; 1 -1 0; 1 0 1; 1 0 -1]) +Polyhedral cone in ambient dimension 3 + +julia> facet_degrees(c) +4-element Vector{Int64}: + 2 + 2 + 2 + 2 + + julia> c = positive_hull([1 0 1 0; 1 0 -1 0; 1 0 0 1; 1 0 0 -1; 1 1 0 0]) +Polyhedral cone in ambient dimension 4 + +julia> facet_degrees(c) +5-element Vector{Int64}: + 4 + 3 + 3 + 3 + 3 +``` +""" function facet_degrees(C::Cone) - return Vector{Int}(pm_object(C).FACET_DEGREES) + return Vector{Int}(Polymake.polytope.facet_degrees(pm_object(C))) end +@doc raw""" + ray_degrees(C::Cone) + +Ray degrees of the cone. If the cone has lineality, the output is empty since +there are no rays that are also faces. + +#Examples +```jldoctest +julia> c = cone_from_inequalities([-1 0 0; 0 -1 0]) +Polyhedral cone in ambient dimension 3 + +julia> ray_degrees(c) +Int64[] + +julia> c = positive_hull([1 0 1 0; 1 0 -1 0; 1 0 0 1; 1 0 0 -1; 1 1 0 0]) +Polyhedral cone in ambient dimension 4 + +julia> ray_degrees(c) +5-element Vector{Int64}: + 3 + 3 + 3 + 3 + 4 +``` +""" +function ray_degrees(C::Cone) + pm_object(C).LINEALITY_DIM > 0 && return Vector{Int}() + return Vector{Int}(Polymake.polytope.vertex_degrees(pm_object(C))) +end ############################################################################### ## Boolean properties diff --git a/src/exports.jl b/src/exports.jl index d43e083bc078..b52b3fcab3d6 100644 --- a/src/exports.jl +++ b/src/exports.jl @@ -1211,6 +1211,7 @@ export rational_equivalence_class export rational_point_coordinates export rational_solutions export rational_to_continued_fraction_hirzebruch_jung +export ray_degrees export ray_indices export ray_vector export rays From 0902f939b3f8d88c6587081baebb8d0035602d7a Mon Sep 17 00:00:00 2001 From: Zoe Geiselmann Date: Thu, 14 Sep 2023 14:02:02 +0200 Subject: [PATCH 03/14] rmv no_labels in vertex_figure --- src/PolyhedralGeometry/Cone/properties.jl | 2 ++ src/PolyhedralGeometry/Polyhedron/properties.jl | 15 +++++---------- .../Polyhedron/standard_constructions.jl | 5 +---- 3 files changed, 8 insertions(+), 14 deletions(-) diff --git a/src/PolyhedralGeometry/Cone/properties.jl b/src/PolyhedralGeometry/Cone/properties.jl index 05fae0cbd25c..bc3c1db59ab1 100644 --- a/src/PolyhedralGeometry/Cone/properties.jl +++ b/src/PolyhedralGeometry/Cone/properties.jl @@ -369,6 +369,8 @@ end Ray degrees of the cone. If the cone has lineality, the output is empty since there are no rays that are also faces. +Note the corresponding `polymake` property is called `VERTEX_DEGREES` and behaves +differently if the cone has lineality. #Examples ```jldoctest diff --git a/src/PolyhedralGeometry/Polyhedron/properties.jl b/src/PolyhedralGeometry/Polyhedron/properties.jl index 881fa56231a5..a3a2c98bfde8 100644 --- a/src/PolyhedralGeometry/Polyhedron/properties.jl +++ b/src/PolyhedralGeometry/Polyhedron/properties.jl @@ -754,16 +754,14 @@ julia> facet_sizes(p) ``` """ function facet_sizes(P::Polyhedron{T}) where T<:scalar_types - is_bounded(P) && return Vector{Int}(pm_object(P).FACET_SIZES) #shortcut, rest of the code works as well - im = IncidenceMatrix(pm_object(P).VERTICES_IN_FACETS) #incidence matrix with pm info with oscar indices + is_bounded(P) && return Vector{Int}(pm_object(P).FACET_SIZES) + im = IncidenceMatrix(pm_object(P).VERTICES_IN_FACETS) nrows = size(im)[1] - #get the vertices that are really vertices - ff = convert(Set{Int}, Polymake.to_one_based_indexing(P.pm_polytope.FAR_FACE)) #indices of vertices that are really rays (or higher dimensional faces) - #get the facets that are really facets + #get the vertices that are really vertices and the facets that are really facets + ff = convert(Set{Int}, Polymake.to_one_based_indexing(P.pm_polytope.FAR_FACE)) i = _facet_at_infinity(pm_object(P)) rows = Vector{Int}(1:nrows) i <= nrows && deleteat!(rows,i) #the face at infinity is not always a facet, so does not always need to be removed - #sum the vertices in facets that are really vertices in facets return [length(Base.setdiff(row(im,i), ff)) for i in 1:length(rows)] end @@ -785,10 +783,7 @@ julia> vertex_sizes(bipyramid(simplex(2))) """ function vertex_sizes(P::Polyhedron{T}) where T<:scalar_types res = Vector{Int}(pm_object(P).VERTEX_SIZES) - fai = [i+1 for i in Vector{Int}(pm_object(P).FAR_FACE)] #indices of vertices that are really rays (or higher dimensional faces) -# ff = convert(Set{Int}, Polymake.to_one_based_indexing(P.pm_polytope.FAR_FACE)) -# vf = Base.setdiff(Set(1:pm_object(P).N_VERTICES),ff) -# I don't think the set version is beneficiary here, bc the nvertices come as a vector and we want a vector back, so i still use symdiff + fai = [i+1 for i in Vector{Int}(pm_object(P).FAR_FACE)] vertices = symdiff(Vector{Int}(1:pm_object(P).N_VERTICES),fai) return keepat!(res,vertices) end diff --git a/src/PolyhedralGeometry/Polyhedron/standard_constructions.jl b/src/PolyhedralGeometry/Polyhedron/standard_constructions.jl index a2abbf5aa47f..ad467588334a 100644 --- a/src/PolyhedralGeometry/Polyhedron/standard_constructions.jl +++ b/src/PolyhedralGeometry/Polyhedron/standard_constructions.jl @@ -2349,7 +2349,7 @@ julia> vertices(T) ``` """ -function vertex_figure(P::Polyhedron{T}, n::Int; cutoff=nothing, no_coordinates=nothing, no_labels=nothing) where {T<:scalar_types} +function vertex_figure(P::Polyhedron{T}, n::Int; cutoff=nothing, no_coordinates=nothing) where {T<:scalar_types} (n<=0 || n > nvertices(P)) && throw(ArgumentError("vertex_figure: There is no vertex "*string(n)*" in this polyhedron")) opts = Dict{Symbol,Any}() if !isnothing(cutoff) @@ -2360,8 +2360,5 @@ function vertex_figure(P::Polyhedron{T}, n::Int; cutoff=nothing, no_coordinates= if !isnothing(no_coordinates) opts[:no_coordinates] = convert(Bool, no_coordinates) end - if !isnothing(no_labels) - opts[:no_labels] = convert(Bool, no_labels) - end return Polyhedron{T}(Polymake.polytope.vertex_figure(pm_object(P),n-1; opts...)) end From 69e224a554caec37a1c9abb189ad3d14acb05a7e Mon Sep 17 00:00:00 2001 From: Zoe Geiselmann Date: Thu, 14 Sep 2023 14:49:24 +0200 Subject: [PATCH 04/14] typo in jldoctest --- src/PolyhedralGeometry/Cone/properties.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PolyhedralGeometry/Cone/properties.jl b/src/PolyhedralGeometry/Cone/properties.jl index bc3c1db59ab1..8f08f8becf96 100644 --- a/src/PolyhedralGeometry/Cone/properties.jl +++ b/src/PolyhedralGeometry/Cone/properties.jl @@ -348,7 +348,7 @@ julia> facet_degrees(c) 2 2 - julia> c = positive_hull([1 0 1 0; 1 0 -1 0; 1 0 0 1; 1 0 0 -1; 1 1 0 0]) +julia> c = positive_hull([1 0 1 0; 1 0 -1 0; 1 0 0 1; 1 0 0 -1; 1 1 0 0]) Polyhedral cone in ambient dimension 4 julia> facet_degrees(c) From 811169dee449fbca198952db477b87a51e4a695b Mon Sep 17 00:00:00 2001 From: Zoe Geiselmann Date: Thu, 21 Sep 2023 15:25:25 +0200 Subject: [PATCH 05/14] add tests, adjust def vertex_figure, adjust vertex_sizes --- src/PolyhedralGeometry/Polyhedron/properties.jl | 1 + .../Polyhedron/standard_constructions.jl | 4 +--- test/PolyhedralGeometry/cone.jl | 4 ++++ test/PolyhedralGeometry/polyhedron.jl | 14 ++++++++++++++ 4 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/PolyhedralGeometry/Polyhedron/properties.jl b/src/PolyhedralGeometry/Polyhedron/properties.jl index a3a2c98bfde8..5780bb374229 100644 --- a/src/PolyhedralGeometry/Polyhedron/properties.jl +++ b/src/PolyhedralGeometry/Polyhedron/properties.jl @@ -782,6 +782,7 @@ julia> vertex_sizes(bipyramid(simplex(2))) ``` """ function vertex_sizes(P::Polyhedron{T}) where T<:scalar_types + pm_object(P).LINEALITY_DIM > 0 && return Vector{Int}() res = Vector{Int}(pm_object(P).VERTEX_SIZES) fai = [i+1 for i in Vector{Int}(pm_object(P).FAR_FACE)] vertices = symdiff(Vector{Int}(1:pm_object(P).N_VERTICES),fai) diff --git a/src/PolyhedralGeometry/Polyhedron/standard_constructions.jl b/src/PolyhedralGeometry/Polyhedron/standard_constructions.jl index ad467588334a..1b360522d61d 100644 --- a/src/PolyhedralGeometry/Polyhedron/standard_constructions.jl +++ b/src/PolyhedralGeometry/Polyhedron/standard_constructions.jl @@ -2316,15 +2316,13 @@ end @doc raw""" vertex_figure(P::Polyhedron, n::Int; cutoff::Rational=1/2) -Construct the vertex figure of the vertex `n` of a polyhedron. The vertex figure is dual to a facet of the dual polytope. +Construct the vertex figure of the vertex `n` of a bounded polytope. The vertex figure is dual to a facet of the dual polytope. # Optional Arguments -`cutoff::Number`: controls the exact location of the cutting hyperplane. It should lie in the open Interval $(0,1)$. Value $0$ would let the hyperplane go through the chosen vertex, thus degenerating the vertex figure to a single point. Value $1$ would let the hyperplane touch the nearest neighbor vertex of a polyhedron. Default value is $\fraction{1}{2}$. -`no_coordinates::Bool`: Skip the coordinates computation, producing a pure combinatorial description. --`no_labels::Bool`: Do not copy `VERTEX_LABELS` from the underlying `pm_object` of the original polytope (`true`), -default: do copy them (`false`). #Example To produce a triangular vertex figure of a $3$-dimensional cube in the positive orthant, do: diff --git a/test/PolyhedralGeometry/cone.jl b/test/PolyhedralGeometry/cone.jl index 2098289e1a6c..c14224bfb008 100644 --- a/test/PolyhedralGeometry/cone.jl +++ b/test/PolyhedralGeometry/cone.jl @@ -132,6 +132,10 @@ for f in (QQ, K) @test f_vector(Cone2) == [0, 2] @test lineality_dim(Cone5) == 0 @test lineality_dim(Cone2) == 1 + @test facet_degrees(Cone5)[1] == 2 + @test facet_degrees(Cone6)[1] == 1 + @test ray_degrees(Cone5)[1] == 2 + @test ray_degrees(Cone6)[1] == 1 @test nfacets(Cone5) == 4 @test relative_interior_point(Cone1) == f.([1//2, 1//2]) diff --git a/test/PolyhedralGeometry/polyhedron.jl b/test/PolyhedralGeometry/polyhedron.jl index 05d189d3e60a..381724888aed 100644 --- a/test/PolyhedralGeometry/polyhedron.jl +++ b/test/PolyhedralGeometry/polyhedron.jl @@ -185,6 +185,13 @@ for f in (QQ, ENF) @test nrays(Q1) == 1 @test lineality_dim(Q2) == 1 @test relative_interior_point(Q0) == [1//3, 1//3] + @test facet_sizes(Q0)[1] == 2 + @test sum(facet_sizes(Q1)) == 6 + @test facet_sizes(Q2)[1] == 1 + @test vertex_sizes(Q0)[1] == 2 + @test vertex_sizes(Q1)[1] == 2 + @test length(vertex_sizes(Q2)) == 0 + end @testset "volume" begin @@ -479,6 +486,13 @@ for f in (QQ, ENF) end @test sum(zonotope_vertices_fukuda_matrix([4 4 2; 2 4 1])) == 0 + + @test_throws ArgumentError vertex_figure(cube(3),10) + let vf = vertex_figure(platonic_solid("octahedron"),1) + @test vf isa Polyhedron{T} + @test ambient_dim(vf) == 3 + @test sum(facet_sizes(vf)) == 8 + end end end From 86213935b3b4e519a4f8b91867927692697f3c6e Mon Sep 17 00:00:00 2001 From: Zoe Geiselmann Date: Thu, 21 Sep 2023 16:27:55 +0200 Subject: [PATCH 06/14] fix vertex_sizes --- src/PolyhedralGeometry/Polyhedron/properties.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PolyhedralGeometry/Polyhedron/properties.jl b/src/PolyhedralGeometry/Polyhedron/properties.jl index 5780bb374229..65e8c6130259 100644 --- a/src/PolyhedralGeometry/Polyhedron/properties.jl +++ b/src/PolyhedralGeometry/Polyhedron/properties.jl @@ -786,7 +786,7 @@ function vertex_sizes(P::Polyhedron{T}) where T<:scalar_types res = Vector{Int}(pm_object(P).VERTEX_SIZES) fai = [i+1 for i in Vector{Int}(pm_object(P).FAR_FACE)] vertices = symdiff(Vector{Int}(1:pm_object(P).N_VERTICES),fai) - return keepat!(res,vertices) + return Base.keepat!(res,vertices) end ############################################################################### From f893da5dfbebe05083e7fb9f47fc53629c623ebc Mon Sep 17 00:00:00 2001 From: Zoe Geiselmann Date: Fri, 22 Sep 2023 10:31:37 +0200 Subject: [PATCH 07/14] remove keepat in vertex_sizes --- src/PolyhedralGeometry/Polyhedron/properties.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PolyhedralGeometry/Polyhedron/properties.jl b/src/PolyhedralGeometry/Polyhedron/properties.jl index 65e8c6130259..651b1727924a 100644 --- a/src/PolyhedralGeometry/Polyhedron/properties.jl +++ b/src/PolyhedralGeometry/Polyhedron/properties.jl @@ -786,7 +786,7 @@ function vertex_sizes(P::Polyhedron{T}) where T<:scalar_types res = Vector{Int}(pm_object(P).VERTEX_SIZES) fai = [i+1 for i in Vector{Int}(pm_object(P).FAR_FACE)] vertices = symdiff(Vector{Int}(1:pm_object(P).N_VERTICES),fai) - return Base.keepat!(res,vertices) + return [res[i] for i in vertices] end ############################################################################### From 4e5b3c8b141559b4e1153ed9c148eb78b1892502 Mon Sep 17 00:00:00 2001 From: zkgeiselmann <136090081+zkgeiselmann@users.noreply.github.com> Date: Thu, 28 Sep 2023 10:21:14 +0200 Subject: [PATCH 08/14] Apply suggestions from code review: Typos and Style Co-authored-by: Benjamin Lorenz --- src/PolyhedralGeometry/Cone/properties.jl | 4 ++-- src/PolyhedralGeometry/Polyhedron/properties.jl | 8 ++++---- .../Polyhedron/standard_constructions.jl | 16 ++++++++-------- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/PolyhedralGeometry/Cone/properties.jl b/src/PolyhedralGeometry/Cone/properties.jl index 8f08f8becf96..5d6cdaf19fd1 100644 --- a/src/PolyhedralGeometry/Cone/properties.jl +++ b/src/PolyhedralGeometry/Cone/properties.jl @@ -335,7 +335,7 @@ lineality_dim(C::Cone) = pm_object(C).LINEALITY_DIM::Int Facet degrees of the cone. The degree of a facet is the number of adjacent facets. In particular a general $2$-dimensional cone has two facets (rays) that meet at the origin. -#Example +# Example Produce the facet degrees of a cone over a square and a cone over a square pyramid. ```jldoctest julia> c = positive_hull([1 1 0; 1 -1 0; 1 0 1; 1 0 -1]) @@ -372,7 +372,7 @@ there are no rays that are also faces. Note the corresponding `polymake` property is called `VERTEX_DEGREES` and behaves differently if the cone has lineality. -#Examples +# Examples ```jldoctest julia> c = cone_from_inequalities([-1 0 0; 0 -1 0]) Polyhedral cone in ambient dimension 3 diff --git a/src/PolyhedralGeometry/Polyhedron/properties.jl b/src/PolyhedralGeometry/Polyhedron/properties.jl index 651b1727924a..a8557b0dbc97 100644 --- a/src/PolyhedralGeometry/Polyhedron/properties.jl +++ b/src/PolyhedralGeometry/Polyhedron/properties.jl @@ -736,7 +736,7 @@ codim(P::Polyhedron) = ambient_dim(P)-dim(P) Number of vertices in each facet. -#Example +# Example ```jldoctest julia> p = johnson_solid(3) Polyhedron in ambient dimension 3 with EmbeddedElem{nf_elem} type coefficients @@ -767,10 +767,10 @@ end @doc raw""" vertex_sizes(P::Polyhedron{T}) - -Number of incident facets for each vertex -#Example +Number of incident facets for each vertex. + +# Example ```jldoctest julia> vertex_sizes(bipyramid(simplex(2))) 5-element Vector{Int64}: diff --git a/src/PolyhedralGeometry/Polyhedron/standard_constructions.jl b/src/PolyhedralGeometry/Polyhedron/standard_constructions.jl index 1b360522d61d..05c689ae204b 100644 --- a/src/PolyhedralGeometry/Polyhedron/standard_constructions.jl +++ b/src/PolyhedralGeometry/Polyhedron/standard_constructions.jl @@ -2319,12 +2319,12 @@ end Construct the vertex figure of the vertex `n` of a bounded polytope. The vertex figure is dual to a facet of the dual polytope. # Optional Arguments --`cutoff::Number`: controls the exact location of the cutting hyperplane. It should lie in the open Interval $(0,1)$. -Value $0$ would let the hyperplane go through the chosen vertex, thus degenerating the vertex figure to a single point. -Value $1$ would let the hyperplane touch the nearest neighbor vertex of a polyhedron. Default value is $\fraction{1}{2}$. --`no_coordinates::Bool`: Skip the coordinates computation, producing a pure combinatorial description. +- `cutoff::Number`: controls the exact location of the cutting hyperplane. It should lie in the open Interval $(0,1)$. + Value $0$ would let the hyperplane go through the chosen vertex, thus degenerating the vertex figure to a single point. + Value $1$ would let the hyperplane touch the nearest neighbor vertex of a polyhedron. Default value is $\fraction{1}{2}$. +- `no_coordinates::Bool`: Skip the coordinates computation, producing a pure combinatorial description. -#Example +# Example To produce a triangular vertex figure of a $3$-dimensional cube in the positive orthant, do: ```jldoctest julia> T = vertex_figure(cube(3), 8) @@ -2348,11 +2348,11 @@ julia> vertices(T) """ function vertex_figure(P::Polyhedron{T}, n::Int; cutoff=nothing, no_coordinates=nothing) where {T<:scalar_types} - (n<=0 || n > nvertices(P)) && throw(ArgumentError("vertex_figure: There is no vertex "*string(n)*" in this polyhedron")) + @req 1 <= n <= nvertices(P) "There is no vertex $n in this polyhedron" opts = Dict{Symbol,Any}() if !isnothing(cutoff) - (cutoff <= 0 || cutoff >=1) && throw(ArgumentError("vertex_figure: cutoff factor must be within (0,1)")) - !isnothing(no_coordinates) && throw(ArgumentError("vertex_figure: cannot specify cutoff and no_coordinates options simultaneously")) + @req 0 < cutoff < 1 "cutoff factor must be within (0,1)" + @req isnothing(no_coordinates) "cannot specify cutoff and no_coordinates options simultaneously" opts[:cutoff] = convert(Number, cutoff) end if !isnothing(no_coordinates) From ea3b626a3523e3d45014a7d47ac83f515ecbb4cd Mon Sep 17 00:00:00 2001 From: zkgeiselmann <136090081+zkgeiselmann@users.noreply.github.com> Date: Thu, 28 Sep 2023 10:28:55 +0200 Subject: [PATCH 09/14] Apply suggestions from code review: Specify Types Co-authored-by: Benjamin Lorenz --- src/PolyhedralGeometry/Polyhedron/standard_constructions.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/PolyhedralGeometry/Polyhedron/standard_constructions.jl b/src/PolyhedralGeometry/Polyhedron/standard_constructions.jl index 05c689ae204b..5472a6c21e2d 100644 --- a/src/PolyhedralGeometry/Polyhedron/standard_constructions.jl +++ b/src/PolyhedralGeometry/Polyhedron/standard_constructions.jl @@ -2314,7 +2314,7 @@ function zonotope_vertices_fukuda_matrix(M::Union{MatElem,AbstractMatrix}) end @doc raw""" - vertex_figure(P::Polyhedron, n::Int; cutoff::Rational=1/2) + vertex_figure(P::Polyhedron, n::Int; cutoff=1//2) Construct the vertex figure of the vertex `n` of a bounded polytope. The vertex figure is dual to a facet of the dual polytope. @@ -2353,10 +2353,10 @@ function vertex_figure(P::Polyhedron{T}, n::Int; cutoff=nothing, no_coordinates= if !isnothing(cutoff) @req 0 < cutoff < 1 "cutoff factor must be within (0,1)" @req isnothing(no_coordinates) "cannot specify cutoff and no_coordinates options simultaneously" - opts[:cutoff] = convert(Number, cutoff) + opts[:cutoff] = convert(Polymake.PolymakeType, cutoff) end if !isnothing(no_coordinates) opts[:no_coordinates] = convert(Bool, no_coordinates) end - return Polyhedron{T}(Polymake.polytope.vertex_figure(pm_object(P),n-1; opts...)) + return Polyhedron{T}(Polymake.polytope.vertex_figure(pm_object(P), n-1; opts...), coefficient_field(P)) end From 678881dd778afb3c3697a9b0816bd407cb06b766 Mon Sep 17 00:00:00 2001 From: zkgeiselmann <136090081+zkgeiselmann@users.noreply.github.com> Date: Thu, 28 Sep 2023 10:31:23 +0200 Subject: [PATCH 10/14] Apply suggestions from code review: Change facet_sizes, vertex_sizes and docs of ray_degrees Co-authored-by: Benjamin Lorenz --- src/PolyhedralGeometry/Cone/properties.jl | 2 -- src/PolyhedralGeometry/Polyhedron/properties.jl | 17 +++++------------ 2 files changed, 5 insertions(+), 14 deletions(-) diff --git a/src/PolyhedralGeometry/Cone/properties.jl b/src/PolyhedralGeometry/Cone/properties.jl index 5d6cdaf19fd1..4f63b1bd1383 100644 --- a/src/PolyhedralGeometry/Cone/properties.jl +++ b/src/PolyhedralGeometry/Cone/properties.jl @@ -369,8 +369,6 @@ end Ray degrees of the cone. If the cone has lineality, the output is empty since there are no rays that are also faces. -Note the corresponding `polymake` property is called `VERTEX_DEGREES` and behaves -differently if the cone has lineality. # Examples ```jldoctest diff --git a/src/PolyhedralGeometry/Polyhedron/properties.jl b/src/PolyhedralGeometry/Polyhedron/properties.jl index a8557b0dbc97..9a12898a14d7 100644 --- a/src/PolyhedralGeometry/Polyhedron/properties.jl +++ b/src/PolyhedralGeometry/Polyhedron/properties.jl @@ -754,15 +754,8 @@ julia> facet_sizes(p) ``` """ function facet_sizes(P::Polyhedron{T}) where T<:scalar_types - is_bounded(P) && return Vector{Int}(pm_object(P).FACET_SIZES) - im = IncidenceMatrix(pm_object(P).VERTICES_IN_FACETS) - nrows = size(im)[1] - #get the vertices that are really vertices and the facets that are really facets - ff = convert(Set{Int}, Polymake.to_one_based_indexing(P.pm_polytope.FAR_FACE)) - i = _facet_at_infinity(pm_object(P)) - rows = Vector{Int}(1:nrows) - i <= nrows && deleteat!(rows,i) #the face at infinity is not always a facet, so does not always need to be removed - return [length(Base.setdiff(row(im,i), ff)) for i in 1:length(rows)] + im = vertex_indices(facets(P)) + return [length(row(im, i)) for i in 1:nrows(im)] end @doc raw""" @@ -784,9 +777,9 @@ julia> vertex_sizes(bipyramid(simplex(2))) function vertex_sizes(P::Polyhedron{T}) where T<:scalar_types pm_object(P).LINEALITY_DIM > 0 && return Vector{Int}() res = Vector{Int}(pm_object(P).VERTEX_SIZES) - fai = [i+1 for i in Vector{Int}(pm_object(P).FAR_FACE)] - vertices = symdiff(Vector{Int}(1:pm_object(P).N_VERTICES),fai) - return [res[i] for i in vertices] + + vertices = Polymake.to_one_based_indexing(Polymake.polytope.bounded_vertices(pm_object(P))) + return res[collect(vertices)] end ############################################################################### From 8f397530240ca1f107d858ca22a9a67583fdb891 Mon Sep 17 00:00:00 2001 From: Zoe Geiselmann Date: Thu, 28 Sep 2023 10:55:55 +0200 Subject: [PATCH 11/14] Apply suggestions: add Functions to md-files --- docs/src/PolyhedralGeometry/Polyhedra/auxiliary.md | 2 ++ docs/src/PolyhedralGeometry/Polyhedra/constructions.md | 1 + docs/src/PolyhedralGeometry/cones.md | 2 ++ 3 files changed, 5 insertions(+) diff --git a/docs/src/PolyhedralGeometry/Polyhedra/auxiliary.md b/docs/src/PolyhedralGeometry/Polyhedra/auxiliary.md index 7e1f4a7df45c..95484c32905c 100644 --- a/docs/src/PolyhedralGeometry/Polyhedra/auxiliary.md +++ b/docs/src/PolyhedralGeometry/Polyhedra/auxiliary.md @@ -32,8 +32,10 @@ relative_interior_point(P::Polyhedron{T}) where T<:scalar_types nfacets(P::Polyhedron) nvertices(P::Polyhedron) f_vector(P::Polyhedron) +facet_sizes(P::Polyhedron) g_vector(P::Polyhedron) h_vector(P::Polyhedron) +vertex_sizes(P::Polyhedron) ``` ## Groups diff --git a/docs/src/PolyhedralGeometry/Polyhedra/constructions.md b/docs/src/PolyhedralGeometry/Polyhedra/constructions.md index 53b66fb06cd7..4a09d534c260 100644 --- a/docs/src/PolyhedralGeometry/Polyhedra/constructions.md +++ b/docs/src/PolyhedralGeometry/Polyhedra/constructions.md @@ -196,6 +196,7 @@ a new polyhedron. bipyramid intersect(::Polyhedron...) pyramid +vertex_figure ``` The convex hull of two polytopes can be computed via `convex_hull`. diff --git a/docs/src/PolyhedralGeometry/cones.md b/docs/src/PolyhedralGeometry/cones.md index 38ea2b4f2690..ec140e1f4215 100644 --- a/docs/src/PolyhedralGeometry/cones.md +++ b/docs/src/PolyhedralGeometry/cones.md @@ -38,6 +38,7 @@ secondary_cone(SOP::SubdivisionOfPoints{T}) where T<:scalar_types ambient_dim(C::Cone) Base.in(v::AbstractVector, C::Cone) Base.issubset(C0::Cone{T}, C1::Cone{T}) where T<:scalar_types +facet_degrees(C::Cone) f_vector(C::Cone) hilbert_basis(C::Cone{QQFieldElem}) codim(C::Cone) @@ -52,4 +53,5 @@ nfacets(C::Cone) nrays(C::Cone) rays(C::Cone{T}) where T<:scalar_types rays_modulo_lineality(C::Cone{T}) where T<:scalar_types +ray_degrees(C::Cone) ``` From dd4c37df9b0be3d7456e6381497ff4350e899a15 Mon Sep 17 00:00:00 2001 From: Zoe Geiselmann Date: Fri, 29 Sep 2023 10:10:09 +0200 Subject: [PATCH 12/14] fix docs for vertex_figure, change docs for facet_sizes --- src/PolyhedralGeometry/Polyhedron/properties.jl | 12 +++++++----- .../Polyhedron/standard_constructions.jl | 2 +- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/PolyhedralGeometry/Polyhedron/properties.jl b/src/PolyhedralGeometry/Polyhedron/properties.jl index 9a12898a14d7..42026e5899da 100644 --- a/src/PolyhedralGeometry/Polyhedron/properties.jl +++ b/src/PolyhedralGeometry/Polyhedron/properties.jl @@ -738,17 +738,19 @@ Number of vertices in each facet. # Example ```jldoctest -julia> p = johnson_solid(3) +julia> p = johnson_solid(4) Polyhedron in ambient dimension 3 with EmbeddedElem{nf_elem} type coefficients -julia> facet_sizes(p) -8-element Vector{Int64}: - 3 +julia> facet_sizes(p) +10-element Vector{Int64}: + 8 4 3 + 4 + 4 3 4 - 6 + 3 3 4 ``` diff --git a/src/PolyhedralGeometry/Polyhedron/standard_constructions.jl b/src/PolyhedralGeometry/Polyhedron/standard_constructions.jl index 5472a6c21e2d..2a996d946d51 100644 --- a/src/PolyhedralGeometry/Polyhedron/standard_constructions.jl +++ b/src/PolyhedralGeometry/Polyhedron/standard_constructions.jl @@ -2321,7 +2321,7 @@ Construct the vertex figure of the vertex `n` of a bounded polytope. The vertex # Optional Arguments - `cutoff::Number`: controls the exact location of the cutting hyperplane. It should lie in the open Interval $(0,1)$. Value $0$ would let the hyperplane go through the chosen vertex, thus degenerating the vertex figure to a single point. - Value $1$ would let the hyperplane touch the nearest neighbor vertex of a polyhedron. Default value is $\fraction{1}{2}$. + Value $1$ would let the hyperplane touch the nearest neighbor vertex of a polyhedron. Default value is $\frac{1}{2}$. - `no_coordinates::Bool`: Skip the coordinates computation, producing a pure combinatorial description. # Example From 0f85aeed21fe6c86febac925d40d287a34f3926e Mon Sep 17 00:00:00 2001 From: zkgeiselmann <136090081+zkgeiselmann@users.noreply.github.com> Date: Fri, 29 Sep 2023 18:07:08 +0200 Subject: [PATCH 13/14] Apply suggestions from code review: remove no_coordinates from vertex_figure Co-authored-by: Benjamin Lorenz --- .../Polyhedron/standard_constructions.jl | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/PolyhedralGeometry/Polyhedron/standard_constructions.jl b/src/PolyhedralGeometry/Polyhedron/standard_constructions.jl index 2a996d946d51..7f2c8ef022b5 100644 --- a/src/PolyhedralGeometry/Polyhedron/standard_constructions.jl +++ b/src/PolyhedralGeometry/Polyhedron/standard_constructions.jl @@ -2322,7 +2322,6 @@ Construct the vertex figure of the vertex `n` of a bounded polytope. The vertex - `cutoff::Number`: controls the exact location of the cutting hyperplane. It should lie in the open Interval $(0,1)$. Value $0$ would let the hyperplane go through the chosen vertex, thus degenerating the vertex figure to a single point. Value $1$ would let the hyperplane touch the nearest neighbor vertex of a polyhedron. Default value is $\frac{1}{2}$. -- `no_coordinates::Bool`: Skip the coordinates computation, producing a pure combinatorial description. # Example To produce a triangular vertex figure of a $3$-dimensional cube in the positive orthant, do: @@ -2347,16 +2346,12 @@ julia> vertices(T) ``` """ -function vertex_figure(P::Polyhedron{T}, n::Int; cutoff=nothing, no_coordinates=nothing) where {T<:scalar_types} +function vertex_figure(P::Polyhedron{T}, n::Int; cutoff=nothing) where {T<:scalar_types} @req 1 <= n <= nvertices(P) "There is no vertex $n in this polyhedron" opts = Dict{Symbol,Any}() if !isnothing(cutoff) @req 0 < cutoff < 1 "cutoff factor must be within (0,1)" - @req isnothing(no_coordinates) "cannot specify cutoff and no_coordinates options simultaneously" opts[:cutoff] = convert(Polymake.PolymakeType, cutoff) end - if !isnothing(no_coordinates) - opts[:no_coordinates] = convert(Bool, no_coordinates) - end return Polyhedron{T}(Polymake.polytope.vertex_figure(pm_object(P), n-1; opts...), coefficient_field(P)) end From da80751fc83ade18d912b856ff880a6cc6c735a0 Mon Sep 17 00:00:00 2001 From: Lars Kastner Date: Wed, 4 Oct 2023 10:37:03 +0200 Subject: [PATCH 14/14] PolyhedralGeometry: Run formatter on modified parts --- src/PolyhedralGeometry/Cone/properties.jl | 173 +++-- .../Polyhedron/properties.jl | 729 ++++++++++++------ .../Polyhedron/standard_constructions.jl | 4 +- 3 files changed, 590 insertions(+), 316 deletions(-) diff --git a/src/PolyhedralGeometry/Cone/properties.jl b/src/PolyhedralGeometry/Cone/properties.jl index 4f63b1bd1383..100e56546813 100644 --- a/src/PolyhedralGeometry/Cone/properties.jl +++ b/src/PolyhedralGeometry/Cone/properties.jl @@ -4,17 +4,21 @@ ############################################################################### ############################################################################### -rays(as::Type{RayVector{T}}, C::Cone{T}) where T<:scalar_types = lineality_dim(C) == 0 ? _rays(as, C) : _empty_subobjectiterator(as, C) -_rays(as::Type{RayVector{T}}, C::Cone{T}) where T<:scalar_types = SubObjectIterator{as}(C, _ray_cone, _nrays(C)) +rays(as::Type{RayVector{T}}, C::Cone{T}) where {T<:scalar_types} = + lineality_dim(C) == 0 ? _rays(as, C) : _empty_subobjectiterator(as, C) +_rays(as::Type{RayVector{T}}, C::Cone{T}) where {T<:scalar_types} = + SubObjectIterator{as}(C, _ray_cone, _nrays(C)) -_ray_cone(U::Type{RayVector{T}}, C::Cone{T}, i::Base.Integer) where T<:scalar_types = ray_vector(coefficient_field(C), view(pm_object(C).RAYS, i, :))::U +_ray_cone(U::Type{RayVector{T}}, C::Cone{T}, i::Base.Integer) where {T<:scalar_types} = + ray_vector(coefficient_field(C), view(pm_object(C).RAYS, i, :))::U -_vector_matrix(::Val{_ray_cone}, C::Cone; homogenized=false) = homogenized ? homogenize(pm_object(C).RAYS, 0) : pm_object(C).RAYS +_vector_matrix(::Val{_ray_cone}, C::Cone; homogenized=false) = + homogenized ? homogenize(pm_object(C).RAYS, 0) : pm_object(C).RAYS _matrix_for_polymake(::Val{_ray_cone}) = _vector_matrix -rays(::Type{<:RayVector}, C::Cone{T}) where T<:scalar_types = rays(RayVector{T}, C) -_rays(::Type{<:RayVector}, C::Cone{T}) where T<:scalar_types = _rays(RayVector{T}, C) +rays(::Type{<:RayVector}, C::Cone{T}) where {T<:scalar_types} = rays(RayVector{T}, C) +_rays(::Type{<:RayVector}, C::Cone{T}) where {T<:scalar_types} = _rays(RayVector{T}, C) @doc raw""" rays(C::Cone) @@ -56,9 +60,8 @@ julia> matrix(ZZ, rays(P)) [2 3] ``` """ -rays(C::Cone{T}) where T<:scalar_types = rays(RayVector{T}, C) -_rays(C::Cone{T}) where T<:scalar_types = _rays(RayVector{T}, C) - +rays(C::Cone{T}) where {T<:scalar_types} = rays(RayVector{T}, C) +_rays(C::Cone{T}) where {T<:scalar_types} = _rays(RayVector{T}, C) @doc raw""" rays_modulo_lineality(as, C::Cone) @@ -109,16 +112,26 @@ julia> RML.lineality_basis 1-element SubObjectIterator{RayVector{QQFieldElem}}: [0, 1] ``` -""" -rays_modulo_lineality(C::Cone{T}) where T<:scalar_types = rays_modulo_lineality(NamedTuple{(:rays_modulo_lineality, :lineality_basis), Tuple{SubObjectIterator{RayVector{T}}, SubObjectIterator{RayVector{T}}}}, C) -function rays_modulo_lineality(::Type{NamedTuple{(:rays_modulo_lineality, :lineality_basis), Tuple{SubObjectIterator{RayVector{T}}, SubObjectIterator{RayVector{T}}}}}, C::Cone{T}) where T<:scalar_types - return ( - rays_modulo_lineality = _rays(C), - lineality_basis = lineality_space(C) - ) +""" +rays_modulo_lineality(C::Cone{T}) where {T<:scalar_types} = rays_modulo_lineality( + NamedTuple{ + (:rays_modulo_lineality, :lineality_basis), + Tuple{SubObjectIterator{RayVector{T}},SubObjectIterator{RayVector{T}}}, + }, + C, +) +function rays_modulo_lineality( + ::Type{ + NamedTuple{ + (:rays_modulo_lineality, :lineality_basis), + Tuple{SubObjectIterator{RayVector{T}},SubObjectIterator{RayVector{T}}}, + }, + }, + C::Cone{T}, +) where {T<:scalar_types} + return (rays_modulo_lineality=_rays(C), lineality_basis=lineality_space(C)) end rays_modulo_lineality(::Type{<:RayVector}, C::Cone) = _rays(C) - @doc raw""" faces(C::Cone, face_dim::Int) @@ -140,30 +153,47 @@ RayVector{QQFieldElem}[[1, 0, 0], [0, 0, 1]] RayVector{QQFieldElem}[[1, 0, 0], [0, 1, 0]] ``` """ -function faces(C::Cone{T}, face_dim::Int) where T<:scalar_types - face_dim == dim(C) - 1 && return SubObjectIterator{Cone{T}}(C, _face_cone_facet, nfacets(C)) - n = face_dim - length(lineality_space(C)) - n < 1 && return nothing - return SubObjectIterator{Cone{T}}(C, _face_cone, size(Polymake.polytope.faces_of_dim(pm_object(C), n), 1), (f_dim = n,)) +function faces(C::Cone{T}, face_dim::Int) where {T<:scalar_types} + face_dim == dim(C) - 1 && + return SubObjectIterator{Cone{T}}(C, _face_cone_facet, nfacets(C)) + n = face_dim - length(lineality_space(C)) + n < 1 && return nothing + return SubObjectIterator{Cone{T}}( + C, _face_cone, size(Polymake.polytope.faces_of_dim(pm_object(C), n), 1), (f_dim=n,) + ) end -function _face_cone(::Type{Cone{T}}, C::Cone{T}, i::Base.Integer; f_dim::Int = 0) where T<:scalar_types - R = pm_object(C).RAYS[collect(Polymake.to_one_based_indexing(Polymake.polytope.faces_of_dim(pm_object(C), f_dim)[i])), :] +function _face_cone( + ::Type{Cone{T}}, C::Cone{T}, i::Base.Integer; f_dim::Int=0 +) where {T<:scalar_types} + R = pm_object(C).RAYS[ + collect( + Polymake.to_one_based_indexing(Polymake.polytope.faces_of_dim(pm_object(C), f_dim)[i]) + ), + :, + ] L = pm_object(C).LINEALITY_SPACE PT = _scalar_type_to_polymake(T) - return Cone{T}(Polymake.polytope.Cone{PT}(RAYS = R, LINEALITY_SPACE = L), coefficient_field(C)) + return Cone{T}( + Polymake.polytope.Cone{PT}(; RAYS=R, LINEALITY_SPACE=L), coefficient_field(C) + ) end -function _ray_indices(::Val{_face_cone}, C::Cone; f_dim::Int = 0) - f = Polymake.to_one_based_indexing(Polymake.polytope.faces_of_dim(pm_object(C), f_dim)) - return IncidenceMatrix([collect(f[i]) for i in 1:length(f)]) +function _ray_indices(::Val{_face_cone}, C::Cone; f_dim::Int=0) + f = Polymake.to_one_based_indexing(Polymake.polytope.faces_of_dim(pm_object(C), f_dim)) + return IncidenceMatrix([collect(f[i]) for i in 1:length(f)]) end -function _face_cone_facet(::Type{Cone{T}}, C::Cone{T}, i::Base.Integer) where T<:scalar_types +function _face_cone_facet( + ::Type{Cone{T}}, C::Cone{T}, i::Base.Integer +) where {T<:scalar_types} R = pm_object(C).RAYS[collect(pm_object(C).RAYS_IN_FACETS[i, :]), :] L = pm_object(C).LINEALITY_SPACE PT = _scalar_type_to_polymake(T) - return Cone{T}(Polymake.polytope.Cone{PT}(RAYS = R, LINEALITY_SPACE = pm_object(C).LINEALITY_SPACE), coefficient_field(C)) + return Cone{T}( + Polymake.polytope.Cone{PT}(; RAYS=R, LINEALITY_SPACE=pm_object(C).LINEALITY_SPACE), + coefficient_field(C), + ) end _ray_indices(::Val{_face_cone_facet}, C::Cone) = pm_object(C).RAYS_IN_FACETS @@ -263,8 +293,7 @@ julia> codim(C) 1 ``` """ -codim(C::Cone) = ambient_dim(C)-dim(C) - +codim(C::Cone) = ambient_dim(C) - dim(C) @doc raw""" f_vector(C::Cone) @@ -293,12 +322,11 @@ julia> f_vector(square) ``` """ function f_vector(C::Cone) - pmc = pm_object(C) - ldim = pmc.LINEALITY_DIM - return Vector{ZZRingElem}(vcat(fill(0, ldim), pmc.F_VECTOR)) + pmc = pm_object(C) + ldim = pmc.LINEALITY_DIM + return Vector{ZZRingElem}(vcat(fill(0, ldim), pmc.F_VECTOR)) end - @doc raw""" lineality_dim(C::Cone) @@ -360,9 +388,7 @@ julia> facet_degrees(c) 3 ``` """ -function facet_degrees(C::Cone) - return Vector{Int}(Polymake.polytope.facet_degrees(pm_object(C))) -end +facet_degrees(C::Cone) = Vector{Int}(Polymake.polytope.facet_degrees(pm_object(C))) @doc raw""" ray_degrees(C::Cone) @@ -391,8 +417,8 @@ julia> ray_degrees(c) ``` """ function ray_degrees(C::Cone) - pm_object(C).LINEALITY_DIM > 0 && return Vector{Int}() - return Vector{Int}(Polymake.polytope.vertex_degrees(pm_object(C))) + pm_object(C).LINEALITY_DIM > 0 && return Vector{Int}() + return Vector{Int}(Polymake.polytope.vertex_degrees(pm_object(C))) end ############################################################################### @@ -421,7 +447,6 @@ false """ is_simplicial(C::Cone) = pm_object(C).SIMPLICIAL_CONE::Bool - @doc raw""" is_smooth(C::Cone{QQFieldElem}) @@ -445,7 +470,6 @@ false """ is_smooth(C::Cone{QQFieldElem}) = pm_object(C).SMOOTH_CONE::Bool - @doc raw""" is_pointed(C::Cone) @@ -509,11 +533,16 @@ julia> f = facets(Halfspace, c) -x_2 + x_3 <= 0 ``` """ -facets(as::Type{<:Union{LinearHalfspace{T}, Cone{T}}}, C::Cone{T}) where T<:scalar_types = SubObjectIterator{as}(C, _facet_cone, nfacets(C)) +facets(as::Type{<:Union{LinearHalfspace{T},Cone{T}}}, C::Cone{T}) where {T<:scalar_types} = + SubObjectIterator{as}(C, _facet_cone, nfacets(C)) -_facet_cone(U::Type{LinearHalfspace{T}}, C::Cone{T}, i::Base.Integer) where T<:scalar_types = linear_halfspace(coefficient_field(C), -pm_object(C).FACETS[[i], :])::U +_facet_cone( + U::Type{LinearHalfspace{T}}, C::Cone{T}, i::Base.Integer +) where {T<:scalar_types} = + linear_halfspace(coefficient_field(C), -pm_object(C).FACETS[[i], :])::U -_facet_cone(::Type{Cone{T}}, C::Cone{T}, i::Base.Integer) where T<:scalar_types = Cone{T}(Polymake.polytope.facet(pm_object(C), i-1), coefficient_field(C)) +_facet_cone(::Type{Cone{T}}, C::Cone{T}, i::Base.Integer) where {T<:scalar_types} = + Cone{T}(Polymake.polytope.facet(pm_object(C), i - 1), coefficient_field(C)) _linear_inequality_matrix(::Val{_facet_cone}, C::Cone) = -pm_object(C).FACETS @@ -523,11 +552,12 @@ _ray_indices(::Val{_facet_cone}, C::Cone) = pm_object(C).RAYS_IN_FACETS _incidencematrix(::Val{_facet_cone}) = _ray_indices -facets(C::Cone{T}) where T<:scalar_types = facets(LinearHalfspace{T}, C) +facets(C::Cone{T}) where {T<:scalar_types} = facets(LinearHalfspace{T}, C) -facets(::Type{<:Halfspace}, C::Cone{T}) where T<:scalar_types = facets(LinearHalfspace{T}, C) +facets(::Type{<:Halfspace}, C::Cone{T}) where {T<:scalar_types} = + facets(LinearHalfspace{T}, C) -facets(::Type{Cone}, C::Cone{T}) where T<:scalar_types = facets(Cone{T}, C) +facets(::Type{Cone}, C::Cone{T}) where {T<:scalar_types} = facets(Cone{T}, C) @doc raw""" lineality_space(C::Cone) @@ -545,11 +575,16 @@ julia> lineality_space(UH) [1, 0] ``` """ -lineality_space(C::Cone{T}) where T<:scalar_types = SubObjectIterator{RayVector{T}}(C, _lineality_cone, lineality_dim(C)) +lineality_space(C::Cone{T}) where {T<:scalar_types} = + SubObjectIterator{RayVector{T}}(C, _lineality_cone, lineality_dim(C)) -_lineality_cone(U::Type{RayVector{T}}, C::Cone{T}, i::Base.Integer) where T<:scalar_types = ray_vector(coefficient_field(C), view(pm_object(C).LINEALITY_SPACE, i, :))::U +_lineality_cone( + U::Type{RayVector{T}}, C::Cone{T}, i::Base.Integer +) where {T<:scalar_types} = + ray_vector(coefficient_field(C), view(pm_object(C).LINEALITY_SPACE, i, :))::U -_generator_matrix(::Val{_lineality_cone}, C::Cone; homogenized=false) = homogenized ? homogenize(pm_object(C).LINEALITY_SPACE, 0) : pm_object(C).LINEALITY_SPACE +_generator_matrix(::Val{_lineality_cone}, C::Cone; homogenized=false) = + homogenized ? homogenize(pm_object(C).LINEALITY_SPACE, 0) : pm_object(C).LINEALITY_SPACE _matrix_for_polymake(::Val{_lineality_cone}) = _generator_matrix @@ -569,9 +604,13 @@ julia> linear_span(c) x_3 = 0 ``` """ -linear_span(C::Cone{T}) where T<:scalar_types = SubObjectIterator{LinearHyperplane{T}}(C, _linear_span, size(pm_object(C).LINEAR_SPAN, 1)) +linear_span(C::Cone{T}) where {T<:scalar_types} = + SubObjectIterator{LinearHyperplane{T}}(C, _linear_span, size(pm_object(C).LINEAR_SPAN, 1)) -_linear_span(U::Type{LinearHyperplane{T}}, C::Cone{T}, i::Base.Integer) where T<:scalar_types = linear_hyperplane(coefficient_field(C), view(pm_object(C).LINEAR_SPAN, i, :))::U +_linear_span( + U::Type{LinearHyperplane{T}}, C::Cone{T}, i::Base.Integer +) where {T<:scalar_types} = + linear_hyperplane(coefficient_field(C), view(pm_object(C).LINEAR_SPAN, i, :))::U _linear_equation_matrix(::Val{_linear_span}, C::Cone) = pm_object(C).LINEAR_SPAN @@ -596,17 +635,24 @@ julia> matrix(ZZ, hilbert_basis(C)) ``` """ function hilbert_basis(C::Cone{QQFieldElem}) - @req is_pointed(C) "Cone not pointed" - return SubObjectIterator{PointVector{ZZRingElem}}(C, _hilbert_generator, size(pm_object(C).HILBERT_BASIS_GENERATORS[1], 1)) + @req is_pointed(C) "Cone not pointed" + return SubObjectIterator{PointVector{ZZRingElem}}( + C, _hilbert_generator, size(pm_object(C).HILBERT_BASIS_GENERATORS[1], 1) + ) end -_hilbert_generator(T::Type{PointVector{ZZRingElem}}, C::Cone{QQFieldElem}, i::Base.Integer) = point_vector(ZZ, view(pm_object(C).HILBERT_BASIS_GENERATORS[1], i, :))::T +_hilbert_generator( + T::Type{PointVector{ZZRingElem}}, C::Cone{QQFieldElem}, i::Base.Integer +) = point_vector(ZZ, view(pm_object(C).HILBERT_BASIS_GENERATORS[1], i, :))::T -_generator_matrix(::Val{_hilbert_generator}, C::Cone; homogenized=false) = homogenized ? homogenize(pm_object(C).HILBERT_BASIS_GENERATORS[1], 0) : pm_object(C).HILBERT_BASIS_GENERATORS[1] +_generator_matrix(::Val{_hilbert_generator}, C::Cone; homogenized=false) = if homogenized + homogenize(pm_object(C).HILBERT_BASIS_GENERATORS[1], 0) +else + pm_object(C).HILBERT_BASIS_GENERATORS[1] +end _matrix_for_polymake(::Val{_hilbert_generator}) = _generator_matrix - @doc raw""" issubset(C0::Cone, C1::Cone) @@ -627,8 +673,8 @@ julia> issubset(C1, C0) false ``` """ -Base.issubset(C0::Cone{T}, C1::Cone{T}) where T<:scalar_types = Polymake.polytope.included_polyhedra(pm_object(C0), pm_object(C1))::Bool - +Base.issubset(C0::Cone{T}, C1::Cone{T}) where {T<:scalar_types} = + Polymake.polytope.included_polyhedra(pm_object(C0), pm_object(C1))::Bool @doc raw""" in(v::AbstractVector, C::Cone) @@ -649,11 +695,12 @@ false """ Base.in(v::AbstractVector, C::Cone) = Polymake.polytope.contains(pm_object(C), v)::Bool - @doc raw""" relative_interior_point(C::Cone) Compute a point in the relative interior point of `C`, i.e. a point in `C` not contained in any facet. """ -relative_interior_point(C::Cone{T}) where T<:scalar_types = point_vector(coefficient_field(C), view(Polymake.common.dense(pm_object(C).REL_INT_POINT), :))::PointVector{T} # broadcast_view +relative_interior_point(C::Cone{T}) where {T<:scalar_types} = point_vector( + coefficient_field(C), view(Polymake.common.dense(pm_object(C).REL_INT_POINT), :) +)::PointVector{T} # broadcast_view diff --git a/src/PolyhedralGeometry/Polyhedron/properties.jl b/src/PolyhedralGeometry/Polyhedron/properties.jl index 42026e5899da..878bc5cfc31f 100644 --- a/src/PolyhedralGeometry/Polyhedron/properties.jl +++ b/src/PolyhedralGeometry/Polyhedron/properties.jl @@ -25,87 +25,148 @@ julia> F = faces(cube(3), 2) Polyhedron in ambient dimension 3 ``` """ -function faces(P::Polyhedron{T}, face_dim::Int) where T<:scalar_types - face_dim == dim(P) - 1 && return SubObjectIterator{Polyhedron{T}}(P, _face_polyhedron_facet, nfacets(P)) - n = face_dim - length(lineality_space(P)) - n < 0 && return nothing - pfaces = Polymake.to_one_based_indexing(Polymake.polytope.faces_of_dim(pm_object(P), n)) - farf = Polymake.to_one_based_indexing(pm_object(P).FAR_FACE) - rfaces = Vector{Int}(filter(i->!(pfaces[i] <= farf), range(1,length(pfaces); step=1))) - return SubObjectIterator{Polyhedron{T}}(P, _face_polyhedron, length(rfaces), (f_dim = n, f_ind = rfaces)) +function faces(P::Polyhedron{T}, face_dim::Int) where {T<:scalar_types} + face_dim == dim(P) - 1 && + return SubObjectIterator{Polyhedron{T}}(P, _face_polyhedron_facet, nfacets(P)) + n = face_dim - length(lineality_space(P)) + n < 0 && return nothing + pfaces = Polymake.to_one_based_indexing(Polymake.polytope.faces_of_dim(pm_object(P), n)) + farf = Polymake.to_one_based_indexing(pm_object(P).FAR_FACE) + rfaces = Vector{Int}(filter(i -> !(pfaces[i] <= farf), range(1, length(pfaces); step=1))) + return SubObjectIterator{Polyhedron{T}}( + P, _face_polyhedron, length(rfaces), (f_dim=n, f_ind=rfaces) + ) end -function _face_polyhedron(::Type{Polyhedron{T}}, P::Polyhedron{T}, i::Base.Integer; f_dim::Int = -1, f_ind::Vector{Int64} = Vector{Int64}()) where T<:scalar_types - pface = Polymake.to_one_based_indexing(Polymake.polytope.faces_of_dim(pm_object(P), f_dim))[f_ind[i]] +function _face_polyhedron( + ::Type{Polyhedron{T}}, + P::Polyhedron{T}, + i::Base.Integer; + f_dim::Int=-1, + f_ind::Vector{Int64}=Vector{Int64}(), +) where {T<:scalar_types} + pface = Polymake.to_one_based_indexing( + Polymake.polytope.faces_of_dim(pm_object(P), f_dim) + )[f_ind[i]] V = pm_object(P).VERTICES[collect(pface), :] L = pm_object(P).LINEALITY_SPACE PT = _scalar_type_to_polymake(T) - return Polyhedron{T}(Polymake.polytope.Polytope{PT}(VERTICES = V, LINEALITY_SPACE = L), coefficient_field(P)) + return Polyhedron{T}( + Polymake.polytope.Polytope{PT}(; VERTICES=V, LINEALITY_SPACE=L), coefficient_field(P) + ) end -function _vertex_indices(::Val{_face_polyhedron}, P::Polyhedron; f_dim = -1, f_ind::Vector{Int64} = Vector{Int64}()) - return IncidenceMatrix(collect.(Polymake.to_one_based_indexing(Polymake.polytope.faces_of_dim(pm_object(P), f_dim)[f_ind])))[:, _vertex_indices(pm_object(P))] +function _vertex_indices( + ::Val{_face_polyhedron}, P::Polyhedron; f_dim=-1, f_ind::Vector{Int64}=Vector{Int64}() +) + return IncidenceMatrix( + collect.( + Polymake.to_one_based_indexing( + Polymake.polytope.faces_of_dim(pm_object(P), f_dim)[f_ind] + ) + ), + )[ + :, _vertex_indices(pm_object(P)) + ] end -function _ray_indices(::Val{_face_polyhedron}, P::Polyhedron; f_dim = -1, f_ind::Vector{Int64} = Vector{Int64}()) - return IncidenceMatrix(collect.(Polymake.to_one_based_indexing(Polymake.polytope.faces_of_dim(pm_object(P), f_dim)[f_ind])))[:, _ray_indices(pm_object(P))] +function _ray_indices( + ::Val{_face_polyhedron}, P::Polyhedron; f_dim=-1, f_ind::Vector{Int64}=Vector{Int64}() +) + return IncidenceMatrix( + collect.( + Polymake.to_one_based_indexing( + Polymake.polytope.faces_of_dim(pm_object(P), f_dim)[f_ind] + ) + ), + )[ + :, _ray_indices(pm_object(P)) + ] end -function _vertex_and_ray_indices(::Val{_face_polyhedron}, P::Polyhedron; f_dim = -1, f_ind::Vector{Int64} = Vector{Int64}()) - return IncidenceMatrix(collect.(Polymake.to_one_based_indexing(Polymake.polytope.faces_of_dim(pm_object(P), f_dim)[f_ind]))) +function _vertex_and_ray_indices( + ::Val{_face_polyhedron}, P::Polyhedron; f_dim=-1, f_ind::Vector{Int64}=Vector{Int64}() +) + return IncidenceMatrix( + collect.( + Polymake.to_one_based_indexing( + Polymake.polytope.faces_of_dim(pm_object(P), f_dim)[f_ind] + ) + ), + ) end _incidencematrix(::Val{_face_polyhedron}) = _vertex_and_ray_indices -function _face_polyhedron_facet(::Type{Polyhedron{T}}, P::Polyhedron{T}, i::Base.Integer) where T<:scalar_types +function _face_polyhedron_facet( + ::Type{Polyhedron{T}}, P::Polyhedron{T}, i::Base.Integer +) where {T<:scalar_types} pface = pm_object(P).VERTICES_IN_FACETS[_facet_index(pm_object(P), i), :] V = pm_object(P).VERTICES[collect(pface), :] L = pm_object(P).LINEALITY_SPACE PT = _scalar_type_to_polymake(T) - return Polyhedron{T}(Polymake.polytope.Polytope{PT}(VERTICES = V, LINEALITY_SPACE = L), coefficient_field(P)) + return Polyhedron{T}( + Polymake.polytope.Polytope{PT}(; VERTICES=V, LINEALITY_SPACE=L), coefficient_field(P) + ) end -_vertex_indices(::Val{_face_polyhedron_facet}, P::Polyhedron) = vcat(pm_object(P).VERTICES_IN_FACETS[1:(_facet_at_infinity(pm_object(P)) - 1), _vertex_indices(pm_object(P))], pm_object(P).VERTICES_IN_FACETS[(_facet_at_infinity(pm_object(P)) + 1):end, _vertex_indices(pm_object(P))]) - -_ray_indices(::Val{_face_polyhedron_facet}, P::Polyhedron) = vcat(pm_object(P).VERTICES_IN_FACETS[1:(_facet_at_infinity(pm_object(P)) - 1), _ray_indices(pm_object(P))], pm_object(P).VERTICES_IN_FACETS[(_facet_at_infinity(pm_object(P)) + 1):end, _ray_indices(pm_object(P))]) - -_vertex_and_ray_indices(::Val{_face_polyhedron_facet}, P::Polyhedron) = vcat(pm_object(P).VERTICES_IN_FACETS[1:(_facet_at_infinity(pm_object(P)) - 1), :], pm_object(P).VERTICES_IN_FACETS[(_facet_at_infinity(pm_object(P)) + 1):end, :]) +_vertex_indices(::Val{_face_polyhedron_facet}, P::Polyhedron) = vcat( + pm_object(P).VERTICES_IN_FACETS[ + 1:(_facet_at_infinity(pm_object(P)) - 1), _vertex_indices(pm_object(P)) + ], + pm_object(P).VERTICES_IN_FACETS[ + (_facet_at_infinity(pm_object(P)) + 1):end, _vertex_indices(pm_object(P)) + ], +) + +_ray_indices(::Val{_face_polyhedron_facet}, P::Polyhedron) = vcat( + pm_object(P).VERTICES_IN_FACETS[ + 1:(_facet_at_infinity(pm_object(P)) - 1), _ray_indices(pm_object(P)) + ], + pm_object(P).VERTICES_IN_FACETS[ + (_facet_at_infinity(pm_object(P)) + 1):end, _ray_indices(pm_object(P)) + ], +) + +_vertex_and_ray_indices(::Val{_face_polyhedron_facet}, P::Polyhedron) = vcat( + pm_object(P).VERTICES_IN_FACETS[1:(_facet_at_infinity(pm_object(P)) - 1), :], + pm_object(P).VERTICES_IN_FACETS[(_facet_at_infinity(pm_object(P)) + 1):end, :], +) _incidencematrix(::Val{_face_polyhedron_facet}) = _vertex_and_ray_indices function _isray(P::Polyhedron, i::Base.Integer) - return in(i, _ray_indices(pm_object(P))) + return in(i, _ray_indices(pm_object(P))) end function _vertex_indices(P::Polymake.BigObject) - vi = Polymake.get_attachment(P, "_vertex_indices") - if isnothing(vi) - A = P.VERTICES - vi = Polymake.Vector{Polymake.to_cxx_type(Int64)}(findall(!iszero, view(A, :, 1))) - Polymake.attach(P, "_vertex_indices", vi) - end - return vi + vi = Polymake.get_attachment(P, "_vertex_indices") + if isnothing(vi) + A = P.VERTICES + vi = Polymake.Vector{Polymake.to_cxx_type(Int64)}(findall(!iszero, view(A, :, 1))) + Polymake.attach(P, "_vertex_indices", vi) + end + return vi end _ray_indices(P::Polymake.BigObject) = collect(Polymake.to_one_based_indexing(P.FAR_FACE)) function _polymake_to_oscar_vertex_index(P::Polymake.BigObject, i::Base.Integer) - return i - sum((>).(i, P.FAR_FACE)) + return i - sum((>).(i, P.FAR_FACE)) end function _polymake_to_oscar_vertex_index(P::Polymake.BigObject, v::AbstractVector) - return [_polymake_to_oscar_vertex_index(P, v[i]) for i in 1:length(v)] + return [_polymake_to_oscar_vertex_index(P, v[i]) for i in 1:length(v)] end function _polymake_to_oscar_ray_index(P::Polymake.BigObject, i::Base.Integer) - return sum((<).(i, P.FAR_FACE)) + return sum((<).(i, P.FAR_FACE)) end function _polymake_to_oscar_ray_index(P::Polymake.BigObject, v::AbstractVector) - return [_polymake_to_oscar_ray_index(P, v[i]) for i in 1:length(v)] + return [_polymake_to_oscar_ray_index(P, v[i]) for i in 1:length(v)] end - @doc raw""" minimal_faces(as, P::Polyhedron) @@ -132,17 +193,26 @@ julia> minimal_faces(P) (base_points = PointVector{QQFieldElem}[[0, 0]], lineality_basis = RayVector{QQFieldElem}[[1, 0]]) ``` """ -minimal_faces(P::Polyhedron{T}) where T<:scalar_types = minimal_faces(NamedTuple{(:base_points, :lineality_basis), Tuple{SubObjectIterator{PointVector{T}}, SubObjectIterator{RayVector{T}}}}, P) -function minimal_faces(::Type{NamedTuple{(:base_points, :lineality_basis), Tuple{SubObjectIterator{PointVector{T}}, SubObjectIterator{RayVector{T}}}}}, P::Polyhedron{T}) where T<:scalar_types - return ( - base_points = _vertices(PointVector{T}, P), - lineality_basis = lineality_space(P) - ) +minimal_faces(P::Polyhedron{T}) where {T<:scalar_types} = minimal_faces( + NamedTuple{ + (:base_points, :lineality_basis), + Tuple{SubObjectIterator{PointVector{T}},SubObjectIterator{RayVector{T}}}, + }, + P, +) +function minimal_faces( + ::Type{ + NamedTuple{ + (:base_points, :lineality_basis), + Tuple{SubObjectIterator{PointVector{T}},SubObjectIterator{RayVector{T}}}, + }, + }, + P::Polyhedron{T}, +) where {T<:scalar_types} + return (base_points=_vertices(PointVector{T}, P), lineality_basis=lineality_space(P)) end minimal_faces(::Type{<:PointVector}, P::Polyhedron) = _vertices(P) - - @doc raw""" rays_modulo_lineality(as, P::Polyhedron) @@ -168,16 +238,26 @@ julia> rmlP.lineality_basis [1, 0, 0] ``` """ -rays_modulo_lineality(P::Polyhedron{T}) where T<:scalar_types = rays_modulo_lineality(NamedTuple{(:rays_modulo_lineality, :lineality_basis), Tuple{SubObjectIterator{RayVector{T}}, SubObjectIterator{RayVector{T}}}}, P) -function rays_modulo_lineality(::Type{NamedTuple{(:rays_modulo_lineality, :lineality_basis), Tuple{SubObjectIterator{RayVector{T}}, SubObjectIterator{RayVector{T}}}}}, P::Polyhedron{T}) where T<:scalar_types - return ( - rays_modulo_lineality = _rays(P), - lineality_basis = lineality_space(P) - ) +rays_modulo_lineality(P::Polyhedron{T}) where {T<:scalar_types} = rays_modulo_lineality( + NamedTuple{ + (:rays_modulo_lineality, :lineality_basis), + Tuple{SubObjectIterator{RayVector{T}},SubObjectIterator{RayVector{T}}}, + }, + P, +) +function rays_modulo_lineality( + ::Type{ + NamedTuple{ + (:rays_modulo_lineality, :lineality_basis), + Tuple{SubObjectIterator{RayVector{T}},SubObjectIterator{RayVector{T}}}, + }, + }, + P::Polyhedron{T}, +) where {T<:scalar_types} + return (rays_modulo_lineality=_rays(P), lineality_basis=lineality_space(P)) end rays_modulo_lineality(::Type{<:RayVector}, P::Polyhedron) = _rays(P) - @doc raw""" vertices(as, P) @@ -203,29 +283,47 @@ julia> vertices(PointVector, P) [1, 2] ``` """ -vertices(as::Type{PointVector{T}}, P::Polyhedron{T}) where T<:scalar_types = lineality_dim(P) == 0 ? _vertices(as, P) : _empty_subobjectiterator(as, P) -_vertices(as::Type{PointVector{T}}, P::Polyhedron{T}) where T<:scalar_types = SubObjectIterator{as}(P, _vertex_polyhedron, length(_vertex_indices(pm_object(P)))) +vertices(as::Type{PointVector{T}}, P::Polyhedron{T}) where {T<:scalar_types} = + lineality_dim(P) == 0 ? _vertices(as, P) : _empty_subobjectiterator(as, P) +_vertices(as::Type{PointVector{T}}, P::Polyhedron{T}) where {T<:scalar_types} = + SubObjectIterator{as}(P, _vertex_polyhedron, length(_vertex_indices(pm_object(P)))) -_vertex_polyhedron(U::Type{PointVector{T}}, P::Polyhedron{T}, i::Base.Integer) where T<:scalar_types = point_vector(coefficient_field(P), @view pm_object(P).VERTICES[_vertex_indices(pm_object(P))[i], 2:end])::U +_vertex_polyhedron( + U::Type{PointVector{T}}, P::Polyhedron{T}, i::Base.Integer +) where {T<:scalar_types} = point_vector( + coefficient_field(P), + @view pm_object(P).VERTICES[_vertex_indices(pm_object(P))[i], 2:end] +)::U -_point_matrix(::Val{_vertex_polyhedron}, P::Polyhedron; homogenized=false) = @view pm_object(P).VERTICES[_vertex_indices(pm_object(P)), (homogenized ? 1 : 2):end] +_point_matrix(::Val{_vertex_polyhedron}, P::Polyhedron; homogenized=false) = + @view pm_object(P).VERTICES[_vertex_indices(pm_object(P)), (homogenized ? 1 : 2):end] _matrix_for_polymake(::Val{_vertex_polyhedron}) = _point_matrix -vertices(::Type{<:PointVector}, P::Polyhedron{T}) where T<:scalar_types = vertices(PointVector{T}, P) -_vertices(::Type{<:PointVector}, P::Polyhedron{T}) where T<:scalar_types = _vertices(PointVector{T}, P) +vertices(::Type{<:PointVector}, P::Polyhedron{T}) where {T<:scalar_types} = + vertices(PointVector{T}, P) +_vertices(::Type{<:PointVector}, P::Polyhedron{T}) where {T<:scalar_types} = + _vertices(PointVector{T}, P) -_facet_indices(::Val{_vertex_polyhedron}, P::Polyhedron) = pm_object(P).FACETS_THRU_VERTICES[_vertex_indices(pm_object(P)),_facet_indices(pm_object(P))] +_facet_indices(::Val{_vertex_polyhedron}, P::Polyhedron) = + pm_object(P).FACETS_THRU_VERTICES[ + _vertex_indices(pm_object(P)), _facet_indices(pm_object(P)) + ] _incidencematrix(::Val{_vertex_polyhedron}) = _facet_indices function _facet_indices(P::Polymake.BigObject) - vi = Polymake.get_attachment(P, "_facet_indices") - if isnothing(vi) - vi = Polymake.Vector{Polymake.to_cxx_type(Int64)}([collect(1:(_facet_at_infinity(P) - 1)); collect((_facet_at_infinity(P) + 1):size(P.FACETS, 1))]) - Polymake.attach(P, "_facet_indices", vi); - end - return vi; + vi = Polymake.get_attachment(P, "_facet_indices") + if isnothing(vi) + vi = Polymake.Vector{Polymake.to_cxx_type(Int64)}( + [ + collect(1:(_facet_at_infinity(P) - 1)) + collect((_facet_at_infinity(P) + 1):size(P.FACETS, 1)) + ], + ) + Polymake.attach(P, "_facet_indices", vi) + end + return vi end @doc raw""" @@ -251,7 +349,6 @@ julia> vertices(P) vertices(P::Polyhedron) = vertices(PointVector, P) _vertices(P::Polyhedron) = _vertices(PointVector, P) - @doc raw""" nrays(P::Polyhedron) @@ -295,7 +392,6 @@ julia> nvertices(C) nvertices(P::Polyhedron)::Int = lineality_dim(P) == 0 ? _nvertices(P) : 0 _nvertices(P::Polyhedron) = size(pm_object(P).VERTICES, 1)::Int - _nrays(P) - @doc raw""" rays(as::Type{T} = RayVector, P::Polyhedron) @@ -317,21 +413,30 @@ julia> rays(RayVector, PO) [0, 1] ``` """ -rays(as::Type{RayVector{T}}, P::Polyhedron{T}) where T<:scalar_types = lineality_dim(P) == 0 ? _rays(as, P) : _empty_subobjectiterator(as, P) -_rays(as::Type{RayVector{T}}, P::Polyhedron{T}) where T<:scalar_types = SubObjectIterator{as}(P, _ray_polyhedron, length(_ray_indices(pm_object(P)))) +rays(as::Type{RayVector{T}}, P::Polyhedron{T}) where {T<:scalar_types} = + lineality_dim(P) == 0 ? _rays(as, P) : _empty_subobjectiterator(as, P) +_rays(as::Type{RayVector{T}}, P::Polyhedron{T}) where {T<:scalar_types} = + SubObjectIterator{as}(P, _ray_polyhedron, length(_ray_indices(pm_object(P)))) -_ray_polyhedron(U::Type{RayVector{T}}, P::Polyhedron{T}, i::Base.Integer) where T<:scalar_types = ray_vector(coefficient_field(P), @view pm_object(P).VERTICES[_ray_indices(pm_object(P))[i], 2:end])::U +_ray_polyhedron( + U::Type{RayVector{T}}, P::Polyhedron{T}, i::Base.Integer +) where {T<:scalar_types} = ray_vector( + coefficient_field(P), @view pm_object(P).VERTICES[_ray_indices(pm_object(P))[i], 2:end] +)::U -_facet_indices(::Val{_ray_polyhedron}, P::Polyhedron) = pm_object(P).FACETS_THRU_RAYS[_ray_indices(pm_object(P)), _facet_indices(pm_object(P))] +_facet_indices(::Val{_ray_polyhedron}, P::Polyhedron) = + pm_object(P).FACETS_THRU_RAYS[_ray_indices(pm_object(P)), _facet_indices(pm_object(P))] -_vector_matrix(::Val{_ray_polyhedron}, P::Polyhedron; homogenized=false) = @view pm_object(P).VERTICES[_ray_indices(pm_object(P)), (homogenized ? 1 : 2):end] +_vector_matrix(::Val{_ray_polyhedron}, P::Polyhedron; homogenized=false) = + @view pm_object(P).VERTICES[_ray_indices(pm_object(P)), (homogenized ? 1 : 2):end] _matrix_for_polymake(::Val{_ray_polyhedron}) = _vector_matrix _incidencematrix(::Val{_ray_polyhedron}) = _facet_indices -rays(::Type{<:RayVector}, P::Polyhedron{T}) where T<:scalar_types = rays(RayVector{T}, P) -_rays(::Type{<:RayVector}, P::Polyhedron{T}) where T<:scalar_types = _rays(RayVector{T}, P) +rays(::Type{<:RayVector}, P::Polyhedron{T}) where {T<:scalar_types} = rays(RayVector{T}, P) +_rays(::Type{<:RayVector}, P::Polyhedron{T}) where {T<:scalar_types} = + _rays(RayVector{T}, P) @doc raw""" rays(P::Polyhedron) @@ -376,8 +481,8 @@ julia> nfacets(cross_polytope(5)) ``` """ function nfacets(P::Polyhedron) - n = size(pm_object(P).FACETS, 1)::Int - return n - (_facet_at_infinity(pm_object(P)) != n + 1) + n = size(pm_object(P).FACETS, 1)::Int + return n - (_facet_at_infinity(pm_object(P)) != n + 1) end @doc raw""" @@ -414,36 +519,68 @@ x_2 <= 1 x_3 <= 1 ``` """ -facets(as::Type{T}, P::Polyhedron{S}) where {R, S<:scalar_types, T<:Union{AffineHalfspace{S}, Pair{R, S}, Polyhedron{S}}} = SubObjectIterator{as}(P, _facet_polyhedron, nfacets(P)) - -function _facet_polyhedron(U::Type{AffineHalfspace{S}}, P::Polyhedron{S}, i::Base.Integer) where S<:scalar_types +facets( + as::Type{T}, P::Polyhedron{S} +) where {R,S<:scalar_types,T<:Union{AffineHalfspace{S},Pair{R,S},Polyhedron{S}}} = + SubObjectIterator{as}(P, _facet_polyhedron, nfacets(P)) + +function _facet_polyhedron( + U::Type{AffineHalfspace{S}}, P::Polyhedron{S}, i::Base.Integer +) where {S<:scalar_types} h = decompose_hdata(view(pm_object(P).FACETS, [_facet_index(pm_object(P), i)], :)) return affine_halfspace(coefficient_field(P), h[1], h[2][])::U end -function _facet_polyhedron(U::Type{Pair{R, S}}, P::Polyhedron{S}, i::Base.Integer) where {R, S<:scalar_types} +function _facet_polyhedron( + U::Type{Pair{R,S}}, P::Polyhedron{S}, i::Base.Integer +) where {R,S<:scalar_types} f = coefficient_field(P) h = decompose_hdata(view(pm_object(P).FACETS, [_facet_index(pm_object(P), i)], :)) return U(f.(view(h[1], :, :)), f(h[2][])) # view_broadcast end -function _facet_polyhedron(::Type{Polyhedron{T}}, P::Polyhedron{T}, i::Base.Integer) where T<:scalar_types - return Polyhedron{T}(Polymake.polytope.facet(pm_object(P), _facet_index(pm_object(P), i) - 1), coefficient_field(P)) +function _facet_polyhedron( + ::Type{Polyhedron{T}}, P::Polyhedron{T}, i::Base.Integer +) where {T<:scalar_types} + return Polyhedron{T}( + Polymake.polytope.facet(pm_object(P), _facet_index(pm_object(P), i) - 1), + coefficient_field(P), + ) end -_affine_inequality_matrix(::Val{_facet_polyhedron}, P::Polyhedron) = -_remove_facet_at_infinity(pm_object(P)) +_affine_inequality_matrix(::Val{_facet_polyhedron}, P::Polyhedron) = + -_remove_facet_at_infinity(pm_object(P)) _affine_matrix_for_polymake(::Val{_facet_polyhedron}) = _affine_inequality_matrix -_vertex_indices(::Val{_facet_polyhedron}, P::Polyhedron) = vcat(pm_object(P).VERTICES_IN_FACETS[1:(_facet_at_infinity(pm_object(P)) - 1), _vertex_indices(pm_object(P))], pm_object(P).VERTICES_IN_FACETS[(_facet_at_infinity(pm_object(P)) + 1):end, _vertex_indices(pm_object(P))]) - -_ray_indices(::Val{_facet_polyhedron}, P::Polyhedron) = vcat(pm_object(P).VERTICES_IN_FACETS[1:(_facet_at_infinity(pm_object(P)) - 1), _ray_indices(pm_object(P))], pm_object(P).VERTICES_IN_FACETS[(_facet_at_infinity(pm_object(P)) + 1):end, _ray_indices(pm_object(P))]) - -_vertex_and_ray_indices(::Val{_facet_polyhedron}, P::Polyhedron) = vcat(pm_object(P).VERTICES_IN_FACETS[1:(_facet_at_infinity(pm_object(P)) - 1), :], pm_object(P).VERTICES_IN_FACETS[(_facet_at_infinity(pm_object(P)) + 1):end, :]) +_vertex_indices(::Val{_facet_polyhedron}, P::Polyhedron) = vcat( + pm_object(P).VERTICES_IN_FACETS[ + 1:(_facet_at_infinity(pm_object(P)) - 1), _vertex_indices(pm_object(P)) + ], + pm_object(P).VERTICES_IN_FACETS[ + (_facet_at_infinity(pm_object(P)) + 1):end, _vertex_indices(pm_object(P)) + ], +) + +_ray_indices(::Val{_facet_polyhedron}, P::Polyhedron) = vcat( + pm_object(P).VERTICES_IN_FACETS[ + 1:(_facet_at_infinity(pm_object(P)) - 1), _ray_indices(pm_object(P)) + ], + pm_object(P).VERTICES_IN_FACETS[ + (_facet_at_infinity(pm_object(P)) + 1):end, _ray_indices(pm_object(P)) + ], +) + +_vertex_and_ray_indices(::Val{_facet_polyhedron}, P::Polyhedron) = vcat( + pm_object(P).VERTICES_IN_FACETS[1:(_facet_at_infinity(pm_object(P)) - 1), :], + pm_object(P).VERTICES_IN_FACETS[(_facet_at_infinity(pm_object(P)) + 1):end, :], +) _incidencematrix(::Val{_facet_polyhedron}) = _vertex_and_ray_indices -facets(::Type{<:Pair}, P::Polyhedron{T}) where T<:scalar_types = facets(Pair{Matrix{T}, T}, P) +facets(::Type{<:Pair}, P::Polyhedron{T}) where {T<:scalar_types} = + facets(Pair{Matrix{T},T}, P) -facets(::Type{Polyhedron}, P::Polyhedron{T}) where T<:scalar_types = facets(Polyhedron{T}, P) +facets(::Type{Polyhedron}, P::Polyhedron{T}) where {T<:scalar_types} = + facets(Polyhedron{T}, P) @doc raw""" facets(P::Polyhedron) @@ -465,33 +602,41 @@ x_2 <= 1 x_3 <= 1 ``` """ -facets(P::Polyhedron{T}) where T<:scalar_types = facets(AffineHalfspace{T}, P) +facets(P::Polyhedron{T}) where {T<:scalar_types} = facets(AffineHalfspace{T}, P) -facets(::Type{<:Halfspace}, P::Polyhedron{T}) where T<:scalar_types = facets(AffineHalfspace{T}, P) +facets(::Type{<:Halfspace}, P::Polyhedron{T}) where {T<:scalar_types} = + facets(AffineHalfspace{T}, P) function _facet_index(P::Polymake.BigObject, i::Base.Integer) - i < _facet_at_infinity(P) && return i - return i + 1 + i < _facet_at_infinity(P) && return i + return i + 1 end function _facet_at_infinity(P::Polymake.BigObject) - fai = Polymake.get_attachment(P, "_facet_at_infinity") - m = size(P.FACETS,1) - if isnothing(fai) - i = 1 - while i <= m - _is_facet_at_infinity(view(P.FACETS, i, :)) && break - i += 1 - end - fai = i - Polymake.attach(P, "_facet_at_infinity", fai) + fai = Polymake.get_attachment(P, "_facet_at_infinity") + m = size(P.FACETS, 1) + if isnothing(fai) + i = 1 + while i <= m + _is_facet_at_infinity(view(P.FACETS, i, :)) && break + i += 1 end - return fai::Int64 + fai = i + Polymake.attach(P, "_facet_at_infinity", fai) + end + return fai::Int64 end _is_facet_at_infinity(v::AbstractVector) = v[1] >= 0 && iszero(v[2:end]) -_remove_facet_at_infinity(P::Polymake.BigObject) = view(P.FACETS, [collect(1:(_facet_at_infinity(P) - 1)); collect((_facet_at_infinity(P) + 1):size(P.FACETS, 1))], :) +_remove_facet_at_infinity(P::Polymake.BigObject) = view( + P.FACETS, + [ + collect(1:(_facet_at_infinity(P) - 1)) + collect((_facet_at_infinity(P) + 1):size(P.FACETS, 1)) + ], + :, +) ############################################################################### ############################################################################### @@ -520,7 +665,6 @@ julia> lineality_dim(C) """ lineality_dim(P::Polyhedron) = pm_object(P).LINEALITY_DIM::Int - @doc raw""" volume(P::Polyhedron) @@ -534,8 +678,8 @@ julia> volume(C) 4 ``` """ -volume(P::Polyhedron{T}) where T<:scalar_types = coefficient_field(P)((pm_object(P)).VOLUME) - +volume(P::Polyhedron{T}) where {T<:scalar_types} = + coefficient_field(P)((pm_object(P)).VOLUME) @doc raw""" lattice_volume(P::Polyhedron{QQFieldElem}) @@ -550,8 +694,8 @@ julia> lattice_volume(C) 8 ``` """ -lattice_volume(P::Polyhedron{QQFieldElem})::ZZRingElem = _assert_lattice(P) && pm_object(P).LATTICE_VOLUME - +lattice_volume(P::Polyhedron{QQFieldElem})::ZZRingElem = + _assert_lattice(P) && pm_object(P).LATTICE_VOLUME @doc raw""" normalized_volume(P::Polyhedron) @@ -566,8 +710,8 @@ julia> normalized_volume(C) 8 ``` """ -normalized_volume(P::Polyhedron) = coefficient_field(P)(factorial(dim(P))*(pm_object(P)).VOLUME) - +normalized_volume(P::Polyhedron) = + coefficient_field(P)(factorial(dim(P)) * (pm_object(P)).VOLUME) @doc raw""" dim(P::Polyhedron) @@ -586,7 +730,6 @@ julia> dim(P) """ dim(P::Polyhedron) = Polymake.polytope.dim(pm_object(P))::Int - @doc raw""" lattice_points(P::Polyhedron{QQFieldElem}) @@ -615,17 +758,21 @@ julia> matrix(ZZ, lattice_points(S)) ``` """ function lattice_points(P::Polyhedron{QQFieldElem}) - @req pm_object(P).BOUNDED "Polyhedron not bounded" - return SubObjectIterator{PointVector{ZZRingElem}}(P, _lattice_point, size(pm_object(P).LATTICE_POINTS_GENERATORS[1], 1)) + @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) = point_vector(ZZ, @view pm_object(P).LATTICE_POINTS_GENERATORS[1][i, 2:end])::T +_lattice_point( + T::Type{PointVector{ZZRingElem}}, P::Polyhedron{QQFieldElem}, 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) = @view pm_object(P).LATTICE_POINTS_GENERATORS[1][:, (homogenized ? 1 : 2):end] +_point_matrix(::Val{_lattice_point}, P::Polyhedron; homogenized=false) = + @view pm_object(P).LATTICE_POINTS_GENERATORS[1][:, (homogenized ? 1 : 2):end] _matrix_for_polymake(::Val{_lattice_point}) = _point_matrix - @doc raw""" interior_lattice_points(P::Polyhedron{QQFieldElem}) @@ -646,13 +793,22 @@ julia> matrix(ZZ, interior_lattice_points(c)) ``` """ function interior_lattice_points(P::Polyhedron{QQFieldElem}) - @req pm_object(P).BOUNDED "Polyhedron not bounded" - return SubObjectIterator{PointVector{ZZRingElem}}(P, _interior_lattice_point, size(pm_object(P).INTERIOR_LATTICE_POINTS, 1)) + @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) = point_vector(ZZ, @view pm_object(P).INTERIOR_LATTICE_POINTS[i, 2:end])::T +_interior_lattice_point( + T::Type{PointVector{ZZRingElem}}, P::Polyhedron{QQFieldElem}, 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) = homogenized ? pm_object(P).INTERIOR_LATTICE_POINTS : @view pm_object(P).INTERIOR_LATTICE_POINTS[:, 2:end] +_point_matrix(::Val{_interior_lattice_point}, P::Polyhedron; homogenized=false) = + if homogenized + pm_object(P).INTERIOR_LATTICE_POINTS + else + @view pm_object(P).INTERIOR_LATTICE_POINTS[:, 2:end] + end _matrix_for_polymake(::Val{_interior_lattice_point}) = _point_matrix @@ -686,13 +842,22 @@ julia> matrix(ZZ, boundary_lattice_points(c)) ``` """ function boundary_lattice_points(P::Polyhedron{QQFieldElem}) - @req pm_object(P).BOUNDED "Polyhedron not bounded" - return SubObjectIterator{PointVector{ZZRingElem}}(P, _boundary_lattice_point, size(pm_object(P).BOUNDARY_LATTICE_POINTS, 1)) + @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) = point_vector(ZZ, @view pm_object(P).BOUNDARY_LATTICE_POINTS[i, 2:end])::T +_boundary_lattice_point( + T::Type{PointVector{ZZRingElem}}, P::Polyhedron{QQFieldElem}, 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) = homogenized ? pm_object(P).BOUNDARY_LATTICE_POINTS : @view pm_object(P).BOUNDARY_LATTICE_POINTS[:, 2:end] +_point_matrix(::Val{_boundary_lattice_point}, P::Polyhedron; homogenized=false) = + if homogenized + pm_object(P).BOUNDARY_LATTICE_POINTS + else + @view pm_object(P).BOUNDARY_LATTICE_POINTS[:, 2:end] + end _matrix_for_polymake(::Val{_boundary_lattice_point}) = _point_matrix @@ -713,7 +878,6 @@ julia> ambient_dim(P) """ ambient_dim(P::Polyhedron) = Polymake.polytope.ambient_dim(pm_object(P))::Int - @doc raw""" codim(P::Polyhedron) @@ -729,7 +893,7 @@ julia> codim(P) 1 ``` """ -codim(P::Polyhedron) = ambient_dim(P)-dim(P) +codim(P::Polyhedron) = ambient_dim(P) - dim(P) @doc raw""" facet_sizes(P::Polyhedron{T}) @@ -755,7 +919,7 @@ julia> facet_sizes(p) 4 ``` """ -function facet_sizes(P::Polyhedron{T}) where T<:scalar_types +function facet_sizes(P::Polyhedron{T}) where {T<:scalar_types} im = vertex_indices(facets(P)) return [length(row(im, i)) for i in 1:nrows(im)] end @@ -776,11 +940,13 @@ julia> vertex_sizes(bipyramid(simplex(2))) 3 ``` """ -function vertex_sizes(P::Polyhedron{T}) where T<:scalar_types +function vertex_sizes(P::Polyhedron{T}) where {T<:scalar_types} pm_object(P).LINEALITY_DIM > 0 && return Vector{Int}() res = Vector{Int}(pm_object(P).VERTEX_SIZES) - vertices = Polymake.to_one_based_indexing(Polymake.polytope.bounded_vertices(pm_object(P))) + vertices = Polymake.to_one_based_indexing( + Polymake.polytope.bounded_vertices(pm_object(P)) + ) return res[collect(vertices)] end @@ -788,7 +954,6 @@ end ## Points properties ############################################################################### - # Previously: This implementation is not correct. Ask Taylor. # Taylor: lineality space generators always look like [0, v] so # v is a natural output. @@ -808,15 +973,19 @@ julia> lineality_space(UH) [1, 0] ``` """ -lineality_space(P::Polyhedron{T}) where T<:scalar_types = SubObjectIterator{RayVector{T}}(P, _lineality_polyhedron, lineality_dim(P)) +lineality_space(P::Polyhedron{T}) where {T<:scalar_types} = + SubObjectIterator{RayVector{T}}(P, _lineality_polyhedron, lineality_dim(P)) -_lineality_polyhedron(U::Type{RayVector{T}}, P::Polyhedron{T}, i::Base.Integer) where T<:scalar_types = ray_vector(coefficient_field(P), @view pm_object(P).LINEALITY_SPACE[i, 2:end])::U +_lineality_polyhedron( + U::Type{RayVector{T}}, P::Polyhedron{T}, i::Base.Integer +) where {T<:scalar_types} = + ray_vector(coefficient_field(P), @view pm_object(P).LINEALITY_SPACE[i, 2:end])::U -_generator_matrix(::Val{_lineality_polyhedron}, P::Polyhedron; homogenized=false) = homogenized ? pm_object(P).LINEALITY_SPACE : @view pm_object(P).LINEALITY_SPACE[:, 2:end] +_generator_matrix(::Val{_lineality_polyhedron}, P::Polyhedron; homogenized=false) = + homogenized ? pm_object(P).LINEALITY_SPACE : @view pm_object(P).LINEALITY_SPACE[:, 2:end] _matrix_for_polymake(::Val{_lineality_polyhedron}) = _generator_matrix - @doc raw""" affine_hull(P::Polytope) @@ -834,9 +1003,12 @@ x_3 = 2 x_4 = 5 ``` """ -affine_hull(P::Polyhedron{T}) where T<:scalar_types = SubObjectIterator{AffineHyperplane{T}}(P, _affine_hull, size(pm_object(P).AFFINE_HULL, 1)) +affine_hull(P::Polyhedron{T}) where {T<:scalar_types} = + SubObjectIterator{AffineHyperplane{T}}(P, _affine_hull, size(pm_object(P).AFFINE_HULL, 1)) -function _affine_hull(U::Type{AffineHyperplane{T}}, P::Polyhedron{T}, i::Base.Integer) where T<:scalar_types +function _affine_hull( + U::Type{AffineHyperplane{T}}, P::Polyhedron{T}, i::Base.Integer +) where {T<:scalar_types} h = decompose_hdata(-view(pm_object(P).AFFINE_HULL, [i], :)) return affine_hyperplane(coefficient_field(P), h[1], h[2][])::U end @@ -845,7 +1017,6 @@ _affine_equation_matrix(::Val{_affine_hull}, P::Polyhedron) = pm_object(P).AFFIN _affine_matrix_for_polymake(::Val{_affine_hull}) = _affine_equation_matrix - @doc raw""" recession_cone(P::Polyhedron) @@ -870,8 +1041,8 @@ julia> rays(recession_cone(P)) [1, 1] ``` """ -recession_cone(P::Polyhedron{T}) where T<:scalar_types = Cone{T}(Polymake.polytope.recession_cone(pm_object(P)), coefficient_field(P)) - +recession_cone(P::Polyhedron{T}) where {T<:scalar_types} = + Cone{T}(Polymake.polytope.recession_cone(pm_object(P)), coefficient_field(P)) @doc raw""" ehrhart_polynomial(P::Polyhedron{QQFieldElem}) @@ -888,11 +1059,10 @@ julia> ehrhart_polynomial(c) ``` """ function ehrhart_polynomial(P::Polyhedron{QQFieldElem}) - R, x = polynomial_ring(QQ, "x") - return ehrhart_polynomial(R, P) + R, x = polynomial_ring(QQ, "x") + return ehrhart_polynomial(R, P) end - @doc raw""" ehrhart_polynomial(R::QQMPolyRing, P::Polyhedron{QQFieldElem}) @@ -916,7 +1086,6 @@ function ehrhart_polynomial(R::QQPolyRing, P::Polyhedron{QQFieldElem}) return (R)(Vector{QQFieldElem}(coeffs)) end - @doc raw""" h_star_polynomial(P::Polyhedron) @@ -932,11 +1101,10 @@ x^3 + 23*x^2 + 23*x + 1 ``` """ function h_star_polynomial(P::Polyhedron{QQFieldElem}) - R, x = polynomial_ring(QQ, "x") - return h_star_polynomial(R, P) + R, x = polynomial_ring(QQ, "x") + return h_star_polynomial(R, P) end - @doc raw""" h_star_polynomial(R::QQMPolyRing, P::Polyhedron) @@ -955,8 +1123,8 @@ x^3 + 23*x^2 + 23*x + 1 ``` """ function h_star_polynomial(R::QQPolyRing, P::Polyhedron{QQFieldElem}) - coeffs = pm_object(P).H_STAR_VECTOR - return (R)(Vector{QQFieldElem}(coeffs)) + coeffs = pm_object(P).H_STAR_VECTOR + return (R)(Vector{QQFieldElem}(coeffs)) end ############################################################################### @@ -982,12 +1150,13 @@ julia> is_lattice_polytope(c) false ``` """ -is_lattice_polytope(P::Polyhedron{QQFieldElem}) = (is_bounded(P) && pm_object(P).LATTICE)::Bool +is_lattice_polytope(P::Polyhedron{QQFieldElem}) = + (is_bounded(P) && pm_object(P).LATTICE)::Bool -_assert_lattice(P::Polyhedron{QQFieldElem}) = is_lattice_polytope(P) || +_assert_lattice(P::Polyhedron{QQFieldElem}) = + is_lattice_polytope(P) || throw(ArgumentError("This is only defined for lattice polytopes.")) - @doc raw""" is_very_ample(P::Polyhedron{QQFieldElem}) @@ -1008,8 +1177,8 @@ julia> is_very_ample(P) false ``` """ -is_very_ample(P::Polyhedron{QQFieldElem}) = _assert_lattice(P) && pm_object(P).VERY_AMPLE::Bool - +is_very_ample(P::Polyhedron{QQFieldElem}) = + _assert_lattice(P) && pm_object(P).VERY_AMPLE::Bool @doc raw""" is_feasible(P::Polyhedron) @@ -1026,7 +1195,6 @@ false """ is_feasible(P::Polyhedron) = pm_object(P).FEASIBLE::Bool - @doc raw""" issubset(P::Polyhedron, Q::Polyhedron) @@ -1047,8 +1215,8 @@ julia> issubset(Q, P) false ``` """ -Base.issubset(P::Polyhedron{T}, Q::Polyhedron{T}) where T<:scalar_types = Polymake.polytope.included_polyhedra(pm_object(P), pm_object(Q))::Bool - +Base.issubset(P::Polyhedron{T}, Q::Polyhedron{T}) where {T<:scalar_types} = + Polymake.polytope.included_polyhedra(pm_object(P), pm_object(Q))::Bool @doc raw""" in(v::AbstractVector, P::Polyhedron) @@ -1067,8 +1235,8 @@ julia> [1, -2] in PO false ``` """ -Base.in(v::AbstractVector, P::Polyhedron) = Polymake.polytope.contains(pm_object(P), coefficient_field(P).([1; v]))::Bool - +Base.in(v::AbstractVector, P::Polyhedron) = + Polymake.polytope.contains(pm_object(P), coefficient_field(P).([1; v]))::Bool @doc raw""" is_smooth(P::Polyhedron{QQFieldElem}) @@ -1086,7 +1254,6 @@ true """ is_smooth(P::Polyhedron{QQFieldElem}) = _assert_lattice(P) && pm_object(P).SMOOTH::Bool - @doc raw""" is_normal(P::Polyhedron{QQFieldElem}) @@ -1111,7 +1278,6 @@ false """ is_normal(P::Polyhedron{QQFieldElem}) = _assert_lattice(P) && pm_object(P).NORMAL::Bool - @doc raw""" is_bounded(P::Polyhedron) @@ -1127,7 +1293,6 @@ false """ is_bounded(P::Polyhedron) = pm_object(P).BOUNDED::Bool - @doc raw""" is_simple(P::Polyhedron) @@ -1144,7 +1309,6 @@ true """ is_simple(P::Polyhedron) = pm_object(P).SIMPLE::Bool - @doc raw""" is_simplicial(P::Polyhedron) @@ -1152,7 +1316,6 @@ Check whether `P` is simplicial. """ is_simplicial(P::Polyhedron) = pm_object(P).SIMPLICIAL::Bool - @doc raw""" is_fulldimensional(P::Polyhedron) @@ -1168,7 +1331,6 @@ false """ is_fulldimensional(P::Polyhedron) = pm_object(P).FULL_DIM::Bool - @doc raw""" f_vector(P::Polyhedron) @@ -1188,11 +1350,11 @@ julia> f_vector(cube(5)) ``` """ function f_vector(P::Polyhedron)::Vector{ZZRingElem} - # the following differs from polymake's count in the unbounded case; - # polymake takes the far face into account, too - ldim = lineality_dim(P) - f_vec=vcat(zeros(Int64, ldim), [length(faces(P,i)) for i in ldim:dim(P)-1]) - return f_vec + # the following differs from polymake's count in the unbounded case; + # polymake takes the far face into account, too + ldim = lineality_dim(P) + f_vec = vcat(zeros(Int64, ldim), [length(faces(P, i)) for i in ldim:(dim(P) - 1)]) + return f_vec end @doc raw""" @@ -1213,11 +1375,10 @@ julia> h_vector(cross_polytope(3)) ``` """ function h_vector(P::Polyhedron)::Vector{ZZRingElem} - @req is_bounded(P) "defined for bounded polytopes only" - return pm_object(P).H_VECTOR + @req is_bounded(P) "defined for bounded polytopes only" + return pm_object(P).H_VECTOR end - @doc raw""" g_vector(P::Polyhedron) @@ -1234,11 +1395,10 @@ julia> g_vector(cross_polytope(3)) ``` """ function g_vector(P::Polyhedron)::Vector{ZZRingElem} - @req is_bounded(P) "defined for bounded polytopes only" - return pm_object(P).G_VECTOR + @req is_bounded(P) "defined for bounded polytopes only" + return pm_object(P).G_VECTOR end - @doc raw""" relative_interior_point(P::Polyhedron) @@ -1270,8 +1430,10 @@ julia> matrix(QQ, vertices(square)) [ 1 1] ``` """ -relative_interior_point(P::Polyhedron{T}) where T<:scalar_types = point_vector(coefficient_field(P), view(dehomogenize(Polymake.common.dense(pm_object(P).REL_INT_POINT)), :))::PointVector{T} #view_broadcast - +relative_interior_point(P::Polyhedron{T}) where {T<:scalar_types} = point_vector( + coefficient_field(P), + view(dehomogenize(Polymake.common.dense(pm_object(P).REL_INT_POINT)), :), +)::PointVector{T} #view_broadcast @doc raw""" support_function(P::Polyhedron; convention::Symbol = :max) @@ -1294,15 +1456,14 @@ julia> ψ([1,2,3]) -6 ``` """ -function support_function(P::Polyhedron{T}; convention = :max) where T<:scalar_types - function h(ω::AbstractVector) - lp=linear_program(P,ω; convention = convention) - return solve_lp(lp)[1] - end - return h +function support_function(P::Polyhedron{T}; convention=:max) where {T<:scalar_types} + function h(ω::AbstractVector) + lp = linear_program(P, ω; convention=convention) + return solve_lp(lp)[1] + end + return h end - _cmp_string(::Val{:lte}) = is_unicode_allowed() ? "≦" : "<=" _cmp_string(::Val{:eq}) = "=" @@ -1337,7 +1498,14 @@ x_1 <= 2 9*x_1 + 9*x_2 + 9*x_3 + 9*x_4 <= 5 ``` """ -function print_constraints(io::IO, A::AnyVecOrMat, b::AbstractVector; trivial::Bool = false, numbered::Bool = false, cmp::Symbol = :lte) +function print_constraints( + io::IO, + A::AnyVecOrMat, + b::AbstractVector; + trivial::Bool=false, + numbered::Bool=false, + cmp::Symbol=:lte, +) zero_char = is_unicode_allowed() ? '₀' : '0' us_ascii = is_unicode_allowed() ? "" : "_" for i in 1:length(b) @@ -1348,11 +1516,39 @@ function print_constraints(io::IO, A::AnyVecOrMat, b::AbstractVector; trivial::B terms[j] = "" else if isone(A[i, j]) || isone(-A[i, j]) - terms[j] = first ? string(isone(A[i, j]) ? "x" : "-x" , us_ascii, reverse([zero_char + d for d in digits(j)])...) : - string(isone(A[i, j]) ? " + x" : " - x", us_ascii, reverse([zero_char + d for d in digits(j)])...) + terms[j] = if first + string( + isone(A[i, j]) ? "x" : "-x", + us_ascii, + reverse([zero_char + d for d in digits(j)])..., + ) + else + string( + isone(A[i, j]) ? " + x" : " - x", + us_ascii, + reverse([zero_char + d for d in digits(j)])..., + ) + end else - terms[j] = first ? string(_constraint_string(A[i, j]), "*x", us_ascii, reverse([zero_char + d for d in digits(j)])...) : - string(A[i, j] < zero(A[i, j]) ? string(" - ", _constraint_string(-A[i, j])) : string(" + ", _constraint_string(A[i, j])), "*x", us_ascii, reverse([zero_char + d for d in digits(j)])...) + terms[j] = if first + string( + _constraint_string(A[i, j]), + "*x", + us_ascii, + reverse([zero_char + d for d in digits(j)])..., + ) + else + string( + if A[i, j] < zero(A[i, j]) + string(" - ", _constraint_string(-A[i, j])) + else + string(" + ", _constraint_string(A[i, j])) + end, + "*x", + us_ascii, + reverse([zero_char + d for d in digits(j)])..., + ) + end end first = false end @@ -1363,7 +1559,12 @@ function print_constraints(io::IO, A::AnyVecOrMat, b::AbstractVector; trivial::B end terms[1] = "0" end - println(io, string(numbered ? string(i, ": ") : "", terms..., " ", _cmp_string(Val(cmp)), " ", b[i])) + println( + io, + string( + numbered ? string(i, ": ") : "", terms..., " ", _cmp_string(Val(cmp)), " ", b[i] + ), + ) end end @@ -1395,86 +1596,110 @@ x_2 <= 1 x_3 <= 1 ``` """ -print_constraints(io::IO, P::Polyhedron; trivial::Bool = false, numbered::Bool = false) = print_constraints(io, halfspace_matrix_pair(facets(P))...; trivial = trivial) +print_constraints(io::IO, P::Polyhedron; trivial::Bool=false, numbered::Bool=false) = + print_constraints(io, halfspace_matrix_pair(facets(P))...; trivial=trivial) -print_constraints(io::IO, H::Halfspace; trivial::Bool = false) = print_constraints(io, permutedims(normal_vector(H)), [negbias(H)]; trivial = trivial) +print_constraints(io::IO, H::Halfspace; trivial::Bool=false) = + print_constraints(io, permutedims(normal_vector(H)), [negbias(H)]; trivial=trivial) -print_constraints(io::IO, H::Hyperplane; trivial::Bool = false) = print_constraints(io, permutedims(normal_vector(H)), [negbias(H)]; trivial = trivial, cmp = :eq) +print_constraints(io::IO, H::Hyperplane; trivial::Bool=false) = print_constraints( + io, permutedims(normal_vector(H)), [negbias(H)]; trivial=trivial, cmp=:eq +) -print_constraints(io::IO, H::SubObjectIterator{<:Halfspace}; numbered::Bool = false) = print_constraints(io, halfspace_matrix_pair(H)...; trivial = true, numbered = numbered) +print_constraints(io::IO, H::SubObjectIterator{<:Halfspace}; numbered::Bool=false) = + print_constraints(io, halfspace_matrix_pair(H)...; trivial=true, numbered=numbered) -print_constraints(io::IO, H::SubObjectIterator{<:Hyperplane}; numbered::Bool = false) = print_constraints(io, halfspace_matrix_pair(H)...; trivial = true, numbered = numbered, cmp = :eq) +print_constraints(io::IO, H::SubObjectIterator{<:Hyperplane}; numbered::Bool=false) = + print_constraints( + io, halfspace_matrix_pair(H)...; trivial=true, numbered=numbered, cmp=:eq + ) # Default `io = stdout` -print_constraints(A::AnyVecOrMat, b::AbstractVector; trivial::Bool = false, numbered::Bool = false, cmp::Symbol = :lte) = - print_constraints(stdout, A, b; trivial = trivial, numbered = numbered, cmp = cmp) +print_constraints( + A::AnyVecOrMat, + b::AbstractVector; + trivial::Bool=false, + numbered::Bool=false, + cmp::Symbol=:lte, +) = print_constraints(stdout, A, b; trivial=trivial, numbered=numbered, cmp=cmp) -print_constraints(P::Polyhedron; trivial::Bool = false, numbered::Bool = false) = - print_constraints(stdout, P; trivial = trivial, numbered = numbered) +print_constraints(P::Polyhedron; trivial::Bool=false, numbered::Bool=false) = + print_constraints(stdout, P; trivial=trivial, numbered=numbered) -print_constraints(H::Union{Halfspace, Hyperplane}; trivial::Bool = false) = - print_constraints(stdout, H; trivial = trivial) +print_constraints(H::Union{Halfspace,Hyperplane}; trivial::Bool=false) = + print_constraints(stdout, H; trivial=trivial) -print_constraints(H::SubObjectIterator{<:Union{Halfspace, Hyperplane}}; numbered::Bool = false) = - print_constraints(stdout, H; numbered = numbered) +print_constraints( + H::SubObjectIterator{<:Union{Halfspace,Hyperplane}}; numbered::Bool=false +) = print_constraints(stdout, H; numbered=numbered) function Base.show(io::IO, H::Halfspace) - n = length(normal_vector(H)) - if iszero(normal_vector(H)) && negbias(H) >= 0 - print(io, "The trivial half-space, R^$n") - else - print(io, "The half-space of R^$n described by\n") - print_constraints(io, H) - end + n = length(normal_vector(H)) + if iszero(normal_vector(H)) && negbias(H) >= 0 + print(io, "The trivial half-space, R^$n") + else + print(io, "The half-space of R^$n described by\n") + print_constraints(io, H) + end end function Base.show(io::IO, H::Hyperplane) - n = length(normal_vector(H)) - b = negbias(H) - if iszero(b) && iszero(normal_vector(H)) - print(io, "The trivial hyperplane, R^$n") - else - print(io, "The hyperplane of R^$n described by\n") - print_constraints(io, H) - end + n = length(normal_vector(H)) + b = negbias(H) + if iszero(b) && iszero(normal_vector(H)) + print(io, "The trivial hyperplane, R^$n") + else + print(io, "The hyperplane of R^$n described by\n") + print_constraints(io, H) + end end -Base.show(io::IO, ::MIME"text/plain", H::SubObjectIterator{<:Union{Halfspace, Hyperplane}}) = show(io, H) +Base.show(io::IO, ::MIME"text/plain", H::SubObjectIterator{<:Union{Halfspace,Hyperplane}}) = + show(io, H) function Base.show(io::IO, H::SubObjectIterator{<:Halfspace}) - s = length(H) - t = typeof(H) - d = displaysize(io)[1] - 5 - print(io, "$s-element $t") - if !isempty(H) - n = length(normal_vector(H[1])) - print(io, " over the Halfspaces of R^$n described by:\n") - if s < d - print_constraints(io, H) - else - A, b = halfspace_matrix_pair(H) - print_constraints(io, view(A, 1:floor(Int, d/2), :), b[1:floor(Int, d/2)]) - println(io, "⋮") - print_constraints(io, A[(s - floor(Int, d/2) + d%2):end, :], b[(s - floor(Int, d/2) + d%2):end]) - end + s = length(H) + t = typeof(H) + d = displaysize(io)[1] - 5 + print(io, "$s-element $t") + if !isempty(H) + n = length(normal_vector(H[1])) + print(io, " over the Halfspaces of R^$n described by:\n") + if s < d + print_constraints(io, H) + else + A, b = halfspace_matrix_pair(H) + print_constraints(io, view(A, 1:floor(Int, d / 2), :), b[1:floor(Int, d / 2)]) + println(io, "⋮") + print_constraints( + io, + A[(s - floor(Int, d / 2) + d % 2):end, :], + b[(s - floor(Int, d / 2) + d % 2):end], + ) end + end end function Base.show(io::IO, H::SubObjectIterator{<:Hyperplane}) - s = length(H) - t = typeof(H) - d = displaysize(io)[1] - 5 - print(io, "$s-element $t") - if !isempty(H) - n = length(normal_vector(H[1])) - print(io, " over the Hyperplanes of R^$n described by:\n") - if s < d - print_constraints(io, H) - else - A, b = halfspace_matrix_pair(H) - print_constraints(io, A[1:floor(Int, d/2), :], b[1:floor(Int, d/2)]; cmp = :eq) - println(io, "⋮") - print_constraints(io, A[(s - floor(Int, d/2) + d%2):end, :], b[(s - floor(Int, d/2) + d%2):end]; cmp = :eq) - end + s = length(H) + t = typeof(H) + d = displaysize(io)[1] - 5 + print(io, "$s-element $t") + if !isempty(H) + n = length(normal_vector(H[1])) + print(io, " over the Hyperplanes of R^$n described by:\n") + if s < d + print_constraints(io, H) + else + A, b = halfspace_matrix_pair(H) + print_constraints(io, A[1:floor(Int, d / 2), :], b[1:floor(Int, d / 2)]; cmp=:eq) + println(io, "⋮") + print_constraints( + io, + A[(s - floor(Int, d / 2) + d % 2):end, :], + b[(s - floor(Int, d / 2) + d % 2):end]; + cmp=:eq, + ) end + end end diff --git a/src/PolyhedralGeometry/Polyhedron/standard_constructions.jl b/src/PolyhedralGeometry/Polyhedron/standard_constructions.jl index 7f2c8ef022b5..7b4c9a306f6c 100644 --- a/src/PolyhedralGeometry/Polyhedron/standard_constructions.jl +++ b/src/PolyhedralGeometry/Polyhedron/standard_constructions.jl @@ -2353,5 +2353,7 @@ function vertex_figure(P::Polyhedron{T}, n::Int; cutoff=nothing) where {T<:scala @req 0 < cutoff < 1 "cutoff factor must be within (0,1)" opts[:cutoff] = convert(Polymake.PolymakeType, cutoff) end - return Polyhedron{T}(Polymake.polytope.vertex_figure(pm_object(P), n-1; opts...), coefficient_field(P)) + return Polyhedron{T}( + Polymake.polytope.vertex_figure(pm_object(P), n - 1; opts...), coefficient_field(P) + ) end