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

#162 - Add macros to automatically create boilerplate code #228

Merged
merged 10 commits into from
Feb 11, 2018
3 changes: 3 additions & 0 deletions docs/src/lib/utils.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,7 @@ end

```@docs
sign_cadlag
@commutative_neutral
@commutative_absorbing
@commutative_neutral_absorbing
```
130 changes: 35 additions & 95 deletions src/CartesianProduct.jl
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ The Cartesian product of three elements is obtained recursively.
See also `CartesianProductArray` for an implementation of a Cartesian product of
many sets without recursion, instead using an array.

The `EmptySet` is the absorbing element for `CartesianProduct`.

Constructors:

- `CartesianProduct{N<:Real, S1<:LazySet{N}, S2<:LazySet{N}}(X1::S1, X2::S2)`
-- default constructor

Expand All @@ -45,9 +49,12 @@ CartesianProduct(Xarr::Vector{S}) where {S<:LazySet{N}} where {N<:Real} =
: CartesianProduct(Xarr[1],
CartesianProduct(Xarr[2:length(Xarr)])))

# EmptySet is the absorbing element for CartesianProduct
@commutative_absorbing(CartesianProduct, EmptySet)

"""
```
*(X::LazySet, Y::LazySet)::CartesianProduct
*(X::LazySet, Y::LazySet)
```

Return the Cartesian product of two convex sets.
Expand All @@ -61,7 +68,7 @@ Return the Cartesian product of two convex sets.

The Cartesian product of the two convex sets.
"""
*(X::LazySet, Y::LazySet)::CartesianProduct = CartesianProduct(X, Y)
*(X::LazySet, Y::LazySet) = CartesianProduct(X, Y)

"""
×
Expand All @@ -70,43 +77,6 @@ Alias for the binary Cartesian product.
"""
×(X::LazySet, Y::LazySet) = *(X, Y)

"""
X × ∅

Right multiplication of a set by an empty set.

### Input

- `X` -- a convex set
- `∅` -- an empty set

### Output

An empty set, because the empty set is the absorbing element for the
Cartesian product.
"""
*(::LazySet, ∅::EmptySet) = ∅

"""
∅ × X

Left multiplication of a set by an empty set.

### Input

- `X` -- a convex set
- `∅` -- an empty set

### Output

An empty set, because the empty set is the absorbing element for the
Cartesian product.
"""
*(∅::EmptySet, ::LazySet) = ∅

# special case: pure empty set multiplication (we require the same numeric type)
(*(∅::E, ::E)) where {E<:EmptySet} = ∅

"""
dim(cp::CartesianProduct)::Int

Expand Down Expand Up @@ -180,32 +150,34 @@ Type that represents the Cartesian product of a finite number of convex sets.

### Notes

- `CartesianProductArray(array::Vector{<:LazySet})` -- default constructor
The `EmptySet` is the absorbing element for `CartesianProductArray`.

- `CartesianProductArray()` -- constructor for an empty Cartesian product
Constructors:
Copy link
Member

Choose a reason for hiding this comment

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

while we are at this line, a general thought is that i find the illustration of the different constructors to be more friendly if it is given as a proper example, rather than a copy paste of the source code -- if one wants that level of detail, then it's better to just look the code, by clicking on "view source", no? (or use Julia's @edit macro). that is to say that for me we can delete this part and instead put some examples of the different uses (in another PR).

Copy link
Member Author

Choose a reason for hiding this comment

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

I added #232.


- `CartesianProductArray(n::Int, [N]::Type=Float64)`
-- constructor for an empty Cartesian product with size hint and numeric type
- `CartesianProductArray(array::Vector{<:LazySet})` -- default constructor

- `CartesianProductArray([n]::Int=0, [N]::Type=Float64)`
-- constructor for an empty product with optional size hint and numeric type
"""
struct CartesianProductArray{N<:Real, S<:LazySet{N}} <: LazySet{N}
array::Vector{S}
end

# type-less convenience constructor
CartesianProductArray(arr::Vector{S}) where {S<:LazySet{N}} where {N<:Real} =
CartesianProductArray{N, S}(arr)
# constructor for an empty Cartesian product of floats
CartesianProductArray() =
CartesianProductArray{Float64, LazySet{Float64}}(Vector{LazySet{Float64}}(0))
# constructor for an empty Cartesian product with size hint and numeric type
function CartesianProductArray(n::Int, N::Type=Float64)::CartesianProductArray

