Skip to content

Commit

Permalink
Merge pull request #191 from invenia/revert-179-dfl/set-operations
Browse files Browse the repository at this point in the history
Revert "Multi-interval set operators"
  • Loading branch information
rofinn authored Jun 1, 2022
2 parents 7a7ec36 + 7f7fd0e commit cb4f4d5
Show file tree
Hide file tree
Showing 13 changed files with 160 additions and 1,068 deletions.
2 changes: 0 additions & 2 deletions .JuliaFormatter.toml

This file was deleted.

1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,3 @@
/docs/build/
/docs/site/
/Manifest.toml
/test/Manifest.toml
15 changes: 14 additions & 1 deletion Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name = "Intervals"
uuid = "d8418881-c3e1-53bb-8760-2df7ec849ed5"
license = "MIT"
authors = ["Invenia Technical Computing"]
version = "1.7.0"
version = "1.7.1"

[deps]
Dates = "ade2ca70-3891-5945-98fb-dc099432e06a"
Expand All @@ -12,6 +12,19 @@ Serialization = "9e88b42a-f829-5b0c-bbe9-9e923198166b"
TimeZones = "f269a46b-ccf7-5d73-abea-4c690281aa53"

[compat]
Documenter = "0.23, 0.24, 0.25, 0.26, 0.27"
Infinity = "0.2.3"
RecipesBase = "0.7, 0.8, 1"
TimeZones = "1.7"
julia = "1.6"

[extras]
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
ImageMagick = "6218d12a-5da1-5696-b52f-db25d2ecc6d1"
Infinity = "a303e19e-6eb4-11e9-3b09-cd9505f79100"
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
VisualRegressionTests = "34922c18-7c2a-561c-bac1-01e79b2c4c92"

[targets]
test = ["Documenter", "ImageMagick", "Infinity", "Plots", "Test", "VisualRegressionTests"]
84 changes: 34 additions & 50 deletions docs/src/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,38 +26,21 @@ This package defines:
* [`Open`](@ref), indicating the endpoint value of the interval is not included
* [`Unbounded`](@ref), indicating the endpoint value is effectively infinite

## Sets

A single interval can be used to represent a contiguous set within a domain but cannot be
used to represent a disjoint set. Due to this restriction all set-based operations that
return an interval will always return a vector of intervals. These operations will combine
any intervals which are overlapping or touching into a single continuous interval and never
return an interval instance which itself is empty.

```julia
julia> union([1..10], [5..15])
1-element Vector{Interval{Int64, Closed, Closed}}:
Interval{Int64, Closed, Closed}(1, 15)
## Example Usage

julia> intersect([1..10], [5..15])
1-element Vector{Interval{Int64, Closed, Closed}}:
Interval{Int64, Closed, Closed}(5, 10)
### Intersection

julia> setdiff([1..10], [5..15])
1-element Vector{Interval{Int64, Closed, Open}}:
Interval{Int64, Closed, Open}(1, 5)
```jldoctest
julia> a = 1..10
Interval{Int64, Closed, Closed}(1, 10)
julia> symdiff([1..10], [5..15])
2-element Vector{Interval{Int64}}:
Interval{Int64, Closed, Open}(1, 5)
Interval{Int64, Open, Closed}(10, 15)
julia> b = 5..15
Interval{Int64, Closed, Closed}(5, 15)
julia> intersect([1..5], [10..15])
Interval[]
julia> intersect(a, b)
Interval{Int64, Closed, Closed}(5, 10)
```

## Example Usage

### Bounds

```jldoctest
Expand Down Expand Up @@ -152,6 +135,31 @@ julia> anchor(he)
2013-02-13T01:00:00-06:00
```

### Plotting
`AbstractInterval` subtypes can be plotted with [Plots.jl](https://github.com/JuliaPlots/Plots.jl).


```julia
julia> using Plots

julia> start_dt = DateTime(2017,1,1,0,0,0);

julia> end_dt = DateTime(2017,1,1,10,30,0);

julia> datetimes = start_dt:Hour(1):end_dt
DateTime("2017-01-01T00:00:00"):Hour(1):DateTime("2017-01-01T10:00:00")

julia> intervals = HE.(datetimes);

