bindings/python/rips.h
author Dmitriy Morozov <dmitriy@mrzv.org>
Tue, 14 Sep 2010 11:12:33 -0700
branchdev
changeset 230 6a222607714c
parent 130 580eaa850c4f
permissions -rw-r--r--
Added ability to iterate over ZigzagPersistence cycles in Python

#ifndef __PYTHON_RIPS_H__
#define __PYTHON_RIPS_H__

#include <topology/rips.h>
#include <utilities/indirect.h>

#include "simplex.h"

#include <boost/python.hpp>
#include <boost/python/stl_iterator.hpp>


namespace bp = boost::python;


namespace dionysus { 
namespace python   {

// This strange wrapper is necessary because Rips<...> stores only a const reference to the distances. 
// Something on the C++ side of things must store the actual DistancesWrapper object, and that's the 
// purpose of this class.
class RipsWithDistances
{
    public:
        class DistancesWrapper
        {
            public:
                typedef             unsigned                                        IndexType;
                typedef             double                                          DistanceType;
        
                                    DistancesWrapper(bp::object distances):
                                        distances_(distances)                       {}
        
                DistanceType        operator()(IndexType a, IndexType b) const      { return bp::extract<DistanceType>(distances_(a, b)); }
        
                IndexType           size() const                                    { return bp::len(distances_); }
                IndexType           begin() const                                   { return 0; }
                IndexType           end() const                                     { return size(); }
        
            private:
                bp::object          distances_;
        };

        typedef             DistancesWrapper::IndexType                             IndexType;
        typedef             DistancesWrapper::DistanceType                          DistanceType;

        typedef             Rips<DistancesWrapper, SimplexVD>                       RipsDS;
        typedef             RipsDS::Comparison                                      Comparison;
        typedef             RipsDS::Evaluator                                       Evaluator;

        class FunctorWrapper
        {
            public:
                                    FunctorWrapper(bp::object functor):
                                        functor_(functor)                           {}
        
                void                operator()(const RipsDS::Simplex& s) const      { functor_(s); }
        
            private:
                bp::object          functor_;
        };


                            RipsWithDistances(bp::object distances):
                                distances_(distances), rips_(distances_),
                                cmp_(Comparison(distances_)), eval_(distances_)     {}

        void                generate(Dimension k, DistanceType max, bp::object functor) const
        { rips_.generate(k, max, FunctorWrapper(functor)); }

        void                vertex_cofaces(IndexType v, Dimension k, DistanceType max, bp::object functor) const
        { rips_.vertex_cofaces(v, k, max, FunctorWrapper(functor)); }
        
        void                edge_cofaces(IndexType u, IndexType v, Dimension k, DistanceType max, bp::object functor) const
        { rips_.edge_cofaces(u, v, k, max, FunctorWrapper(functor)); }

        void                generate_candidates(Dimension k, DistanceType max, bp::object functor, bp::object seq) const
        { 
            rips_.generate(k, max, FunctorWrapper(functor), 
                           bp::stl_input_iterator<IndexType>(seq), bp::stl_input_iterator<IndexType>());
        }
        
        void                vertex_cofaces_candidate(IndexType v, Dimension k, DistanceType max, 
                                                     bp::object functor, bp::object seq) const
        { 
            rips_.vertex_cofaces(v, k, max, FunctorWrapper(functor), 
                                 bp::stl_input_iterator<IndexType>(seq), bp::stl_input_iterator<IndexType>());
        }
        
        void                edge_cofaces_candidates(IndexType u, IndexType v, Dimension k, DistanceType max, 
                                                    bp::object functor, bp::object seq) const
        { 
            rips_.edge_cofaces(u, v, k, max, FunctorWrapper(functor), 
                               bp::stl_input_iterator<IndexType>(seq), bp::stl_input_iterator<IndexType>());
        }

        int                 cmp(const SimplexObject& s1, const SimplexObject& s2) const                     { return cmp_native(s1, s2); }
        int                 cmp_native(const SimplexVD& s1, const SimplexVD& s2) const                      { return cmp_.compare(s1, s2); }
        
        DistanceType        eval(const SimplexObject& s) const                                              { return eval_native(s); }
        DistanceType        eval_native(const SimplexVD& s) const                                           { return eval_(s); }
        
    private:
        DistancesWrapper                            distances_;
        RipsDS                                      rips_;
        ThreeOutcomeCompare<Comparison>             cmp_;           // in Python, cmp is a three outcome comparison
        Evaluator                                   eval_;
};

} } // namespace dionysus::python

#endif