CohomologyPersistence returns dying cocycles + StaticCohomologyPersistence records them and normalizes coefficients + minor changes
--- a/bindings/python/cohomology-persistence.cpp Fri Jun 08 15:40:09 2012 -0700
+++ b/bindings/python/cohomology-persistence.cpp Sat Jun 09 12:17:17 2012 -0700
@@ -26,11 +26,11 @@
}
-bp::tuple chp_add(dp::CohomPersistence& chp,
- bp::object bdry,
- dp::BirthID birth,
- bool store,
- bool image,
+bp::tuple chp_add(dp::CohomPersistence& chp,
+ bp::object bdry,
+ dp::BirthID birth,
+ bool store,
+ bool image,
bp::object coefficients)
{
dp::CohomPersistence::SimplexIndex i;
@@ -42,28 +42,34 @@
boost::tie(i,d,ccl) = chp.add(bp::stl_input_iterator<int>(coefficients),
bp::stl_input_iterator<dp::CohomPersistence::SimplexIndex>(bdry),
bp::stl_input_iterator<dp::CohomPersistence::SimplexIndex>(),
- birth, store, dp::CohomPersistence::SimplexData(), image);
+ birth, store, dp::CohomPersistence::SimplexData(), image);
} else
{
boost::tie(i,d,ccl) = chp.add(bp::stl_input_iterator<dp::CohomPersistence::SimplexIndex>(bdry),
bp::stl_input_iterator<dp::CohomPersistence::SimplexIndex>(),
- birth, store, dp::CohomPersistence::SimplexData(), image);
+ birth, store, dp::CohomPersistence::SimplexData(), image);
}
- // TODO: return ccl as well
- return bp::make_tuple(i,d);
+ return bp::make_tuple(i,d, ccl);
}
-dp::CohomPersistence::ZColumn::const_iterator
-cocycle_zcolumn_begin(dp::CohomPersistence::Cocycle& ccl)
+dp::CohomPersistence::ZColumn::const_iterator
+zcolumn_begin(dp::CohomPersistence::ZColumn& zcol)
+{ return zcol.begin(); }
+
+dp::CohomPersistence::ZColumn::const_iterator
+zcolumn_end(dp::CohomPersistence::ZColumn& zcol)
+{ return zcol.end(); }
+
+dp::CohomPersistence::ZColumn::const_iterator
+cocycle_zcolumn_begin(dp::CohomPersistence::Cocycle& ccl)
{ return ccl.zcolumn.begin(); }
-dp::CohomPersistence::ZColumn::const_iterator
-cocycle_zcolumn_end(dp::CohomPersistence::Cocycle& ccl)
+dp::CohomPersistence::ZColumn::const_iterator
+cocycle_zcolumn_end(dp::CohomPersistence::Cocycle& ccl)
{ return ccl.zcolumn.end(); }
-
// SimplexIndex
template<class T>
unsigned si_order(T& si)
@@ -79,7 +85,7 @@
bp::class_<dp::CohomPersistence::SimplexIndex>("CHSimplexIndex")
.add_property("order", &si_order<dp::CohomPersistence::SimplexIndex>)
;
-
+
bp::class_<dp::CohomPersistence::SNode>("CHSNode", bp::no_init)
.add_property("coefficient", &dp::CohomPersistence::SNode::coefficient)
.add_property("si", &dp::CohomPersistence::SNode::si)
@@ -89,7 +95,7 @@
.def("__init__", bp::make_constructor(&init))
.def("__init__", bp::make_constructor(&init_from_prime))
.def("add", &chp_add, (bp::arg("bdry"), bp::arg("birth"), bp::arg("store")=true, bp::arg("image")=true, bp::arg("coefficients")=false))
-
+
.def("__iter__", bp::range(&dp::CohomPersistence::begin, &dp::CohomPersistence::end))
.def("show_cocycles", &dp::CohomPersistence::show_cocycles)
;
@@ -98,4 +104,9 @@
.add_property("birth", &dp::CohomPersistence::Cocycle::birth)
.def("__iter__", bp::range(&cocycle_zcolumn_begin, &cocycle_zcolumn_end))
;
+
+ bp::class_<dp::CohomPersistence::ZColumn,
+ boost::shared_ptr<dp::CohomPersistence::ZColumn> >("ZColumn", bp::no_init)
+ .def("__iter__", bp::range(&zcolumn_begin, &zcolumn_end))
+ ;
}
--- a/bindings/python/dionysus/adaptor.py Fri Jun 08 15:40:09 2012 -0700
+++ b/bindings/python/dionysus/adaptor.py Sat Jun 09 12:17:17 2012 -0700
@@ -1,8 +1,9 @@
-from _dionysus import CohomologyPersistence, PersistenceDiagram
+from _dionysus import CohomologyPersistence, PersistenceDiagram, Cocycle
class StaticCohomologyPersistence(object):
def __init__(self, filtration, prime = 2, subcomplex = lambda s: True):
self.filtration = filtration
+ self.prime = prime
self.subcomplex = subcomplex
self.persistence = CohomologyPersistence(prime)
self.pairs = []
@@ -12,16 +13,26 @@
for i,s in enumerate(self.filtration):
sc = self.subcomplex(s)
boundary = (indices[self.filtration(ss)] for ss in s.boundary)
- idx,d = self.persistence.add(boundary, i, image = sc)
+ idx,d,ccl = self.persistence.add(boundary, i, image = sc)
indices.append(idx)
self.pairs.append([i, sc, []])
if d: # Death
if self.pairs[d][1]: # Birth was in the subcomplex
self.pairs[i][0] = d # i killed d
self.pairs[d][0] = i # d was killed by i
+ self.pairs[d][2] = self._cocycle_list(ccl) # record the cocycle at the time of death
else:
cocycle = self.persistence.__iter__().next()
- self.pairs[-1][2] = [(n.coefficient, n.si.order) for n in cocycle]
+ self.pairs[-1][2] = cocycle
+
+ # Replace cocycles with lists
+ for i in xrange(len(self.pairs)):
+ ccl = self.pairs[i][2]
+ if isinstance(ccl, Cocycle):
+ self.pairs[i][2] = self._cocycle_list(ccl)
+
+ def _cocycle_list(self, ccl):
+ return [(n.coefficient if n.coefficient <= self.prime/2 else n.coefficient - self.prime, n.si.order) for n in ccl]
def __call__(self, n):
return n.i
--- a/bindings/python/dionysus/circular/__init__.py Fri Jun 08 15:40:09 2012 -0700
+++ b/bindings/python/dionysus/circular/__init__.py Sat Jun 09 12:17:17 2012 -0700
@@ -17,8 +17,11 @@
face_indices.append(j)
c *= -1
+ # Cocycle can be larger than D; we implicitly project it down
+ cocycle_max = max(zz[1] for zz in cocycle)
+
# D is a coboundary matrix
- dimension = max(max(coface_indices), max(face_indices)) + 1
+ dimension = max(max(coface_indices), max(face_indices), cocycle_max) + 1
D = spmatrix(coefficient, coface_indices, face_indices, (dimension, dimension))
z = spmatrix([zz[0] for zz in cocycle],
@@ -29,7 +32,7 @@
if bool(D*D):
raise Exception('D^2 is not 0')
if bool(v1):
- raise Exception('Expect a cocycle as input')
+ raise Exception('Expected a cocycle as input')
z = matrix(z)
def Dfun(x,y,trans = 'N'):
--- a/bindings/python/dionysus/viewer/PyGLWidget.py Fri Jun 08 15:40:09 2012 -0700
+++ b/bindings/python/dionysus/viewer/PyGLWidget.py Sat Jun 09 12:17:17 2012 -0700
@@ -37,7 +37,7 @@
import numpy
import numpy.linalg as linalg
import OpenGL
-OpenGL.ERROR_CHECKING = True
+OpenGL.ERROR_CHECKING = False
from OpenGL.GL import *
from OpenGL.GLU import *
--- a/bindings/python/dionysus/viewer/complex3d.py Fri Jun 08 15:40:09 2012 -0700
+++ b/bindings/python/dionysus/viewer/complex3d.py Sat Jun 09 12:17:17 2012 -0700
@@ -6,9 +6,14 @@
class ComplexViewer3D(PyGLWidget):
def __init__(self, points, complex = None, values = None, point_size = 3.):
+ self.display_list = None
PyGLWidget.__init__(self)
+
+ #glEnable( GL_BLEND )
+ #glEnable( GL_LINE_SMOOTH )
+ #glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
+
self.point_size = point_size
-
self.points = points
if complex:
self.complex = [s for s in complex]
@@ -41,7 +46,8 @@
def paintGL(self):
PyGLWidget.paintGL(self)
- glCallList(self.display_list)
+ if self.display_list:
+ glCallList(self.display_list)
def make_display_list(self):
self.display_list = glGenLists(1)
@@ -97,7 +103,6 @@
# TODO: cycle
def show_complex_3D(points, complex = None, values = None, app = None, point_size = 3.):
- print "Point size:", point_size
#app = QtGui.QApplication([])
view = ComplexViewer3D(points, complex, values, point_size)
view.show()
--- a/doc/python/cohomology-persistence.rst Fri Jun 08 15:40:09 2012 -0700
+++ b/doc/python/cohomology-persistence.rst Sat Jun 09 12:17:17 2012 -0700
@@ -5,11 +5,11 @@
.. class:: CohomologyPersistence
- .. method:: __init__(prime)
+ .. method:: __init__(prime = 11)
Initializes :class:`CohomologyPersistence` with the given `prime`; from
this point on all the computation will be performed with coefficients
- coming from :math:`\mathbb{Z}/prime \mathbb{Z}`.
+ in :math:`\mathbb{Z}/prime \mathbb{Z}`.
.. method:: add(boundary, birth, [store = True], [image = True], [coefficients = []])
@@ -19,7 +19,7 @@
it for future reference.
If `store` is ``False`` and a class is born, it will not be stored in
- :class:`CohomologyPersistence`. This is useful to not waste space on the
+ :class:`CohomologyPersistence`. This avoids wasting space on the
classes of the dimension equal to the maximum-dimensional simplices of
the complex since such classes will never die.
@@ -34,15 +34,18 @@
coefficients for the corresponding boundary elements. If empty, it is
assumed to be :math:`(-1)^i`.
- :returns: a pair (`i`, `d`). The first element is the index `i`.
+ :returns: a triple (`i`, `d`, `ccl`). The first element is the index `i`.
It is the internal representation of the newly added simplex,
- and should be used later for removal or when constructing the
+ and should be used later when constructing the
boundaries of its cofaces. In other words, `boundary` must
consist of these indices. The second element `d` is the death
element. It is `None` if a birth occurred, otherwise it
contains the value passed as `birth` to
:meth:`~CohomologyPersistence.add` when the class that just
died was born.
+ The third element `ccl` returns the dying cocycle
+ (iterable over instances of :class:`CHSNode`), in case of a death.
+ It's empty if a birth occurs.
.. method:: __iter__()
@@ -141,7 +144,7 @@
.. attribute:: cocycle
- If the simplex is positive, this attribute stores a cocycle it created.
+ If the simplex is positive, this attribute stores a cocycle it created (recorded at the time of its death).
The 1-dimensional cocycles can be used with the :func:`circular.smooth` function to turn
them into circle-valued maps.
::