examples/rips/rips-pairwise.cpp
author Dmitriy Morozov <dmitriy@mrzv.org>
Sat Nov 28 16:45:42 2009 -0800 (2 years ago)
branchdev
changeset 174 3f1034dca432
parent 142ae2b1702c936
child 182451748b3c888
permissions -rw-r--r--
Instrumented code for counting:
* added counters to addition in cohomology and ChainWrapper
* rips-pairwise-cohomology counts the maximum elements stored in the cycles
* added alphashapes3d-cohomology
* moved progress_display from DynamicPersistence to StaticPersistence
     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>
     6 
     7 #include <geometry/l2distance.h>
     8 #include <geometry/distances.h>
     9 
    10 #include <utilities/containers.h>           // for BackInsertFunctor
    11 #include <utilities/timer.h>
    12 
    13 #include <vector>
    14 
    15 #include <boost/program_options.hpp>
    16 
    17 
    18 typedef         PairwiseDistances<PointContainer, L2Distance>           PairDistances;
    19 typedef         PairDistances::DistanceType                             DistanceType;
    20 typedef         PairDistances::IndexType                                Vertex;
    21 
    22 typedef         Rips<PairDistances>                                     Generator;
    23 typedef         Generator::Simplex                                      Smplx;
    24 typedef         std::vector<Smplx>                                      SimplexVector;
    25 typedef         Filtration<SimplexVector, unsigned>                     Fltr;
    26 typedef         StaticPersistence<>                                     Persistence;
    27 // typedef         DynamicPersistenceChains<>                              Persistence;
    28 typedef         PersistenceDiagram<>                                    PDgm;
    29 
    30 void            program_options(int argc, char* argv[], std::string& infilename, Dimension& skeleton, DistanceType& max_distance, std::string& diagram_name);
    31 
    32 int main(int argc, char* argv[])
    33 {
    34     Dimension               skeleton;
    35     DistanceType            max_distance;
    36     std::string             infilename, diagram_name;
    37 
    38     program_options(argc, argv, infilename, skeleton, max_distance, diagram_name);
    39     std::ofstream           diagram_out(diagram_name.c_str());
    40     std::cout << "Diagram:         " << diagram_name << std::endl;
    41 
    42     PointContainer          points;
    43     read_points(infilename, points);
    44 
    45     PairDistances           distances(points);
    46     Generator               rips(distances);
    47     Generator::Evaluator    size(distances);
    48     SimplexVector           complex;
    49     
    50     // Generate 2-skeleton of the Rips complex for epsilon = 50
    51     rips.generate(skeleton, max_distance, make_push_back_functor(complex));
    52     std::sort(complex.begin(), complex.end(), Smplx::VertexComparison());       // unnecessary
    53     std::cout << "Generated complex of size: " << complex.size() << std::endl;
    54 
    55     // Generate filtration with respect to distance and compute its persistence
    56     Fltr f(complex.begin(), complex.end(), Generator::Comparison(distances));
    57 
    58     Timer persistence_timer; persistence_timer.start();
    59     Persistence p(f);
    60     p.pair_simplices();
    61     persistence_timer.stop();
    62 
    63     // Output cycles
    64     for (Persistence::OrderIndex cur = p.begin(); cur != p.end(); ++cur)
    65     {
    66         Persistence::Cycle& cycle = cur->cycle;
    67 
    68         if (!cur->sign())        // only negative simplices have non-empty cycles
    69         {
    70             Persistence::OrderIndex birth = cur->pair;      // the cycle that cur killed was born when we added birth (another simplex)
    71 
    72             const Smplx& b = f.simplex(f.begin() + (birth - p.begin()));        // eventually this will be encapsulated behind an interface
    73             const Smplx& d = f.simplex(f.begin() + (cur   - p.begin()));
    74             
    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->pair == cur)    // positive could be unpaired
    80         {
    81             const Smplx& b = f.simplex(f.begin() + (cur - p.begin()));
    82             // if (b.dimension() != 1) continue;
    83             
    84             // std::cout << "Unpaired birth: " << size(b) << std::endl;
    85             // cycle = cur->chain;
    86             if (b.dimension() >= skeleton) continue;
    87             diagram_out << b.dimension() << " " << size(b) << " inf" << std::endl;
    88         }
    89 
    90         // Iterate over the cycle
    91         // for (Persistence::Cycle::const_iterator si =  cycle.begin();
    92         //                                                          si != cycle.end();     ++si)
    93         // {
    94         //     const Smplx& s = f.simplex(f.begin() + (*si - p.begin()));
    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;
    99         // }
   100     }
   101     
   102     persistence_timer.check("# Persistence timer");
   103 }
   104 
   105 void        program_options(int argc, char* argv[], std::string& infilename, Dimension& skeleton, DistanceType& max_distance, std::string& diagram_name)
   106 {
   107     namespace po = boost::program_options;
   108 
   109     po::options_description     hidden("Hidden options");
   110     hidden.add_options()
   111         ("input-file",          po::value<std::string>(&infilename),        "Point set whose Rips zigzag we want to compute");
   112     
   113     po::options_description visible("Allowed options", 100);
   114     visible.add_options()
   115         ("help,h",                                                                                  "produce help message")
   116         ("skeleton-dimsnion,s", po::value<Dimension>(&skeleton)->default_value(2),                  "Dimension of the Rips complex we want to compute")
   117         ("max-distance,m",      po::value<DistanceType>(&max_distance)->default_value(Infinity),    "Maximum value for the Rips complex construction")
   118         ("diagram,d",           po::value<std::string>(&diagram_name),                              "Filename where to output the persistence diagram");
   119 #if LOGGING
   120     std::vector<std::string>    log_channels;
   121     visible.add_options()
   122         ("log,l",               po::value< std::vector<std::string> >(&log_channels),           "log channels to turn on (info, debug, etc)");
   123 #endif
   124 
   125     po::positional_options_description pos;
   126     pos.add("input-file", 1);
   127     
   128     po::options_description all; all.add(visible).add(hidden);
   129 
   130     po::variables_map vm;
   131     po::store(po::command_line_parser(argc, argv).
   132                   options(all).positional(pos).run(), vm);
   133     po::notify(vm);
   134 
   135 #if LOGGING
   136     for (std::vector<std::string>::const_iterator cur = log_channels.begin(); cur != log_channels.end(); ++cur)
   137         stderrLog.subscribeTo( RLOG_CHANNEL(cur->c_str()) );
   138 #endif
   139 
   140     if (vm.count("help") || !vm.count("input-file"))
   141     { 
   142         std::cout << "Usage: " << argv[0] << " [options] input-file" << std::endl;
   143         std::cout << visible << std::endl; 
   144         std::abort();
   145     }
   146 }