Skip to content

Commit 687831d

Browse files
lxvmblegat
authored andcommitted
[BREAKING] Move functionality to extension packages (#328)
* move jump to extension * support for regular dependency in julia 1.6 * reorganize JuMP ext * move RecipesBase and GeometryBasics to ext * uncomment verbose statement * add error message for Mesh * add news file describing breaking change * update docs * update examples * simplify doc * fix verbose print of model * remove exported JuMP function * import functions missing in GeometryBasicsExt * add missing compat entry
1 parent 09302cd commit 687831d

15 files changed

+137
-97
lines changed

NEWS.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Polyhedra.jl v0.8 Release Notes
2+
3+
## Load time improvements
4+
- Dependencies on JuMP.jl, RecipesBase.jl, and GeometryBasics.jl were moved to
5+
weak dependencies on Julia versions supporting package extensions, i.e. v1.9
6+
and above. On v1.10 this reduces installation time by 15% and load time by
7+
18% (see [#328]).
8+
9+
## Breaking changes
10+
- `JuMP.optimizer_with_attributes` is no longer exported. Call it from JuMP.jl instead.
11+
- The following change is only breaking on Julia v1.9 and above:
12+
`Polyhedra.Mesh` is now implemented in a package extension requiring
13+
GeometryBasics.jl. It is sufficient to load your plotting package, i.e.
14+
Makie.jl or MeshCat.jl, **before** calling `Polyhedra.Mesh`

Project.toml

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,32 @@ version = "0.7.8"
66
[deps]
77
GenericLinearAlgebra = "14197337-ba66-59df-a3e3-ca00e7dcff7a"
88
GeometryBasics = "5c1252a2-5f33-56bf-86c9-59e7332b4326"
9-
JuMP = "4076af6c-e467-56ae-b986-b466b2749572"
109
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
10+
JuMP = "4076af6c-e467-56ae-b986-b466b2749572"
11+
MathOptInterface = "b8f27783-ece8-5eb3-8dc8-9495eed66fee"
1112
MutableArithmetics = "d8a4904e-b15c-11e9-3269-09a3773c0cb0"
1213
RecipesBase = "3cdcf5f2-1ef4-517c-9805-6587b60abb01"
1314
SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
1415
StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"
1516

17+
[weakdeps]
18+
GeometryBasics = "5c1252a2-5f33-56bf-86c9-59e7332b4326"
19+
JuMP = "4076af6c-e467-56ae-b986-b466b2749572"
20+
RecipesBase = "3cdcf5f2-1ef4-517c-9805-6587b60abb01"
21+
22+
[extensions]
23+
PolyhedraGeometryBasicsExt = "GeometryBasics"
24+
PolyhedraJuMPExt = "JuMP"
25+
PolyhedraRecipesBaseExt = "RecipesBase"
26+
1627
[compat]
1728
GenericLinearAlgebra = "0.2, 0.3"
1829
GeometryBasics = "0.2, 0.3, 0.4"
1930
JuMP = "0.23, 1"
31+
LinearAlgebra = "1.6"
32+
MathOptInterface = "1"
2033
MutableArithmetics = "1"
2134
RecipesBase = "0.7, 0.8, 1.0"
35+
SparseArrays = "1.6"
2236
StaticArrays = "0.12, 1.0"
2337
julia = "1.6"

docs/src/plot.md

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -63,26 +63,25 @@ Polyhedron DefaultPolyhedron{Rational{BigInt}, Polyhedra.Intersection{Rational{B
6363
Ray(Rational{BigInt}[0, 0, 1])
6464
```
6565

66-
Then, we need to create a mesh from the polyhedron:
67-
```jldoctest plots3
68-
julia> m = Polyhedra.Mesh(p)
69-
Polyhedra.Mesh{3, Rational{BigInt}, DefaultPolyhedron{Rational{BigInt}, Polyhedra.Intersection{Rational{BigInt}, Vector{Rational{BigInt}}, Int64}, Polyhedra.Hull{Rational{BigInt}, Vector{Rational{BigInt}}, Int64}}}(convexhull([0, 0, 0]) + convexhull(Ray(Rational{BigInt}[1, 0, 0]), Ray(Rational{BigInt}[0, 1, 0]), Ray(Rational{BigInt}[0, 0, 1])), nothing, nothing, nothing)
70-
```
71-
72-
```@docs
73-
Polyhedra.Mesh
74-
```
75-
76-
The polyhedron can be plotted with [MeshCat](https://github.com/rdeits/MeshCat.jl) as follows
66+
The polyhedron can then be plotted with [MeshCat](https://github.com/rdeits/MeshCat.jl) as follows
7767
```julia
7868
julia> using MeshCat
7969

70+
julia> m = Polyhedra.Mesh(p)
71+
8072
julia> vis = Visualizer()
8173

8274
julia> setobject!(vis, m)
8375

8476
julia> open(vis)
8577
```
78+
79+
Note that the `Mesh` object should be created **after** loading the plotting package:
80+
81+
```@docs
82+
Polyhedra.Mesh
83+
```
84+
8685
To plot it in a notebook, replace `open(vis)` with `IJuliaCell(vis)`.
8786

8887
To plot it with [Makie](https://github.com/JuliaPlots/Makie.jl) instead, you can use for instance `mesh` or `wireframe`.

examples/3D Plotting a projection of the 4D permutahedron.ipynb

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -77,23 +77,7 @@
7777
"cell_type": "markdown",
7878
"metadata": {},
7979
"source": [
80-
"To get a plottable object, we transform the polyhedron into a mesh as follows."
81-
]
82-
},
83-
{
84-
"cell_type": "code",
85-
"execution_count": 5,
86-
"metadata": {},
87-
"outputs": [],
88-
"source": [
89-
"m = Polyhedra.Mesh(p3);"
90-
]
91-
},
92-
{
93-
"cell_type": "markdown",
94-
"metadata": {},
95-
"source": [
96-
"We can now plot this mesh with [MeshCat](https://github.com/rdeits/MeshCat.jl) or [Makie](https://github.com/JuliaPlots/Makie.jl) as follows:"
80+
"We can now plot this polyhedron with [MeshCat](https://github.com/rdeits/MeshCat.jl) or [Makie](https://github.com/JuliaPlots/Makie.jl) as follows:"
9781
]
9882
},
9983
{
@@ -129,6 +113,7 @@
129113
],
130114
"source": [
131115
"using MeshCat\n",
116+
"m = Polyhedra.Mesh(p3)\n",
132117
"vis = Visualizer()\n",
133118
"setobject!(vis, m)\n",
134119
"IJuliaCell(vis)"

examples/Polyhedral Function.ipynb

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -840,22 +840,14 @@
840840
"The top of the shape will have no face as it is unbounded in this direction."
841841
]
842842
},
843-
{
844-
"cell_type": "code",
845-
"execution_count": null,
846-
"metadata": {},
847-
"outputs": [],
848-
"source": [
849-
"m = Polyhedra.Mesh(p)"
850-
]
851-
},
852843
{
853844
"cell_type": "code",
854845
"execution_count": null,
855846
"metadata": {},
856847
"outputs": [],
857848
"source": [
858849
"using MeshCat\n",
850+
"m = Polyhedra.Mesh(p)\n",
859851
"vis = Visualizer()\n",
860852
"setobject!(vis, m)\n",
861853
"IJuliaCell(vis)"

src/decompose.jl renamed to ext/PolyhedraGeometryBasicsExt.jl

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
1+
module PolyhedraGeometryBasicsExt
2+
3+
using LinearAlgebra
14
import GeometryBasics
5+
using Polyhedra
6+
using Polyhedra: FullDim, isapproxzero, _planar_hull, counterclockwise, rotate
7+
using StaticArrays
28

39
"""
410
struct Mesh{N, T, PT <: Polyhedron{T}} <: GeometryBasics.GeometryPrimitive{N, T}
@@ -29,7 +35,7 @@ function Mesh(polyhedron::Polyhedron, N::Int)
2935
# use polyhedron built from StaticArrays vector to avoid that.
3036
return Mesh{N}(polyhedron)
3137
end
32-
function Mesh(polyhedron::Polyhedron)
38+
function Polyhedra.Mesh(polyhedron::Polyhedron)
3339
return Mesh(polyhedron, FullDim(polyhedron))
3440
end
3541

@@ -223,3 +229,5 @@ GeometryBasics.coordinates(poly::Mesh) = (fulldecompose!(poly); poly.coordinates
223229
GeometryBasics.faces(poly::Mesh) = (fulldecompose!(poly); poly.faces)
224230
GeometryBasics.texturecoordinates(poly::Mesh) = nothing
225231
GeometryBasics.normals(poly::Mesh) = (fulldecompose!(poly); poly.normals)
232+
233+
end

ext/PolyhedraJuMPExt.jl

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
module PolyhedraJuMPExt
2+
3+
import JuMP
4+
import Polyhedra: hrep, LPHRep, polyhedron, _optimize!
5+
using Polyhedra: Rep, Projection, _moi_set, fulldim, dimension_names, PolyhedraToLPBridge, ProjectionBridge
6+
7+
"""
8+
hrep(model::JuMP.Model)
9+
10+
Builds an H-representation from the feasibility set of the JuMP model `model`.
11+
Note that if non-linear constraint are present in the model, they are ignored.
12+
"""
13+
hrep(model::JuMP.Model) = LPHRep(model)
14+
LPHRep(model::JuMP.Model) = LPHRep(JuMP.backend(model))
15+
polyhedron(model::JuMP.Model, args...) = polyhedron(hrep(model), args...)
16+
_optimize!(model::JuMP.Model) = JuMP.optimize!(model)
17+
18+
struct VariableInSet{V <: JuMP.ScalarVariable, S <: Union{Rep, Projection}} <: JuMP.AbstractVariable
19+
variables::Vector{V}
20+
set::S
21+
end
22+
function JuMP.build_variable(error_fun::Function, variables::Vector{<:JuMP.ScalarVariable}, set::Union{Rep, Projection})
23+
if length(variables) != fulldim(set)
24+
error("Number of variables ($(length(variables))) does not match the full dimension of the polyhedron ($(fulldim(set))).")
25+
end
26+
return VariableInSet(variables, set)
27+
end
28+
function JuMP.add_variable(model::JuMP.AbstractModel, v::VariableInSet, names)
29+
dim_names = dimension_names(v.set)
30+
if dim_names !== nothing
31+
names = copy(names)
32+
for i in eachindex(names)
33+
if isempty(names[i]) && !isempty(dim_names[i])
34+
names[i] = dim_names[i]
35+
end
36+
end
37+
end
38+
JuMP.add_bridge(model, PolyhedraToLPBridge)
39+
JuMP.add_bridge(model, ProjectionBridge)
40+
return JuMP.add_variable(model, JuMP.VariablesConstrainedOnCreation(v.variables, _moi_set(v.set)), names)
41+
end
42+
function JuMP.build_constraint(error_fun::Function, func, set::Rep)
43+
return JuMP.BridgeableConstraint(
44+
JuMP.build_constraint(error_fun, func, _moi_set(set)),
45+
PolyhedraToLPBridge)
46+
end
47+
function JuMP.build_constraint(error_fun::Function, func, set::Projection)
48+
return JuMP.BridgeableConstraint(JuMP.BridgeableConstraint(
49+
JuMP.build_constraint(error_fun, func, _moi_set(set)),
50+
ProjectionBridge), PolyhedraToLPBridge)
51+
end
52+
53+
end

src/recipe.jl renamed to ext/PolyhedraRecipesBaseExt.jl

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
1+
module PolyhedraRecipesBaseExt
2+
3+
using LinearAlgebra
14
using RecipesBase
5+
using Polyhedra
6+
using Polyhedra: basis, _semi_hull
27

38
function planar_contour(p::Polyhedron)
49
if fulldim(p) != 2
@@ -17,7 +22,7 @@ function planar_contour(p::Polyhedron)
1722
error("Plotting empty polyhedron is not supported.")
1823
end
1924
sort!(ps, by = x -> x[1])
20-
counterclockwise(p1, p2) = dot(cross([p1; 0], [p2; 0]), [0, 0, 1])
25+
counterclockwise = (p1, p2) -> dot(cross([p1; 0], [p2; 0]), [0, 0, 1])
2126
sweep_norm = basis(eltype(ps), fulldim(p), 1)
2227
top = _semi_hull(ps, 1, counterclockwise, sweep_norm)
2328
bot = _semi_hull(ps, -1, counterclockwise, sweep_norm)
@@ -39,3 +44,5 @@ end
3944
legend --> false
4045
planar_contour(p)
4146
end
47+
48+
end

src/Polyhedra.jl

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,14 @@ import GenericLinearAlgebra
1212
import MutableArithmetics
1313
const MA = MutableArithmetics
1414

15+
import MathOptInterface as MOI
16+
import MathOptInterface.Utilities as MOIU
17+
1518
export Polyhedron
1619

1720
abstract type Library end
1821
abstract type Polyhedron{T} end
1922

20-
using JuMP
21-
export optimizer_with_attributes
22-
2323
coefficient_type(::Union{AbstractVector{T}, Type{<:AbstractVector{T}}}) where T = T
2424
similar_type(::Type{<:Vector}, ::Int, ::Type{T}) where T = Vector{T}
2525
similar_type(::Type{SparseVector{S, IT}}, ::Int, ::Type{T}) where {S, IT, T} = SparseVector{T, IT}
@@ -81,7 +81,6 @@ include("extended.jl")
8181
include("vecrep.jl")
8282
include("mixedrep.jl")
8383
include("lphrep.jl")
84-
include("jump.jl")
8584
include("matrep.jl")
8685
include("liftedrep.jl")
8786
include("doubledescription.jl") # FIXME move it after projection.jl once it stops depending on LiftedRep
@@ -100,7 +99,23 @@ include("projection_opt.jl")
10099

101100
# Visualization
102101
include("show.jl")
103-
include("recipe.jl")
104-
include("decompose.jl")
102+
103+
"""
104+
Mesh(p::Polyhedron)
105+
106+
Returns wrapper of a polyhedron suitable for plotting with MeshCat.jl and Makie.jl.
107+
108+
!!! note "Extension in Julia 1.9 and above"
109+
Although we require `using GeometryBasics` to use this function in Julia 1.9 and above,
110+
in most use cases this extension dependency is loaded by the plotting package and no
111+
further action is required.
112+
"""
113+
Mesh(p) = p isa Polyhedron ? error("this method requires using GeometryBasics") : throw(MethodError(Mesh, p))
114+
115+
if !isdefined(Base, :get_extension)
116+
include("../ext/PolyhedraJuMPExt.jl")
117+
include("../ext/PolyhedraRecipesBaseExt.jl")
118+
include("../ext/PolyhedraGeometryBasicsExt.jl")
119+
end
105120

106121
end # module

src/center.jl

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
export maximum_radius_with_center, hchebyshevcenter, vchebyshevcenter, chebyshevcenter
2-
using JuMP
32

43
"""
54
maximum_radius_with_center(h::HRep, center)

0 commit comments

Comments
 (0)