otorus(torus)
{
TEST_ADD(persistence_TestSuite::test_matrix_reduction);
+ TEST_ADD(persistence_TestSuite::test_betti_numbers);
+ TEST_ADD(persistence_TestSuite::test_lowestones);
}
protected:
// \ /
// 9
- scomplex::Simplex ssring[] = {
+ scomplex::simplex ssring[] = {
// dimension, faces, value...
/* 1 */ {0, {}, 1},
/* 2 */ {0, {}, 2},
/* 23 */ {2, {12, 13, 22}, 6.1201},
/* 24 */ {2, {8, 16, 22}, 6.1202}
};
- const size_t cntssring = sizeof(ssring)/sizeof(scomplex::Simplex);
+ const size_t cntssring = sizeof(ssring)/sizeof(scomplex::simplex);
ring.add_simplices(ssring, cntssring);
oring.reset();
- scomplex::Simplex sstorus[] = {
+ scomplex::simplex sstorus[] = {
// dimension, faces, value...
/* 25 */ {0, {}, 7},
/* 26 */ {0, {}, 8},
/* 53 */ {2, {10, 46, 44}, 9.1505},
/* 54 */ {2, {43, 46, 28}, 9.1506},
};
- const size_t cntsstorus = sizeof(sstorus)/sizeof(scomplex::Simplex);
+ const size_t cntsstorus = sizeof(sstorus)/sizeof(scomplex::simplex);
torus = ring;
torus.add_simplices(sstorus, cntsstorus);
otorus.reset();
- scomplex::Simplex ssball[] = {
+ scomplex::simplex ssball[] = {
// dimension, faces, value...
{0, {}, 1},
{0, {}, 2},
{3, {21, 14, 15, 19}, 22},
{3, {21, 16, 17, 20}, 23},
};
- const size_t cntssball = sizeof(ssball)/sizeof(scomplex::Simplex);
+ const size_t cntssball = sizeof(ssball)/sizeof(scomplex::simplex);
ball.add_simplices(ssball, cntssball);
oball.reset();
}
void test_matrix_reduction() {
pers ringp(oring);
+ ringp.compute_matrices();
const bm &ringbm = ringp.get_boundary_matrix();
const bm &ringrbm = ringp.get_reduced_boundary_matrix();
const tm &ringtm = ringp.get_transformation_matrix();
TEST_ASSERT(ringrbm == ringbm * ringtm);
pers torusp(otorus);
+ torusp.compute_matrices();
const bm &torusbm = torusp.get_boundary_matrix();
const bm &torusrbm = torusp.get_reduced_boundary_matrix();
const tm &torustm = torusp.get_transformation_matrix();
torusrbme.set_all(torusrbme_coords, sizeof(torusrbme_coords)/(2*sizeof(uint32_t)), true);
TEST_ASSERT(torusrbme == torusrbm);
-
pers ballp(oball);
+ ballp.compute_matrices();
const bm &ballbm = ballp.get_boundary_matrix();
const bm &ballrbm = ballp.get_reduced_boundary_matrix();
const tm &balltm = ballp.get_transformation_matrix();
//std::cout << std::endl;
//ballp.interpret_reduction(std::cout);
+ //torusp.compute_diagrams();
+ //torusp.interpret_persistence(std::cout);
+ //std::cout << std::endl;
+ //std::cout << std::endl;
+ }
+
+ void test_betti_numbers() {
+ pers ringp(oring);
+ ringp.compute_diagrams();
+
+ TEST_ASSERT(ringp.get_persistence_diagram(-1).betti() == 0);
+ TEST_ASSERT(ringp.get_persistence_diagram(0).betti() == 0);
+ TEST_ASSERT(ringp.get_persistence_diagram(1).betti() == 1);
+ TEST_ASSERT(ringp.get_persistence_diagram(2).betti() == 0);
+ TEST_ASSERT(ringp.get_persistence_diagram(3).betti() == 0);
+ for (unsigned d=0; d < 3; ++d)
+ TEST_ASSERT(ringp.get_persistence_diagram(d).persistent_betti(oring.size()-1, oring.size()-1) ==
+ ringp.get_persistence_diagram(d).betti());
+
+
+ pers torusp(otorus);
+ torusp.compute_diagrams();
+
+ TEST_ASSERT(torusp.get_persistence_diagram(-1).betti() == 0);
+ TEST_ASSERT(torusp.get_persistence_diagram(0).betti() == 0);
+ TEST_ASSERT(torusp.get_persistence_diagram(1).betti() == 2);
+ TEST_ASSERT(torusp.get_persistence_diagram(2).betti() == 1);
+ TEST_ASSERT(torusp.get_persistence_diagram(3).betti() == 0);
+ for (unsigned d=0; d < 3; ++d)
+ TEST_ASSERT(torusp.get_persistence_diagram(d).persistent_betti(otorus.size()-1, otorus.size()-1) ==
+ torusp.get_persistence_diagram(d).betti());
+
+ // Torus was made from ring. Hence, persistent betti numbers must correspond to betti numbers of ring.
+ for (unsigned d=0; d < 3; ++d)
+ TEST_ASSERT(torusp.get_persistence_diagram(d).persistent_betti(oring.size()-1, oring.size()-1) ==
+ ringp.get_persistence_diagram(d).betti());
+
+
+ pers ballp(oball);
+ ballp.compute_diagrams();
+
+ //std::cout << std::endl;
+ //ballp.interpret_reduction(std::cout);
+ //std::cout << std::endl;
+
+ TEST_ASSERT(ballp.get_persistence_diagram(-1).betti() == 0);
+ TEST_ASSERT(ballp.get_persistence_diagram(0).betti() == 0);
+ TEST_ASSERT(ballp.get_persistence_diagram(1).betti() == 0);
+ TEST_ASSERT(ballp.get_persistence_diagram(2).betti() == 0);
+ TEST_ASSERT(ballp.get_persistence_diagram(3).betti() == 0);
+ for (unsigned d=0; d < 3; ++d)
+ TEST_ASSERT(ballp.get_persistence_diagram(d).persistent_betti(oball.size()-1, oball.size()-1) ==
+ ballp.get_persistence_diagram(d).betti());
+
+ // Before we inserted the two tetrahedra and the interior triangle, we had a sphere.
+ TEST_ASSERT(ballp.get_persistence_diagram(-1).persistent_betti(oball.size()-4, oball.size()-4) == 0);
+ TEST_ASSERT(ballp.get_persistence_diagram(0).persistent_betti(oball.size()-4, oball.size()-4) == 0);
+ TEST_ASSERT(ballp.get_persistence_diagram(1).persistent_betti(oball.size()-4, oball.size()-4) == 0);
+ TEST_ASSERT(ballp.get_persistence_diagram(2).persistent_betti(oball.size()-4, oball.size()-4) == 1);
+ TEST_ASSERT(ballp.get_persistence_diagram(3).persistent_betti(oball.size()-4, oball.size()-4) == 0);
+
+ // Before we inserted the two tetrahedra, we had a double-sphere.
+ TEST_ASSERT(ballp.get_persistence_diagram(-1).persistent_betti(oball.size()-3, oball.size()-3) == 0);
+ TEST_ASSERT(ballp.get_persistence_diagram(0).persistent_betti(oball.size()-3, oball.size()-3) == 0);
+ TEST_ASSERT(ballp.get_persistence_diagram(1).persistent_betti(oball.size()-3, oball.size()-3) == 0);
+ TEST_ASSERT(ballp.get_persistence_diagram(2).persistent_betti(oball.size()-3, oball.size()-3) == 2);
+ TEST_ASSERT(ballp.get_persistence_diagram(3).persistent_betti(oball.size()-3, oball.size()-3) == 0);
+ }
+
+ void test_lowestones() {
+ test_lowestones_impl(oring);
+ test_lowestones_impl(otorus);
+ test_lowestones_impl(oball);
+ }
+
+ void test_lowestones_impl(const scomplex::simplex_order& so) {
+ pers p(so);
+ p.compute_matrices();
+ const bm &lowestones = p.get_lowestones_matrix();
+
+ for (unsigned c=0; c < lowestones.size(); ++c)
+ assert(lowestones.get_column(c).size() <= 1);
+ for (unsigned r=0; r < lowestones.size(); ++r)
+ assert(lowestones.get_row(r).size() <= 1);
+ for (unsigned c=0; c < lowestones.size(); ++c) {
+ // If (r,c) is a one then
+ // (i) a cycle dies with c --> row c is zero
+ // (ii) a cycle is born with r --> column r is zero
+ //Hence
+ // (i) the column r is a zero-column
+ // (i) the row c is a zero-column
+ if (lowestones.get_column(c).size() > 0) {
+ const uint32_t r = lowestones.get_column(c).back();
+ assert(lowestones.get_column(r).size() == 0);
+ assert(lowestones.get_row(c).size() == 0);
+ }
+ }
}
};