# constructor for an empty product with optional size hint and numeric type
function CartesianProductArray(n::Int=0, N::Type=Float64)::CartesianProductArray
arr = Vector{LazySet{N}}(0)
sizehint!(arr, n)
return CartesianProductArray(arr)
end

"""
```
*(cpa::CartesianProductArray, S::LazySet)::CartesianProductArray
CartesianProductArray(cpa::CartesianProductArray,
S::LazySet)::CartesianProductArray
```

Multiply a convex set to a Cartesian product of a finite number of convex sets
Expand All @@ -220,14 +192,16 @@ from the right.

The modified Cartesian product of a finite number of convex sets.
"""
function *(cpa::CartesianProductArray, S::LazySet)::CartesianProductArray
function CartesianProductArray(cpa::CartesianProductArray,
S::LazySet)::CartesianProductArray
push!(cpa.array, S)
return cpa
end

"""
```
*(S::LazySet, cpa::CartesianProductArray)::CartesianProductArray
CartesianProductArray(S::LazySet,
cpa::CartesianProductArray)::CartesianProductArray
```

Multiply a convex set to a Cartesian product of a finite number of convex sets
Expand All @@ -242,52 +216,15 @@ from the left.

The modified Cartesian product of a finite number of convex sets.
"""
function *(S::LazySet, cpa::CartesianProductArray)::CartesianProductArray
push!(cpa.array, S)
return cpa
function CartesianProductArray(S::LazySet,
Copy link
Member

@mforets mforets Feb 10, 2018

Choose a reason for hiding this comment

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

ok, this change is to save the symbol * for the binary operator only, in other words these two that used to be the same are now different:

julia>  b = Ball2(zeros(2), 1.);

julia> c = CartesianProductArray([b, b])

julia> CartesianProductArray(b, c)
LazySets.CartesianProductArray{Float64,LazySets.Ball2{Float64}}(LazySets.Ball2{Float64}[LazySets.Ball2{Float64}([0.0, 0.0], 1.0), LazySets.Ball2{Float64}([0.0, 0.0], 1.0), LazySets.Ball2{Float64}([0.0, 0.0],
 1.0)])

julia> b * c
LazySets.CartesianProduct{Float64,LazySets.Ball2{Float64},LazySets.CartesianProductArray{Float64,LazySets.Ball2{Float64}}}(LazySets.Ball2{Float64}([0.0, 0.0], 1.0), LazySets.CartesianProductArray{Float64,Laz
ySets.Ball2{Float64}}(LazySets.Ball2{Float64}[LazySets.Ball2{Float64}([0.0, 0.0], 1.0), LazySets.Ball2{Float64}([0.0, 0.0], 1.0), LazySets.Ball2{Float64}([0.0, 0.0], 1.0)]))

i doubt a bit, but maybe it is more sensible the new behavior.

Copy link
Member Author

Choose a reason for hiding this comment

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

Actually I wanted to discuss this.
Previously * and CartesianProduct were not identical. I found this inconsistent, because *(S, T) was said to be an alias for CartesianProduct(S, T).
Now it is identical, but we get what you observed.

I propose to additionally add a similar macro relating CartesianProduct and CartesianProductArray (and similarly for the other two) such that we also get the old behavior.
If you agree, should I do it here or in a follow-up PR?

Copy link
Member

Choose a reason for hiding this comment

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

follow-up PR

Copy link
Member Author

Choose a reason for hiding this comment

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

Okay, I took a note in the related issue #162.

cpa::CartesianProductArray)::CartesianProductArray
return CartesianProductArray(cpa, S)
end

"""
```
*(cpa::CartesianProductArray, ∅::EmptySet)
```

Right multiplication of a `CartesianProductArray` by an empty set.

### Input

- `cpa` -- Cartesian product array
- `∅` -- an empty set

### Output

An empty set, because the empty set is the absorbing element for the
Cartesian product.
"""
*(::CartesianProductArray, ∅::EmptySet) = ∅

"""
```
*(S::EmptySet, cpa::CartesianProductArray)
```

Left multiplication of a set by an empty set.

### Input

- `X` -- a convex set
- `∅` -- an empty set

### Output

An empty set, because the empty set is the absorbing element for the
Cartesian product.
"""
*(∅::EmptySet, ::CartesianProductArray) = ∅

