diff --git a/src/repop.jl b/src/repop.jl index 00b31f3e..3c2b3365 100644 --- a/src/repop.jl +++ b/src/repop.jl @@ -244,18 +244,20 @@ Transform the polyhedron represented by ``p`` into ``\\alpha p`` by transforming each element of the V-representation (points, symmetric points, rays and lines) `x` into ``\\alpha x``. """ -function Base.:(*)(α::Number, p::Polyhedron) +function Base.:(*)(α::Number, p::Polyhedron{T}) where T if vrepiscomputed(p) || iszero(α) return (α * LinearAlgebra.I) * p else - return p / (inv(α) * LinearAlgebra.I) + # If `α` is `Int` and `T` is `Rational{BigInt}`, + # `inv(α)` would be `Float64` and then we'll have `BigFloat`. + return p / (inv(convert(T, α)) * LinearAlgebra.I) end end function Base.:(*)(α::Number, p::VRepresentation) return (α * LinearAlgebra.I) * p end -function Base.:(*)(α::Number, p::HRepresentation) - return p / (inv(α) * LinearAlgebra.I) +function Base.:(*)(α::Number, p::HRepresentation{T}) where {T} + return p / (inv(convert(T, α)) * LinearAlgebra.I) end """ diff --git a/test/liftedrep.jl b/test/liftedrep.jl index e66eaa4f..3677002e 100644 --- a/test/liftedrep.jl +++ b/test/liftedrep.jl @@ -1,4 +1,4 @@ -@testset "Lifted Representation" begin +function test_lifted_representation() change_fulldim_test(LiftedHRepresentation) change_fulldim_test(LiftedVRepresentation) diff --git a/test/lphrep.jl b/test/lphrep.jl index 5b43a970..93f6697e 100644 --- a/test/lphrep.jl +++ b/test/lphrep.jl @@ -1,4 +1,4 @@ -@testset "LPHRep" begin +function test_lphrep() hs = HalfSpace([1, 0], 1) hp = HyperPlane([0, 1], 1) h = hs ∩ hp diff --git a/test/matrep.jl b/test/matrep.jl index a11aa69d..98137cff 100644 --- a/test/matrep.jl +++ b/test/matrep.jl @@ -1,4 +1,4 @@ -@testset "MixMatRep" begin +function test_MixMatRep() change_fulldim_test(MixedMatHRep) change_fulldim_test(MixedMatVRep) diff --git a/test/representation.jl b/test/representation.jl index 6479f9ae..e5c11dee 100644 --- a/test/representation.jl +++ b/test/representation.jl @@ -1,7 +1,26 @@ +module TestRepresentation + +using Test + using LinearAlgebra, SparseArrays, Test +using Polyhedra + +include("utils.jl") include("inconsistentvrep.jl") using JuMP, StaticArrays +include("solvers.jl") + +function runtests() + for name in names(@__MODULE__; all = true) + if startswith("$(name)", "test_") + @testset "$(name)" begin + getfield(@__MODULE__, name)() + end + end + end + return +end function change_fulldim_test(Rep) T = Int @@ -76,7 +95,8 @@ function vtest(vr::VRepresentation, AT::Type{<:AbstractVector}) @test_throws DimensionMismatch ones(2, 1) * vr end -function eltype_incorrect() +# eltype for some iterators is incorrect #7 +function test_eltype_incorrect() hps = [HyperPlane([1, 2, 3], 7.)] shps = [@inferred HyperPlane((@SVector [1, 2, 3]), 7.)] @test eltype(shps) == HyperPlane{Float64, SVector{3, Float64}} @@ -136,7 +156,7 @@ function eltype_incorrect() vtest(vrep([1 2; 3 4]), Vector{Int}) end -function polar_test() +function test_polar() v = convexhull([-1, 2]) + conichull([1, 0], Line([1, 0])) for p in [v, polyhedron(v)] h = polar(p) @@ -162,259 +182,275 @@ function polar_test() end end -@testset "Representation tests" begin - - include("vecrep.jl") - include("lphrep.jl") - include("matrep.jl") - include("liftedrep.jl") +include("vecrep.jl") +include("lphrep.jl") +include("matrep.jl") +include("liftedrep.jl") - @testset "eltype for some iterators is incorrect #7" begin - eltype_incorrect() +# Iterating over halfspaces of a MixedMatHRep broken #9 +function test_iterating() + A = [1 2; 3 4; 5 6] + b = [1, 2, 3] + halfspace = [1, 3] + hyperplane = [2] + linset = BitSet(2) + hr = hrep(A, b, linset) + Aall = [3 4; -3 -4; 1 2; 5 6] + ball = [2, -2, 1, 3] + for (i, h) in enumerate(allhalfspaces(hr)) + @test h.a == Aall[i, :] + @test h.β == ball[i] + @test isa(h, HalfSpace{Int}) end - - @testset "Iterating over halfspaces of a MixedMatHRep broken #9" begin - A = [1 2; 3 4; 5 6] - b = [1, 2, 3] - halfspace = [1, 3] - hyperplane = [2] - linset = BitSet(2) - hr = hrep(A, b, linset) - Aall = [3 4; -3 -4; 1 2; 5 6] - ball = [2, -2, 1, 3] - for (i, h) in enumerate(allhalfspaces(hr)) - @test h.a == Aall[i, :] - @test h.β == ball[i] - @test isa(h, HalfSpace{Int}) - end - for (i, h) in enumerate(halfspaces(hr)) - @test h.a == A[halfspace[i], :] - @test h.β == b[halfspace[i]] - @test isa(h, HalfSpace{Int}) - end - for (i, h) in enumerate(hyperplanes(hr)) - @test h.a == A[hyperplane[i], :] - @test h.β == b[hyperplane[i]] - @test isa(h, HyperPlane{Int}) - end + for (i, h) in enumerate(halfspaces(hr)) + @test h.a == A[halfspace[i], :] + @test h.β == b[halfspace[i]] + @test isa(h, HalfSpace{Int}) end - - @testset "Building rep with different type" begin - @test Polyhedra.coefficient_type(MixedMatHRep{Float64}([1 2; 3 4], [1, 2], BitSet())) == Float64 - @test Polyhedra.coefficient_type(MixedMatVRep{Float64}([1 2; 3 4], [1 2; 3 4], BitSet())) == Float64 - @test Polyhedra.coefficient_type(LiftedHRepresentation{Float64}([1 2; 3 4])) == Float64 - @test Polyhedra.coefficient_type(LiftedVRepresentation{Float64}([1 2; 3 4])) == Float64 + for (i, h) in enumerate(hyperplanes(hr)) + @test h.a == A[hyperplane[i], :] + @test h.β == b[hyperplane[i]] + @test isa(h, HyperPlane{Int}) end +end - @testset "Radius of largest inscribed ball at a given center" begin - p = hrep(Matrix(1I, 2, 2), zeros(2)) - r = Polyhedra.maximum_radius_with_center(p, zeros(2)) - @test r == 0 +function test_building_rep_with_different_type() + @test Polyhedra.coefficient_type(MixedMatHRep{Float64}([1 2; 3 4], [1, 2], BitSet())) == Float64 + @test Polyhedra.coefficient_type(MixedMatVRep{Float64}([1 2; 3 4], [1 2; 3 4], BitSet())) == Float64 + @test Polyhedra.coefficient_type(LiftedHRepresentation{Float64}([1 2; 3 4])) == Float64 + @test Polyhedra.coefficient_type(LiftedVRepresentation{Float64}([1 2; 3 4])) == Float64 +end - p = hrep([0 0], [0]) - @test_throws ErrorException Polyhedra.maximum_radius_with_center(p, zeros(2)) - p = hrep([1 0], [-1]) - @test_throws ErrorException Polyhedra.maximum_radius_with_center(p, zeros(2)) +# Radius of largest inscribed ball at a given center +function test_radius() + p = hrep(Matrix(1I, 2, 2), zeros(2)) + r = Polyhedra.maximum_radius_with_center(p, zeros(2)) + @test r == 0 - A = [ 2 1 - 2 -1 - -1 2 - -1 -2] - b = ones(4) - p = hrep(A, b) - r = Polyhedra.maximum_radius_with_center(p, zeros(2)) - @test r ≈ inv(√5) atol=1e-6 + p = hrep([0 0], [0]) + @test_throws ErrorException Polyhedra.maximum_radius_with_center(p, zeros(2)) + p = hrep([1 0], [-1]) + @test_throws ErrorException Polyhedra.maximum_radius_with_center(p, zeros(2)) - p = polyhedron(vrep([ 0 0 - 1 0 - 1 1 - 0 1])) - @test Polyhedra.maximum_radius_with_center(p, [0.00, 0.00]) == 0.00 - @test Polyhedra.maximum_radius_with_center(p, [1.00, 1.00]) == 0.00 - @test Polyhedra.maximum_radius_with_center(p, [0.50, 0.50]) == 0.50 - @test Polyhedra.maximum_radius_with_center(p, [0.50, 0.25]) == 0.25 - @test Polyhedra.maximum_radius_with_center(p, [0.25, 0.50]) == 0.25 - @test Polyhedra.maximum_radius_with_center(p, [0.25, 0.25]) == 0.25 - end + A = [ 2 1 + 2 -1 + -1 2 + -1 -2] + b = ones(4) + p = hrep(A, b) + r = Polyhedra.maximum_radius_with_center(p, zeros(2)) + @test r ≈ inv(√5) atol=1e-6 - @testset "Chebyshev center" begin - p = hrep(Matrix(1I, 2, 2), zeros(2)) - @test_throws ErrorException chebyshevcenter(p, lp_solver) # unbounded + p = polyhedron(vrep([ 0 0 + 1 0 + 1 1 + 0 1])) + @test Polyhedra.maximum_radius_with_center(p, [0.00, 0.00]) == 0.00 + @test Polyhedra.maximum_radius_with_center(p, [1.00, 1.00]) == 0.00 + @test Polyhedra.maximum_radius_with_center(p, [0.50, 0.50]) == 0.50 + @test Polyhedra.maximum_radius_with_center(p, [0.50, 0.25]) == 0.25 + @test Polyhedra.maximum_radius_with_center(p, [0.25, 0.50]) == 0.25 + @test Polyhedra.maximum_radius_with_center(p, [0.25, 0.25]) == 0.25 +end - p = hrep([1 1; -1 -1], [0, -1]) - @test_throws ErrorException chebyshevcenter(p, lp_solver) # empty +function test_chebyshev_center() + p = hrep(Matrix(1I, 2, 2), zeros(2)) + @test_throws ErrorException chebyshevcenter(p, lp_solver) # unbounded - # examples/chebyshevcenter.ipynb - A = [ 2 1 - 2 -1 - -1 2 - -1 -2] - b = ones(4) - p = hrep(A, b) - c, r = chebyshevcenter(p, lp_solver) - @test c ≈ [0, 0] atol=1e-6 - @test r ≈ 0.4472135955 atol=1e-6 + p = hrep([1 1; -1 -1], [0, -1]) + @test_throws ErrorException chebyshevcenter(p, lp_solver) # empty - _interval(c, r) = HalfSpace([1], c + r) ∩ HalfSpace([-1], -c + r) - c_exp = [-4, 3, 8] - for rs in [[1, 2, 3], [3, 1, 2], [3, 2, 1], [2, 1, 2]] - h = _interval(c_exp[1], rs[1]) * _interval(c_exp[2], rs[2]) * _interval(c_exp[3], rs[3]) - c, r = hchebyshevcenter(h, lp_solver, verbose=1) - @test c ≈ c_exp atol=1e-6 - @test r ≈ 1 atol=1e-6 + # examples/chebyshevcenter.ipynb + A = [ 2 1 + 2 -1 + -1 2 + -1 -2] + b = ones(4) + p = hrep(A, b) + c, r = chebyshevcenter(p, lp_solver) + @test c ≈ [0, 0] atol=1e-6 + @test r ≈ 0.4472135955 atol=1e-6 - c, r = hchebyshevcenter(h, lp_solver, proper=false) - for i in 1:3 - @test c_exp[i] - rs[i] + 1 - 1e-6 <= c[i] - @test c[i] <= c_exp[i] + rs[i] - 1 + 1e-6 - end - @test r ≈ 1 atol=1e-6 + _interval(c, r) = HalfSpace([1], c + r) ∩ HalfSpace([-1], -c + r) + c_exp = [-4, 3, 8] + for rs in [[1, 2, 3], [3, 1, 2], [3, 2, 1], [2, 1, 2]] + h = _interval(c_exp[1], rs[1]) * _interval(c_exp[2], rs[2]) * _interval(c_exp[3], rs[3]) + c, r = hchebyshevcenter(h, lp_solver, verbose=1) + @test c ≈ c_exp atol=1e-6 + @test r ≈ 1 atol=1e-6 + + c, r = hchebyshevcenter(h, lp_solver, proper=false) + for i in 1:3 + @test c_exp[i] - rs[i] + 1 - 1e-6 <= c[i] + @test c[i] <= c_exp[i] + rs[i] - 1 + 1e-6 end + @test r ≈ 1 atol=1e-6 + end - h = _interval(0, 0) * _interval(0, 1) - c, r = hchebyshevcenter(h, lp_solver, linearity_detected=true, verbose=1) - @test c[1] ≈ 0 atol=1e-6 - @test -1 - 1e-6 <= c[2] <= 1 + 1e-6 - @test r ≈ 0 atol=1e-6 + h = _interval(0, 0) * _interval(0, 1) + c, r = hchebyshevcenter(h, lp_solver, linearity_detected=true, verbose=1) + @test c[1] ≈ 0 atol=1e-6 + @test -1 - 1e-6 <= c[2] <= 1 + 1e-6 + @test r ≈ 0 atol=1e-6 - p = convexhull([0, 0], [0, 1], [1, 0]) - @test_throws ErrorException chebyshevcenter(p) # Not yet implemented - end + p = convexhull([0, 0], [0, 1], [1, 0]) + @test_throws ErrorException chebyshevcenter(p) # Not yet implemented +end - @testset "V-consistency with iterator constructor" begin - T = Int - AT = Vector{Int} - for VRepType in (Polyhedra.LiftedVRepresentation{T, Matrix{T}}, - Polyhedra.MixedMatVRep{T, Matrix{T}}, - Polyhedra.Hull{T, AT, Int}) - @test_throws ErrorException VRepType(2, AT[], [Line([1, 2])]) - @test_throws ErrorException VRepType(2, AT[], Line{T, AT}[], [Ray([1, 2])]) - @test_throws ErrorException VRepType(2, AT[], [Line([1, 2])], [Ray([1, 2])]) - v = VRepType(2, [Line([1, 2])]) - @test collect(points(v)) == [[0, 0]] - @test collect(lines(v)) == [Line([1, 2])] - @test !hasrays(v) - end - for vinc in (InconsistentVRep{T, AT, Int}(2, AT[], Line{T, AT}[], [Ray([1, 2])]), - InconsistentVRep{T, AT, Int}(2, AT[], [Line([1, 2])], Ray{T, AT}[]), - InconsistentVRep{T, AT, Int}(2, AT[], [Line([1, 2])], [Ray([1, 2])])) - @test_throws ErrorException Polyhedra.checkvconsistency(vinc) - pinc = polyhedron(vinc) - @test_throws ErrorException Polyhedra.checkvconsistency(pinc) - end - let - AT = StaticArrays.SVector{1, Int} - VRepType = Polyhedra.Hull{T, AT, Int} - @test isempty(VRepType(2, AT[], Line{T, AT}[], Ray{T, AT}[])) - @test isempty(VRepType(2, Line{T, AT}[], Ray{T, AT}[])) - end +# V-consistency with iterator constructor +function test_Vconsistency() + T = Int + AT = Vector{Int} + for VRepType in (Polyhedra.LiftedVRepresentation{T, Matrix{T}}, + Polyhedra.MixedMatVRep{T, Matrix{T}}, + Polyhedra.Hull{T, AT, Int}) + @test_throws ErrorException VRepType(2, AT[], [Line([1, 2])]) + @test_throws ErrorException VRepType(2, AT[], Line{T, AT}[], [Ray([1, 2])]) + @test_throws ErrorException VRepType(2, AT[], [Line([1, 2])], [Ray([1, 2])]) + v = VRepType(2, [Line([1, 2])]) + @test collect(points(v)) == [[0, 0]] + @test collect(lines(v)) == [Line([1, 2])] + @test !hasrays(v) end - @testset "Combination of different coefficient type" begin - @testset "V-representation" begin - generator_fulltest(convexhull([1, 0], Line([0, 1.])), convexhull(Line([0, 1]), [1, 0.])) - @test conichull(convexhull([1, 0.]), conichull([0, 1])) isa Polyhedra.RaysHull{Float64} - @test convexhull(convexhull([1, 0]), Line([0, 1.])) isa Polyhedra.Hull{Float64} - @test convexhull(Line([0, 1.]), convexhull([1, 0])) isa Polyhedra.Hull{Float64} - @test convexhull(convexhull(Line([0, 1.])), [1, 0]) isa Polyhedra.Hull{Float64} - @test convexhull(convexhull(Line([1, 0])), Line([0, 1.])) isa Polyhedra.LinesHull{Float64} - @test convexhull(conichull([1, 0.]), Line([0, 1])) isa Polyhedra.RaysHull{Float64} - @test convexhull(conichull([1, 0.]), [0, 1]) isa Polyhedra.Hull{Float64} - end - @testset "H-representation" begin - #FIXME inference fails @test (@inferred (HyperPlane([1, 1], 0) ∩ HyperPlane([1, 0], 1)) ∩ (HyperPlane([1, 1], 0) ∩ HyperPlane([1., 0.], 1))) isa Polyhedra.HyperPlanesIntersection{Float64} - @test ((HyperPlane([1, 1], 0) ∩ HyperPlane([1, 0], 1)) ∩ (HyperPlane([1, 1], 0) ∩ HyperPlane([1., 0.], 1))) isa Polyhedra.HyperPlanesIntersection{Float64} - @test HyperPlane([1, 1], 0) ∩ HalfSpace([1., 0.], 1.) isa Polyhedra.Intersection{Float64} - #FIXME inference fails @test (@inferred (HalfSpace([1., 0.], 1.) ∩ (HyperPlane([1, 1], 0) ∩ HyperPlane([1, 0], 1)))) isa Polyhedra.Intersection{Float64} - @test ((HalfSpace([1., 0.], 1.) ∩ (HyperPlane([1, 1], 0) ∩ HyperPlane([1, 0], 1)))) isa Polyhedra.Intersection{Float64} - end + for vinc in (InconsistentVRep{T, AT, Int}(2, AT[], Line{T, AT}[], [Ray([1, 2])]), + InconsistentVRep{T, AT, Int}(2, AT[], [Line([1, 2])], Ray{T, AT}[]), + InconsistentVRep{T, AT, Int}(2, AT[], [Line([1, 2])], [Ray([1, 2])])) + @test_throws ErrorException Polyhedra.checkvconsistency(vinc) + pinc = polyhedron(vinc) + @test_throws ErrorException Polyhedra.checkvconsistency(pinc) end - @testset "Conversion with different array type" begin - @testset "V-representation" begin - vv = convexhull(@SVector [0, 1]) + conichull((@SVector [1, 1]), Line(@SVector [1, 0])) - mv = vrep([0 1], [1 1; 1 0], BitSet([2])) - generator_fulltest(vv, mv) - mvv = @inferred convert(typeof(mv), vv) - vmv = @inferred convert(typeof(vv), mv) - generator_fulltest(vv, mvv) - generator_fulltest(vmv, vv) - end - @testset "H-representation" begin - vh = HalfSpace((@SVector [1, 0]), 0) ∩ HyperPlane((@SVector [0, 1]), 1) - mh = hrep([0 1; 1 0], [1, 0], BitSet(1)) - inequality_fulltest(vh, mh) - mvh = @inferred convert(typeof(mh), vh) - vmh = @inferred convert(typeof(vh), mh) - inequality_fulltest(vh, mvh) - inequality_fulltest(vmh, vh) - end + let + AT = StaticArrays.SVector{1, Int} + VRepType = Polyhedra.Hull{T, AT, Int} + @test isempty(VRepType(2, AT[], Line{T, AT}[], Ray{T, AT}[])) + @test isempty(VRepType(2, Line{T, AT}[], Ray{T, AT}[])) end - @testset "Copy test" begin - @testset "V-representation" begin - vr = convexhull(@SVector [0, 1]) - vc = copy(vr) - @test vc !== vr - @test vc.points !== vr.points - generator_fulltest(vc, vr) - vr = conichull(Line(@SVector [1, 1]), Line(@SVector [1, 0])) - vc = copy(vr) - @test vc !== vr - @test vc.lines !== vr.lines - generator_fulltest(vc, vr) - vr = conichull(Line(@SVector [1, 1]), Line(@SVector [1, 0]), @SVector [1, 1]) - vc = copy(vr) - @test vc !== vr - @test vc.rays !== vr.rays - @test vc.lines !== vr.lines - @test vc.lines.lines !== vr.lines.lines - generator_fulltest(vc, vr) - vr = convexhull(@SVector [0, 1]) + conichull(Line(@SVector [1, 1]), (@SVector [1, 1]), Line(@SVector [1, 0])) - vc = copy(vr) - @test vc !== vr - @test vc.points !== vr.points - @test vc.points.points !== vr.points.points - @test vc.rays !== vr.rays - @test vc.rays.lines !== vr.rays.lines - @test vc.rays.lines.lines !== vr.rays.lines.lines - @test vc.rays.rays !== vr.rays.rays - generator_fulltest(vc, vr) - end - @testset "H-representation" begin - hr = HyperPlane([1, 0], 1) ∩ HyperPlane([0, 1], -1) - hc = copy(hr) - @test hc !== hr - @test hc.hyperplanes !== hr.hyperplanes - inequality_fulltest(hc, hr) - hr = HyperPlane([1, 0], 1) ∩ HyperPlane([1, 1], 0) ∩ HalfSpace([0, 1], -1) - hc = copy(hr) - @test hc !== hr - @test hc.hyperplanes !== hr.hyperplanes - @test hc.hyperplanes.hyperplanes !== hr.hyperplanes.hyperplanes - @test hc.halfspaces !== hr.halfspaces - inequality_fulltest(hc, hr) - end +end +function test_combination_different_coef_type() + @testset "V-representation" begin + generator_fulltest(convexhull([1, 0], Line([0, 1.])), convexhull(Line([0, 1]), [1, 0.])) + @test conichull(convexhull([1, 0.]), conichull([0, 1])) isa Polyhedra.RaysHull{Float64} + @test convexhull(convexhull([1, 0]), Line([0, 1.])) isa Polyhedra.Hull{Float64} + @test convexhull(Line([0, 1.]), convexhull([1, 0])) isa Polyhedra.Hull{Float64} + @test convexhull(convexhull(Line([0, 1.])), [1, 0]) isa Polyhedra.Hull{Float64} + @test convexhull(convexhull(Line([1, 0])), Line([0, 1.])) isa Polyhedra.LinesHull{Float64} + @test convexhull(conichull([1, 0.]), Line([0, 1])) isa Polyhedra.RaysHull{Float64} + @test convexhull(conichull([1, 0.]), [0, 1]) isa Polyhedra.Hull{Float64} end - @testset "Preserving sparsity" begin - for h in (HalfSpace(sparsevec([1], [1], 2), 1) ∩ HyperPlane(sparsevec([2], [-1]), 3), hrep(sparse([1, 2], [1, 2], [1, -1]), [1, 3])) - @test Polyhedra.Intersection(h) isa Polyhedra.Intersection{Int, SparseVector{Int, Int}} - @test LPHRep(h) isa LPHRep{Int} - @test MixedMatHRep(h) isa MixedMatHRep{Int, SparseMatrixCSC{Int, Int}} - @test LiftedHRepresentation(h) isa LiftedHRepresentation{Int, SparseMatrixCSC{Int, Int}} - @test Polyhedra.Intersection{Float64}(h) isa Polyhedra.Intersection{Float64, SparseVector{Float64, Int}} - @test LPHRep{Float64}(h) isa LPHRep{Float64} - @test MixedMatHRep{Float64}(h) isa MixedMatHRep{Float64, SparseMatrixCSC{Float64, Int}} - @test LiftedHRepresentation{Float64}(h) isa LiftedHRepresentation{Float64, SparseMatrixCSC{Float64, Int}} - end - for v in (convexhull(sparsevec([1], [1], 2), sparsevec([2], [-1])), vrep(sparse([1, 2], [1, 2], [1, -1]))) - @test Polyhedra.Hull(v) isa Polyhedra.Hull{Int, SparseVector{Int, Int}} - @test MixedMatVRep(v) isa MixedMatVRep{Int, SparseMatrixCSC{Int, Int}} - @test LiftedVRepresentation(v) isa LiftedVRepresentation{Int, SparseMatrixCSC{Int, Int}} - @test Polyhedra.Hull{Float64}(v) isa Polyhedra.Hull{Float64, SparseVector{Float64, Int}} - @test MixedMatVRep{Float64}(v) isa MixedMatVRep{Float64, SparseMatrixCSC{Float64, Int}} - @test LiftedVRepresentation{Float64}(v) isa LiftedVRepresentation{Float64, SparseMatrixCSC{Float64, Int}} - end + @testset "H-representation" begin + #FIXME inference fails @test (@inferred (HyperPlane([1, 1], 0) ∩ HyperPlane([1, 0], 1)) ∩ (HyperPlane([1, 1], 0) ∩ HyperPlane([1., 0.], 1))) isa Polyhedra.HyperPlanesIntersection{Float64} + @test ((HyperPlane([1, 1], 0) ∩ HyperPlane([1, 0], 1)) ∩ (HyperPlane([1, 1], 0) ∩ HyperPlane([1., 0.], 1))) isa Polyhedra.HyperPlanesIntersection{Float64} + @test HyperPlane([1, 1], 0) ∩ HalfSpace([1., 0.], 1.) isa Polyhedra.Intersection{Float64} + #FIXME inference fails @test (@inferred (HalfSpace([1., 0.], 1.) ∩ (HyperPlane([1, 1], 0) ∩ HyperPlane([1, 0], 1)))) isa Polyhedra.Intersection{Float64} + @test ((HalfSpace([1., 0.], 1.) ∩ (HyperPlane([1, 1], 0) ∩ HyperPlane([1, 0], 1)))) isa Polyhedra.Intersection{Float64} end - - @testset "Polar tests" begin - polar_test() +end +function test_conversion_different_array_type() + @testset "V-representation" begin + vv = convexhull(@SVector [0, 1]) + conichull((@SVector [1, 1]), Line(@SVector [1, 0])) + mv = vrep([0 1], [1 1; 1 0], BitSet([2])) + generator_fulltest(vv, mv) + mvv = @inferred convert(typeof(mv), vv) + vmv = @inferred convert(typeof(vv), mv) + generator_fulltest(vv, mvv) + generator_fulltest(vmv, vv) + end + @testset "H-representation" begin + vh = HalfSpace((@SVector [1, 0]), 0) ∩ HyperPlane((@SVector [0, 1]), 1) + mh = hrep([0 1; 1 0], [1, 0], BitSet(1)) + inequality_fulltest(vh, mh) + mvh = @inferred convert(typeof(mh), vh) + vmh = @inferred convert(typeof(vh), mh) + inequality_fulltest(vh, mvh) + inequality_fulltest(vmh, vh) end end +function test_copy() + @testset "V-representation" begin + vr = convexhull(@SVector [0, 1]) + vc = copy(vr) + @test vc !== vr + @test vc.points !== vr.points + generator_fulltest(vc, vr) + vr = conichull(Line(@SVector [1, 1]), Line(@SVector [1, 0])) + vc = copy(vr) + @test vc !== vr + @test vc.lines !== vr.lines + generator_fulltest(vc, vr) + vr = conichull(Line(@SVector [1, 1]), Line(@SVector [1, 0]), @SVector [1, 1]) + vc = copy(vr) + @test vc !== vr + @test vc.rays !== vr.rays + @test vc.lines !== vr.lines + @test vc.lines.lines !== vr.lines.lines + generator_fulltest(vc, vr) + vr = convexhull(@SVector [0, 1]) + conichull(Line(@SVector [1, 1]), (@SVector [1, 1]), Line(@SVector [1, 0])) + vc = copy(vr) + @test vc !== vr + @test vc.points !== vr.points + @test vc.points.points !== vr.points.points + @test vc.rays !== vr.rays + @test vc.rays.lines !== vr.rays.lines + @test vc.rays.lines.lines !== vr.rays.lines.lines + @test vc.rays.rays !== vr.rays.rays + generator_fulltest(vc, vr) + end + @testset "H-representation" begin + hr = HyperPlane([1, 0], 1) ∩ HyperPlane([0, 1], -1) + hc = copy(hr) + @test hc !== hr + @test hc.hyperplanes !== hr.hyperplanes + inequality_fulltest(hc, hr) + hr = HyperPlane([1, 0], 1) ∩ HyperPlane([1, 1], 0) ∩ HalfSpace([0, 1], -1) + hc = copy(hr) + @test hc !== hr + @test hc.hyperplanes !== hr.hyperplanes + @test hc.hyperplanes.hyperplanes !== hr.hyperplanes.hyperplanes + @test hc.halfspaces !== hr.halfspaces + inequality_fulltest(hc, hr) + end +end +function test_perserve_sparsity() + for h in (HalfSpace(sparsevec([1], [1], 2), 1) ∩ HyperPlane(sparsevec([2], [-1]), 3), hrep(sparse([1, 2], [1, 2], [1, -1]), [1, 3])) + @test Polyhedra.Intersection(h) isa Polyhedra.Intersection{Int, SparseVector{Int, Int}} + @test LPHRep(h) isa LPHRep{Int} + @test MixedMatHRep(h) isa MixedMatHRep{Int, SparseMatrixCSC{Int, Int}} + @test LiftedHRepresentation(h) isa LiftedHRepresentation{Int, SparseMatrixCSC{Int, Int}} + @test Polyhedra.Intersection{Float64}(h) isa Polyhedra.Intersection{Float64, SparseVector{Float64, Int}} + @test LPHRep{Float64}(h) isa LPHRep{Float64} + @test MixedMatHRep{Float64}(h) isa MixedMatHRep{Float64, SparseMatrixCSC{Float64, Int}} + @test LiftedHRepresentation{Float64}(h) isa LiftedHRepresentation{Float64, SparseMatrixCSC{Float64, Int}} + end + for v in (convexhull(sparsevec([1], [1], 2), sparsevec([2], [-1])), vrep(sparse([1, 2], [1, 2], [1, -1]))) + @test Polyhedra.Hull(v) isa Polyhedra.Hull{Int, SparseVector{Int, Int}} + @test MixedMatVRep(v) isa MixedMatVRep{Int, SparseMatrixCSC{Int, Int}} + @test LiftedVRepresentation(v) isa LiftedVRepresentation{Int, SparseMatrixCSC{Int, Int}} + @test Polyhedra.Hull{Float64}(v) isa Polyhedra.Hull{Float64, SparseVector{Float64, Int}} + @test MixedMatVRep{Float64}(v) isa MixedMatVRep{Float64, SparseMatrixCSC{Float64, Int}} + @test LiftedVRepresentation{Float64}(v) isa LiftedVRepresentation{Float64, SparseMatrixCSC{Float64, Int}} + end +end + +function _test_scalar_multiplication(T=Rational{BigInt}) + v = convexhull(T[1, 2], T[2, 1]) + v2 = 2v + @test Polyhedra.coefficient_type(v2) == T + ps = collect(points(v2)) + @test ps[1] == T[2, 4] + @test ps[2] == T[4, 2] + h = HalfSpace(T[4, 2], 0) ∩ HalfSpace(T[2, 4], 3) + h2 = 2h + @test Polyhedra.coefficient_type(h2) == T + hs = collect(halfspaces(h2)) + @test hs[1] == HalfSpace(T[2, 1], 0) + @test hs[2] == HalfSpace(T[1, 2], 3) +end + +function test_scalar_multiplication() + _test_scalar_multiplication(Float64) + _test_scalar_multiplication(Rational{BigInt}) +end + +end # module + +TestRepresentation.runtests() diff --git a/test/vecrep.jl b/test/vecrep.jl index b3ca017b..1b0411da 100644 --- a/test/vecrep.jl +++ b/test/vecrep.jl @@ -1,4 +1,4 @@ -function convexhull_test() +function test_convexhull() v = convexhull([1, 0, 0]) + conichull(Ray([0, 1, 0]), Line([0, 0, 1])) @test npoints(v) == 1 @test nlines(v) == 1 @@ -34,7 +34,7 @@ function convexhull_test() @test nrays(v) == 2 end -function intersect_test() +function test_intersect() h = HalfSpace([1, 0], 1) ∩ HyperPlane([0, 1], 1) @test nhyperplanes(h) == 1 @test nhalfspaces(h) == 1 @@ -54,12 +54,3 @@ function intersect_test() @test nhyperplanes(h) == 2 @test nhalfspaces(h) == 2 end - -@testset "VecRep" begin - @testset "Convex hull" begin - convexhull_test() - end - @testset "Intersection" begin - intersect_test() - end -end