use oxilean_kernel::{BinderInfo, Declaration, Environment, Expr, Level, Name};
use std::collections::{HashMap, HashSet};
use super::types::{
AlphaComplex, BarCode, CechComplex, ContourTree, CoverElement, DiscreteMorseFunction,
FormanCriticalSimplex, MapperGraph, MapperResult, MorseComplex, MorsePair, PersistenceDiagram,
PersistenceInterval, PersistencePair, PersistentHomologyRepresentation, ReducedBoundaryMatrix,
ReebGraph, ReebNodeType, Simplex, SimplicialComplex, TDASummaryStatistic,
TomographicProjection, VietorisRipsComplex,
};
pub fn app(f: Expr, a: Expr) -> Expr {
Expr::App(Box::new(f), Box::new(a))
}
pub fn app2(f: Expr, a: Expr, b: Expr) -> Expr {
app(app(f, a), b)
}
pub fn app3(f: Expr, a: Expr, b: Expr, c: Expr) -> Expr {
app(app2(f, a, b), c)
}
pub fn cst(s: &str) -> Expr {
Expr::Const(Name::str(s), vec![])
}
pub fn prop() -> Expr {
Expr::Sort(Level::zero())
}
pub fn type0() -> Expr {
Expr::Sort(Level::succ(Level::zero()))
}
pub fn pi(bi: BinderInfo, name: &str, dom: Expr, body: Expr) -> Expr {
Expr::Pi(bi, Name::str(name), Box::new(dom), Box::new(body))
}
pub fn arrow(a: Expr, b: Expr) -> Expr {
pi(BinderInfo::Default, "_", a, b)
}
pub fn bvar(n: u32) -> Expr {
Expr::BVar(n)
}
pub fn bool_ty() -> Expr {
cst("Bool")
}
pub fn nat_ty() -> Expr {
cst("Nat")
}
pub fn real_ty() -> Expr {
cst("Real")
}
pub fn list_ty(a: Expr) -> Expr {
app(cst("List"), a)
}
pub fn option_ty(a: Expr) -> Expr {
app(cst("Option"), a)
}
pub fn simplex_ty() -> Expr {
type0()
}
pub fn simplicial_complex_ty() -> Expr {
type0()
}
pub fn vietoris_rips_ty() -> Expr {
type0()
}
pub fn cech_complex_ty() -> Expr {
type0()
}
pub fn alpha_complex_ty() -> Expr {
type0()
}
pub fn dimension_ty() -> Expr {
arrow(cst("SimplicialComplex"), nat_ty())
}
pub fn euler_characteristic_ty() -> Expr {
arrow(cst("SimplicialComplex"), cst("Int"))
}
pub fn faces_ty() -> Expr {
arrow(cst("Simplex"), list_ty(cst("Simplex")))
}
pub fn boundary_matrix_ty() -> Expr {
arrow(
cst("SimplicialComplex"),
arrow(nat_ty(), list_ty(list_ty(cst("Int")))),
)
}
pub fn persistence_interval_ty() -> Expr {
type0()
}
pub fn persistence_diagram_ty() -> Expr {
type0()
}
pub fn barcode_ty() -> Expr {
type0()
}
pub fn persistence_pair_ty() -> Expr {
type0()
}
pub fn reduced_boundary_matrix_ty() -> Expr {
type0()
}
pub fn persistent_betti_ty() -> Expr {
arrow(
cst("PersistenceDiagram"),
arrow(nat_ty(), arrow(nat_ty(), nat_ty())),
)
}
pub fn bottleneck_distance_ty() -> Expr {
arrow(
cst("PersistenceDiagram"),
arrow(cst("PersistenceDiagram"), real_ty()),
)
}
pub fn wasserstein_distance_ty() -> Expr {
arrow(
cst("PersistenceDiagram"),
arrow(cst("PersistenceDiagram"), arrow(real_ty(), real_ty())),
)
}
pub fn reduce_boundary_matrix_ty() -> Expr {
arrow(list_ty(list_ty(cst("Int"))), cst("ReducedBoundaryMatrix"))
}
pub fn cover_element_ty() -> Expr {
type0()
}
pub fn mapper_graph_ty() -> Expr {
type0()
}
pub fn mapper_result_ty() -> Expr {
type0()
}
pub fn tomographic_projection_ty() -> Expr {
type0()
}
pub fn mapper_run_ty() -> Expr {
arrow(
list_ty(list_ty(real_ty())),
arrow(nat_ty(), arrow(real_ty(), cst("MapperResult"))),
)
}
pub fn discrete_morse_function_ty() -> Expr {
type0()
}
pub fn morse_pair_ty() -> Expr {
type0()
}
pub fn morse_complex_ty() -> Expr {
type0()
}
pub fn forman_critical_simplex_ty() -> Expr {
type0()
}
pub fn critical_cells_ty() -> Expr {
arrow(cst("DiscreteMorseFunction"), list_ty(cst("Simplex")))
}
pub fn morse_index_ty() -> Expr {
arrow(cst("FormanCriticalSimplex"), nat_ty())
}
pub fn is_gradient_pair_ty() -> Expr {
arrow(
cst("Simplex"),
arrow(
cst("Simplex"),
arrow(cst("DiscreteMorseFunction"), bool_ty()),
),
)
}
pub fn reeb_graph_ty() -> Expr {
type0()
}
pub fn contour_tree_ty() -> Expr {
type0()
}
pub fn persistent_homology_repr_ty() -> Expr {
type0()
}
pub fn tda_summary_statistic_ty() -> Expr {
type0()
}
pub fn reeb_graph_from_function_ty() -> Expr {
arrow(
cst("SimplicialComplex"),
arrow(arrow(nat_ty(), real_ty()), cst("ReebGraph")),
)
}
pub fn betti_numbers_ty() -> Expr {
arrow(cst("SimplicialComplex"), list_ty(nat_ty()))
}
pub fn persistence_entropy_ty() -> Expr {
arrow(cst("PersistenceDiagram"), real_ty())
}
pub fn persistence_landscape_ty() -> Expr {
arrow(
cst("PersistenceDiagram"),
arrow(nat_ty(), arrow(real_ty(), real_ty())),
)
}
pub fn build_env(env: &mut Environment) {
let axioms: &[(&str, Expr)] = &[
("Simplex", simplex_ty()),
("SimplicialComplex", simplicial_complex_ty()),
("VietorisRipsComplex", vietoris_rips_ty()),
("CechComplex", cech_complex_ty()),
("AlphaComplex", alpha_complex_ty()),
("dimension", dimension_ty()),
("euler_characteristic", euler_characteristic_ty()),
("faces", faces_ty()),
("boundary_matrix", boundary_matrix_ty()),
("PersistenceInterval", persistence_interval_ty()),
("PersistenceDiagram", persistence_diagram_ty()),
("BarCode", barcode_ty()),
("PersistencePair", persistence_pair_ty()),
("ReducedBoundaryMatrix", reduced_boundary_matrix_ty()),
("persistent_betti", persistent_betti_ty()),
("bottleneck_distance", bottleneck_distance_ty()),
("wasserstein_distance", wasserstein_distance_ty()),
("reduce_boundary_matrix", reduce_boundary_matrix_ty()),
("CoverElement", cover_element_ty()),
("MapperGraph", mapper_graph_ty()),
("MapperResult", mapper_result_ty()),
("TomographicProjection", tomographic_projection_ty()),
("mapper_run", mapper_run_ty()),
("DiscreteMorseFunction", discrete_morse_function_ty()),
("MorsePair", morse_pair_ty()),
("MorseComplex", morse_complex_ty()),
("FormanCriticalSimplex", forman_critical_simplex_ty()),
("critical_cells", critical_cells_ty()),
("morse_index", morse_index_ty()),
("is_gradient_pair", is_gradient_pair_ty()),
("ReebGraph", reeb_graph_ty()),
("ContourTree", contour_tree_ty()),
(
"PersistentHomologyRepresentation",
persistent_homology_repr_ty(),
),
("TDASummaryStatistic", tda_summary_statistic_ty()),
("reeb_graph_from_function", reeb_graph_from_function_ty()),
("betti_numbers", betti_numbers_ty()),
("persistence_entropy", persistence_entropy_ty()),
("persistence_landscape", persistence_landscape_ty()),
];
for (name, ty) in axioms {
env.add(Declaration::Axiom {
name: Name::str(*name),
univ_params: vec![],
ty: ty.clone(),
})
.ok();
}
}
pub fn run_mapper(
filter: &TomographicProjection,
num_intervals: usize,
overlap: f64,
) -> MapperResult {
let n = filter.values.len();
let lo = filter.min_val();
let hi = filter.max_val();
if n == 0 || hi <= lo || num_intervals == 0 {
return MapperResult {
graph: MapperGraph::new(),
cover: vec![],
filter_values: filter.values.clone(),
};
}
let step = (hi - lo) / num_intervals as f64;
let half_overlap = step * overlap / 2.0;
let mut cover: Vec<CoverElement> = (0..num_intervals)
.map(|i| {
let lower = lo + i as f64 * step - half_overlap;
let upper = lo + (i + 1) as f64 * step + half_overlap;
let points: Vec<usize> = (0..n)
.filter(|&j| filter.values[j] >= lower && filter.values[j] < upper)
.collect();
CoverElement::new(i, lower, upper, points)
})
.collect();
for elem in &mut cover {
if elem.points.len() <= 1 {
elem.num_clusters = elem.points.len();
continue;
}
let m = elem.points.len();
let mut parent: Vec<usize> = (0..m).collect();
fn find_p(parent: &mut Vec<usize>, x: usize) -> usize {
if parent[x] != x {
parent[x] = find_p(parent, parent[x]);
}
parent[x]
}
for a in 0..m {
for b in (a + 1)..m {
let fa = filter.values[elem.points[a]];
let fb = filter.values[elem.points[b]];
if (fa - fb).abs() < step / 2.0 {
let pa = find_p(&mut parent, a);
let pb = find_p(&mut parent, b);
if pa != pb {
parent[pa] = pb;
}
}
}
}
let roots: HashSet<usize> = (0..m).map(|i| find_p(&mut parent, i)).collect();
let root_list: Vec<usize> = roots.into_iter().collect();
elem.clusters = (0..m)
.map(|i| {
root_list
.iter()
.position(|&r| r == find_p(&mut parent, i))
.unwrap_or(0)
})
.collect();
elem.num_clusters = root_list.len();
}
let mut graph = MapperGraph::new();
let mut node_map: HashMap<(usize, usize), usize> = HashMap::new();
for (ci, elem) in cover.iter().enumerate() {
for cl in 0..elem.num_clusters {
let pts: Vec<usize> = elem
.points
.iter()
.enumerate()
.filter(|(idx, _)| elem.clusters[*idx] == cl)
.map(|(_, &p)| p)
.collect();
let color = if pts.is_empty() {
0.0
} else {
pts.iter().map(|&p| filter.values[p]).sum::<f64>() / pts.len() as f64
};
let node_id = graph.add_node(ci, cl, color);
node_map.insert((ci, cl), node_id);
}
}
for ci in 0..cover.len() {
for cj in (ci + 1)..cover.len() {
let common: HashSet<usize> = cover[ci]
.points
.iter()
.copied()
.collect::<HashSet<_>>()
.intersection(&cover[cj].points.iter().copied().collect::<HashSet<_>>())
.copied()
.collect();
for &p in &common {
let idx_i = cover[ci]
.points
.iter()
.position(|&q| q == p)
.expect("p is in cover[ci].points: p came from the intersection");
let idx_j = cover[cj]
.points
.iter()
.position(|&q| q == p)
.expect("p is in cover[cj].points: p came from the intersection");
let cli = cover[ci].clusters[idx_i];
let clj = cover[cj].clusters[idx_j];
if let (Some(&ni), Some(&nj)) = (node_map.get(&(ci, cli)), node_map.get(&(cj, clj)))
{
if !graph.edges.contains(&(ni, nj)) && !graph.edges.contains(&(nj, ni)) {
graph.add_edge(ni, nj);
}
}
}
}
}
MapperResult {
graph,
cover,
filter_values: filter.values.clone(),
}
}
pub fn zigzag_filtration_ty() -> Expr {
type0()
}
pub fn zigzag_persistence_module_ty() -> Expr {
type0()
}
pub fn zigzag_barcode_ty() -> Expr {
type0()
}
pub fn zigzag_decomposition_theorem_ty() -> Expr {
arrow(
cst("ZigzagPersistenceModule"),
arrow(cst("ZigzagBarcode"), prop()),
)
}
pub fn extended_persistence_diagram_ty() -> Expr {
type0()
}
pub fn extended_persistence_stability_ty() -> Expr {
arrow(
cst("ExtendedPersistenceDiagram"),
arrow(cst("ExtendedPersistenceDiagram"), arrow(real_ty(), prop())),
)
}
pub fn multidim_persistence_module_ty() -> Expr {
arrow(nat_ty(), type0())
}
pub fn multidim_barcode_ty() -> Expr {
type0()
}
pub fn rank_invariant_ty() -> Expr {
arrow(
app(cst("MultidimensionalPersistenceModule"), nat_ty()),
arrow(arrow(nat_ty(), arrow(nat_ty(), nat_ty())), prop()),
)
}
pub fn multidim_persistence_classification_ty() -> Expr {
arrow(
app(cst("MultidimensionalPersistenceModule"), nat_ty()),
prop(),
)
}
pub fn interleaving_distance_ty() -> Expr {
type0()
}
pub fn vietoris_rips_stability_ty() -> Expr {
arrow(
real_ty(),
arrow(
cst("PersistenceDiagram"),
arrow(cst("PersistenceDiagram"), prop()),
),
)
}
pub fn interleaving_distance_stability_ty() -> Expr {
arrow(
cst("InterleavingDistance"),
arrow(
cst("PersistenceDiagram"),
arrow(cst("PersistenceDiagram"), prop()),
),
)
}
pub fn algebraic_stability_theorem_ty() -> Expr {
arrow(
cst("PersistenceDiagram"),
arrow(
cst("PersistenceDiagram"),
arrow(cst("InterleavingDistance"), prop()),
),
)
}
pub fn bottleneck_distance_stability_ty() -> Expr {
arrow(
cst("SimplicialComplex"),
arrow(cst("SimplicialComplex"), arrow(real_ty(), prop())),
)
}
pub fn nerve_theorem_ty() -> Expr {
arrow(cst("SimplicialComplex"), prop())
}
pub fn cech_complex_nerve_theorem_ty() -> Expr {
arrow(cst("CechComplex"), arrow(cst("SimplicialComplex"), prop()))
}
pub fn cech_rips_interleaving_ty() -> Expr {
arrow(
real_ty(),
arrow(
cst("PersistenceDiagram"),
arrow(cst("PersistenceDiagram"), prop()),
),
)
}
pub fn witness_complex_ty() -> Expr {
type0()
}
pub fn weak_witness_complex_ty() -> Expr {
type0()
}
pub fn witness_complex_approximation_ty() -> Expr {
arrow(
cst("WitnessComplex"),
arrow(cst("CechComplex"), arrow(real_ty(), prop())),
)
}
pub fn delaunay_triangulation_ty() -> Expr {
type0()
}
pub fn delaunay_triangulation_stability_ty() -> Expr {
arrow(cst("DelaunayTriangulation"), arrow(real_ty(), prop()))
}
pub fn alpha_complex_delaunay_sub_ty() -> Expr {
arrow(
cst("AlphaComplex"),
arrow(cst("DelaunayTriangulation"), prop()),
)
}
pub fn sheaf_ty() -> Expr {
arrow(type0(), type0())
}
pub fn sheaf_cohomology_ty() -> Expr {
type0()
}
pub fn cosheaf_ty() -> Expr {
arrow(type0(), type0())
}
pub fn cosheaf_homology_ty() -> Expr {
type0()
}
pub fn sheaf_to_persistence_ty() -> Expr {
arrow(
cst("SimplicialComplex"),
arrow(
cst("SheafCohomology"),
arrow(cst("PersistenceDiagram"), prop()),
),
)
}
pub fn six_functor_formalism_ty() -> Expr {
arrow(app(cst("Sheaf"), type0()), prop())
}
pub fn cubical_complex_ty() -> Expr {
type0()
}
pub fn elementary_cube_ty() -> Expr {
type0()
}
pub fn cubical_homology_ty() -> Expr {
arrow(cst("CubicalComplex"), arrow(nat_ty(), type0()))
}
pub fn cubical_boundary_operator_ty() -> Expr {
arrow(
cst("CubicalComplex"),
arrow(
nat_ty(),
arrow(arrow(cst("ElementaryCube"), cst("ElementaryCube")), prop()),
),
)
}
pub fn cubical_vietoris_rips_comparison_ty() -> Expr {
arrow(
cst("CubicalComplex"),
arrow(cst("SimplicialComplex"), prop()),
)
}
pub fn morse_smale_pair_ty() -> Expr {
type0()
}
pub fn morse_smale_complex_ty() -> Expr {
type0()
}
pub fn morse_smale_decomposition_ty() -> Expr {
arrow(
cst("SimplicialComplex"),
arrow(
cst("DiscreteMorseFunction"),
arrow(cst("MorseSmaleComplex"), prop()),
),
)
}
pub fn morse_smale_cancellation_ty() -> Expr {
arrow(
cst("MorseSmaleComplex"),
arrow(nat_ty(), arrow(nat_ty(), prop())),
)
}
pub fn forman_weak_morse_inequality_ty() -> Expr {
arrow(
cst("SimplicialComplex"),
arrow(cst("DiscreteMorseFunction"), arrow(nat_ty(), prop())),
)
}
pub fn forman_strong_morse_inequality_ty() -> Expr {
arrow(
cst("SimplicialComplex"),
arrow(cst("DiscreteMorseFunction"), arrow(nat_ty(), prop())),
)
}
pub fn persistent_cohomology_ty() -> Expr {
type0()
}
pub fn cup_product_ty() -> Expr {
arrow(
cst("PersistentCohomology"),
arrow(cst("PersistentCohomology"), cst("PersistentCohomology")),
)
}
pub fn persistence_cohomology_duality_ty() -> Expr {
arrow(
cst("PersistenceDiagram"),
arrow(cst("PersistentCohomology"), prop()),
)
}
pub fn mapper_nerve_approximation_ty() -> Expr {
arrow(
cst("MapperResult"),
arrow(cst("SimplicialComplex"), arrow(real_ty(), prop())),
)
}
pub fn mapper_statistical_consistency_ty() -> Expr {
arrow(cst("MapperResult"), arrow(real_ty(), prop()))
}
pub fn mapper_cover_refinement_ty() -> Expr {
arrow(cst("MapperResult"), arrow(cst("MapperResult"), prop()))
}
pub fn register_tda_extended(env: &mut Environment) -> Result<(), String> {
let axioms: &[(&str, Expr)] = &[
("ZigzagFiltration", zigzag_filtration_ty()),
("ZigzagPersistenceModule", zigzag_persistence_module_ty()),
("ZigzagBarcode", zigzag_barcode_ty()),
(
"zigzag_decomposition_theorem",
zigzag_decomposition_theorem_ty(),
),
(
"ExtendedPersistenceDiagram",
extended_persistence_diagram_ty(),
),
(
"extended_persistence_stability",
extended_persistence_stability_ty(),
),
("MultidimensionalBarcode", multidim_barcode_ty()),
("rank_invariant", rank_invariant_ty()),
(
"multidim_persistence_classification",
multidim_persistence_classification_ty(),
),
("InterleavingDistance", interleaving_distance_ty()),
("vietoris_rips_stability", vietoris_rips_stability_ty()),
(
"interleaving_distance_stability",
interleaving_distance_stability_ty(),
),
(
"algebraic_stability_theorem",
algebraic_stability_theorem_ty(),
),
(
"bottleneck_distance_stability",
bottleneck_distance_stability_ty(),
),
("nerve_theorem", nerve_theorem_ty()),
(
"cech_complex_nerve_theorem",
cech_complex_nerve_theorem_ty(),
),
("CechRipsInterleaving", cech_rips_interleaving_ty()),
("WitnessComplex", witness_complex_ty()),
("WeakWitnessComplex", weak_witness_complex_ty()),
(
"witness_complex_approximation",
witness_complex_approximation_ty(),
),
("DelaunayTriangulation", delaunay_triangulation_ty()),
(
"delaunay_triangulation_stability",
delaunay_triangulation_stability_ty(),
),
(
"alpha_complex_delaunay_sub",
alpha_complex_delaunay_sub_ty(),
),
("SheafCohomology", sheaf_cohomology_ty()),
("CosheafHomology", cosheaf_homology_ty()),
("sheaf_to_persistence", sheaf_to_persistence_ty()),
("six_functor_formalism", six_functor_formalism_ty()),
("CubicalComplex", cubical_complex_ty()),
("ElementaryCube", elementary_cube_ty()),
("cubical_homology", cubical_homology_ty()),
("cubical_boundary_operator", cubical_boundary_operator_ty()),
(
"cubical_vietoris_rips_comparison",
cubical_vietoris_rips_comparison_ty(),
),
("MorseSmalePair", morse_smale_pair_ty()),
("MorseSmaleComplex", morse_smale_complex_ty()),
("morse_smale_decomposition", morse_smale_decomposition_ty()),
("morse_smale_cancellation", morse_smale_cancellation_ty()),
(
"forman_weak_morse_inequality",
forman_weak_morse_inequality_ty(),
),
(
"forman_strong_morse_inequality",
forman_strong_morse_inequality_ty(),
),
("PersistentCohomology", persistent_cohomology_ty()),
("cup_product", cup_product_ty()),
(
"persistence_cohomology_duality",
persistence_cohomology_duality_ty(),
),
(
"mapper_nerve_approximation",
mapper_nerve_approximation_ty(),
),
(
"mapper_statistical_consistency",
mapper_statistical_consistency_ty(),
),
("mapper_cover_refinement", mapper_cover_refinement_ty()),
];
for (name, ty) in axioms {
env.add(Declaration::Axiom {
name: Name::str(*name),
univ_params: vec![],
ty: ty.clone(),
})
.map_err(|e| format!("Failed to add {name}: {e:?}"))?;
}
Ok(())
}
pub(super) fn tda_ext_euclidean_dist(a: &[f64], b: &[f64]) -> f64 {
a.iter()
.zip(b.iter())
.map(|(x, y)| (x - y).powi(2))
.sum::<f64>()
.sqrt()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_simplex_faces() {
let s = Simplex::new(vec![0, 1, 2]);
assert_eq!(s.dimension(), 2);
let faces = s.faces();
assert_eq!(faces.len(), 3);
}
#[test]
fn test_simplicial_complex_euler() {
let mut sc = SimplicialComplex::new();
sc.add_simplex(Simplex::new(vec![0, 1, 2]));
let chi = sc.euler_characteristic();
assert_eq!(chi, 1);
}
#[test]
fn test_vietoris_rips() {
let dist = vec![
vec![0.0, 1.0, 1.0],
vec![1.0, 0.0, 1.0],
vec![1.0, 1.0, 0.0],
];
let vr = VietorisRipsComplex::build(&dist, 1.0, 2);
assert!(vr.complex.simplices.contains(&Simplex::new(vec![0, 1])));
assert!(vr.complex.simplices.contains(&Simplex::new(vec![0, 1, 2])));
}
#[test]
fn test_persistence_diagram() {
let mut diag = PersistenceDiagram::new();
diag.add(PersistenceInterval::new(0, 0.0, 1.0));
diag.add(PersistenceInterval::new(0, 0.0, f64::INFINITY));
diag.add(PersistenceInterval::new(1, 0.5, 1.5));
assert_eq!(diag.persistent_betti(0, 0.5), 2);
assert_eq!(diag.persistent_betti(1, 1.0), 1);
}
#[test]
fn test_bottleneck_distance_same() {
let mut d1 = PersistenceDiagram::new();
d1.add(PersistenceInterval::new(0, 0.0, 1.0));
let mut d2 = PersistenceDiagram::new();
d2.add(PersistenceInterval::new(0, 0.0, 1.0));
assert!((d1.bottleneck_distance(&d2) - 0.0).abs() < 1e-10);
}
#[test]
fn test_reduced_boundary_matrix() {
let mat = vec![vec![1, 1, 0], vec![1, 0, 1], vec![0, 1, 1]];
let reduced = ReducedBoundaryMatrix::reduce(&mat);
assert_eq!(reduced.num_rows, 3);
}
#[test]
fn test_mapper_single_point() {
let filter = TomographicProjection {
name: "x".to_string(),
values: vec![0.0],
};
let result = run_mapper(&filter, 2, 0.2);
assert!(result.graph.nodes.len() <= 2);
}
#[test]
fn test_morse_complex() {
let mut sc = SimplicialComplex::new();
sc.add_simplex(Simplex::new(vec![0, 1]));
sc.add_simplex(Simplex::new(vec![1, 2]));
let mut mf = DiscreteMorseFunction::new();
mf.set_value(&Simplex::new(vec![0]), 0.0);
mf.set_value(&Simplex::new(vec![1]), 1.0);
mf.set_value(&Simplex::new(vec![2]), 2.0);
mf.set_value(&Simplex::new(vec![0, 1]), 0.5);
mf.set_value(&Simplex::new(vec![1, 2]), 1.5);
let mc = MorseComplex::build(&sc, &mf);
assert!(!mc.critical_simplices.is_empty());
}
#[test]
fn test_reeb_graph() {
let mut rg = ReebGraph::new();
let n0 = rg.add_node(0.0, ReebNodeType::Minimum);
let n1 = rg.add_node(1.0, ReebNodeType::Maximum);
rg.add_edge(n0, n1);
assert_eq!(rg.minima().len(), 1);
assert_eq!(rg.maxima().len(), 1);
}
#[test]
fn test_build_env() {
let mut env = Environment::new();
build_env(&mut env);
assert!(env.get(&Name::str("SimplicialComplex")).is_some());
assert!(env.get(&Name::str("PersistenceDiagram")).is_some());
assert!(env.get(&Name::str("ReebGraph")).is_some());
assert!(env.get(&Name::str("MorseComplex")).is_some());
}
}