include/topology/vineyard.h
author Dmitriy Morozov <dmitriy@mrzv.org>
Thu, 10 May 2012 15:42:21 -0700
branchdev
changeset 247 ad3aefb5a0e0
parent 180 27508309a680
permissions -rw-r--r--
Added wasserstein_distance()

/*
 * Author: Dmitriy Morozov
 * Department of Computer Science, Duke University, 2005 -- 2009
 */

#ifndef __VINEYARD_H__
#define __VINEYARD_H__

#include "utilities/types.h"
#include <list>
#include <string>

#include <boost/serialization/access.hpp>
#include <boost/serialization/vector.hpp>
#include <boost/serialization/nvp.hpp>
#include <boost/serialization/list.hpp>
    
#include <boost/iterator/iterator_traits.hpp>


class Knee;
class Vine;

/**
 * Vineyard class. Keeps track of vines and knees. switched() is the key function called
 * when pairing switches.
 *
 * \ingroup topology
 */
template<class Index_, class Iterator_, class Evaluator_>
class Vineyard
{
    public:
        typedef                         Index_                                          Index;
        typedef                         Iterator_                                       Iterator;
        typedef                         Evaluator_                                      Evaluator;

        typedef                         std::list<Vine>                                 VineList;
        typedef                         std::list<VineList>                             VineListList;
        typedef                         std::vector<VineListList::iterator>             VineListVector;
                                        
    public:
                                        Vineyard(Evaluator* eval = 0): 
                                            evaluator(eval)                             {}

        void                            start_vines(Iterator bg, Iterator end);
        void                            switched(Index i, Index j);
        template<class Iter>
        void                            record_knee(Iter i);
        void                            record_diagram(Iterator bg, Iterator end);

        void                            set_evaluator(Evaluator* eval)                  { evaluator = eval; }

        void                            save_edges(const std::string& filename, bool skip_infinite = false) const;
        void                            save_vines(const std::string& filename, bool skip_infinite = false) const;

    private:
        template<class Iter>
        void                            start_vine(Iter i);

    private:
        VineListList                    vines;            // stores vine lists
        VineListVector                  vines_vector;     // stores pointers (iterators) to vine lists
        Evaluator*                      evaluator;
};

/**
 * Knee class stores the knee in R^3.
 *
 * \ingroup topology
 */
class Knee
{
    public:
        RealType                birth;
        RealType                death;
        RealType                time;
            
                                // Default parameters for serialization
                                Knee(RealType b = 0, RealType d = 0, RealType t = 0):
                                    birth(b), death(d), time(t)
                                {}
                                Knee(const Knee& other): 
                                    birth(other.birth), death(other.death), time(other.time)
                                {}

        bool                    is_diagonal() const                             { return birth == death; }
        bool                    is_infinite() const                             { return (death == Infinity) || (birth == Infinity); }

        std::ostream&           operator<<(std::ostream& out) const             { return out << "(" << birth << ", " 
                                                                                                    << death << ", " 
                                                                                                    << time  << ")"; }
    
    private:
        friend class boost::serialization::access;

        template<class Archive>
        void                    serialize(Archive& ar, version_type );
};

std::ostream& operator<<(std::ostream& out, const Knee& k)                      { return k.operator<<(out); }

/**
 * Vine is a list of Knees
 */
class Vine: public std::list<Knee>
{   
    public:
        typedef                 std::list<Knee>                                 VineRepresentation;
        typedef                 VineRepresentation::const_iterator              const_knee_iterator;
        
                                Vine()                                          {}
                                Vine(const Vine& other): 
                                    VineRepresentation(other)                   {}
                                Vine(const VineRepresentation& other): 
                                    VineRepresentation(other)                   {}
                                Vine(const Knee& k)                             { add(k); }
        
        void                    add(RealType b, RealType d, RealType t)         { push_back(Knee(b,d,t)); }
        void                    add(const Knee& k)                              { push_back(k); }

        std::ostream&           operator<<(std::ostream& out) const             { std::copy(begin(), end(), std::ostream_iterator<Knee>(out, " ")); return out; }

        using VineRepresentation::begin;
        using VineRepresentation::end;
        using VineRepresentation::front;
        using VineRepresentation::back;
        using VineRepresentation::size;
        using VineRepresentation::empty;

    protected:
        using VineRepresentation::push_back;

    private:
        friend class boost::serialization::access;

        template<class Archive>
        void                    serialize(Archive& ar, version_type );
};

std::ostream& operator<<(std::ostream& out, const Vine& v)                      { return v.operator<<(out); }


class VineData
{
    public:
        void        set_vine(Vine* vine) const                                          { vine_ = vine; }
        Vine*       vine() const                                                        { return vine_; }

    private:
        mutable Vine*       vine_;      // cheap trick to work around MultiIndex's constness
};


#include "vineyard.hpp"

#endif // __VINEYARD_H__