## DomainSets.jl

A Julia package for describing domains in Euclidean space
Author JuliaApproximation
Popularity
14 Stars
Updated Last
1 Year Ago
Started In
May 2017

# DomainSets.jl

DomainSets.jl is a package designed to represent simple infinite sets, that can be used to encode domains of functions. For example, the domain of the function `log(x::Float64)` is the infinite open interval, which is represented by the type `HalfLine{Float64}()`.

## Examples

### Intervals

DomainSets.jl uses IntervalSets.jl for closed and open intervals. In addition, it defines a few standard intervals.

```julia> using DomainSets, StaticArrays

julia> UnitInterval()
0.0..1.0 (Unit)

julia> ChebyshevInterval()
-1.0..1.0 (Chebyshev)

julia> HalfLine()
0.0..Inf (closed–open) (HalfLine)```

### Rectangles

Rectangles can be constructed as a product of intervals, where the elements of the domain are `SVector{2}`:

```julia> using DomainSets: ×

julia> (-1..1) × (0..3) × (4.0..5.0)
(-1.0..1.0) × (0.0..3.0) × (4.0..5.0)

julia> SVector(1,2) in (-1..1) × (0..3)
true

julia> UnitInterval()^3
UnitCube()```

### Circles and Spheres

A `UnitSphere` contains `x` if `norm(x) == 1`. The unit sphere is N-dimensional, and its dimension is specified with the constructor. The element types are `SVector{N,T}` when the dimension is specified as `Val(3)`, and they are `Vector{T}` when the dimension is specified by an integer value instead:

```julia> SVector(0,0,1.0) in UnitSphere(Val(3))
true

julia> [0.0,1.0,0.0,0.0] in UnitSphere(4)
true```

`UnitSphere` itself is an abstract type, hence the examples above return concrete types `<:UnitSphere`. The intended element type can also be explicitly specified with the `UnitSphere{T}` constructor:

```julia> typeof(UnitSphere{SVector{3,BigFloat}}())
EuclideanUnitSphere{3, BigFloat} (alias for StaticUnitSphere{SArray{Tuple{3}, BigFloat, 1, 3}})

julia> typeof(UnitSphere{Vector{Float32}}(6))
VectorUnitSphere{Float32} (alias for DynamicUnitSphere{Array{Float32, 1}})```

Without arguments, `UnitSphere()` defaults to a 3D domain with `SVector{3,Float64}` elements. Similarly, there is a special case `UnitCircle` in 2D:

```julia> SVector(1,0) in UnitCircle()
true```

### Disks and Balls

A `UnitBall` contains `x` if `norm(x) ≤ 1`. As with `UnitSphere`, the dimension is specified via the constructor by type or by value:

```julia> SVector(0.1,0.2,0.3) in UnitBall(Val(3))
true

julia> [0.1,0.2,0.3,-0.1] in UnitBall(4)
true```

By default `N=3`, but `UnitDisk` is a special case in 2D, and so are `ComplexUnitDisk` and `ComplexUnitCircle` in the complex plane:

```julia> SVector(0.1,0.2) in UnitDisk()
true

julia> 0.5+0.2im ∈ ComplexUnitDisk()
true```

`UnitBall` itself is an abstract type, hence the examples above return concrete types `<:UnitBall`. The types are similar to those associated with `UnitSphere`. Like intervals, balls can also be open or closed:

```julia> EuclideanUnitBall{3,Float64,:open}()
the 3-dimensional open unit ball```

### Product domains

The cartesian product of domains is constructed with the `ProductDomain` or `ProductDomain{T}` constructor. This abstract constructor returns concrete types best adapted to the arguments given.

If `T` is not given, `ProductDomain` makes a suitable choice based on the arguments. If all arguments are Euclidean, i.e., their element types are numbers or static vectors, then the product is a Euclidean domain as well:

