7. Representatives and threads
Two last things come almost for free.
// Step 7: representatives, by the involution, which needs the transpose (the boundary)
let delta_t = (&delta).with_transpose(Boundary(&volume));
let with_reps = timed("... with representatives", || {
barcode::cohomology_with_involution(&delta_t, Algorithm::Clearing(algorithm.clone()))
});
let longest = with_reps
.iter()
.filter(|bar| volume.dimension(bar.birth.0) == 2 && bar.death.is_some())
.max_by_key(|bar| bar.death.unwrap().1 - bar.birth_value)
.expect("a finite cavity");
println!(
" the longest finite H2 bar, [{}, {}), is a closed surface of {} squares",
longest.birth_value,
longest.death.unwrap().1,
longest.representative.as_ref().unwrap().len()
);
// ... and all cores
#[cfg(feature = "parallel")]
let parallel = timed("cohomology, parallel clearing", || {
let parallel = Clearing::new()
.with_columns(HeapColumns)
.cache_columns(false)
.parallel();
barcode::cohomology(&delta, Algorithm::ParallelClearing(parallel))
});
Representatives
barcode::cohomology_with_involution computes the pairs by cohomology and then cycle representatives by a small
homology reduction of just the death and essential birth columns (the involution). It
needs the boundary, attached as the transpose. Each Bar’s representative is a list of (coefficient, cell): for a
bar in \(H_2\), a closed surface of squares enclosing a dark cavity in the volume.
... with representatives 4121.2 ms
the longest finite H2 bar, [0.536, 0.632), is a closed surface of 1268 squares
Threads
Clearing::new().parallel() (feature parallel) reduces each dimension on all cores
(parallel clearing):
cohomology, parallel clearing 1575.0 ms
(against 2020 ms on one thread, on a laptop with four cores). The reduction itself is a small part of the work here, since most columns finish at their pivot.
What not to turn on
phlite also has PHAT’s tricks: dense indices for vector bookkeeping,
pivot columns and stored R. They need an array over every cell,
which is exactly what this oracle avoids, and they pay when many columns need genuine reduction, which isn’t the
case here. If your complex is like that, build it explicitly with the phlite Python package,
which applies them all.
Next
The same ideas, applied to Vietoris–Rips with much more care over enumerating cofacets, are phlite_rips; its source
(phlite_rips/src/lib.rs onwards, comments marked TUTORIAL) is a good next read.