1 #include <topology/cohomology-persistence.h>
2 #include <topology/rips.h>
4 #include <geometry/l2distance.h>
5 #include <geometry/distances.h>
7 #include <utilities/containers.h> // for BackInsertFunctor
8 #include <utilities/property-maps.h>
9 #include <utilities/timer.h>
10 #include <utilities/log.h>
11 #include <utilities/counter.h>
12 #include <utilities/memory.h>
14 #include <sys/resource.h>
19 #include <boost/tuple/tuple.hpp>
20 #include <boost/program_options.hpp>
21 #include <boost/progress.hpp>
25 typedef PairwiseDistances<PointContainer, L2Distance> PairDistances;
26 typedef PairDistances::DistanceType DistanceType;
27 typedef PairDistances::IndexType Vertex;
29 typedef boost::tuple<Dimension, DistanceType> BirthInfo;
30 typedef CohomologyPersistence<BirthInfo, Wrapper<unsigned> > Persistence;
31 typedef Persistence::SimplexIndex Index;
32 typedef Persistence::Death Death;
33 typedef Persistence::CocyclePtr CocyclePtr;
35 typedef Rips<PairDistances, Simplex<Vertex, Index> > Generator;
36 typedef Generator::Simplex Smplx;
37 typedef std::vector<Smplx> SimplexVector;
38 typedef SimplexVector::const_iterator SV_const_iterator;
40 typedef std::map<Smplx, Index, Smplx::VertexComparison> Complex;
42 #include "output.h" // for output_*()
44 void program_options(int argc, char* argv[], std::string& infilename, Dimension& skeleton, DistanceType& max_distance, ZpField::Element& prime, std::string& boundary_name, std::string& cocycle_prefix, std::string& vertices_name, std::string& diagram_name);
46 int main(int argc, char* argv[])
49 rlog::RLogInit(argc, argv);
51 stderrLog.subscribeTo( RLOG_CHANNEL("error") ); 55 DistanceType max_distance;
56 ZpField::Element prime;
57 std::string infilename, boundary_name, cocycle_prefix, vertices_name, diagram_name;
59 program_options(argc, argv, infilename, skeleton, max_distance, prime, boundary_name, cocycle_prefix, vertices_name, diagram_name);
60 std::ofstream bdry_out(boundary_name.c_str());
61 std::ofstream vertices_out(vertices_name.c_str());
62 std::ofstream diagram_out(diagram_name.c_str());
63 std::cout << "Boundary matrix: " << boundary_name << std::endl;
64 std::cout << "Cocycles: " << cocycle_prefix << "*.ccl" << std::endl;
65 std::cout << "Vertices: " << vertices_name << std::endl;
66 std::cout << "Diagram: " << diagram_name << std::endl;
68 Timer total_timer; total_timer.start();
69 PointContainer points;
70 read_points(infilename, points);
72 PairDistances distances(points);
73 Generator rips(distances);
74 Generator::Evaluator size(distances);
75 Generator::Comparison cmp(distances);
78 Timer rips_timer; rips_timer.start();
79 rips.generate(skeleton, max_distance, make_push_back_functor(v));
80 std::sort(v.begin(), v.end(), Smplx::VertexComparison());
82 std::vector<unsigned> index_in_v(v.size());
83 for (unsigned idx = 0; idx < v.size(); ++idx)
84 index_in_v[idx] = idx;
85 std::sort(index_in_v.begin(), index_in_v.end(), IndirectIndexComparison<SimplexVector, Generator::Comparison>(v, cmp));
87 BinarySearchMap<Smplx, SimplexVector::iterator, Smplx::VertexComparison> map_of_v(v.begin(), v.end());
90 std::cout << "Simplex vector generated, size: " << v.size() << std::endl;
92 output_boundary_matrix(bdry_out, v, Smplx::VertexComparison());
93 output_vertex_indices(vertices_out, v);
95 Timer persistence_timer; persistence_timer.start();
98 boost::progress_display show_progress(v.size());
101 Counter::CounterType max_element_count = 0;
102 unsigned max_memory = 0;
108 int max_uordblks = 0;
109 int max_fordblks = 0;
112 for (unsigned j = 0; j < index_in_v.size(); ++j)
114 SimplexVector::const_iterator cur = v.begin() + index_in_v[j];
115 std::vector<Index> boundary;
116 for (Smplx::BoundaryIterator bcur = cur->boundary_begin(); bcur != cur->boundary_end(); ++bcur)
117 boundary.push_back(map_of_v[*bcur]->data());
119 Index idx; Death d; CocyclePtr ccl;
120 bool store = cur->dimension() < skeleton;
121 boost::tie(idx, d, ccl) = p.add(boundary.begin(), boundary.end(), boost::make_tuple(cur->dimension(), size(*cur)), store, index_in_v[j]);
125 map_of_v[*cur]->data() = idx;
127 if (d && (size(*cur) - d->get<1>()) > 0)
129 AssertMsg(d->get<0>() == cur->dimension() - 1, "Dimensions must match");
130 diagram_out << (cur->dimension() - 1) << " " << d->get<1>() << " " << size(*cur) << std::endl;
135 max_element_count = std::max(max_element_count, cCohomologyElementCount->count);
136 // max_memory = std::max(max_memory, report_memory());
138 // struct rusage usage;
139 // getrusage(RUSAGE_SELF, &usage);
140 // max_rss = std::max(max_rss, usage.ru_maxrss);
141 // max_ixrss = std::max(max_ixrss, usage.ru_ixrss);
142 // max_idrss = std::max(max_idrss, usage.ru_idrss);
143 // max_isrss = std::max(max_isrss, usage.ru_isrss);
145 // struct mallinfo info = mallinfo();
146 // max_uordblks = std::max(max_uordblks, info.uordblks);
147 // max_fordblks = std::max(max_fordblks, info.fordblks);
150 // output infinte persistence pairs
151 for (Persistence::CocycleIndex cur = p.begin(); cur != p.end(); ++cur)
152 diagram_out << cur->birth.get<0>() << " " << cur->birth.get<1>() << " inf" << std::endl;
153 persistence_timer.stop();
156 // p.show_cocycles();
157 // Output alive cocycles of dimension 1
158 if (!cocycle_prefix.empty())
161 for (Persistence::Cocycles::const_iterator cur = p.begin(); cur != p.end(); ++cur)
163 if (cur->birth.get<0>() != 1) continue;
164 output_cocycle(cocycle_prefix, i, v, cur->birth, cur->zcolumn, prime);
165 // std::cout << "Cocycle of dimension: " << cur->birth.get<0>() << " born at " << cur->birth.get<1>() << std::endl;
170 rips_timer.check("Rips timer"); 171 persistence_timer.check("Persistence timer"); 172 total_timer.check("Total timer"); 175 std::cout << "Max element count: " << max_element_count << std::endl;
176 // std::cout << "Max memory use: " << max_memory << " kB" << std::endl;
177 // std::cout << "Max RSS: " << max_rss << " " << max_ixrss << " " << max_idrss << " " << max_isrss << std::endl;
178 // std::cout << "Max Blks: " << max_uordblks << " " << max_fordblks << std::endl;
182 void program_options(int argc, char* argv[], std::string& infilename, Dimension& skeleton, DistanceType& max_distance, ZpField::Element& prime, std::string& boundary_name, std::string& cocycle_prefix, std::string& vertices_name, std::string& diagram_name)
184 namespace po = boost::program_options;
186 po::options_description hidden("Hidden options"); 188 ("input-file", po::value<std::string>(&infilename), "Point set whose Rips zigzag we want to compute"); 190 po::options_description visible("Allowed options", 100); 191 visible.add_options()
192 ("help,h", "produce help message") 193 ("skeleton-dimsnion,s", po::value<Dimension>(&skeleton)->default_value(2), "Dimension of the Rips complex we want to compute") 194 ("prime,p", po::value<ZpField::Element>(&prime)->default_value(11), "Prime p for the field F_p") 195 ("max-distance,m", po::value<DistanceType>(&max_distance)->default_value(Infinity), "Maximum value for the Rips complex construction") 196 ("boundary,b", po::value<std::string>(&boundary_name), "Filename where to output the boundary matrix") 197 ("cocycle,c", po::value<std::string>(&cocycle_prefix), "Prefix of the filename where to output the 1-dimensional cocycles") 198 ("vertices,v", po::value<std::string>(&vertices_name), "Filename where to output the simplex-vertex mapping") 199 ("diagram,d", po::value<std::string>(&diagram_name), "Filename where to output the persistence diagram"); 201 std::vector<std::string> log_channels;
202 visible.add_options()
203 ("log,l", po::value< std::vector<std::string> >(&log_channels), "log channels to turn on (info, debug, etc)"); 206 po::positional_options_description pos;
207 pos.add("input-file", 1); 209 po::options_description all; all.add(visible).add(hidden);
211 po::variables_map vm;
212 po::store(po::command_line_parser(argc, argv).
213 options(all).positional(pos).run(), vm);
217 for (std::vector<std::string>::const_iterator cur = log_channels.begin(); cur != log_channels.end(); ++cur)
218 stderrLog.subscribeTo( RLOG_CHANNEL(cur->c_str()) );
221 if (vm.count("help") || !vm.count("input-file")) 223 std::cout << "Usage: " << argv[0] << " [options] input-file" << std::endl;
224 std::cout << visible << std::endl;