Hi, everyone!
I’ve been planning a redesign for SpecialSets.jl to target use cases needed by Rewrite.jl, but figured that using representations of abstract/infinite sets shouldn’t require reinventing the wheel. I found the following packages which include relevant features:
- AbstractDomains.jl (by @zennatavares)
- ChainRules.jl (by @jrevels)
- SpecialSets.jl (by @HarrisonGrodin)
- IntervalSets.jl (cc: @tim.holy, @dlfivefifty)
- IntervalArithmetic.jl (cc: @dpsanders)
In this post and the discussion following, I’m hoping to compare the existing packages and come up with a list of necessary features in hopes of developing a common API or central package.
Features
Throughout the remainder of this post, sets will be represented using set-builder notation:
\{\ x \mid \ p_1(x),\ p_2(x),\ \dots\ \}, where p_n is a predicate on x
Elementwise Operations
There should be some way to apply standard functions to each element in a set.
- \{\ y \mid (f(x) = y), p_1(x),\ p_2(x),\ \dots\ \}
It’s not entirely clear how operations between multiple sets should behave. The most natural interpretation I came up with is as follows:
A = {a::Int | a ≥ 0} # pseudocode
@assert A - A == {0} # interpreting as {a-a | a ≥ 0}
@assert A - copy(A) == ℤ # interpreting as {a-a' | a ≥ 0, a' ≥ 0}
Set Operations
Common set operations should obviously be supported: \in, \subseteq, \cup, \cap, set equality, set difference.
There should be default representations of combinations and opportunities to define custom combination rules:
-
{x | isprime(x)} ∪ {x | x < -10}→{x | (isprime(x) || x < -10)}(default union) -
{x | x > 5} ∩ {x | x > 7}→{x | x > 7}(custom intersection of>predicates) -
{y | (y = 2x), x ∈ ℝ} ∩ {y | (y = 3x), x ∈ ℝ}→{y | (y = 6x), x ∈ ℝ}(custom intersection of operations)
It’s possible that the logic behind this could be derived from an existing SMT solver (e.g. Z3). Also, we should probably consider how cross-type predicates behave (e.g. {x | x > 3} ⊆ {x | x > 2.0}?).
Implicit algebraic properties about these operations (e.g. associativity/commutativity of ∪ and ∩, transitivity of ⊆) would also be rather convenient.
Clear Connection With Julia Types
It seems reasonable to connect set elements with Julia types. There are many ways this could be done:
-
{x | x isa Int, x < 10}(interpreting types as predicates) -
{x::Int | x < 10}(requiring that the most general type ofxbe asserted, drawing inspiration from LiquidHaskell)
We may also want to consider support for more complex typing rules, such as {xs::AbstractVector{<:Number} | length(xs) > 7}.
More…
I neglected to discuss support for dealing with function signatures and variable domains (e.g. ℝ×ℝ → ℝ, x ∈ ℤ⁻ ∪ ℙ), since it seems like that might belong in an adjacent tool. I’m open to discussing that here as well, though, if people are interested. ![]()
I doubt this is a comprehensive list, but hopefully it can serve as a starting point for discussion. Looking forward to making headway on this key part of symbolic mathematics in Julia!
-Harrison