Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

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.