include/topology/rips.h
author Dmitriy Morozov <dmitriy@mrzv.org>
Thu, 29 Jan 2009 10:16:56 -0800
branchdev
changeset 112 f209958b5c17
parent 109 75eb7a4628f2
child 113 3e8bebb5d857
permissions -rw-r--r--
Added python bindings for ZigzagPersistence (as well as ImageZigzagPersistence)

#ifndef __RIPS_H__
#define __RIPS_H__

#include <vector>
#include <string>
#include "simplex.h"

/**
 * RipsBase class
 *
 * Base class for the generator of Rips complexes.
 *
 * Distances_ is expected to define types IndexType and DistanceType as well as 
 *               provide operator()(...) which given two IndexTypes should return 
 *               the distance between them. There should be methods begin() and end() 
 *               for iterating over IndexTypes as well as a method size().
 */
template<class Distances_, class Simplex_ = Simplex<typename Distances_::IndexType> >
class RipsBase
{
    public:
        typedef             Distances_                                      Distances; 
        typedef             typename Distances::IndexType                   IndexType;
        typedef             typename Distances::DistanceType                DistanceType;

        typedef             Simplex_                                        Simplex;
        typedef             std::vector<Simplex>                            SimplexVector;

        class               Evaluator;
        class               Comparison;
        struct              ComparePair;

    public:
                            RipsBase(const Distances& distances): 
                                distances_(distances)                       {}

        const Distances&    distances() const                               { return distances_; }
        DistanceType        max_distance() const;
        
        DistanceType        distance(const Simplex& s1, const Simplex& s2) const;

    private:
        const Distances&    distances_;
};
        
template<class Distances_, class Simplex_ = Simplex<typename Distances_::IndexType> >
class RipsGenerator: public RipsBase<Distances_, Simplex_>
{
    public:
        typedef             RipsBase<Distances_, Simplex_>                  Parent;
        typedef             typename Parent::Distances                      Distances;
        typedef             typename Parent::Simplex                        Simplex;
        typedef             typename Parent::SimplexVector                  SimplexVector;
        typedef             typename Parent::DistanceType                   DistanceType;
        typedef             typename Parent::IndexType                      IndexType;
        typedef             typename Parent::ComparePair                    ComparePair;

                            RipsGenerator(const Distances& distances):
                                Parent(distances)                           {}

        using               Parent::distances;

        /// generate k-skeleton of the Rips complex
        void                generate(SimplexVector& v, Dimension k, DistanceType max) const;
};

// Much more memory efficient, but also much slower
template<class Distances_, class Simplex_ = Simplex<typename Distances_::IndexType> >
class RipsGeneratorMemory: public RipsBase<Distances_, Simplex_>
{
    public:
        typedef             RipsBase<Distances_, Simplex_>                  Parent;
        typedef             typename Parent::Distances                      Distances;
        typedef             typename Parent::Simplex                        Simplex;
        typedef             typename Parent::SimplexVector                  SimplexVector;
        typedef             typename Parent::DistanceType                   DistanceType;
        typedef             typename Parent::IndexType                      IndexType;
        typedef             typename Parent::ComparePair                    ComparePair;

                            RipsGeneratorMemory(const Distances& distances):
                                Parent(distances)                           {}

        using               Parent::distances;
        using               Parent::distance;

        /// generate k-skeleton of the Rips complex
        void                generate(SimplexVector& v, Dimension k, DistanceType max) const;
};


template<class Distances_, class Simplex_>
class RipsBase<Distances_, Simplex_>::Evaluator
{
    public:
        typedef             Simplex_                                        Simplex;

                            Evaluator(const Distances& distances): 
                                distances_(distances)                       {}

        DistanceType        operator()(const Simplex& s) const;

    private:
        const Distances&    distances_;
};

template<class Distances_, class Simplex_>
class RipsBase<Distances_, Simplex_>::Comparison
{
    public:
        typedef             Simplex_                                        Simplex;

                            Comparison(const Distances& distances):
                                eval_(distances)                            {}

        bool                operator()(const Simplex& s1, const Simplex& s2) const    { return eval_(s1) < eval_(s2); }

    private:
        Evaluator           eval_;
};

/**
 * Class: ExplicitDistances 
 * Stores the pairwise distances of Distances_ instance passed at construction. 
 * It's a protypical Distances template argument for the Rips complex.
 */
template<class Distances_>
class ExplicitDistances
{
    public:
        typedef             Distances_                                      Distances;
        typedef             size_t                                          IndexType;
        typedef             typename Distances::DistanceType                DistanceType;

                            ExplicitDistances(const Distances& distances);

        DistanceType        operator()(IndexType a, IndexType b) const;

        size_t              size() const                                    { return size_; }
        IndexType           begin() const                                   { return 0; }
        IndexType           end() const                                     { return size(); }

    private:
        std::vector<DistanceType>                   distances_;
        size_t                                      size_;
};


/**
 * Class: PairwiseDistances
 * Given a Container_ of points and a Distance_, it computes distances between elements 
 * in the container (given as instances of Index_ defaulted to unsigned) using the Distance_ functor.
 *
 * Container_ is assumed to be an std::vector. That simplifies a number of things.
 */
template<class Container_, class Distance_, typename Index_ = unsigned>
class PairwiseDistances
{
    public:
        typedef             Container_                                      Container;
        typedef             Distance_                                       Distance;
        typedef             Index_                                          IndexType;
        typedef             typename Distance::value_type                   DistanceType;


                            PairwiseDistances(const Container& container, 
                                              const Distance& distance = Distance()):
                                container_(container), distance_(distance)  {}

        DistanceType        operator()(IndexType a, IndexType b) const      { return distance_(container_[a], container_[b]); }

        size_t              size() const                                    { return container_.size(); }
        IndexType           begin() const                                   { return 0; }
        IndexType           end() const                                     { return size(); }

    private:
        const Container&    container_;
        Distance            distance_;
};

#include "rips.hpp"

#endif // __RIPS_H__