include/topology/persistence-diagram.h
author Dmitriy Morozov <dmitriy@mrzv.org>
Mon, 06 Mar 2023 12:54:27 -0800
changeset 302 47512d24f907
parent 247 ad3aefb5a0e0
permissions -rw-r--r--
Fix doc/conf.py

#ifndef __PERSISTENCE_DIAGRAM_H__
#define __PERSISTENCE_DIAGRAM_H__

#include <utilities/types.h>

#include <vector>
#include <iostream>
#include <cmath>

#include <boost/compressed_pair.hpp>
#include <boost/optional.hpp>
#include <boost/serialization/access.hpp>

/**
 * Class: PDPoint
 *
 * Stores birth-death pair plus any additional information provided by `Data` template parameter.
 */
template<class Data_ = Empty<> >
class PDPoint
{
    public:
        typedef                 Data_                                       Data;

                                PDPoint(const PDPoint& other):
                                    point_(other.point_)                    {}
                                PDPoint(RealType x = 0, RealType y = 0, const Data& data = Data());

        RealType                x() const                                   { return point_.first().first; }
        RealType                y() const                                   { return point_.first().second; }
        const Data&             data() const                                { return point_.second(); }
        Data&                   data()                                      { return point_.second(); }

        std::ostream&           operator<<(std::ostream& out) const         { return (out << x() << " " << y()); } // << " " << data()); }

        struct Visitor
        {
            template<class Iterator>
            void                point(Iterator i, PDPoint& p) const         {}
        };

    private:
        RealType&               x()                                         { return point_.first().first; }
        RealType&               y()                                         { return point_.first().second; }

    private:
        boost::compressed_pair<std::pair<RealType, RealType>, Data>       point_;

    private:
        /* Serialization */
        friend class boost::serialization::access;

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

template<class Data>
std::ostream&                   operator<<(std::ostream& out, const PDPoint<Data>& point)
{ return (point.operator<<(out)); }

template<class Point, class Iterator, class Evaluator, class Visitor>
boost::optional<Point>
make_point(Iterator i, const Evaluator& evaluator, const Visitor& visitor);

template<class Point, class Iterator, class Evaluator>
boost::optional<Point>
make_point(Iterator i, const Evaluator& evaluator)
{ return make_point<Point>(i, evaluator, Point::Visitor()); }


/**
 * Class: PersistenceDiagram
 *
 * Stores birth-death pairs, i.e. points in the extended plane. Each point can also store
 * additional information described by `Data_` template parameter.
 */
template<class Data_ = Empty<> >
class PersistenceDiagram
{
    public:
        typedef                 Data_                                       Data;
        typedef                 PDPoint<Data>                               Point;
        typedef                 std::vector<Point>                          PointVector;
        typedef                 typename PointVector::const_iterator        const_iterator;

                                PersistenceDiagram()                        {}

                                PersistenceDiagram( Dimension dimension ):
                                    dimension_( dimension )                  {}

        template<class OtherData>
                                PersistenceDiagram(const PersistenceDiagram<OtherData>& other);

        template<class Iterator, class Evaluator>
                                PersistenceDiagram(Iterator bg, Iterator end,
                                                   const Evaluator& eval = Evaluator());

        template<class Iterator, class Evaluator, class Visitor>
                                PersistenceDiagram(Iterator bg, Iterator end,
                                                   const Evaluator& eval = Evaluator(),
                                                   const Visitor& visitor = Visitor());

        template<class Iterator, class Evaluator, class Visitor>
        void                    init(Iterator bg, Iterator end,
                                     const Evaluator& eval = Evaluator(),
                                     const Visitor& visitor = Visitor());

        const_iterator          begin() const                               { return points_.begin(); }
        const_iterator          end() const                                 { return points_.end(); }
        size_t                  size() const                                { return points_.size(); }

        void                    push_back(const Point& point)               { points_.push_back(point); }

        std::ostream&           operator<<(std::ostream& out) const;

        Dimension               dimension() const                           { return dimension_; }

    private:
        PointVector             points_;
        Dimension               dimension_;

    private:
        /* Serialization */
        friend class boost::serialization::access;

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

template<class Data>
std::ostream&                   operator<<(std::ostream& out, const PersistenceDiagram<Data>& pd)
{ return (pd.operator<<(out)); }

// Function: init_diagram_vector()
template<class Diagrams, class Iterator, class Evaluator, class DimensionExtractor>
void                    init_diagrams(Diagrams& diagrams,
                                      Iterator bg, Iterator end,
                                      const Evaluator& evaluator = Evaluator(),
                                      const DimensionExtractor& dimension = DimensionExtractor());

template<class Diagrams, class Iterator, class Evaluator, class DimensionExtractor, class Visitor>
void                    init_diagrams(Diagrams& diagrams,
                                      Iterator bg, Iterator end,
                                      const Evaluator& evaluator = Evaluator(),
                                      const DimensionExtractor& dimension = DimensionExtractor(),
                                      const Visitor& visitor = Visitor());

// Class: Linfty
// Functor that computes L infinity norm between two points
template<class Point1, class Point2>
struct Linfty
{
    RealType            operator()(const Point1& p1, const Point2& p2) const        { return std::max(std::abs(p1.x() - p2.x()),
                                                                                                      std::abs(p1.y() - p2.y())); }

    template<class Point>
    RealType            diagonal(const Point& p) const                              { return std::abs(p.y() - p.x())/2; }
};

// Function: bottleneck_distance(dgm1, dgm2)
// Computes bottleneck distance between the two diagrams.
template<class Diagram1,
         class Diagram2,
         class Norm>
RealType                bottleneck_distance(const Diagram1& dgm1, const Diagram2& dgm2, const Norm& norm = Norm());

template<class Diagram1,
         class Diagram2>
RealType                bottleneck_distance(const Diagram1& dgm1, const Diagram2& dgm2)
{ return bottleneck_distance(dgm1, dgm2, Linfty<typename Diagram1::Point, typename Diagram2::Point>()); }

template<class Diagram>
RealType                wasserstein_distance(const Diagram& dgm1, const Diagram& dgm2, unsigned p);


#include "persistence-diagram.hpp"

#endif // __PERSISTENCE_DIAGRAM_H__