```julia> ProductDomain(0..2, UnitCircle())
0.0..2.0 x the unit circle

julia> eltype(ans)
SVector{3, Float64} (alias for SArray{Tuple{3}, Float64, 1, 3})```

The elements of the interval and the unit circle are flattened into a single vector, much like the `vcat` function. The result is a `VcatDomain`.

If a `Vector` of domains is given, the element type is a `Vector` as well:

```julia> 1:5 in ProductDomain([0..i for i in 1:5])
true```

In other cases, the points are concatenated into a tuple and membership is evaluated element-wise:

```julia> ("a", 0.4) ∈ ProductDomain(["a","b"], 0..1)
true```

Some arguments are recognized and return a more specialized product domain. Examples are the unit box and more general hyperrectangles:

```julia> ProductDomain(UnitInterval(), UnitInterval())
0.0..1.0 (Unit) x 0.0..1.0 (Unit)

julia> ProductDomain(0..2, 4..5, 6..7.0)
0.0..2.0 x 4.0..5.0 x 6.0..7.0

julia> typeof(ans)
Rectangle{SVector{3, Float64}}```

### Union, intersection, and setdiff of domains

Domains can be unioned and intersected together:

```julia> d = UnitCircle() ∪ 2UnitCircle();

julia> in.([SVector(1,0),SVector(0,2), SVector(1.5,1.5)], d)
3-element BitArray{1}:
1
1
0

julia> d = UnitCircle() ∩ (2UnitCircle() .+ SVector(1.0,0.0))
the intersection of 2 domains:
1.	: the unit circle
2.	: A mapped domain based on the unit circle

julia> SVector(1,0) in d
false

julia> SVector(-1,0) in d
true```

### Level sets

A domain can be defined by the level sets of a function. The domains of all points `[x,y]` for which `x*y = 1` or `x*y >= 1` are represented as follows:

```julia> d = LevelSet{SVector{2,Float64}}(prod, 1.0)
level set f(x) = 1.0 with f = prod

julia> [0.5,2] ∈ d
true

julia> SuperlevelSet{SVector{2,Float64}}(prod, 1.0)
superlevel set f(x) >= 1.0 with f = prod```

There is also `SublevelSet`, and there are the special cases `ZeroSet`, `SubzeroSet` and `SuperzeroSet`.

### Indicator functions

A domain can be defined by an indicator function or a characteristic function. This is a function `f(x)` which evaluates to true or false, depending on whether or not the point `x` belongs to the domain.

```julia> d = IndicatorFunction{Float64}( t ->  cos(t) > 0)
indicator domain defined by function f = #5

julia> 0.5 ∈ d, 3.1 ∈ d
(true, false)```

This enables generator syntax to define domains:

```julia> d = Domain(x>0 for x in -1..1)
indicator function bounded by: -1..1

julia> 0.5 ∈ d, -0.5 ∈ d
(true, false)

julia> d = Domain( x*y > 0 for (x,y) in UnitDisk())
indicator function bounded by: the 2-dimensional closed unit ball

julia> [0.2, 0.3] ∈ d, [0.2, -0.3] ∈ d
(true, false)

julia> d = Domain( x+y+z > 0 for (x,y,z) in ProductDomain(UnitDisk(), 0..1))
indicator function bounded by: the 2-dimensional closed unit ball x 0..1

julia> [0.3,0.2,0.5] ∈ d
true```

### The domain interface

A domain is any type that implements the functions `eltype` and `in`. If `d` is an instance of a type that implements the domain interface, then the domain consists of all `x` that is an `eltype(d)` such that `x in d` returns true.

Domains often represent continuous mathematical domains, for example, a domain `d` representing the interval `[0,1]` would have `eltype(d) == Int` but still have `0.2 in d` return true.

### The `Domain` type

DomainSets.jl contains an abstract type `Domain{T}`. All subtypes of `Domain{T}` must implement the domain interface, and in addition support `convert(Domain{T}, d)`.