1 #include <topology/rips.h>
2 #include <topology/filtration.h>
3 #include <topology/static-persistence.h>
4 #include <topology/dynamic-persistence.h>
5 #include <topology/persistence-diagram.h>
7 #include <geometry/l2distance.h>
8 #include <geometry/distances.h>
10 #include <utilities/containers.h> // for BackInsertFunctor
11 #include <utilities/timer.h>
15 #include <boost/program_options.hpp>
18 typedef PairwiseDistances<PointContainer, L2Distance> PairDistances;
19 typedef PairDistances::DistanceType DistanceType;
20 typedef PairDistances::IndexType Vertex;
22 typedef Rips<PairDistances> Generator;
23 typedef Generator::Simplex Smplx;
24 typedef Filtration<Smplx> Fltr;
25 // typedef StaticPersistence<> Persistence;
26 typedef DynamicPersistenceChains<> Persistence;
27 typedef PersistenceDiagram<> PDgm;
29 void program_options(int argc, char* argv[], std::string& infilename, Dimension& skeleton, DistanceType& max_distance, std::string& diagram_name);
31 int main(int argc, char* argv[])
34 DistanceType max_distance;
35 std::string infilename, diagram_name;
37 program_options(argc, argv, infilename, skeleton, max_distance, diagram_name);
38 std::ofstream diagram_out(diagram_name.c_str());
39 std::cout << "Diagram: " << diagram_name << std::endl;
41 PointContainer points;
42 read_points(infilename, points);
44 PairDistances distances(points);
45 Generator rips(distances);
46 Generator::Evaluator size(distances);
49 // Generate 2-skeleton of the Rips complex for epsilon = 50
50 rips.generate(skeleton, max_distance, make_push_back_functor(f));
51 std::cout << "# Generated complex of size: " << f.size() << std::endl;
53 // Generate filtration with respect to distance and compute its persistence
54 f.sort(Generator::Comparison(distances));
56 Timer persistence_timer; persistence_timer.start();
59 persistence_timer.stop();
63 Persistence::SimplexMap<Fltr> m = p.make_simplex_map(f);
64 for (Persistence::iterator cur = p.begin(); cur != p.end(); ++cur)
66 const Persistence::Cycle& cycle = cur->cycle;
68 if (!cur->sign()) // only negative simplices have non-empty cycles
70 Persistence::OrderIndex birth = cur->pair; // the cycle that cur killed was born when we added birth (another simplex)
72 const Smplx& b = m[birth];
73 const Smplx& d = m[cur];
75 // if (b.dimension() != 1) continue;
76 // std::cout << "Pair: (" << size(b) << ", " << size(d) << ")" << std::endl; 77 if (b.dimension() >= skeleton) continue;
78 diagram_out << b.dimension() << " " << size(b) << " " << size(d) << std::endl;
79 } else if (cur->unpaired()) // positive could be unpaired
81 const Smplx& b = m[cur];
82 // if (b.dimension() != 1) continue;
84 // std::cout << "Unpaired birth: " << size(b) << std::endl;
85 // cycle = cur->chain; // TODO
86 if (b.dimension() >= skeleton) continue;
87 diagram_out << b.dimension() << " " << size(b) << " inf" << std::endl;
90 // Iterate over the cycle
91 // for (Persistence::Cycle::const_iterator si = cycle.begin();
92 // si != cycle.end(); ++si)
94 // const Smplx& s = m[*si];
95 // //std::cout << s.dimension() << std::endl;
96 // const Smplx::VertexContainer& vertices = s.vertices(); // std::vector<Vertex> where Vertex = Distances::IndexType
97 // AssertMsg(vertices.size() == s.dimension() + 1, "dimension of a simplex is one less than the number of its vertices");
98 // std::cout << vertices[0] << " " << vertices[1] << std::endl;
103 persistence_timer.check("# Persistence timer"); 106 void program_options(int argc, char* argv[], std::string& infilename, Dimension& skeleton, DistanceType& max_distance, std::string& diagram_name)
108 namespace po = boost::program_options;
110 po::options_description hidden("Hidden options"); 112 ("input-file", po::value<std::string>(&infilename), "Point set whose Rips zigzag we want to compute"); 114 po::options_description visible("Allowed options", 100); 115 visible.add_options()
116 ("help,h", "produce help message") 117 ("skeleton-dimsnion,s", po::value<Dimension>(&skeleton)->default_value(2), "Dimension of the Rips complex we want to compute") 118 ("max-distance,m", po::value<DistanceType>(&max_distance)->default_value(Infinity), "Maximum value for the Rips complex construction") 119 ("diagram,d", po::value<std::string>(&diagram_name), "Filename where to output the persistence diagram"); 121 std::vector<std::string> log_channels;
122 visible.add_options()
123 ("log,l", po::value< std::vector<std::string> >(&log_channels), "log channels to turn on (info, debug, etc)"); 126 po::positional_options_description pos;
127 pos.add("input-file", 1); 129 po::options_description all; all.add(visible).add(hidden);
131 po::variables_map vm;
132 po::store(po::command_line_parser(argc, argv).
133 options(all).positional(pos).run(), vm);
137 for (std::vector<std::string>::const_iterator cur = log_channels.begin(); cur != log_channels.end(); ++cur)
138 stderrLog.subscribeTo( RLOG_CHANNEL(cur->c_str()) );
141 if (vm.count("help") || !vm.count("input-file")) 143 std::cout << "Usage: " << argv[0] << " [options] input-file" << std::endl;
144 std::cout << visible << std::endl;