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)
}