~mht/cra

63085b47e24f22ebf93b33214955616d10a181a9 — Martin Hafskjold Thoresen 1 year, 3 months ago ad35e14
Fix Makefile, add comments, and break persistence.rs

Have started factoring out the `r_when_born` from `Simplex`, since
this shouldn't be there. The only thing the `persistence` module
should need to know of the simplices are their boundaries.

Should consider moving the alpha thing out, or to another module.
5 files changed, 87 insertions(+), 47 deletions(-)

M cra/Makefile
M cra/listings.tex
M cra/src/main.rs
M cra/src/output.rs
M cra/src/persistence.rs
M cra/Makefile => cra/Makefile +8 -2
@@ 9,13 9,19 @@ data/%.tri: data/%.points triangulate2
	./triangulate2 < $^ > $@

# Cargo eh
target/release/cra: src/main.rs
target/release/cra: src/main.rs src/output.rs src/persistence.rs
	cargo build --release

# Output from the reduction algorithm
output/.%: data/%.tri target/release/cra
	target/release/cra $* < $<
	-mkdir -p output/$*
	env RUST_BACKTRACE=1 target/debug/cra -t="-" < $< \
		--graphviz=output/$*/graph.dot \
		--diagram=output/$*/persistence.pdf \
		--svg=output/$*/rendering.svg \
		--tex-table=output/$*/perf-stats.tex
	convert -size 800x800 output/$*/rendering.svg output/$*/rendering.png
	touch $@

# Triangulation exec
triangulate2: triangulate2.cpp

M cra/listings.tex => cra/listings.tex +14 -14
@@ 32,20 32,20 @@

\clearpage

