examples/cohomology/rips-pairwise-cohomology.cpp
author Dmitriy Morozov <dmitriy@mrzv.org>
Thu Jan 07 10:27:18 2010 -0800 (2 years ago)
branchdev
changeset 187 25e468323d77
parent 1743f1034dca432
child 203f31527c1f962
permissions -rw-r--r--
CohomologyPersistence::add returns the dying cocycle
     1 #include <topology/cohomology-persistence.h>
     2 #include <topology/rips.h>
     3 
     4 #include <geometry/l2distance.h>
     5 #include <geometry/distances.h>
     6 
     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>
    13 
    14 #include <sys/resource.h>
    15 #include <malloc.h>
    16 
    17 #include <string>
    18 
    19 #include <boost/tuple/tuple.hpp>
    20 #include <boost/program_options.hpp>
    21 #include <boost/progress.hpp>
    22 
    23 #include "wrappers.h"
    24 
    25 typedef     PairwiseDistances<PointContainer, L2Distance>           PairDistances;
    26 typedef     PairDistances::DistanceType                             DistanceType;
    27 typedef     PairDistances::IndexType                                Vertex;
    28  
    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;
    34 
    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;
    39 
    40 typedef     std::map<Smplx, Index, Smplx::VertexComparison>         Complex;
    41 
    42 #include "output.h"         // for output_*()
    43 
    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);
    45 
    46 int main(int argc, char* argv[])
    47 {
    48 #ifdef LOGGING
    49     rlog::RLogInit(argc, argv);
    50 
    51     stderrLog.subscribeTo( RLOG_CHANNEL("error") );
    52 #endif
    53 
    54     Dimension               skeleton;
    55     DistanceType            max_distance;
    56     ZpField::Element        prime;
    57     std::string             infilename, boundary_name, cocycle_prefix, vertices_name, diagram_name;
    58 
    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;
    67 
    68     Timer total_timer; total_timer.start();
    69     PointContainer          points;
    70     read_points(infilename, points);
    71 
    72     PairDistances           distances(points);
    73     Generator               rips(distances);
    74     Generator::Evaluator    size(distances);
    75     Generator::Comparison   cmp(distances);
    76     SimplexVector           v;
    77     
    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());
    81 
    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));
    86 
    87     BinarySearchMap<Smplx, SimplexVector::iterator, Smplx::VertexComparison> map_of_v(v.begin(), v.end());
    88 
    89     rips_timer.stop();
    90     std::cout << "Simplex vector generated, size: " << v.size() << std::endl;
    91 
    92     output_boundary_matrix(bdry_out, v, Smplx::VertexComparison());
    93     output_vertex_indices(vertices_out, v);
    94 
    95     Timer persistence_timer; persistence_timer.start();
    96     ZpField                 zp(prime);
    97     Persistence             p(zp);
    98     boost::progress_display show_progress(v.size());
    99     
   100     #ifdef COUNTERS
   101     Counter::CounterType    max_element_count = 0;
   102     unsigned                max_memory = 0;
   103     long                    max_rss = 0;
   104     long                    max_ixrss = 0;
   105     long                    max_idrss = 0;
   106     long                    max_isrss = 0;
   107 
   108     int                     max_uordblks = 0;
   109     int                     max_fordblks = 0;
   110     #endif
   111 
   112     for (unsigned j = 0; j < index_in_v.size(); ++j)
   113     {
   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());
   118         
   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]);
   122         
   123         // c[*cur] = idx;
   124         if (store)
   125             map_of_v[*cur]->data() = idx;
   126 
   127         if (d && (size(*cur) - d->get<1>()) > 0)
   128         {
   129             AssertMsg(d->get<0>() == cur->dimension() - 1, "Dimensions must match");
   130             diagram_out << (cur->dimension() - 1) << " " << d->get<1>() << " " << size(*cur) << std::endl;
   131         }
   132         ++show_progress;
   133         
   134         #ifdef COUNTERS
   135         max_element_count = std::max(max_element_count, cCohomologyElementCount->count);
   136         // max_memory = std::max(max_memory, report_memory());
   137 
   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);
   144 
   145         // struct mallinfo info = mallinfo();
   146         // max_uordblks = std::max(max_uordblks, info.uordblks);
   147         // max_fordblks = std::max(max_fordblks, info.fordblks);
   148         #endif
   149     }
   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();
   154 
   155 
   156     // p.show_cocycles();
   157     // Output alive cocycles of dimension 1
   158     if (!cocycle_prefix.empty())
   159     {
   160         unsigned i = 0;
   161         for (Persistence::Cocycles::const_iterator cur = p.begin(); cur != p.end(); ++cur)
   162         {
   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;
   166             ++i;
   167         }
   168     }
   169     total_timer.stop();
   170     rips_timer.check("Rips timer");
   171     persistence_timer.check("Persistence timer");
   172     total_timer.check("Total timer");
   173 
   174     #ifdef COUNTERS
   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;
   179     #endif
   180 }
   181 
   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)
   183 {
   184     namespace po = boost::program_options;
   185 
   186     po::options_description     hidden("Hidden options");
   187     hidden.add_options()
   188         ("input-file",          po::value<std::string>(&infilename),        "Point set whose Rips zigzag we want to compute");
   189     
   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");
   200 #if LOGGING
   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)");
   204 #endif
   205 
   206     po::positional_options_description pos;
   207     pos.add("input-file", 1);
   208     
   209     po::options_description all; all.add(visible).add(hidden);
   210 
   211     po::variables_map vm;
   212     po::store(po::command_line_parser(argc, argv).
   213                   options(all).positional(pos).run(), vm);
   214     po::notify(vm);
   215 
   216 #if LOGGING
   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()) );
   219 #endif
   220 
   221     if (vm.count("help") || !vm.count("input-file"))
   222     { 
   223         std::cout << "Usage: " << argv[0] << " [options] input-file" << std::endl;
   224         std::cout << visible << std::endl; 
   225         std::abort();
   226     }
   227 }