Implementing the scalable symbolic-numeric set computations ideas of LazySets.jl in Rust.
This summary is based on the LazySets.jl paper. Sets and their operations are represented lazily, having them live in the same abstraction layer and returning operation values "by need" using compsable computations.
For example, consider the set
ConvexHull
├── MinkowskiSum
│ ├── ExponentialMap(A delta)
│ │ └── X_0
│ └── LinearMap(delta B)
│ └── U
└── X_0
With this lazy representation, say we want to compute a support value for a direction
Now, we don't know the support vector for this set directly, but say we do know the support vector for the underlying sets
Evaulating the tree above, it is clear the support function can be computed by
Translating a set by
A line segment through the origin with endpoints
In Rust, this means that all operations and set primitives are implemented as structs with a shared trait LazySet
. For example, the ConvexHull
is defined as
/// Convex hull of two convex sets.
pub struct ConvexHull<N, const D: usize> {
/// The first support function (left hand side).
lhs: Box<dyn LazySet<N, D>>,
/// The second support function (right hand side).
rhs: Box<dyn LazySet<N, D>>,
}
...
// implement the LazySet trait for ConvexHull
impl<N, const D: usize> LazySet<N, D> for ConvexHull<N, D>
where
N: RealField,
{
fn support(&self, direction: &SVector<N, D>) -> (N, SVector<N, D>) {
let (d1, p1) = self.lhs.support(direction);
let (d2, p2) = self.rhs.support(direction);
if d1 > d2 {
(d1, p1)
} else {
(d2, p2)
}
}
}
Forets, M., & Schilling, C. (2021). LazySets. jl: Scalable symbolic-numeric set computations. arXiv preprint arXiv:2110.01711.