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 __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