include/topology/weighted-rips.h
author Christos Mantoulidis <cmad@stanford.edu>
Tue, 28 Jul 2009 15:04:06 -0700
branchdev
changeset 155 1dde8a05fcd7
parent 153 7731c42892de
child 156 f75fb57d2831
permissions -rw-r--r--
Added rips-weighted-cohomology, and channeled WeightedRips logging to the same channel as Rips

#ifndef __WEIGHTED_RIPS_H__
#define __WEIGHTED_RIPS_H__

#include <vector>
#include <string>
#include "simplex.h"
#include "rips.h"
#include <boost/iterator/counting_iterator.hpp>

/**
 * WeightedRips class
 *
 * Class providing basic operations to work with Rips complexes. It implements Bron-Kerbosch algorithm, 
 * and provides simple wrappers for various functions.
 *
 * 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, typename Distances_::DistanceType> >
class WeightedRips : public Rips<Distances_, Simplex_>
{
    public:

        /* redeclaring the typedefs because they cannot be inherited at compile-time */
        typedef             Distances_                                      Distances; 
        typedef             typename Distances::IndexType                   IndexType;
        typedef             typename Distances::DistanceType                DistanceType;

        typedef             Simplex_                                        Simplex;
        typedef             typename Simplex::Vertex                        Vertex;             // should be the same as IndexType
        typedef             typename Simplex::VertexContainer               VertexContainer;

        class               Evaluator;
        class               Comparison;

    public:
                            WeightedRips(const Distances& distances):
                                Rips<Distances_, Simplex_>(distances)                             {}

                            template<class Functor>
                            void generate(Dimension k, DistanceType max, const Functor& f) const;

};

/**
 * DistanceDataStackingFunctor class
 * 
 * Class providing a functor that is to be called by WeightedRips::generate(). This functor
 * takes as an argument (to its constructor) the original functor passed by the user to
 * generate(), and a new ``double'' functor is created. Assuming that the functor acts on
 * simplices, first the value of the simplex is computed (the radius at which the simplex
 * appears in the weighted Rips complex), the data field of the simplex is populated with
 * this value, and then the original functor is called (it has no idea that it was
 * intercepted).
 */

template<class Rips_, class Functor_>
class DistanceDataStackingFunctor
{
	public:
		typedef     typename Rips_::Simplex         Simplex_;

		DistanceDataStackingFunctor(const Rips_ &r, const Functor_ &f):
			rips(r), original_functor(f) { }

		void operator()(const Simplex_ &s) const
		{
			Simplex_         s_new(s);
			s_new.data()   = rips.distance(s_new, s_new);
			original_functor(s_new);
		}

	private:
		const Rips_       &rips;
		const Functor_    &original_functor;
};

template<class Distances_, class Simplex_>
template<class Functor>
void WeightedRips<Distances_,Simplex_>::generate(Dimension k, DistanceType max, const Functor &f) const
{
	Rips<Distances_,Simplex_>::generate(k, max, DistanceDataStackingFunctor<WeightedRips<Distances_,Simplex_>,Functor>(*this, f));
}

template<class Distances_, class Simplex_>
class WeightedRips<Distances_, Simplex_>::Evaluator: public Rips<Distances_, Simplex_>::Evaluator
{
    public:
                            Evaluator(const Distances& distances): 
                                Rips<Distances_, Simplex_>::Evaluator(distances)                       {}

        DistanceType       operator()(const Simplex& s) const { return s.data(); }
};

template<class Distances_, class Simplex_>
class WeightedRips<Distances_, Simplex_>::Comparison: public Rips<Distances_, Simplex_>::Comparison
{
    public:
                            Comparison(const Distances& distances):
                                Rips<Distances_, Simplex_>::Comparison(distances)                            {}

        bool                operator()(const Simplex& s1, const Simplex& s2) const    
        { 
                            if (s1.dimension() != s2.dimension())
                                return s1.dimension() < s2.dimension();
                            return s1.data() < s2.data();
        }
};

#endif // __WEIGHTED_RIPS_H__