CohomologyPersistence returns dying cocycles + StaticCohomologyPersistence records them and normalizes coefficients + minor changes dev
authorDmitriy Morozov <dmitriy@mrzv.org>
Sat, 09 Jun 2012 12:17:17 -0700
branchdev
changeset 267 2f02384a4d9b
parent 266 38cf887cb139
child 268 9b0da55e5df0
CohomologyPersistence returns dying cocycles + StaticCohomologyPersistence records them and normalizes coefficients + minor changes
bindings/python/cohomology-persistence.cpp
bindings/python/dionysus/adaptor.py
bindings/python/dionysus/circular/__init__.py
bindings/python/dionysus/viewer/PyGLWidget.py
bindings/python/dionysus/viewer/complex3d.py
doc/python/cohomology-persistence.rst
--- 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.
         ::