examples/cohomology/rips-pairwise-cohomology.cpp
author Dmitriy Morozov <dmitriy@mrzv.org>
Mon Jul 25 23:21:29 2011 -0700 (10 months ago)
branchdev
changeset 244 66235db8d8b7
parent 18725e468323d77
permissions -rw-r--r--
Added cohomology/candidates counter to i/t/cohomology-persistence.hpp
dmitriy@116
     1
#include <topology/cohomology-persistence.h>
dmitriy@116
     2
#include <topology/rips.h>
dmitriy@122
     3
dmitriy@122
     4
#include <geometry/l2distance.h>
dmitriy@136
     5
#include <geometry/distances.h>
dmitriy@116
     6
dmitriy@116
     7
#include <utilities/containers.h>           // for BackInsertFunctor
cmad@157
     8
#include <utilities/property-maps.h>
dmitriy@116
     9
#include <utilities/timer.h>
dmitriy@137
    10
#include <utilities/log.h>
dmitriy@174
    11
#include <utilities/counter.h>
dmitriy@174
    12
#include <utilities/memory.h>
dmitriy@116
    13
dmitriy@116
    14
#include <string>
dmitriy@116
    15
dmitriy@116
    16
#include <boost/tuple/tuple.hpp>
dmitriy@116
    17
#include <boost/program_options.hpp>
dmitriy@170
    18
#include <boost/progress.hpp>
dmitriy@116
    19
cmad@157
    20
#include "wrappers.h"
cmad@157
    21
dmitriy@116
    22
typedef     PairwiseDistances<PointContainer, L2Distance>           PairDistances;
dmitriy@116
    23
typedef     PairDistances::DistanceType                             DistanceType;
dmitriy@116
    24
typedef     PairDistances::IndexType                                Vertex;
dmitriy@137
    25
 
cmad@157
    26
typedef     boost::tuple<Dimension, DistanceType>                   BirthInfo;
cmad@157
    27
typedef     CohomologyPersistence<BirthInfo, Wrapper<unsigned> >    Persistence;
cmad@157
    28
typedef     Persistence::SimplexIndex                               Index;
cmad@157
    29
typedef     Persistence::Death                                      Death;
dmitriy@187
    30
typedef     Persistence::CocyclePtr                                 CocyclePtr;
cmad@157
    31
cmad@157
    32
typedef     Rips<PairDistances, Simplex<Vertex, Index> >            Generator;
dmitriy@137
    33
typedef     Generator::Simplex                                      Smplx;
dmitriy@137
    34
typedef     std::vector<Smplx>                                      SimplexVector;
dmitriy@137
    35
typedef     SimplexVector::const_iterator                           SV_const_iterator;
dmitriy@137
    36
dmitriy@137
    37
typedef     std::map<Smplx, Index, Smplx::VertexComparison>         Complex;
dmitriy@116
    38
dmitriy@138
    39
#include "output.h"         // for output_*()
dmitriy@138
    40
dmitriy@138
    41
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);
dmitriy@116
    42
dmitriy@116
    43
