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