include/topology/cohomology-persistence.h
author Christos Mantoulidis <cmad@stanford.edu>
Tue, 04 Aug 2009 13:23:16 -0700
branchdev
changeset 156 f75fb57d2831
parent 137 069596c71902
child 172 a6605dc232f2
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 __COHOMOLOGY_PERSISTENCE_H__
#define __COHOMOLOGY_PERSISTENCE_H__

#if DEBUG_CONTAINERS
    #include <debug/list>
    #include <debug/vector>
    namespace s = std::__debug;
    #warning "Using debug/list and debug/vector in CohomologyPersistence"
#else
    #include <list>
    #include <vector>
    namespace s = std;
#endif

#include <vector>
#include <list>
#include <utility>

#include <topology/field-arithmetic.h>
#include "utilities/types.h"

#include <boost/optional.hpp>
#include <boost/intrusive/list.hpp>
namespace bi = boost::intrusive;


template<class BirthInfo_, class SimplexData_ = Empty<>, class Field_ = ZpField>
class CohomologyPersistence
{
    public:
        typedef             BirthInfo_                                                  BirthInfo;
        typedef             SimplexData_                                                SimplexData;
        typedef             Field_                                                      Field;

        typedef             typename Field::Element                                     FieldElement;


                            CohomologyPersistence(const Field& field = Field()):
                                field_(field)                                           {}


        // An entry in a cocycle column
        struct  SNode;      // members: si, coefficient, ci
        typedef             s::vector<SNode>                                            ZColumn;
        typedef             bi::list<SNode, bi::constant_time_size<false> >             ZRow;
        class   CompareSNode;

        struct  SHead;      // members: row, order
        typedef             s::list<SHead>                                              Simplices;
        typedef             typename Simplices::iterator                                SimplexIndex;

        struct  Cocycle;    // members: zcolumn, birth, order
        typedef             s::list<Cocycle>                                            Cocycles;
        typedef             typename Cocycles::iterator                                 CocycleIndex;
        typedef             std::pair<CocycleIndex, FieldElement>                       CocycleCoefficientPair;

        typedef             boost::optional<BirthInfo>                                  Death;
        typedef             std::pair<SimplexIndex, Death>                              IndexDeathPair;

        // return either a SimplexIndex or a Death
        // BI = BoundaryIterator; it should dereference to a SimplexIndex
        template<class BI>
        IndexDeathPair      add(BI begin, BI end, BirthInfo b, bool store = true, const SimplexData& sd = SimplexData());

        void                show_cocycles() const;
        CocycleIndex        begin()                                                     { return cocycles_.begin(); }
        CocycleIndex        end()                                                       { return cocycles_.end(); }

    private:
        void                add_cocycle(CocycleCoefficientPair& z1, CocycleCoefficientPair& z2);

    private:
        Simplices           simplices_;
        Cocycles            cocycles_;
        Field               field_;
};
        
// Simplex representation
template<class BirthInfo_, class SimplexData_, class Field_>
struct CohomologyPersistence<BirthInfo_, SimplexData_, Field_>::SHead: public SimplexData
{
                    SHead(const SHead& other):
                        SimplexData(other), order(other.order)                  {}  // don't copy row since we can't
                    SHead(const SimplexData& sd, unsigned o): 
                        SimplexData(sd), order(o)                               {}

    // intrusive list corresponding to row of s in Z^*, not ordered in any particular order
    ZRow            row;
    unsigned        order;
};

// An entry in a cocycle column; it's also an element in an intrusive list, hence the list_base_hook<>
typedef             bi::list_base_hook<bi::link_mode<bi::auto_unlink> >         auto_unlink_hook;
template<class BirthInfo_, class SimplexData_, class Field_>
struct CohomologyPersistence<BirthInfo_, SimplexData_, Field_>::SNode: public auto_unlink_hook
{
                    SNode(const SNode& other):
                        si(other.si), coefficient(other.coefficient), 
                        ci(other.ci)                                            {}

                    SNode(SimplexIndex sidx, FieldElement coef, CocycleIndex cidx): 
                        si(sidx), coefficient(coef), ci(cidx)                   {}

    SimplexIndex    si;
    FieldElement    coefficient;

    CocycleIndex    ci;                         // TODO: is there no way to get rid of this overhead?

    void            unlink()                    { auto_unlink_hook::unlink(); }
};

template<class BirthInfo_, class SimplexData_, class Field_>
struct CohomologyPersistence<BirthInfo_, SimplexData_, Field_>::Cocycle
{
                    Cocycle(const BirthInfo& b, unsigned o):
                        birth(b), order(o)                                      {}

    ZColumn         zcolumn;
    BirthInfo       birth;
    unsigned        order;

    bool            operator<(const Cocycle& other) const                       { return order > other.order; }
    bool            operator==(const Cocycle& other) const                      { return order == other.order; }
};


#include "cohomology-persistence.hpp"

#endif // __COHOMOLOGY_PERSISTENCE_H__