int main(int argc, char* argv[])
dmitriy@116
    44
{
dmitriy@137
    45
#ifdef LOGGING
dmitriy@137
    46
    rlog::RLogInit(argc, argv);
dmitriy@137
    47
dmitriy@137
    48
    stderrLog.subscribeTo( RLOG_CHANNEL("error") );
dmitriy@137
    49
#endif
dmitriy@137
    50
dmitriy@135
    51
    Dimension               skeleton;
dmitriy@116
    52
    DistanceType            max_distance;
dmitriy@137
    53
    ZpField::Element        prime;
dmitriy@138
    54
    std::string             infilename, boundary_name, cocycle_prefix, vertices_name, diagram_name;
dmitriy@116
    55
dmitriy@138
    56
    program_options(argc, argv, infilename, skeleton, max_distance, prime, boundary_name, cocycle_prefix, vertices_name, diagram_name);
dmitriy@138
    57
    std::ofstream           bdry_out(boundary_name.c_str());
dmitriy@138
    58
    std::ofstream           vertices_out(vertices_name.c_str());
dmitriy@138
    59
    std::ofstream           diagram_out(diagram_name.c_str());
dmitriy@138
    60
    std::cout << "Boundary matrix: " << boundary_name << std::endl;
dmitriy@138
    61
    std::cout << "Cocycles:        " << cocycle_prefix << "*.ccl" << std::endl;
dmitriy@138
    62
    std::cout << "Vertices:        " << vertices_name << std::endl;
dmitriy@138
    63
    std::cout << "Diagram:         " << diagram_name << std::endl;
dmitriy@116
    64
dmitriy@137
    65
    Timer total_timer; total_timer.start();
dmitriy@116
    66
    PointContainer          points;
dmitriy@135
    67
    read_points(infilename, points);
dmitriy@116
    68
dmitriy@116
    69
    PairDistances           distances(points);
dmitriy@116
    70
    Generator               rips(distances);
dmitriy@116
    71
    Generator::Evaluator    size(distances);
dmitriy@138
    72
    Generator::Comparison   cmp(distances);
dmitriy@116
    73
    SimplexVector           v;
dmitriy@116
    74
    
dmitriy@137
    75
    Timer rips_timer; rips_timer.start();
dmitriy@116
    76
    rips.generate(skeleton, max_distance, make_push_back_functor(v));
cmad@157
    77
    std::sort(v.begin(), v.end(), Smplx::VertexComparison());
cmad@157
    78
cmad@157
    79
    std::vector<unsigned> index_in_v(v.size());
cmad@157
    80
    for (unsigned idx = 0; idx < v.size(); ++idx)
cmad@157
    81
        index_in_v[idx] = idx;
cmad@157
    82
    std::sort(index_in_v.begin(), index_in_v.end(), IndirectIndexComparison<SimplexVector, Generator::Comparison>(v, cmp));
cmad@157
    83
cmad@157
    84
    BinarySearchMap<Smplx, SimplexVector::iterator, Smplx::VertexComparison> map_of_v(v.begin(), v.end());
cmad@157
    85
dmitriy@137
    86
    rips_timer.stop();
dmitriy@116
    87
    std::cout << "Simplex vector generated, size: " << v.size() << std::endl;
dmitriy@138
    88
cmad@157
    89
    output_boundary_matrix(bdry_out, v, Smplx::VertexComparison());
dmitriy@138
    90
    output_vertex_indices(vertices_out, v);
dmitriy@116
    91
dmitriy@116
    92
    Timer persistence_timer; persistence_timer.start();
dmitriy@137
    93
    ZpField                 zp(prime);
dmitriy@137
    94
    Persistence             p(zp);
dmitriy@170
    95
    boost::progress_display show_progress(v.size());
dmitriy@174
    96
    
dmitriy@174
    97
    #ifdef COUNTERS
dmitriy@174
    98
    Counter::CounterType    max_element_count = 0;
dmitriy@174
    99
    unsigned                max_memory = 0;
dmitriy@174
   100
    long                    max_rss = 0;
dmitriy@174
   101
    long                    max_ixrss = 0;
dmitriy@174
   102
    long                    max_idrss = 0;
dmitriy@174
   103
    long                    max_isrss = 0;
dmitriy@174
   104
dmitriy@174
   105
    int                     max_uordblks = 0;
dmitriy@174
   106
    int                     max_fordblks = 0;
dmitriy@174
   107
    #endif
dmitriy@174
   108
cmad@157
   109
    for (unsigned j = 0; j < index_in_v.size(); ++j)
dmitriy@116
   110
    {
cmad@157
   111
        SimplexVector::const_iterator cur = v.begin() + index_in_v[j];
dmitriy@116
   112
        std::vector<Index>      boundary;
dmitriy@137
   113
        for (Smplx::BoundaryIterator bcur  = cur->boundary_begin(); bcur != cur->boundary_end(); ++bcur)
cmad@157
   114
            boundary.push_back(map_of_v[*bcur]->data());
dmitriy@116
   115
        
dmitriy@187
   116
        Index idx; Death d; CocyclePtr ccl;
dmitriy@137
   117
        bool store = cur->dimension() < skeleton;
dmitriy@187
   118
        boost::tie(idx, d, ccl)     = p.add(boundary.begin(), boundary.end(), boost::make_tuple(cur->dimension(), size(*cur)), store, index_in_v[j]);
dmitriy@137
   119
        
dmitriy@137
   120
        // c[*cur] = idx;
dmitriy@137
   121
        if (store)
cmad@157
   122
            map_of_v[*cur]->data() = idx;
dmitriy@137
   123
dmitriy@137
   124
        if (d && (size(*cur) - d->get<1>()) > 0)
dmitriy@137
   125
        {
dmitriy@137
   126
            AssertMsg(d->get<0>() == cur->dimension() - 1, "Dimensions must match");
dmitriy@138
   127
            diagram_out << (cur->dimension() - 1) << " " << d->get<1>() << " " << size(*cur) << std::endl;
dmitriy@137
   128
        }
dmitriy@170
   129
        ++show_progress;
dmitriy@174
   130
        
dmitriy@174
   131
        #ifdef COUNTERS
dmitriy@174
   132
        max_element_count = std::max(max_element_count, cCohomologyElementCount->count);
dmitriy@174
   133
        #endif
dmitriy@116
   134
    }
dmitriy@138
   135
    // output infinte persistence pairs 
dmitriy@137
   136
    for (Persistence::CocycleIndex cur = p.begin(); cur != p.end(); ++cur)
dmitriy@138
   137
        diagram_out << cur->birth.get<0>() << " " << cur->birth.get<1>() << " inf" << std::endl;
dmitriy@116
   138
    persistence_timer.stop();
dmitriy@137
   139
dmitriy@137
   140
dmitriy@137
   141
    // p.show_cocycles();
dmitriy@138
   142
    // Output alive cocycles of dimension 1
dmitriy@174
   143
    if (!cocycle_prefix.empty())
dmitriy@137
   144
    {
dmitriy@174
   145
        unsigned i = 0;
dmitriy@174
   146
        for (Persistence::Cocycles::const_iterator cur = p.begin(); cur != p.end(); ++cur)
dmitriy@174
   147
        {
dmitriy@174
   148
            if (cur->birth.get<0>() != 1) continue;
dmitriy@187
   149
            output_cocycle(cocycle_prefix, i, v, cur->birth, cur->zcolumn, prime);
dmitriy@174
   150
            // std::cout << "Cocycle of dimension: " << cur->birth.get<0>() << " born at " << cur->birth.get<1>() << std::endl;
dmitriy@174
   151
            ++i;
dmitriy@174
   152
        }
dmitriy@137
   153
    }
dmitriy@137
   154
    total_timer.stop();
dmitriy@137
   155
    rips_timer.check("Rips timer");
dmitriy@116
   156
    persistence_timer.check("Persistence timer");
dmitriy@137
   157
    total_timer.check("Total timer");
dmitriy@174
   158
dmitriy@174
   159
    #ifdef COUNTERS
dmitriy@174
   160
    std::cout << "Max element count: " << max_element_count << std::endl;
dmitriy@174
   161
    #endif
dmitriy@116
   162
}
dmitriy@116
   163