"""
```
*(cpa1::CartesianProductArray, cpa2::CartesianProductArray)::CartesianProductArray
CartesianProductArray(cpa1::CartesianProductArray,
cpa2::CartesianProductArray)::CartesianProductArray
```

Multiply a finite Cartesian product of convex sets to another finite Cartesian
Expand All @@ -302,12 +239,15 @@ product.

The modified first Cartesian product.
"""
function *(cpa1::CartesianProductArray,
cpa2::CartesianProductArray)::CartesianProductArray
function CartesianProductArray(cpa1::CartesianProductArray,
cpa2::CartesianProductArray)::CartesianProductArray
append!(cpa1.array, cpa2.array)
return cpa1
end

# EmptySet is the absorbing element for CartesianProduct
@commutative_absorbing(CartesianProductArray, EmptySet)

"""
array(cpa::CartesianProductArray{N, S})::Vector{S} where {N<:Real, S<:LazySet{N}}

Expand Down
70 changes: 26 additions & 44 deletions src/ConvexHull.jl
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ Type that represents the convex hull of the union of two convex sets.
- `X` -- convex set
- `Y` -- convex set

### Notes

The `EmptySet` is the neutral element for `ConvexHull`.

### Examples

Convex hull of two 100-dimensional Euclidean balls:
Expand All @@ -42,48 +46,16 @@ end
ConvexHull(X::S1, Y::S2) where {S1<:LazySet{N}, S2<:LazySet{N}} where {N<:Real} =
ConvexHull{N, S1, S2}(X, Y)

# EmptySet is the neutral element for ConvexHull
@commutative_neutral(ConvexHull, EmptySet)

"""
CH

Alias for `ConvexHull`.
"""
const CH = ConvexHull

"""
ConvexHull(X, ∅)

Convex hull of a set with the empty set from the right.

### Input

- `X` -- a convex set
- `∅` -- an empty set

### Output

The given set because the empty set is neutral for the convex hull.
"""
ConvexHull(X::LazySet{N}, ::EmptySet{N}) where {N<:Real} = X

"""
ConvexHull(∅, X)

Convex hull of a set with the empty set from the left.

### Input

- `∅` -- an empty set
- `X` -- a convex set

### Output

The given set because the empty set is neutral for the convex hull.
"""
ConvexHull(::EmptySet{N}, X::LazySet{N}) where {N<:Real} = X

# special case: pure empty set convex hull (we require the same numeric type)
(ConvexHull(∅::E, ::E)) where {E<:EmptySet} = ∅

"""
dim(ch::ConvexHull)::Int

Expand Down Expand Up @@ -132,6 +104,17 @@ Type that represents the symbolic convex hull of a finite number of convex sets.

- `array` -- array of sets

### Notes

The `EmptySet` is the neutral element for `ConvexHullArray`.

Constructors:

- `ConvexHullArray(array::Vector{<:LazySet})` -- default constructor

- `ConvexHullArray([n]::Int=0, [N]::Type=Float64)`
-- constructor for an empty hull with optional size hint and numeric type

### Examples

Convex hull of 100 two-dimensional balls whose centers follows a sinusoidal:
Expand All @@ -145,29 +128,28 @@ julia> c = ConvexHullArray(b);
struct ConvexHullArray{N<:Real, S<:LazySet{N}} <: LazySet{N}
array::Vector{S}
end
# type-less convenience constructor
ConvexHullArray(a::Vector{S}) where {S<:LazySet{N}} where {N<:Real} = ConvexHullArray{N, S}(a)

# constructor for an empty convex hull array
ConvexHullArray() = ConvexHullArray{Float64, LazySet{Float64}}(Vector{LazySet{Float64}}(0))
# type-less convenience constructor
ConvexHullArray(a::Vector{S}) where {S<:LazySet{N}} where {N<:Real} =
ConvexHullArray{N, S}(a)

# constructor for an empty convex hull array with size hint and numeric type
function ConvexHullArray(n::Int, N::Type=Float64)::ConvexHullArray
# constructor for an empty hull with optional size hint and numeric type
function ConvexHullArray(n::Int=0, N::Type=Float64)::ConvexHullArray
a = Vector{LazySet{N}}(0)
sizehint!(a, n)
return ConvexHullArray(a)
end

# EmptySet is the neutral element for ConvexHullArray
@commutative_neutral(ConvexHullArray, EmptySet)

"""
CHArray

Alias for `ConvexHullArray`.
"""
const CHArray = ConvexHullArray

CH(cha::ConvexHullArray, ∅::EmptySet) = cha
CH(∅::EmptySet, cha::ConvexHullArray) = cha

CH(cha1::ConvexHullArray, cha2::ConvexHullArray) = ConvexHullArray(vcat(cha1.array, cha2.array))

"""
Expand Down
Loading