Skip to content

Commit 4d3c5fe

Browse files
committed
fix 'linear_map' for Universe
1 parent 3bdbc6e commit 4d3c5fe

File tree

4 files changed

+58
-23
lines changed

4 files changed

+58
-23
lines changed

docs/src/lib/sets/Universe.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ Undocumented implementations:
8484
* [`reflect`](@ref reflect(::LazySet))
8585
* [`distance`](@ref distance(::AbstractVector, ::LazySet))
8686
* [``](@ref ∈(::AbstractVector, ::LazySet))
87+
* [`linear_map`](@ref linear_map(::AbstractMatrix, ::LazySet))
8788
* [`permute`](@ref permute(::LazySet, ::AbstractVector{Int}))
8889
* [`project`](@ref project(::LazySet, ::AbstractVector{Int}))
8990
* [`rationalize`](@ref rationalize(::LazySet))
@@ -115,7 +116,6 @@ Inherited from [`LazySet`](@ref):
115116
* [`affine_map`](@ref affine_map(::AbstractMatrix, ::LazySet, ::AbstractVector))
116117
* [`exponential_map`](@ref exponential_map(::AbstractMatrix, ::LazySet))
117118
* [`is_interior_point`](@ref is_interior_point(::AbstractVector, ::LazySet))
118-
* [`linear_map`](@ref linear_map(::AbstractMatrix, ::LazySet))
119119
* [`sample`](@ref sample(::LazySet, ::Int=1))
120120
* [``](@ref ≈(::LazySet, ::LazySet))
121121
* [`isdisjoint`](@ref isdisjoint(::LazySet, ::LazySet))

src/Sets/Universe/UniverseModule.jl

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@ using ReachabilityBase.Require: require
1414
constraints_list, diameter, dim, isbounded,
1515
isboundedtype, isempty, isoperationtype, isuniversal,
1616
norm, radius, rand, rectify, reflect, volume, ,
17-
permute, project, scale, scale!, ρ, σ, translate,
18-
translate!, cartesian_product, convex_hull, difference,
19-
distance, intersection, isdisjoint, ,
17+
linear_map, permute, project, scale, scale!, ρ, σ,
18+
translate, translate!, cartesian_product, convex_hull,
19+
difference, distance, intersection, isdisjoint, ,
2020
linear_combination, minkowski_difference, minkowski_sum
2121
@reexport import ..LazySets: constrained_dimensions, linear_map_inverse,
2222
rationalize, tosimplehrep, triangulate
@@ -49,6 +49,7 @@ include("rectify.jl")
4949
include("reflect.jl")
5050
include("volume.jl")
5151
include("in.jl")
52+
include("linear_map.jl")
5253
include("permute.jl")
5354
include("project.jl")
5455
include("scale.jl")

src/Sets/Universe/linear_map.jl

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
"""
2+
# Extended help
3+
4+
linear_map(M::AbstractMatrix, U::Universe)
5+
6+
### Output
7+
8+
Either a `Universe`, or an `HPolyhedron` if the map contains zero rows.
9+
"""
10+
@validate function linear_map(M::AbstractMatrix, U::Universe)
11+
m = size(M, 1)
12+
N = promote_type(eltype(M), eltype(U))
13+
first_zero_row = 0
14+
for i in 1:m
15+
if iszero(M[i, :])
16+
first_zero_row = i
17+
break
18+
end
19+
end
20+
if first_zero_row == 0
21+
return Universe{N}(m)
22+
end
23+
24+
require(@__MODULE__, :LazySets; fun_name="linear_map")
25+
clist = Vector{HalfSpace{N,SingleEntryVector{N}}}()
26+
_push_zero_constraint!(clist, N, first_zero_row, m)
27+
for i in (first_zero_row + 1):m
28+
if iszero(M[i, :])
29+
_push_zero_constraint!(clist, N, i, m)
30+
end
31+
end
32+
return HPolyhedron(clist)
33+
end
34+
35+
function _push_zero_constraint!(clist, N, i, n)
36+
push!(clist, HalfSpace(SingleEntryVector(i, n, one(N)), zero(N)))
37+
push!(clist, HalfSpace(SingleEntryVector(i, n, N(-1)), zero(N)))
38+
end

test/Sets/Universe.jl

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -196,14 +196,12 @@ for N in @tN([Float64, Float32, Rational{Int}])
196196
# affine_map
197197
@test_throws DimensionMismatch affine_map(ones(N, 2, 3), U, N[1, 1])
198198
@test_throws DimensionMismatch affine_map(ones(N, 2, 2), U, N[1])
199-
@static if isdefined(@__MODULE__, :Polyhedra) && isdefined(@__MODULE__, :CDDLib)
200-
# TODO this should work, even without Polyhedra
201-
@test_broken affine_map(ones(N, 2, 2), U, N[1, 1])
202-
# U2 = affine_map(ones(N, 2, 2), U, N[1, 1])
203-
# @test isidentical(U, U2)
204-
# U2 = affine_map(ones(N, 3, 2), U, N[1, 1, 3])
205-
# @test isidentical(U3, U2)
206-
end
199+
U2 = affine_map(ones(N, 2, 2), U, N[1, 1])
200+
@test isidentical(U, U2)
201+
X = affine_map(N[1 2; 0 0], U, N[1, 1])
202+
@test X isa HPolyhedron{N} && isequivalent(X, Hyperplane(N[0, 1], N(1)))
203+
U2 = affine_map(ones(N, 3, 2), U, N[1, 1, 3])
204+
@test isidentical(U3, U2)
207205

208206
# distance (between point and set)
209207
@test_throws DimensionMismatch distance(U, N[0])
@@ -233,16 +231,14 @@ for N in @tN([Float64, Float32, Rational{Int}])
233231

234232
# linear_map
235233
@test_throws DimensionMismatch linear_map(ones(N, 2, 3), U)
236-
@static if isdefined(@__MODULE__, :Polyhedra) && isdefined(@__MODULE__, :CDDLib)
237-
# TODO this should work, even without Polyhedra
238-
@test_broken linear_map(ones(N, 2, 2), U)
239-
# U2 = linear_map(ones(N, 2, 2), U)
240-
# @test_broken isidentical(U, U2)
241-
@test_broken linear_map(ones(N, 3, 2), U)
242-
# U2 = linear_map(ones(N, 3, 2), U)
243-
# @test U2 isa HPolyhedron{N} # TODO this should change
244-
# @test_broken isidentical(U3, U2)
245-
end
234+
U2 = linear_map(ones(N, 2, 2), U)
235+
@test isidentical(U, U2)
236+
U2 = linear_map(ones(N, 3, 2), U)
237+
@test isidentical(U3, U2)
238+
P = linear_map(N[1 0; 0 0], U)
239+
@test P isa HPolyhedron{N} && isequivalent(P, Hyperplane(N[0, 1], N(0)))
240+
P = linear_map(N[0 0; 0 0; 0 0], U)
241+
@test P isa HPolyhedron{N} && isequivalent(P, ZeroSet{N}(3))
246242

247243
# linear_map_inverse
248244
U2 = LazySets.linear_map_inverse(ones(N, 2, 3), U)
@@ -466,5 +462,5 @@ for N in @tN([Float64, Float32])
466462

467463
# exponential_map
468464
U2 = exponential_map(ones(N, 2, 2), U)
469-
@test_broken isidentical(U, U2) # TODO this should change
465+
@test isidentical(U, U2)
470466
end

0 commit comments

Comments
 (0)