include/topology/dynamic-persistence.h
author Christos Mantoulidis <cmad@stanford.edu>
Tue, 04 Aug 2009 13:23:16 -0700
branchdev
changeset 156 f75fb57d2831
parent 125 0a2c2283e4a8
child 174 3f1034dca432
child 179 d15c6d144645
permissions -rw-r--r--
Changed implementation of WeightedRips to store simplex values (max distance between simplices' vertices) as an invisible layer on top of each simplex object, so that the data() field of WeightedRips has been freed for use by the users again.

#ifndef __DYNAMIC_PERSISTENCE_H__
#define __DYNAMIC_PERSISTENCE_H__

#include "static-persistence.h"
#include <utilities/types.h>

#include <boost/progress.hpp>

#ifdef COUNTERS
static Counter*  cTrailLength =             GetCounter("persistence/pair/traillength");     // the size of matrix U in RU decomposition
static Counter*  cChainLength =             GetCounter("persistence/pair/chainlength");     // the size of matrix V in R=DV decomposition
#endif // COUNTERS

template<class Data_, class ChainTraits_, class ContainerTraits_, class ConsistencyIndex_>
struct TrailData: public PairCycleData<Data_, ChainTraits_, ContainerTraits_, 
                                       TrailData<Data_, ChainTraits_, ContainerTraits_, ConsistencyIndex_> >
{
    typedef     Data_                                                                   Data;
    typedef     ConsistencyIndex_                                                       ConsistencyIndex;

    typedef     PairCycleData<Data_, ChainTraits_, ContainerTraits_, TrailData>         Parent;
    typedef     TrailData<Data_, ChainTraits_, ContainerTraits_, ConsistencyIndex_>     Self;

    // typedef     typename ContainerTraits_::template rebind<Self>::other                 ContainerTraits;
    // typedef     typename ContainerTraits::Index                                         Index;
    // typedef     typename ChainTraits_::template rebind<Index>::other                    ChainTraits;
    // typedef     typename ChainTraits::Chain                                             Chain;
    typedef     typename Parent::Index                                                  Index;
    typedef     typename Parent::Chain                                                  Chain;
    typedef     Chain                                                                   Trail;
    
    template<class Comparison>
    struct ConsistencyComparison: public std::binary_function<const Index&, const Index&, bool>
    {
                        ConsistencyComparison(const Comparison& cmp = Comparison()): 
                            cmp_(cmp)                                                   {}

        bool            operator()(const Index& a, const Index& b) const                { return cmp_(a->consistency, b->consistency); }

        Comparison      cmp_;
    };

    Trail                                                                       trail;
    ConsistencyIndex                                                            consistency;
};

/**
 * Class: DynamicPersistenceTrails
 * Derives from StaticPersistence and allows one to update persistence 
 * after a transposition of two contiguous simplices in a filtration. 
 * In addition to reduced cycles, it stores each OrderElement's trails,
 * i.e. in addition to matrix R, it stores matrix U in vineyard notation.
 *
 * Template parameters:
 *   Data_ -                auxilliary contents to store with each OrderElement
 *   OrderDescriptor_ -     class describing how the order is stored; it defaults to <VectorOrderDescriptor> 
 *                          which serves as a prototypical class
 */
// TODO: perhaps Consistency should be wrapped into a ConsistencyDescriptor that somehow knows how to initialize it. 
// That way one could provide a simple consistency descriptor that just stored some integers describing the original 
// position, or one could provide consistency that is references into the complex
template<class Data_ =                  Empty<>, 
         class ChainTraits_ =           VectorChains<>,
         class Comparison_ =            GreaterComparison<>,
         class ContainerTraits_ =       VectorContainer<>,
         class ConsistencyIndex_ =      size_t,
         class ConsistencyComparison_ = std::less<ConsistencyIndex_>,
         class Element_ =               TrailData<Data_, ChainTraits_, ContainerTraits_, ConsistencyIndex_> >
class DynamicPersistenceTrails: 
    public StaticPersistence<Data_, ChainTraits_, Comparison_, ContainerTraits_, Element_>
{
    public:
        typedef         Data_                                                           Data;
        typedef         Element_                                                        Element;
        typedef         StaticPersistence<Data_, ChainTraits_, Comparison_,
                                          ContainerTraits_, Element_>                   Parent;
 
        typedef         typename Parent::ContainerTraits                                Traits;
        typedef         typename Parent::Order                                          Order;
        typedef         typename Parent::OrderComparison                                OrderComparison;
        typedef         typename Parent::OrderIndex                                     OrderIndex;
        typedef         ConsistencyIndex_                                               ConsistencyIndex;
        typedef         ThreeOutcomeCompare<
                            typename Element::
                            template ConsistencyComparison<ConsistencyComparison_> >    ConsistencyComparison;

        /**
         * Constructor: DynamicPersistenceTrails()
         * TODO: write a description
         *
         * Template parameters:
         *   Filtration -           filtration of the complex whose persistence we are computing
         */
        template<class Filtration>      DynamicPersistenceTrails(const Filtration&              f, 
                                                                 const OrderComparison&         ocmp =  OrderComparison(),
                                                                 const ConsistencyComparison&   ccmp =  ConsistencyComparison());
        
        void                            pair_simplices();

        // Function: transpose(i)
        // Tranpose i and the next element. 
        // Returns: true iff the pairing switched.
        bool                            transpose(OrderIndex i)                         { return transpose(i, TranspositionVisitor()); }
        
        template<class Visitor>
        bool                            transpose(OrderIndex i, const Visitor& visitor = Visitor());

        using                           Parent::begin;
        using                           Parent::end;
        using                           Parent::size;

        // Struct: TranspositionVisitor
        //
        // For example, a VineardVisitor could implement this archetype.
        struct TranspositionVisitor
        {
            // Function: transpose(i)
            // This function is called before transposition is processed 
            // (at the very beginning of <transpose(i, visitor)>). It is meant to update any structures 
            // that may need to be updated, but perhaps it has other uses as well.
            void                        transpose(OrderIndex i) const                   {}

            // Function: switched(i, type)
            // This function is called after the transposition if the switch in pairing has occured.
            // `i` is the index of the preceding simplex after the transposition. 
            // `type` indicates the <SwitchType>.
            void                        switched(OrderIndex i, SwitchType type) const   {}
        };

    protected:
        using                           Parent::order;

    private:
        void                            swap(OrderIndex i, OrderIndex j);
        void                            pairing_switch(OrderIndex i, OrderIndex j);

        struct PairingTrailsVisitor: public Parent::PairVisitor 
        {
            // TODO: this is specialized for std::vector
                                        PairingTrailsVisitor(OrderIndex bg, ConsistencyComparison ccmp): 
                                            bg_(bg), ccmp_(ccmp)                        {}

            void                        init(OrderIndex i) const                        { i->consistency = i - bg_; i->trail.append(i, ccmp_); Count(cTrailLength); }
            void                        update(OrderIndex j, OrderIndex i) const        { i->pair->trail.append(j, ccmp_); Count(cTrailLength); }

            OrderIndex                  bg_;
            ConsistencyComparison       ccmp_;
        };

        ConsistencyComparison           ccmp_;
};

template<class Data_, class ChainTraits_, class ContainerTraits_, class ConsistencyIndex_>
struct ChainData: public PairCycleData<Data_, ChainTraits_, ContainerTraits_,
                                       ChainData<Data_, ChainTraits_, ContainerTraits_, ConsistencyIndex_> >
{
    typedef     Data_                                                                   Data;
    typedef     ConsistencyIndex_                                                       ConsistencyIndex;

    typedef     PairCycleData<Data_, ChainTraits_, ContainerTraits_, ChainData>         Parent;
    typedef     ChainData<Data_, ChainTraits_, ContainerTraits_, ConsistencyIndex_>     Self;

    typedef     typename Parent::Index                                                  Index;
    typedef     typename Parent::Chain                                                  Chain;
    typedef     Chain                                                                   Trail;
    
    template<class Comparison>
    struct ConsistencyComparison: public std::binary_function<const Index&, const Index&, bool>
    {
                        ConsistencyComparison(const Comparison& cmp = Comparison()): 
                            cmp_(cmp)                                                   {}

        bool            operator()(const Index& a, const Index& b) const                { return cmp_(a->consistency, b->consistency); }

        Comparison      cmp_;
    };

    Chain                                                                       chain;
    ConsistencyIndex                                                            consistency;
};

/**
 * Class: DynamicPersistenceChains
 *
 * TODO: below comment is incorrect; nothing dynamic about this yet.
 * Derives from StaticPersistence and allows one to update persistence 
 * after a transposition of two contiguous simplices in a filtration. 
 * In addition to reduced cycles, it stores each OrderElement's chains,
 * i.e. in addition to matrix R, it stores matrix V in vineyard notation.
 *
 * Template parameters:
 *   Data_ -                auxilliary contents to store with each OrderElement
 *   OrderDescriptor_ -     class describing how the order is stored; it defaults to <VectorOrderDescriptor> 
 *                          which serves as a prototypical class
 */
template<class Data_ =                  Empty<>, 
         class ChainTraits_ =           VectorChains<>,
         class Comparison_ =            GreaterComparison<>,
         class ContainerTraits_ =       VectorContainer<>,
         class ConsistencyIndex_ =      size_t,
         class ConsistencyComparison_ = std::less<ConsistencyIndex_>,
         class Element_ =               ChainData<Data_, ChainTraits_, ContainerTraits_, ConsistencyIndex_> >
class DynamicPersistenceChains: 
    public StaticPersistence<Data_, ChainTraits_, Comparison_, ContainerTraits_, Element_>
{
    public:
        typedef         Data_                                                           Data;
        typedef         Element_                                                        Element;
        typedef         StaticPersistence<Data_, ChainTraits_, Comparison_,
                                          ContainerTraits_, Element_>                   Parent;
 
        typedef         typename Parent::ContainerTraits                                Traits;
        typedef         typename Parent::Order                                          Order;
        typedef         typename Parent::OrderComparison                                OrderComparison;
        typedef         typename Parent::OrderIndex                                     OrderIndex;
        typedef         ConsistencyIndex_                                               ConsistencyIndex;
        typedef         ThreeOutcomeCompare<
                            typename Element::
                            template ConsistencyComparison<ConsistencyComparison_> >    ConsistencyComparison;

        /**
         * Constructor: DynamicPersistenceChains()
         * TODO: write a description
         *
         * Template parameters:
         *   Filtration -           filtration of the complex whose persistence we are computing
         */
        template<class Filtration>      DynamicPersistenceChains(const Filtration&              f, 
                                                                 const OrderComparison&         ocmp =  OrderComparison(),
                                                                 const ConsistencyComparison&   ccmp =  ConsistencyComparison());
        
        void                            pair_simplices();

        // Function: transpose(i)
        // Tranpose i and the next element. 
        // Returns: true iff the pairing switched.
        // TODO
        //bool                            transpose(OrderIndex i)                         { return transpose(i, TranspositionVisitor()); }
        
        // TODO: the main missing piece to be dynamic
        //template<class Visitor>
        //bool                            transpose(OrderIndex i, const Visitor& visitor = Visitor());

        using                           Parent::begin;
        using                           Parent::end;
        using                           Parent::size;

        // Struct: TranspositionVisitor
        //
        // For example, a VineardVisitor could implement this archetype.
        struct TranspositionVisitor
        {
            // Function: transpose(i)
            // This function is called before transposition is processed 
            // (at the very beginning of <transpose(i, visitor)>). It is meant to update any structures 
            // that may need to be updated, but perhaps it has other uses as well.
            void                        transpose(OrderIndex i) const                   {}

            // Function: switched(i, type)
            // This function is called after the transposition if the switch in pairing has occured.
            // `i` is the index of the preceding simplex after the transposition. 
            // `type` indicates the <SwitchType>.
            void                        switched(OrderIndex i, SwitchType type) const   {}
        };

    protected:
        using                           Parent::order;

    private:
        void                            swap(OrderIndex i, OrderIndex j);
        void                            pairing_switch(OrderIndex i, OrderIndex j);

        struct PairingChainsVisitor: public Parent::PairVisitor 
        {
            // TODO: this is specialized for std::vector
                                        PairingChainsVisitor(OrderIndex bg, ConsistencyComparison ccmp, unsigned size): 
                                            bg_(bg), ccmp_(ccmp), show_progress(size)   {}

            void                        init(OrderIndex i) const                        { i->consistency = i - bg_; i->chain.append(i, ccmp_); }
            void                        update(OrderIndex j, OrderIndex i) const        { j->chain.add(i->pair->chain, ccmp_); }
            void                        finished(OrderIndex i) const                    { CountBy(cChainLength, i->chain.size()); ++show_progress; }

            OrderIndex                  bg_;
            ConsistencyComparison       ccmp_;

            mutable boost::progress_display     
                                        show_progress;
        };

        ConsistencyComparison           ccmp_;
};


#include "dynamic-persistence.hpp"

#endif  // __DYNAMIC_PERSISTENCE_H__