julia> plot(intervals, 1:11)
```

![Example Plot](assets/HE.png)

In the plot, inclusive boundaries are marked with a vertical bar, whereas exclusive boundaries just end.



### Comparisons

#### Equality
Expand Down Expand Up @@ -239,30 +247,6 @@ julia> round(AnchoredInterval{+0.5}(0.5), on=:right)
AnchoredInterval{0.5, Float64, Closed, Open}(0.5)
```

### Plotting

`AbstractInterval` subtypes can be plotted with [Plots.jl](https://github.com/JuliaPlots/Plots.jl).

```julia
julia> using Plots

julia> start_dt = DateTime(2017,1,1,0,0,0);

julia> end_dt = DateTime(2017,1,1,10,30,0);

julia> datetimes = start_dt:Hour(1):end_dt
DateTime("2017-01-01T00:00:00"):Hour(1):DateTime("2017-01-01T10:00:00")

julia> intervals = HE.(datetimes);

julia> plot(intervals, 1:11)
```

![Example Plot](assets/HE.png)

In the plot, inclusive boundaries are marked with a vertical bar, whereas exclusive boundaries just end.


## API

```@docs
Expand Down
1 change: 0 additions & 1 deletion src/Intervals.jl
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ bounds_types(x::AbstractInterval{T,L,R}) where {T,L,R} = (L, R)
include("isfinite.jl")
include("endpoint.jl")
include("interval.jl")
include("interval_sets.jl")
include("anchoredinterval.jl")
include("parse.jl")
include("description.jl")
Expand Down
3 changes: 1 addition & 2 deletions src/endpoint.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ const Right = Direction{:Right}()
const Beginning = Left
const Ending = Right

abstract type AbstractEndpoint end
struct Endpoint{T, D, B <: Bound} <: AbstractEndpoint
struct Endpoint{T, D, B <: Bound}
endpoint::T

function Endpoint{T,D,B}(ep::T) where {T, D, B <: Bounded}
Expand Down
54 changes: 54 additions & 0 deletions src/interval.jl
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,60 @@ function Base.intersect(a::AbstractInterval{S}, b::AbstractInterval{T}) where {S
return Interval(left, right)
end

# There is power in a union.
"""
union(intervals::AbstractVector{<:AbstractInterval})
Flattens a vector of overlapping intervals into a new, smaller vector containing only
non-overlapping intervals.
"""
function Base.union(intervals::AbstractVector{<:AbstractInterval})
return union!(convert(Vector{AbstractInterval}, intervals))
end

"""
union!(intervals::AbstractVector{<:Union{Interval, AbstractInterval}})
Flattens a vector of overlapping intervals in-place to be a smaller vector containing only
non-overlapping intervals.
"""
function Base.union!(intervals::Union{AbstractVector{<:Interval}, AbstractVector{AbstractInterval}})
sort!(intervals)

i = 2
n = length(intervals)
while i <= n
prev = intervals[i - 1]
curr = intervals[i]

# If the current and previous intervals don't meet then move along
if !overlaps(prev, curr) && !contiguous(prev, curr)
i = i + 1

# If the two intervals meet then we absorb the current interval into
# the previous one.
else
intervals[i - 1] = merge(prev, curr)
deleteat!(intervals, i)
n -= 1
end
end

return intervals
end

"""
superset(intervals::AbstractArray{<:AbstractInterval}) -> Interval
Create the smallest single interval which encompasses all of the provided intervals.
"""
function superset(intervals::AbstractArray{<:AbstractInterval})
left = minimum(LeftEndpoint.(intervals))
right = maximum(RightEndpoint.(intervals))

return Interval(left, right)
end

function Base.merge(a::AbstractInterval, b::AbstractInterval)
if !overlaps(a, b) && !contiguous(a, b)
throw(ArgumentError("$a and $b are neither overlapping or contiguous."))
Expand Down
Loading

2 comments on commit cb4f4d5

@rofinn
Copy link
Member Author

@rofinn rofinn commented on cb4f4d5 Jun 1, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Registration pull request created: JuliaRegistries/General/61497

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a v1.7.1 -m "<description of version>" cb4f4d59553a3630fdaff795d18fd99d653ac01c
git push origin v1.7.1

Please sign in to comment.