\begin{figure}[ht]
\centering
\includegraphics[height=0.23\textheight]{output/#1/add_size_sum.pdf}
\vspace{\baselineskip}

\includegraphics[height=0.23\textheight]{output/#1/num_iters.pdf}
\vspace{\baselineskip}

\includegraphics[height=0.23\textheight]{output/#1/ex_searches.pdf}
\vspace{\baselineskip}

\includegraphics[height=0.23\textheight]{output/#1/ex_reductions.pdf}
\end{figure}
\clearpage
% \begin{figure}[ht]
% \centering
% \includegraphics[height=0.23\textheight]{output/#1/add_size_sum.pdf}
% \vspace{\baselineskip}
% 
% \includegraphics[height=0.23\textheight]{output/#1/num_iters.pdf}
% \vspace{\baselineskip}
% 
% \includegraphics[height=0.23\textheight]{output/#1/ex_searches.pdf}
% \vspace{\baselineskip}
% 
% \includegraphics[height=0.23\textheight]{output/#1/ex_reductions.pdf}
% \end{figure}
% \clearpage
}



M cra/src/main.rs => cra/src/main.rs +30 -12
@@ 30,14 30,23 @@ fn f64_eq(a: f64, b: f64) -> bool {
/// All the statistics we want to measure for performance reasoning.
#[derive(Debug)]
pub struct Statistics {
    /// Count the number of times we add two simplices
    col_adds: usize,
    /// Count the number of times we add two simplices of a specific dimension
    col_add_dimens: Vec<usize>,
    /// Count the sizes of the simplices we add
    add_size: Vec<(usize, usize)>,
    /// Count the sum of the sizes.
    /// TODO: this is redundant
    add_size_sum: Vec<usize>,
    /// Count the number of iterations for reducing one simplex
    num_iters: Vec<usize>,
    /// Count the number of extra reductions we do when the exhaustive variant is ran.
    ex_reductions: Vec<usize>,
    ex_searches: Vec<usize>,
    /// Count the number of simplices that are reduced to the empty set.
    zeroed: usize,
    /// Count the number of simplices that are reduced to the empty set, but for each dimension.
    zeroed_d: [usize; MAX_DIM],
    placed_single: usize,
    placed_full: usize,


@@ 47,7 56,7 @@ pub struct Statistics {
    // Number of simlpices in all dimensions
    num_of_dimens: [usize; MAX_DIM],
    skip_d: [usize; MAX_DIM],

    // Record the wall-clock time spent.
    time: u64,
}



@@ 178,12 187,14 @@ impl Point {
///
/// ### Note
/// This only reads a 2D triangulation.

pub fn read_triangulation<R: Read>(
    r: &mut R,
) -> Result<(Vec<[f64; 2]>, Vec<Simplex>), Box<dyn std::error::Error>> {
    let mut lines = BufReader::new(r).lines();
    let first_line = lines.next().ok_or("reader is empty")??;
    let first_line = lines
        .next()
        .ok_or("reader is empty in `read_triangulation`")??;

    let number_of_vertices: usize = first_line.parse::<usize>()?;

    let points = (&mut lines)


@@ 309,19 320,26 @@ fn main() {
        (@arg svg: --svg[FILE] "Draw the compex to an .svg.")
        (@arg alpha: -a --alpha "Ignore the ordering of the simplices given and calculate and use the alpha ordering.")
        (@arg stats: -s --stats "Print out statistics.")
        (@arg graphviz: --graphiviz[FILE] "Use `graphviz` to graph out which simplices are added together.")
        (@arg graphviz: --graphviz[FILE] "Use `graphviz` to graph out which simplices are added together.")
        (@arg diagram: --diagram[FILE] "Use `gnuplot` to print out the persistence diagram.")
        (@arg textable: --("tex-table")[FILE] "Output a `tex` formatted table of statistics.")
    ).get_matches();

    if let Some(path) = matches.value_of("triangulation") {
    let mut persistence = if let Some(path) = matches.value_of("triangulation") {
        // TODO: input triangulation thing here
        println!("{:?}", path);
    }

    // By here we should have a `Persistence`

    let mut persistence = read_input_stdin2().unwrap();
        let mut reader: Box<dyn std::io::Read> = if path == "-" {
            Box::new(std::io::stdin())
        } else {
            Box::new(File::open(path).expect("No such file"))
        };
        let (points, mut simplices) =
            read_triangulation(&mut reader).expect("failed to read triangulation");
        compute_alpha_values_2d(&points, &mut simplices);
        Persistence { simplices, points }
    } else {
        // Need to take some other format, then!
        unimplemented!();
    };

    // TODO: this should be done somewhere else!
    {


@@ 434,7 452,7 @@ fn main() {
    //    );

    if let Some(path) = matches.value_of("graphviz") {
        let mut f = File::create("test.dot").unwrap();
        let mut f = File::create(Path::new(path)).unwrap();
        output::graphviz(
            &persistence,
            &standard_reduction,

M cra/src/output.rs => cra/src/output.rs +6 -2
@@ 266,6 266,8 @@ fn make_histogram(data: &[usize]) -> Vec<usize> {
    freq
}

/// Use `gnuplot` to make a persistence diagram with the given pairs.
/// This is really just a point plot with labeled axes.
pub fn persistence(pairs: &[(f64, f64)], out_file: &Path) {
    let in_file_path = "temp-persistence";
    let mut file = File::create(in_file_path).unwrap();


@@ 734,8 736,10 @@ pub fn run_gnuplot(script: &str, out_file: &Path) {
        other => panic!("`gnuplot` process returned error: {:?}", other),
    }

    let mut f = File::create(out_file).unwrap();
    f.write_all(&output.stdout).unwrap();
    println!("{:?}", out_file);
    let mut f = File::create(out_file).expect("Failed to create gnuplot output file");
    f.write_all(&output.stdout)
        .expect("Failed to write to gnuplot output file");
}

pub fn stats<W: Write>(st: &Statistics, writer: &mut W) -> Result<(), std::io::Error> {

M cra/src/persistence.rs => cra/src/persistence.rs +29 -17
@@ 22,8 22,8 @@ pub struct Simplex {
    pub j: usize,
    /// Indices of the faces of this simplex
    pub faces: Vec<usize>,
    /// The ball radius when this simplex is born.
    pub r_when_born: f64,
    // The ball radius when this simplex is born.
    // pub r_when_born: f64,
}

impl Simplex {


@@ 154,11 154,11 @@ pub fn reduce(p: &Persistence, variant: Variant, stats: &mut Statistics) -> Redu
            continue;
        }
        let s_dim = simplex.dim().max(0) as usize;
        // If this simplex is born too late we also skip it.
        if simplex.r_when_born >= R_CUTOFF {
            stats.skip(s_dim);
            continue;
        }
        //        // If this simplex is born too late we also skip it.
        //        if simplex.r_when_born >= R_CUTOFF {
        //            stats.skip(s_dim);
        //            continue;
        //        }
        // TODO: this probably doens't need to be cloned.
        let mut current_simplex = simplex.faces.clone();
        current_simplex.sort();


@@ 351,7 351,10 @@ fn column_add(

/// Compute the alpha values for the simplices, given the point location.
/// As the name suggests, this is only for dimension 2 and less.
pub fn compute_alpha_values_2d(points: &[[f64; 2]], simplices: &mut [Simplex]) {
pub fn compute_alpha_values_2d(
    points: &[[f64; 2]],
    simplices: &[Simplex],
) -> (Vec<Simplex>, Vec<f64>) {
    fn alpha_1d(simplex: &Simplex, points: &[[f64; 2]]) -> f64 {
        let p0 = Point(points[simplex.faces[0] - 1]);
        let p1 = Point(points[simplex.faces[1] - 1]);


@@ 427,18 430,27 @@ pub fn compute_alpha_values_2d(points: &[[f64; 2]], simplices: &mut [Simplex]) {
        &mut *target
    }

    let mut tuples = Vec::new();

    for current_simplex_i in 0..simplices.len() {
        let (former, latter) = simplices.split_at_mut(current_simplex_i);
        let simplex = &mut latter[0];
        match simplex.dim() {
            -1 | 0 => simplex.r_when_born = 0.0,
            1 => {
                simplex.r_when_born = alpha_1d(&simplex, &points);
            }
            2 => {
                simplex.r_when_born = alpha_2d(&simplex, &points, former);
            }
        let alpha = match simplex.dim() {
            -1 | 0 => 0.0,
            1 => alpha_1d(&simplex, &points),
            2 => alpha_2d(&simplex, &points, former),
            more => panic!("Only support 2d simplices! ({} > 2)", more),
        }
        };
        tuples.push((alpha, current_simplex_i));
    }

    tuples.sort_by(|(f1, i1), (f2, i2)| f1.partial_cmp(f2).unwrap_or(i1.cmp(i2)));

    let mut ordered_simplices = Vec::new();
    for &(_, i) in tuples.iter() {
        ordered_simplices.push(simplices[i].clone());
    }
    let alphas = tuples.into_iter().map(|t| t.0).collect::<Vec<_>>();

    (ordered_simplices, alphas)
}