///|
/// All 2^universe subsets in O(universe) graph nodes.
pub fn Family::powerset(
universe : Int32,
limits~ : Limits = Limits::default(),
) -> Family raise ZddError {
let e = engine(universe, limits)
let mut root = 1
for v = universe - 1; v >= 0; v = v - 1 {
root = e.make(v, root, root)
}
e.finish(root)
}
///|
/// Exactly the k-element subsets. Impossible nonnegative k returns the empty family.
pub fn Family::choose(
universe : Int32,
k : Int32,
limits~ : Limits = Limits::default(),
) -> Family raise ZddError {
let e = engine(universe, limits)
if k < 0 {
raise Invalid("cardinality must be nonnegative")
}
let cache : Map[(Int32, Int32), Int32] = Map([])
fn visit(v : Int32, needed : Int32) -> Int32 raise ZddError {
e.tick()
if needed == 0 {
return 1
}
if needed > universe - v {
return 0
}
let key = (v, needed)
if cache.get(key) is Some(found) {
return found
}
let low = visit(v + 1, needed)
let high = visit(v + 1, needed - 1)
let out = e.make(v, low, high)
cache[key] = out
out
}
e.finish(visit(0, k))
}
///|
/// Every singleton item in the universe (empty when the universe is empty).
pub fn Family::items(
universe : Int32,
limits~ : Limits = Limits::default(),
) -> Family raise ZddError {
Family::choose(universe, 1, limits~)
}