From 46e2e26363bfa07dc79d912ebe6df772942536bd Mon Sep 17 00:00:00 2001 From: Stefan Huber Date: Mon, 11 Nov 2013 17:02:42 +0100 Subject: [PATCH] Add tests for matrix reduction of complex examples - Move matrix_reduction() to a persistence class. - Add persistence test suite. - Add a few helper functions to boolean_matrix classes. --- include/libstick-0.1/booleanmatrix.h | 66 ++++++- include/libstick-0.1/matrixreduction.h | 51 ------ include/libstick-0.1/persistence.h | 201 +++++++++++++++++++++ include/libstick-0.1/simplicialcomplex.h | 6 + tests/main.cc | 2 + tests/persistence.h | 217 +++++++++++++++++++++++ tests/simplicialcomplex.h | 78 ++------ 7 files changed, 502 insertions(+), 119 deletions(-) delete mode 100644 include/libstick-0.1/matrixreduction.h create mode 100644 include/libstick-0.1/persistence.h create mode 100644 tests/persistence.h diff --git a/include/libstick-0.1/booleanmatrix.h b/include/libstick-0.1/booleanmatrix.h index 774aeb7..1fb4dd2 100644 --- a/include/libstick-0.1/booleanmatrix.h +++ b/include/libstick-0.1/booleanmatrix.h @@ -25,11 +25,13 @@ class boolean_colmatrix_base { typedef std::vector column_type; typedef D derived; + protected: /** Create a matrix with 'width' columns, initalized with zero entries. */ boolean_colmatrix_base(size_t width) : cols(width) { } + public: /** Get height resp. width of the matrix. */ size_t width() const { return cols.size(); @@ -47,6 +49,12 @@ class boolean_colmatrix_base { get_derived()->_set(r, c, value); } + /** For each of the 'count'-many (row-index, column-pair) pair in 'indices', set the specific value. */ + void set_all(index_type indices[][2], size_t count, bool value) { + for (unsigned i=0; i < count; ++i) + set(indices[i][0], indices[i][1], value); + } + /** Get the c-th column. */ const column_type& get_column(index_type c) const { assert(c < width()); @@ -73,6 +81,24 @@ class boolean_colmatrix_base { return !(*this == m); } + /** Print index pairs of the 1s as { {r, c}, {r, c}, {r, c} } */ + void print_indexpairs(std::ostream &os) const { + bool first=true; + + os << "{"; + for (unsigned c=0; c < width(); ++c) { + const column_type &col = get_column(c); + for (typename column_type::const_iterator it = col.begin(); it != col.end(); ++it) { + if (first) + first = false; + else + os << ","; + os << " {" << *it << ", " << c << "}"; + } + } + os << " }"; + } + protected: /** Set the matrix entry at row 'r' and column 'c'. */ void _set(index_type r, index_type c, bool value) { @@ -148,12 +174,14 @@ class boolean_rowmatrix_base { typedef std::vector row_type; typedef D derived; + protected: /** Create a matrix with 'height' rows, initalized with zero entries. * */ boolean_rowmatrix_base(size_t height) : rows(height) { } + public: /** Get height resp. width of the matrix. */ size_t height() const { return rows.size(); @@ -171,6 +199,12 @@ class boolean_rowmatrix_base { get_derived()->_set(r, c, value); } + /** For each of the 'count'-many (row-index, column-pair) pair in 'indices', set the specific value. */ + void set_all(index_type indices[][2], size_t count, bool value) { + for (unsigned i=0; i < count; ++i) + set(indices[i][0], indices[i][1], value); + } + /** Get the r-th row. */ const row_type& get_row(index_type r) const { assert(r < height()); @@ -301,6 +335,11 @@ class boolean_colrowmatrix : public boolean_colmatrix_base - boolean_colrowmatrix operator*(const boolean_colmatrix_base &b) { + boolean_colrowmatrix operator*(const boolean_colmatrix_base &b) const { boolean_colrowmatrix c(size()); multiply_matrix(c, *this, b); return c; @@ -353,14 +392,14 @@ size_t count_set_intersection (InputIterator1 first1, InputIterator1 last1, Inpu } /** Multiply a*b and save the product in 'result'. It is assumed that 'result' is intially empty and has appropriate size. */ -template -void multiply_matrix(RT &result, const boolean_rowmatrix_base &a, const boolean_colmatrix_base &b) { +template +void multiply_matrix(RT &result, const boolean_rowmatrix_base &a, const boolean_colmatrix_base &b) { assert(a.height() == b.width()); for (unsigned r=0; r < a.height(); ++r) { - const typename boolean_rowmatrix_base::row_type &row = a.get_row(r); + const typename boolean_rowmatrix_base::row_type &row = a.get_row(r); for (unsigned c=0; c < b.width(); ++c) { - const typename boolean_colmatrix_base::column_type &col = b.get_column(c); + const typename boolean_colmatrix_base::column_type &col = b.get_column(c); if (count_set_intersection(row.begin(), row.end(), col.begin(), col.end()) % 2 == 1) result.set(r, c, true); } @@ -377,7 +416,24 @@ MT create_unit_matrix(size_t size) { template std::ostream& operator<<(std::ostream &os, const boolean_colrowmatrix &mat) { + + os << " "; + for (unsigned c=0; c < mat.size(); ++c) { + const unsigned d = (c % 10); + if (d > 0) + os << d; + else + os << " "; + } + os << std::endl; + for (unsigned r=0; r < mat.size(); ++r) { + const unsigned d = (r % 10); + if (d > 0) + os << d; + else + os << " "; + for (unsigned c=0; c < mat.size(); ++c) os << (mat.get(r,c) ? "X" : "."); diff --git a/include/libstick-0.1/matrixreduction.h b/include/libstick-0.1/matrixreduction.h deleted file mode 100644 index d9624cc..0000000 --- a/include/libstick-0.1/matrixreduction.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef matrixreduction_h_aPeinoXeiFeethuz -#define matrixreduction_h_aPeinoXeiFeethuz - -#include - -#include "booleanmatrix.h" - - -namespace libstick { - -/** Takes the boundary matrix b and transforms it inplace into a reduced matrix - * b. The matrix v is required to be a unit matrix having the same dimensions - * as b. It is maintained in order to leave the product b*inverse(v) as an - * invariant. Hence, the resulting b is equal to the product of the boundary - * matrix times v. */ -template -void reduce_boundary_matrix(boolean_colrowmatrix &b, boolean_colmatrix_base &v) { - assert(b.size() == v.width()); - - // Make every column reduced, i.e., it is a zero-column or contains only one 1. - for (unsigned c=0; c < b.size(); ++c) { - const typename boolean_colrowmatrix::colbase::column_type &col = b.get_column(c); - if (col.size() == 0) - continue; - - // The column is not a zero-column, take the lowest 1, and reduce the other columns at the row - IT r = col.back(); - assert(b.get(r, c)); - - // Get a copy of the r-th row - typename boolean_colrowmatrix::rowbase::row_type row(b.get_row(r).size()); - copy(b.get_row(r).begin(), b.get_row(r).end(), row.begin()); - assert(row.size() >= 1); - - // Get rid of 1s at that row right of column c. - typename boolean_colrowmatrix::row_type::const_iterator it = lower_bound(row.begin(), row.end(), c); - for(; it != row.end(); ++it) { - if (*it <= c) - continue; - - assert(b.get(r, *it)); - b.add_column(*it, col); - v.add_column(*it, v.get_column(c)); - assert(!b.get(r, *it)); - } - } -} - -} - -#endif diff --git a/include/libstick-0.1/persistence.h b/include/libstick-0.1/persistence.h new file mode 100644 index 0000000..937a4cc --- /dev/null +++ b/include/libstick-0.1/persistence.h @@ -0,0 +1,201 @@ +#ifndef persistence_h_aPeinoXeiFeethuz +#define persistence_h_aPeinoXeiFeethuz + +#include +#include +#include + +#include "simplicialcomplex.h" +#include "booleanmatrix.h" + + +namespace libstick { + + +template +std::ostream& operator<<(std::ostream &, const std::vector &); + + +/** Persistence computers various persistent homology information on a + * simplex_order of a simplicial_complex. */ +template +class persistence { + + public: + typedef typename simplicial_complex::simplex_order simplex_order; + typedef typename simplex_order::boundary_matrix boundary_matrix; + typedef boolean_colmatrix transformation_matrix; + + /** A point in a diagram comprises birth- and death-index. These are the + * indices of the simplices of 'order' that give birth and death to the + * class. */ + struct diagram_point { + IT birth; + IT death; + }; + + + public: + /** Create a new peristence object on the given simplex_order */ + persistence(const simplex_order &order) : + order(order), + bm(0), + rbm(0), + tm(0) + { + reset(); + } + + /** Reset all results gained from 'order'. */ + void reset() { + done_matrices = false; + } + + /** Get boundary matrix 'bm' of 'order', compute reduces boundary + * matrix 'rbm', and the transformation matrix 'tm' such that rbm = bm * + * tm. */ + void compute_matrices() { + if (done_matrices) + return; + done_matrices = true; + + bm = order.get_boundary_matrix(); + rbm = bm; + tm = create_unit_matrix(bm.size()); + reduce_boundary_matrix(rbm, tm); + + assert(rbm == bm * tm); + } + + /** Get the boundary matrix of 'order'. */ + const boundary_matrix& get_boundary_matrix() { + compute_matrices(); + return bm; + } + + /** Get the reduced boundary matrix of 'order'. */ + const boundary_matrix& get_reduced_boundary_matrix() { + compute_matrices(); + return rbm; + } + + /** Get the transformation matrix of 'order', which transforms the + * boundary matrix to the reduced boundary matrix, when multiplied from + * the right. */ + const transformation_matrix& get_transformation_matrix() { + compute_matrices(); + return tm; + } + + + /** Print the sequence of births and deaths of cycles (homology classes). */ + void interpret_reduction(std::ostream &os) { + compute_matrices(); + for (unsigned c=0; c < bm.size(); ++c) { + os << c << ". inserting "; + + switch (bm.get_column(c).size()) { + case 0: + os << "dummy vertex of dim -1"; + break; + case 1: + os << "vertex"; + break; + case 2: + os << "edge"; + break; + case 3: + os << "triangle"; + break; + case 4: + os << "tetrahedron"; + break; + default: + os << "simplex"; + break; + } + + os << std::endl; + os << " boundary: " << bm.get_column(c) << std::endl; + + typename boolean_colrowmatrix::colbase::column_type col = rbm.get_column(c); + if (col.size() == 0) { + os << " \033[1;32mbirth\033[0;m of a cycle: " << tm.get_column(c) << std::endl; + } else { + os << " \033[1;31mdeath\033[0;m of a cycle: " << rbm.get_column(c) << std::endl; + os << " boundary of: " << tm.get_column(c) << std::endl; + } + os << std::endl; + } + } + + private: + + /** The underlying simplex order of this diagram. */ + const simplex_order ℴ + + bool done_matrices; + + boundary_matrix bm; + boundary_matrix rbm; + transformation_matrix tm; +}; + + +/** Takes the boundary matrix b and transforms it inplace into a reduced matrix + * b. The matrix v is required to be a unit matrix having the same dimensions + * as b. It is maintained in order to leave the product b*inverse(v) as an + * invariant. Hence, the resulting b is equal to the product of the boundary + * matrix times v. */ +template +void reduce_boundary_matrix(boolean_colrowmatrix &b, boolean_colmatrix_base &v) { + assert(b.size() == v.width()); + + // Make every column reduced, i.e., it is a zero-column or contains only one 1. + for (unsigned c=0; c < b.size(); ++c) { + const typename boolean_colrowmatrix::colbase::column_type &col = b.get_column(c); + if (col.size() == 0) + continue; + + // The column is not a zero-column, take the lowest 1, and reduce the other columns at the row + IT r = col.back(); + assert(b.get(r, c)); + + // Get a copy of the r-th row + typename boolean_colrowmatrix::rowbase::row_type row(b.get_row(r).size()); + copy(b.get_row(r).begin(), b.get_row(r).end(), row.begin()); + assert(row.size() >= 1); + + // Get rid of 1s at that row right of column c. + typename boolean_colrowmatrix::row_type::const_iterator it = lower_bound(row.begin(), row.end(), c); + for(; it != row.end(); ++it) { + if (*it <= c) + continue; + + assert(b.get(r, *it)); + b.add_column(*it, col); + v.add_column(*it, v.get_column(c)); + assert(!b.get(r, *it)); + } + } +} + +template +std::ostream& operator<<(std::ostream& os, const std::vector &vec) { + os << "["; + + typename std::vector::const_iterator it = vec.begin(); + while ( it != vec.end()) { + os << *it; + if (++it != vec.end()) + os << " "; + } + + os << "]"; + return os; +} + + +} // namespace libstick + +#endif diff --git a/include/libstick-0.1/simplicialcomplex.h b/include/libstick-0.1/simplicialcomplex.h index 47a88c6..707fd4f 100644 --- a/include/libstick-0.1/simplicialcomplex.h +++ b/include/libstick-0.1/simplicialcomplex.h @@ -223,6 +223,12 @@ class simplicial_complex { simplices.push_back(s); } + /** Add an array of simplices */ + void add_simplices(Simplex* sarray, size_t count) { + for (unsigned i=0; i < count; ++i) + add_simplex(sarray[i]); + } + /** Return true iff for each simplex i with dimension dim it holds that * the faces of i are contained in the complex and have dimension dim-1. */ bool is_complex() const { diff --git a/tests/main.cc b/tests/main.cc index ef4977e..0b3dd99 100644 --- a/tests/main.cc +++ b/tests/main.cc @@ -3,6 +3,7 @@ #include "booleanmatrix.h" #include "simplicialcomplex.h" +#include "persistence.h" using namespace std; @@ -15,6 +16,7 @@ int main(int argc, char* argv[]) { ts.add(auto_ptr(new boolean_matrix_TestSuite)); ts.add(auto_ptr(new simplicial_complex_TestSuite)); + ts.add(auto_ptr(new persistence_TestSuite)); Test::TextOutput output(Test::TextOutput::Verbose); return ts.run(output); diff --git a/tests/persistence.h b/tests/persistence.h new file mode 100644 index 0000000..55774dd --- /dev/null +++ b/tests/persistence.h @@ -0,0 +1,217 @@ +#ifndef persistence_h_Fahlaewahgaebaqu +#define persistence_h_Fahlaewahgaebaqu + +#include +#include + +#include + +using namespace libstick; + + +class persistence_TestSuite: public Test::Suite { + + private: + typedef simplicial_complex<3, uint32_t, double> scomplex; + typedef persistence<3, uint32_t, double> pers; + typedef pers::boundary_matrix bm; + typedef pers::transformation_matrix tm; + + bool setupcalled; + scomplex ball, ring, torus; + scomplex::simplex_order oball, oring, otorus; + + public: + persistence_TestSuite() : + setupcalled(false), + oball(ball), + oring(ring), + otorus(torus) + { + TEST_ADD(persistence_TestSuite::test_matrix_reduction); + } + + protected: + virtual void setup() { + if (setupcalled) + return; + setupcalled = true; + + // 7 ------------------------------------- 8 + // \ / + // \ 4 ------------------------- 5 / + // \ \ / / + // \ \ 1 ------- 2 / / + // \ \ \ / / / + // \ \ \ / / / + // \ \ \ / / / + // \ \ \ / / / + // \ \ 3 / / + // \ \ / / + // \ \ / / + // \ \ / / + // \ \ / / + // \ \ / / + // \ \ / / + // \ 6 / + // \ / + // \ / + // \ / + // 9 + + scomplex::Simplex ssring[] = { + // dimension, faces, value... + /* 1 */ {0, {}, 1}, + /* 2 */ {0, {}, 2}, + /* 3 */ {0, {}, 3}, + /* 4 */ {0, {}, 4}, + /* 5 */ {0, {}, 5}, + /* 6 */ {0, {}, 6}, + /* 7 */ {1, {2, 3}, 6.01}, + /* 8 */ {1, {3, 1}, 6.02}, + /* 9 */ {1, {1, 2}, 6.03}, + /* 10 */ {1, {4, 5}, 6.04}, + /* 11 */ {1, {5, 6}, 6.05}, + /* 12 */ {1, {6, 4}, 6.06}, + /* 13 */ {1, {1, 4}, 6.07}, + /* 14 */ {1, {1, 5}, 6.08}, + /* 15 */ {2, {13, 14, 10}, 6.0801}, + /* 16 */ {1, {3, 6}, 6.09}, + /* 17 */ {1, {2, 5}, 6.10}, + /* 18 */ {1, {2, 6}, 6.11}, + /* 19 */ {2, {9, 14, 17}, 6.1101}, + /* 20 */ {2, {7, 16, 18}, 6.1102}, + /* 21 */ {2, {11, 17, 18}, 6.1103}, + /* 22 */ {1, {1, 6}, 6.12}, + /* 23 */ {2, {12, 13, 22}, 6.1201}, + /* 24 */ {2, {8, 16, 22}, 6.1202} + }; + const size_t cntssring = sizeof(ssring)/sizeof(scomplex::Simplex); + ring.add_simplices(ssring, cntssring); + oring.reset(); + + scomplex::Simplex sstorus[] = { + // dimension, faces, value... + /* 25 */ {0, {}, 7}, + /* 26 */ {0, {}, 8}, + /* 27 */ {0, {}, 9}, + /* 28 */ {1, {25, 26}, 9.01}, + /* 29 */ {1, {26, 27}, 9.02}, + /* 30 */ {1, {25, 27}, 9.03}, + /* 31 */ {1, {25, 1}, 9.04}, + /* 32 */ {1, {26, 1}, 9.05}, + /* 33 */ {2, {28, 31, 32}, 9.0501}, + /* 34 */ {1, {27, 1}, 9.06}, + /* 35 */ {2, {30, 31, 34}, 9.0601}, + /* 36 */ {1, {27, 3}, 9.07}, + /* 37 */ {2, {36, 34, 8}, 9.0701}, + /* 38 */ {1, {27, 2}, 9.08}, + /* 39 */ {1, {26, 2}, 9.09}, + /* 40 */ {2, {9, 32, 39}, 9.0901}, + /* 41 */ {2, {29, 38, 39}, 9.0902}, + /* 42 */ {2, {7, 38, 36}, 9.0903}, + /* 43 */ {1, {4, 25}, 9.10}, + /* 44 */ {1, {5, 26}, 9.11}, + /* 45 */ {1, {6, 27}, 9.12}, + /* 46 */ {1, {4, 26}, 9.13}, + /* 47 */ {1, {4, 27}, 9.14}, + /* 48 */ {1, {5, 27}, 9.15}, + /* 49 */ {2, {43, 47, 30}, 9.1501}, + /* 50 */ {2, {12, 45, 47}, 9.1502}, + /* 51 */ {2, {29, 44, 48}, 9.1503}, + /* 52 */ {2, {48, 11, 45}, 9.1504}, + /* 53 */ {2, {10, 46, 44}, 9.1505}, + /* 54 */ {2, {43, 46, 28}, 9.1506}, + }; + const size_t cntsstorus = sizeof(sstorus)/sizeof(scomplex::Simplex); + torus = ring; + torus.add_simplices(sstorus, cntsstorus); + otorus.reset(); + + scomplex::Simplex ssball[] = { + // dimension, faces, value... + {0, {}, 1}, + {0, {}, 2}, + {0, {}, 3}, + {0, {}, 4}, + {0, {}, 5}, + {1, {1, 2}, 6}, + {1, {2, 3}, 7}, + {1, {3, 4}, 8}, + {1, {4, 1}, 9}, + {1, {1, 5}, 10}, + {1, {2, 5}, 11}, + {1, {3, 5}, 12}, + {1, {4, 5}, 13}, + {2, {6, 10, 11}, 14}, + {2, {7, 11, 12}, 15}, + {2, {8, 12, 13}, 16}, + {2, {9, 13, 10}, 17}, + {1, {1, 3}, 18}, + {2, {18, 6, 7}, 19}, + {2, {18, 8, 9}, 20}, + {2, {18, 10, 12}, 21}, + {3, {21, 14, 15, 19}, 22}, + {3, {21, 16, 17, 20}, 23}, + }; + const size_t cntssball = sizeof(ssball)/sizeof(scomplex::Simplex); + ball.add_simplices(ssball, cntssball); + oball.reset(); + } + + virtual void tear_down() { + } + + void test_matrix_reduction() { + pers ringp(oring); + 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); + const bm &torusbm = torusp.get_boundary_matrix(); + const bm &torusrbm = torusp.get_reduced_boundary_matrix(); + const tm &torustm = torusp.get_transformation_matrix(); + TEST_ASSERT(torusrbm == torusbm * torustm); + + uint32_t torusrbme_coords[][2] = { + {0, 1}, {2, 7}, {3, 7}, {1, 8}, {2, 8}, {4, 10}, {5, 10}, {4, 11}, {6, 11}, {1, 13}, + {4, 13}, {10, 15}, {13, 15}, {14, 15}, {9, 19}, {10, 19}, {13, 19}, {17, 19}, {7, 20}, + {16, 20}, {18, 20}, {7, 21}, {9, 21}, {10, 21}, {11, 21}, {13, 21}, {16, 21}, {12, 23}, + {13, 23}, {22, 23}, {7, 24}, {8, 24}, {9, 24}, {10, 24}, {11, 24}, {12, 24}, {25, 28}, + {26, 28}, {25, 29}, {27, 29}, {1, 31}, {25, 31}, {28, 33}, {31, 33}, {32, 33}, {30, 35}, + {31, 35}, {34, 35}, {8, 37}, {30, 37}, {31, 37}, {36, 37}, {9, 40}, {28, 40}, {31, 40}, + {39, 40}, {9, 41}, {28, 41}, {29, 41}, {31, 41}, {38, 41}, {7, 42}, {8, 42}, {9, 42}, + {28, 42}, {29, 42}, {30, 42}, {7, 49}, {8, 49}, {9, 49}, {28, 49}, {29, 49}, {43, 49}, + {47, 49}, {10, 50}, {11, 50}, {28, 50}, {29, 50}, {43, 50}, {45, 50}, {29, 51}, {44, 51}, + {48, 51}, {10, 52}, {28, 52}, {43, 52}, {44, 52}, {28, 53}, {43, 53}, {46, 53 } + }; + bm torusrbme(torusbm.size()); + torusrbme.set_all(torusrbme_coords, sizeof(torusrbme_coords)/(2*sizeof(uint32_t)), true); + TEST_ASSERT(torusrbme == torusrbm); + + + pers ballp(oball); + const bm &ballbm = ballp.get_boundary_matrix(); + const bm &ballrbm = ballp.get_reduced_boundary_matrix(); + const tm &balltm = ballp.get_transformation_matrix(); + TEST_ASSERT(ballrbm == ballbm * balltm); + + uint32_t ballrbme_coords[][2] = { + {0, 1}, {1, 6}, {2, 6}, {1, 7}, {3, 7}, {1, 8}, {4, 8}, {1, 10}, {5, 10}, {6, 14}, + {10, 14}, {11, 14}, {6, 15}, {7, 15}, {10, 15}, {12, 15}, {6, 16}, {7, 16}, {8, 16}, + {10, 16}, {13, 16}, {6, 17}, {7, 17}, {8, 17}, {9, 17}, {6, 19}, {7, 19}, {18, 19}, + {14, 22}, {15, 22}, {19, 22}, {21, 22}, {14, 23}, {15, 23}, {16, 23}, {17, 23}, {19, 23}, + {20, 23 } + }; + bm ballrbme(ballrbm.size()); + ballrbme.set_all(ballrbme_coords, sizeof(ballrbme_coords)/(2*sizeof(uint32_t)), true); + TEST_ASSERT(ballrbme == ballrbm); + + //std::cout << std::endl; + //ballp.interpret_reduction(std::cout); + } +}; + +#endif diff --git a/tests/simplicialcomplex.h b/tests/simplicialcomplex.h index 3736883..6e63f54 100644 --- a/tests/simplicialcomplex.h +++ b/tests/simplicialcomplex.h @@ -5,7 +5,6 @@ #include #include -#include using namespace libstick; @@ -13,7 +12,7 @@ using namespace libstick; class simplicial_complex_TestSuite: public Test::Suite { private: - typedef simplicial_complex<2, uint32_t, double> scomplex; + typedef simplicial_complex<3, uint32_t, double> scomplex; typedef scomplex::simplex_order::boundary_matrix bm; bool setupcalled; @@ -33,7 +32,6 @@ class simplicial_complex_TestSuite: public Test::Suite { TEST_ADD(simplicial_complex_TestSuite::test_is_order_filtration); TEST_ADD(simplicial_complex_TestSuite::test_is_order_monotone); TEST_ADD(simplicial_complex_TestSuite::test_boundary_matrix); - TEST_ADD(simplicial_complex_TestSuite::test_matrix_reduction); } protected: @@ -42,8 +40,7 @@ class simplicial_complex_TestSuite: public Test::Suite { return; setupcalled = true; - const unsigned num = 11; - scomplex::Simplex ss[num] = { + scomplex::Simplex ss[] = { // dimension, faces, value... {0, {}, 1}, {0, {}, 2}, @@ -57,6 +54,8 @@ class simplicial_complex_TestSuite: public Test::Suite { {2, {7, 8, 9}, 10}, {2, {5, 6, 9}, 11} }; + const size_t cntss = sizeof(ss)/sizeof(scomplex::Simplex); + c1.add_simplices(ss, cntss); // This is o1 This is o2 This is o3(b) // (value = index) (values) (values) @@ -73,10 +72,6 @@ class simplicial_complex_TestSuite: public Test::Suite { // | \| | \| | \| // 4 ----7---- 3 4 ----7---- 3 4 ----7---- 3 - // Build the complex - for (unsigned i=0; i(b.size()); - - bm b_orig = b; - reduce_boundary_matrix(b, v); - TEST_ASSERT(b == b_orig*v); - - //std::cout << std::endl << "after reduce: " << std::endl; - //std::cout << std::endl << b << std::endl; - //std::cout << std::endl << v << std::endl; - //std::cout << std::endl << (b_orig*v) << std::endl; - } }; #endif -- 2.30.2