| dmitriy@92 | 1 | #include <topology/rips.h> |
| dmitriy@113 | 2 | #include <topology/filtration.h> |
| dmitriy@113 | 3 | #include <topology/static-persistence.h> |
| dmitriy@115 | 4 | #include <topology/dynamic-persistence.h> |
| dmitriy@113 | 5 | #include <topology/persistence-diagram.h> |
| dmitriy@113 | 6 | #include <utilities/containers.h> // for BackInsertFunctor |
| dmitriy@113 | 7 | |
| dmitriy@113 | 8 | #include <fstream> |
| dmitriy@113 | 9 | #include <boost/archive/binary_oarchive.hpp> |
| dmitriy@113 | 10 | #include <boost/serialization/map.hpp> |
| dmitriy@92 | 11 | |
| dmitriy@109 | 12 | // Trivial example of size() points on a line with integer coordinates |
| dmitriy@92 | 13 | struct Distances |
| dmitriy@92 | 14 | { |
| dmitriy@92 | 15 | typedef int IndexType; |
| dmitriy@92 | 16 | typedef double DistanceType; |
| dmitriy@92 | 17 | |
| dmitriy@92 | 18 | DistanceType operator()(IndexType a, IndexType b) const { return std::abs(a - b); } |
| dmitriy@92 | 19 | |
| dmitriy@92 | 20 | size_t size() const { return 2000; } |
| dmitriy@92 | 21 | IndexType begin() const { return 0; } |
| dmitriy@92 | 22 | IndexType end() const { return size(); } |
| dmitriy@92 | 23 | }; |
| dmitriy@92 | 24 | |
| dmitriy@113 | 25 | //typedef Rips<ExplicitDistances<Distances> > Generator; |
| dmitriy@113 | 26 | typedef Rips<Distances> Generator; |
| dmitriy@113 | 27 | typedef Generator::Simplex Smplx; |
| dmitriy@179 | 28 | typedef Filtration<Smplx> Fltr; |
| dmitriy@179 | 29 | typedef StaticPersistence<> Persistence; |
| dmitriy@179 | 30 | // typedef DynamicPersistenceChains<> Persistence; |
| dmitriy@115 | 31 | typedef PersistenceDiagram<> PDgm; |
| dmitriy@113 | 32 | |
| dmitriy@113 | 33 | |
| dmitriy@92 | 34 | int main(int argc, char* argv[]) |
| dmitriy@92 | 35 | { |
| dmitriy@92 | 36 | #ifdef LOGGING |
| dmitriy@92 | 37 | rlog::RLogInit(argc, argv); |
| dmitriy@92 | 38 | |
| dmitriy@92 | 39 | stdoutLog.subscribeTo( RLOG_CHANNEL("error") ); |
| dmitriy@113 | 40 | stdoutLog.subscribeTo( RLOG_CHANNEL("info") ); |
| dmitriy@113 | 41 | //stdoutLog.subscribeTo( RLOG_CHANNEL("rips/info") ); |
| dmitriy@113 | 42 | //stdoutLog.subscribeTo( RLOG_CHANNEL("rips/debug") ); |
| dmitriy@92 | 43 | #endif |
| dmitriy@92 | 44 | |
| dmitriy@92 | 45 | Distances distances; |
| morozov@94 | 46 | |
| dmitriy@109 | 47 | // Storing ExplicitDistances speeds up the computation (at the price of memory) |
| dmitriy@113 | 48 | //ExplicitDistances<Distances> explicit_distances(distances); |
| dmitriy@92 | 49 | |
| dmitriy@113 | 50 | Generator rips(distances); |
| dmitriy@113 | 51 | Generator::Evaluator size(distances); |
| dmitriy@179 | 52 | Fltr f; |
| dmitriy@92 | 53 | |
| dmitriy@113 | 54 | // Generate 2-skeleton of the Rips complex for epsilon = 50 |
| dmitriy@179 | 55 | rips.generate(2, 10, make_push_back_functor(f)); |
| dmitriy@179 | 56 | rInfo("Generated complex of size: %d", f.size()); |
| dmitriy@113 | 57 | |
| dmitriy@113 | 58 | // Generate filtration with respect to distance and compute its persistence |
| dmitriy@179 | 59 | f.sort(Generator::Comparison(distances)); |
| dmitriy@113 | 60 | Persistence p(f); |
| dmitriy@113 | 61 | p.pair_simplices(); |
| dmitriy@113 | 62 | rInfo("Simplices paired"); |
| dmitriy@113 | 63 | |
| dmitriy@179 | 64 | Persistence::SimplexMap<Fltr> m = p.make_simplex_map(f); |
| dmitriy@179 | 65 | |
| dmitriy@113 | 66 | // Record the persistence intervals in the persistence diagrams |
| dmitriy@113 | 67 | std::map<Dimension, PDgm> dgms; |
| dmitriy@113 | 68 | init_diagrams(dgms, p.begin(), p.end(), |
| dmitriy@179 | 69 | evaluate_through_map(m, size), |
| dmitriy@179 | 70 | evaluate_through_map(m, Smplx::DimensionExtractor())); |
| dmitriy@113 | 71 | |
| dmitriy@113 | 72 | // Serialize the diagrams to a file |
| dmitriy@113 | 73 | std::ofstream ofs("rips-diagrams"); |
| dmitriy@113 | 74 | boost::archive::binary_oarchive oa(ofs); |
| dmitriy@113 | 75 | oa << dgms; |
| dmitriy@115 | 76 | |
| dmitriy@115 | 77 | // Output cycles |
| dmitriy@179 | 78 | for (Persistence::iterator cur = p.begin(); cur != p.end(); ++cur) |
| dmitriy@115 | 79 | { |
| dmitriy@179 | 80 | const Persistence::Cycle& cycle = cur->cycle; |
| dmitriy@115 | 81 | |
| dmitriy@115 | 82 | if (!cur->sign()) // only negative simplices have non-empty cycles |
| dmitriy@115 | 83 | { |
| dmitriy@115 | 84 | Persistence::OrderIndex birth = cur->pair; // the cycle that cur killed was born when we added birth (another simplex) |
| dmitriy@115 | 85 | |
| dmitriy@179 | 86 | const Smplx& b = m[birth]; |
| dmitriy@179 | 87 | const Smplx& d = m[cur]; |
| dmitriy@115 | 88 | |
| dmitriy@115 | 89 | if (b.dimension() != 1) continue; |
| dmitriy@115 | 90 | std::cout << "Pair: (" << size(b) << ", " << size(d) << ")" << std::endl; |
| dmitriy@179 | 91 | } else if (cur->unpaired()) // positive could be unpaired |
| dmitriy@115 | 92 | { |
| dmitriy@179 | 93 | const Smplx& b = m[cur]; |
| dmitriy@115 | 94 | if (b.dimension() != 1) continue; |
| dmitriy@115 | 95 | |
| dmitriy@115 | 96 | std::cout << "Unpaired birth: " << size(b) << std::endl; |
| dmitriy@179 | 97 | // cycle = cur->chain; |
| dmitriy@115 | 98 | } |
| dmitriy@115 | 99 | |
| dmitriy@115 | 100 | // Iterate over the cycle |
| dmitriy@179 | 101 | for (Persistence::Cycle::const_iterator si = cycle.begin(); si != cycle.end(); ++si) |
| dmitriy@115 | 102 | { |
| dmitriy@179 | 103 | const Smplx& s = m[*si]; |
| dmitriy@115 | 104 | //std::cout << s.dimension() << std::endl; |
| dmitriy@115 | 105 | const Smplx::VertexContainer& vertices = s.vertices(); // std::vector<Vertex> where Vertex = Distances::IndexType |
| dmitriy@115 | 106 | AssertMsg(vertices.size() == s.dimension() + 1, "dimension of a simplex is one less than the number of its vertices"); |
| dmitriy@115 | 107 | std::cout << vertices[0] << " " << vertices[1] << std::endl; |
| dmitriy@115 | 108 | } |
| dmitriy@115 | 109 | } |
| dmitriy@92 | 110 | } |