dmitriy@138
   164
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)
dmitriy@116
   165
{
dmitriy@116
   166
    namespace po = boost::program_options;
dmitriy@116
   167
dmitriy@116
   168
    po::options_description     hidden("Hidden options");
dmitriy@116
   169
    hidden.add_options()
dmitriy@116
   170
        ("input-file",          po::value<std::string>(&infilename),        "Point set whose Rips zigzag we want to compute");
dmitriy@116
   171
    
dmitriy@116
   172
    po::options_description visible("Allowed options", 100);
dmitriy@116
   173
    visible.add_options()
dmitriy@116
   174
        ("help,h",                                                                                  "produce help message")
dmitriy@116
   175
        ("skeleton-dimsnion,s", po::value<Dimension>(&skeleton)->default_value(2),                  "Dimension of the Rips complex we want to compute")
dmitriy@138
   176
        ("prime,p",             po::value<ZpField::Element>(&prime)->default_value(11),             "Prime p for the field F_p")
dmitriy@138
   177
        ("max-distance,m",      po::value<DistanceType>(&max_distance)->default_value(Infinity),    "Maximum value for the Rips complex construction")
dmitriy@138
   178
        ("boundary,b",          po::value<std::string>(&boundary_name),                             "Filename where to output the boundary matrix")
dmitriy@138
   179
        ("cocycle,c",           po::value<std::string>(&cocycle_prefix),                            "Prefix of the filename where to output the 1-dimensional cocycles")
dmitriy@138
   180
        ("vertices,v",          po::value<std::string>(&vertices_name),                             "Filename where to output the simplex-vertex mapping")
dmitriy@138
   181
        ("diagram,d",           po::value<std::string>(&diagram_name),                              "Filename where to output the persistence diagram");
dmitriy@137
   182
#if LOGGING
dmitriy@137
   183
    std::vector<std::string>    log_channels;
dmitriy@137
   184
    visible.add_options()
dmitriy@137
   185
        ("log,l",               po::value< std::vector<std::string> >(&log_channels),           "log channels to turn on (info, debug, etc)");
dmitriy@137
   186
#endif
dmitriy@116
   187
dmitriy@116
   188
    po::positional_options_description pos;
dmitriy@116
   189
    pos.add("input-file", 1);
dmitriy@116
   190
    
dmitriy@116
   191
    po::options_description all; all.add(visible).add(hidden);
dmitriy@116
   192
dmitriy@116
   193
    po::variables_map vm;
dmitriy@116
   194
    po::store(po::command_line_parser(argc, argv).
dmitriy@116
   195
                  options(all).positional(pos).run(), vm);
dmitriy@116
   196
    po::notify(vm);
dmitriy@116
   197
dmitriy@137
   198
#if LOGGING
dmitriy@137
   199
    for (std::vector<std::string>::const_iterator cur = log_channels.begin(); cur != log_channels.end(); ++cur)
dmitriy@137
   200
        stderrLog.subscribeTo( RLOG_CHANNEL(cur->c_str()) );
dmitriy@137
   201
#endif
dmitriy@137
   202
dmitriy@116
   203
    if (vm.count("help") || !vm.count("input-file"))
dmitriy@116
   204
    { 
dmitriy@116
   205
        std::cout << "Usage: " << argv[0] << " [options] input-file" << std::endl;
dmitriy@116
   206
        std::cout << visible << std::endl; 
dmitriy@116
   207
        std::abort();
dmitriy@116
   208
    }
dmitriy@116
   209
}