Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#1344 - Efficient intersection with intervals #1345

Merged
merged 1 commit into from
May 14, 2019
Merged

Conversation

schillic
Copy link
Member

@schillic schillic commented May 4, 2019

Closes #1344.

julia> using LazySets, BenchmarkTools

julia> i = Interval([1., 2.]);

julia> hs = HalfSpace([1.], 1.5);

julia> hp = Hyperplane([-1.], -1.5);

julia> b = Ball1([2.], 0.5);

julia> c = ConvexHull(Singleton([-5.]), Singleton([-1.]));

julia> @btime intersection(i, hs)  # master
  60.737 μs (210 allocations: 14.02 KiB)
HPolytope{Float64}(HalfSpace{Float64}[HalfSpace{Float64}([-1.0], -1.0), HalfSpace{Float64}([1.0], 1.5)])

julia> @which intersection(i, hs)  # uses generic intersection of polyhedra
intersection(P1::AbstractPolyhedron{N}, P2::AbstractPolyhedron{N}) where N<:Real in LazySets at LazySets/src/concrete_intersection.jl:345

julia> @btime intersection(i, hs)  # new
  338.991 ns (9 allocations: 160 bytes)
Interval{Float64,IntervalArithmetic.Interval{Float64}}([1, 1.5])

julia> @btime intersection(i, hp)  # master
  81.807 μs (276 allocations: 18.55 KiB)
HPolytope{Float64}(HalfSpace{Float64}[HalfSpace{Float64}([-1.0], -1.5), HalfSpace{Float64}([1.0], 1.5)])

julia> @which intersection(i, hp)  # uses generic intersection of polyhedra
intersection(P1::AbstractPolyhedron{N}, P2::AbstractPolyhedron{N}) where N<:Real in LazySets at LazySets/src/concrete_intersection.jl:345

julia> @btime intersection(i, hp)  # new
  1.962 μs (5 allocations: 160 bytes)
Singleton{Float64,Array{Float64,1}}([1.5])

julia> @btime intersection(i, b)  # master
  86.117 μs (295 allocations: 19.34 KiB)
HPolytope{Float64}(HalfSpace{Float64}[HalfSpace{Float64}([1.0], 2.0), HalfSpace{Float64}([-1.0], -1.5)])

julia> @btime intersection(i, b)  # new
  309.758 ns (7 allocations: 608 bytes)
Interval{Float64,IntervalArithmetic.Interval{Float64}}([1.5, 2])

julia> @btime intersection(i, c)  # master
ERROR: MethodError: no method matching intersection(::Interval{Float64,IntervalArithmetic.Interval{Float64}}, ::ConvexHull{Float64,Singleton{Float64,Array{Float64,1}},Singleton{Float64,Array{Float64,1}}})

julia> @btime intersection(i, c)  # new
  160.299 ns (2 allocations: 192 bytes)
EmptySet{Float64}()

@schillic schillic requested a review from mforets May 4, 2019 18:38
@schillic schillic changed the title #1344 - Efficient intersection of Interval and HalfSpace/Hyperplane WIP #1344 - Efficient intersection with intervals May 4, 2019
@schillic schillic changed the title WIP #1344 - Efficient intersection with intervals #1344 - Efficient intersection with intervals May 4, 2019
@mforets
Copy link
Member

mforets commented May 7, 2019

This is awesome! 🚀

I started to read the logic of intersection(::Interval, ::HalfSpace) which i agree. The variation considered below gives ~35% faster comparing the tests. Seems to me that it amounts to merging your far_bound and close_bound checks...?

function intersection_b(X::Interval{N}, hs::HalfSpace{N})::Union{Interval{N}, EmptySet{N}} where {N<:Real}
    @assert dim(hs) == 1 "cannot take the intersection between an interval " *
                         "and a $(dim(hs))-dimensional half-space"

    lo = min(X); hi = max(X)
    b = hs.b; a = hs.a[1]
    b_over_a = b / a
    
    if _geq(a, zero(N))
        if _leq(b_over_a, lo)
            return EmptySet()
        else
            return Interval(lo, min(b_over_a, hi))
        end
    else
        if _geq(b_over_a, hi)
            return EmptySet()
        else
            return Interval(max(b_over_a, l), hi)
        end
    end
end

@schillic
Copy link
Member Author

schillic commented May 7, 2019

if _geq(a, zero(N))

Using approximations for a sign check does not make sense to me.

@mforets
Copy link
Member

mforets commented May 7, 2019

Using approximations for a sign check does not make sense to me.

👍 it should be dropped

@schillic
Copy link
Member Author

The variation considered below gives ~35% faster comparing the tests.

I added a new version following your idea. It is, however, not as small as yours because there were problems with division by zero.

@mforets
Copy link
Member

mforets commented May 13, 2019

This code does divides in b_over_a = b / a; if the normal vector was zero the half-space is either the universal set or the empty set, depending on b; i think that if we encounter those case in practice we can just an assertion in the HalfSpace constructor.

@schillic
Copy link
Member Author

Yes, I cared for that. I would say it can happen in practice that a is very close to zero.

@schillic schillic merged commit b5d9a98 into master May 14, 2019
@schillic schillic deleted the schillic/1344 branch May 14, 2019 06:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Efficient intersection with intervals
2 participants