Merge dev into default, to avoid the need for 'hg up tip' after clone
authorDmitriy Morozov <dmitriy@mrzv.org>
Tue, 27 Jun 2017 09:37:05 -0700
changeset 285 d9a79a28e3cc
parent 58 b3b810b64a79 (current diff)
parent 284 67644b9c7668 (diff)
child 286 0496c5f88b2a
Merge dev into default, to avoid the need for 'hg up tip' after clone
FindCGAL.Makefile
examples/grid/CMakeLists.txt
examples/grid/combustion-vineyard.cpp
examples/grid/grid2D.h
examples/grid/grid2D.hpp
examples/grid/grid2Dvineyard.h
examples/grid/grid2Dvineyard.hpp
examples/grid/pdbdistance-vineyard.cpp
examples/grid/pdbdistance.h
examples/grid/test-grid2D.cpp
include/topology/cycle.h
include/topology/cycle.hpp
include/topology/filtrationcontainer.h
include/topology/filtrationsimplex.h
include/topology/lowerstarfiltration.hpp
include/utilities/debug.h
include/utilities/sys.h
src/debug.cpp
--- a/.hgignore	Fri Aug 24 16:58:25 2007 -0400
+++ b/.hgignore	Tue Jun 27 09:37:05 2017 -0700
@@ -3,3 +3,4 @@
 docs
 aux
 build
+doc/.build
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.issues/.filters	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,11 @@
+[kinetic]
+category=kinetic
+
+[functionality]
+category=functionality
+
+[installation]
+category=installation
+
+[efficiency]
+category=efficiency
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.issues/89ae955518665a61/new/1221008555.M726241P30017Q23.cole	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,15 @@
+From: Dmitriy Morozov <morozov@cs.duke.edu>
+Date: Tue, 26 Feb 2008 18:22:06 -0500
+State: new
+Subject: Get rid of intostring() and .c_str()
+Message-Id: <89ae955518665a61-0-artemis@metatron>
+
+Get rid of the need for intostring() (in addition to tostring()), and having to
+place .c_str() after tostring() in rLog calls.
+
+The former is necessary because of some problem with disambiguating which
+operator<<(ostream,T) to use when Event is being output, so intostring() calls
+T.operator<<(ostream) explicitly. This problem seems to exist only for Events.
+
+It should be possible to solve the latter by returning char* from tostring()
+rather than std::string.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.issues/8a14b4849071f910/new/1221008555.M667846P30017Q17.cole	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,9 @@
+From: Dmitriy Morozov <morozov@cs.duke.edu>
+Date: Thu, 10 Jan 2008 04:36:03 -0500
+State: resolved
+Subject: Remove maintenance of "lazy decomposition"
+Message-Id: <8a14b4849071f910-0-artemis@metatron>
+resolution: fixed
+
+The maintenance of "lazy decomposition" (added in [a0736dd3c671]) is
+incorrect (due to original theoretical errors). Remove it completely.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.issues/8a14b4849071f910/new/1229837212.M576947P31212Q2.rufus	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,9 @@
+From: Dmitriy Morozov <dmitriy@mrzv.org>
+Date: Sat, 20 Dec 2008 21:26:52
+Subject: properties changes (state, resolution)
+Message-Id: <8a14b4849071f910-c82a77e7b320c7e8-artemis@rufus>
+References: <8a14b4849071f910-0-artemis@metatron>
+In-Reply-To: <8a14b4849071f910-0-artemis@metatron>
+
+state=resolved
+resolution=fixed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.issues/8aa25bcae639fc99/new/1221008555.M674695P30017Q18.cole	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,8 @@
+From: Dmitriy Morozov <morozov@cs.duke.edu>
+Date: Fri, 04 Apr 2008 11:18:00
+State: fixed
+Subject: Switch in the pairing in Case 1.2
+Message-Id: <8aa25bcae639fc99-0-artemis@moscow>
+
+If simplex i is unpaired in Case 1.2, while i+1 is paired with l, and R[i,l]=1
+there is a switch in the pairing in Case 1.2.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.issues/8aa25bcae639fc99/new/1221008555.M677989P30017Q19.cole	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,8 @@
+From: Dmitriy Morozov <morozov@cs.duke.edu>
+Date: Fri, 04 Apr 2008 16:16:41
+Subject: Handled but mislabeled
+Message-Id: <8aa25bcae639fc99-bbca170318887f06-artemis@moscow>
+References: <8aa25bcae639fc99-0-artemis@moscow>
+In-Reply-To: <8aa25bcae639fc99-0-artemis@moscow>
+
+The situation is already handled in the code, but was mislabeled as Case 1.1.2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.issues/8aa25bcae639fc99/new/1221008555.M679929P30017Q20.cole	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,8 @@
+From: Dmitriy Morozov <morozov@cs.duke.edu>
+Date: Fri, 04 Apr 2008 16:17:10
+Subject: properties changes (state)
+Message-Id: <8aa25bcae639fc99-a4a82c4ab8c0f536-artemis@moscow>
+References: <8aa25bcae639fc99-0-artemis@moscow>
+In-Reply-To: <8aa25bcae639fc99-0-artemis@moscow>
+
+state=fixed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.issues/91986229a564f7e0/new/1221008555.M732706P30017Q24.cole	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,8 @@
+From: Dmitriy Morozov <morozov@cs.duke.edu>
+Date: Thu, 21 Feb 2008 04:23:29 -0500
+State: fixed
+Subject: More elabroate domain in avida-landscape
+Message-Id: <91986229a564f7e0-0-artemis@metatron>
+
+Try minimum spanning tree (i.e., take only negative edges from avida-distance).
+Try a combination: all edges up to a certain (realtively small) length + MST.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.issues/91986229a564f7e0/new/1221008555.M735706P30017Q25.cole	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,8 @@
+From: Dmitriy Morozov <morozov@cs.duke.edu>
+Date: Mon, 25 Feb 2008 07:09:30 -0500
+Subject: properties changes (state)
+Message-Id: <91986229a564f7e0-9886ad2e18d12feb-artemis@metatron>
+References: <91986229a564f7e0-0-artemis@metatron>
+In-Reply-To: <91986229a564f7e0-0-artemis@metatron>
+
+state=fixed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.issues/957a589d7c6c3fa8/new/1230356422.M300560P11955Q1.rufus	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,11 @@
+From: Dmitriy Morozov <dmitriy@mrzv.org>
+Date: Fri, 26 Dec 2008 21:34:29
+State: new
+Subject: namespace dionysus
+Message-Id: <957a589d7c6c3fa8-0-artemis@rufus>
+category: installation
+
+Put everything in namespace dionysus. Besides making things more organized, it
+will also allow us to get rid of the problem of having to typedef Simplex<...>
+to Smplx. If it were in dionysus namespace, then 
+`typedef dionysus::Simplex<...> Simplex;` would work.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.issues/957a589d7c6c3fa8/new/1239235561.M108369P10645Q1.cole	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,7 @@
+From: Dmitriy Morozov <dmitriy@mrzv.org>
+Date: Wed, 08 Apr 2009 17:06:01
+Subject: changed properties (category=installation)
+Message-Id: <957a589d7c6c3fa8-e9829eb7352224cf-artemis@cole>
+References: <957a589d7c6c3fa8-0-artemis@rufus>
+In-Reply-To: <957a589d7c6c3fa8-0-artemis@rufus>
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.issues/96b51b44f7764f5c/new/1221008595.M830007P30168Q1.cole	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,8 @@
+From: Dmitriy Morozov <dmitriy@mrzv.org>
+Date: Tue, 09 Sep 2008 18:03:00
+State: resolved
+Subject: Boost 1.36
+Message-Id: <96b51b44f7764f5c-0-artemis@cole>
+resolution: fixed
+
+Make the software compile with Boost 1.36
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.issues/96b51b44f7764f5c/new/1229837196.M796227P31208Q2.rufus	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,9 @@
+From: Dmitriy Morozov <dmitriy@mrzv.org>
+Date: Sat, 20 Dec 2008 21:26:36
+Subject: properties changes (state, resolution)
+Message-Id: <96b51b44f7764f5c-85f856488e2d4827-artemis@rufus>
+References: <96b51b44f7764f5c-0-artemis@cole>
+In-Reply-To: <96b51b44f7764f5c-0-artemis@cole>
+
+state=resolved
+resolution=fixed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.issues/b5d8a8403ae3a0d2/new/1221008555.M687915P30017Q21.cole	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,7 @@
+From: Dmitriy Morozov <morozov@cs.duke.edu>
+Date: Thu, 21 Feb 2008 04:54:00 -0500
+State: fixed
+Subject: Segfault in tests/geometry/test-kinetic-sort.cpp
+Message-Id: <b5d8a8403ae3a0d2-0-artemis@metatron>
+
+test-kinetic-sort segfaults when we subscribe to geometry/simulator RLog channel.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.issues/b5d8a8403ae3a0d2/new/1221008555.M690386P30017Q22.cole	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,8 @@
+From: Dmitriy Morozov <morozov@cs.duke.edu>
+Date: Fri, 22 Feb 2008 13:05:55 -0500
+Subject: properties changes (state)
+Message-Id: <b5d8a8403ae3a0d2-a0288cca74095157-artemis@metatron>
+References: <b5d8a8403ae3a0d2-0-artemis@metatron>
+In-Reply-To: <b5d8a8403ae3a0d2-0-artemis@metatron>
+
+state=fixed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.issues/c420501cc5285bbc/new/1221008555.M610599P30017Q9.cole	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,8 @@
+From: Dmitriy Morozov <morozov@cs.duke.edu>
+Date: Tue, 26 Feb 2008 05:22:56 -0500
+State: fixed
+Subject: Non-optimized CGAL runtime error
+Message-Id: <c420501cc5285bbc-0-artemis@metatron>
+
+If the code is compiled with optimizations off or with debug on, CGAL gives a
+runtime error.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.issues/c420501cc5285bbc/new/1221008555.M614720P30017Q10.cole	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,8 @@
+From: Dmitriy Morozov <morozov@cs.duke.edu>
+Date: Tue, 26 Feb 2008 08:00:23 -0500
+Subject: properties changes (state)
+Message-Id: <c420501cc5285bbc-e983173b6cd399a6-artemis@metatron>
+References: <c420501cc5285bbc-0-artemis@metatron>
+In-Reply-To: <c420501cc5285bbc-0-artemis@metatron>
+
+state=fixed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.issues/c420501cc5285bbc/new/1221008555.M618213P30017Q11.cole	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,10 @@
+From: Dmitriy Morozov <morozov@cs.duke.edu>
+Date: Tue, 26 Feb 2008 08:00:50 -0500
+Subject: Fixed by adding CGAL_NO_ASSERTIONS
+Message-Id: <c420501cc5285bbc-d75d85d67d421f7e-artemis@metatron>
+References: <c420501cc5285bbc-0-artemis@metatron>
+In-Reply-To: <c420501cc5285bbc-0-artemis@metatron>
+
+I suspect the bug in CGAL (since everything works fine with CGAL_NO_ASSERTIONS
+set), so I disabled the offending assertion (and all the rest of them) by
+setting a CXX flag in CMakeLists.txt.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.issues/c420501cc5285bbc/new/1221008555.M619987P30017Q12.cole	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,8 @@
+From: Dmitriy Morozov <morozov@cs.duke.edu>
+Date: Wed, 19 Mar 2008 12:47:24 -0400
+Subject: Fixed in 0a18d6902a55
+Message-Id: <c420501cc5285bbc-db67b15857938f7b-artemis@metatron>
+References: <c420501cc5285bbc-0-artemis@metatron>
+In-Reply-To: <c420501cc5285bbc-0-artemis@metatron>
+
+Fixed by dealing with infinite simplices in 0a18d6902a55
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.issues/c420501cc5285bbc/new/1221008555.M621758P30017Q13.cole	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,8 @@
+From: Dmitriy Morozov <morozov@cs.duke.edu>
+Date: Wed, 19 Mar 2008 12:49:01 -0400
+Subject: Reopened for ar-vineyard
+Message-Id: <c420501cc5285bbc-8f74ccde6b3f0bea-artemis@metatron>
+References: <c420501cc5285bbc-0-artemis@metatron>
+In-Reply-To: <c420501cc5285bbc-0-artemis@metatron>
+
+Fix for ar-vineyard like for alphashapes
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.issues/c420501cc5285bbc/new/1221008555.M623619P30017Q14.cole	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,8 @@
+From: Dmitriy Morozov <morozov@cs.duke.edu>
+Date: Wed, 19 Mar 2008 12:49:47 -0400
+Subject: properties changes (state)
+Message-Id: <c420501cc5285bbc-ef5f506b45aba335-artemis@metatron>
+References: <c420501cc5285bbc-0-artemis@metatron>
+In-Reply-To: <c420501cc5285bbc-0-artemis@metatron>
+
+state=open
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.issues/c420501cc5285bbc/new/1221008555.M625407P30017Q15.cole	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,8 @@
+From: Dmitriy Morozov <morozov@cs.duke.edu>
+Date: Wed, 19 Mar 2008 13:17:30 -0400
+Subject: Fixed for ar-vineyard
+Message-Id: <c420501cc5285bbc-feb676745fc16b8c-artemis@metatron>
+References: <c420501cc5285bbc-8f74ccde6b3f0bea-artemis@metatron>
+In-Reply-To: <c420501cc5285bbc-8f74ccde6b3f0bea-artemis@metatron>
+
+Fixed for ar-vineyard.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.issues/c664b2f69b5f6ea3/new/1221008555.M741909P30017Q26.cole	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,8 @@
+From: Dmitriy Morozov <morozov@cs.duke.edu>
+Date: Thu, 28 Feb 2008 05:33:34 -0500
+State: fixed
+Subject: Two simulators
+Message-Id: <c664b2f69b5f6ea3-0-artemis@metatron>
+
+Consider using two simulators instead of one to make sure that trajectory
+changes are processed before simplex swaps.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.issues/c664b2f69b5f6ea3/new/1221008555.M745065P30017Q27.cole	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,8 @@
+From: Dmitriy Morozov <morozov@cs.duke.edu>
+Date: Sat, 01 Mar 2008 04:45:05 -0500
+Subject: properties changes (state)
+Message-Id: <c664b2f69b5f6ea3-f8bf16bdff01098d-artemis@metatron>
+References: <c664b2f69b5f6ea3-0-artemis@metatron>
+In-Reply-To: <c664b2f69b5f6ea3-0-artemis@metatron>
+
+state=fixed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.issues/c664b2f69b5f6ea3/new/1221008555.M746854P30017Q28.cole	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,8 @@
+From: Dmitriy Morozov <morozov@cs.duke.edu>
+Date: Sat, 01 Mar 2008 04:45:29 -0500
+Subject: Fixed in f236c7d659d0
+Message-Id: <c664b2f69b5f6ea3-a1742f0eb7b5e1c0-artemis@metatron>
+References: <c664b2f69b5f6ea3-0-artemis@metatron>
+In-Reply-To: <c664b2f69b5f6ea3-0-artemis@metatron>
+
+Fixed in f236c7d659d0.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.issues/cd79223a108d3900/new/1221008555.M511949P30017Q2.cole	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,9 @@
+From: Dmitriy Morozov <morozov@cs.duke.edu>
+Date: Fri, 22 Feb 2008 18:39:31 -0500
+State: new
+Subject: Incorrect sign_at() in UPolynomial<double>
+Message-Id: <cd79223a108d3900-0-artemis@metatron>
+category: kinetic
+
+UPolynomial<double>::sign_at() reports -1 as the sign of -2*x + 4 at x = 2. 
+Should be 0.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.issues/cd79223a108d3900/new/1239235469.M178107P10641Q1.cole	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,7 @@
+From: Dmitriy Morozov <dmitriy@mrzv.org>
+Date: Wed, 08 Apr 2009 17:04:29
+Subject: changed properties (category=kinetic)
+Message-Id: <cd79223a108d3900-8e019293f49e27ce-artemis@cole>
+References: <cd79223a108d3900-0-artemis@metatron>
+In-Reply-To: <cd79223a108d3900-0-artemis@metatron>
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.issues/cff004eda75a26c2/new/1221008555.M586932P30017Q7.cole	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,9 @@
+From: Dmitriy Morozov <morozov@cs.duke.edu>
+Date: Tue, 11 Mar 2008 04:05:25 -0400
+State: fixed
+Subject: Scale fitness
+Message-Id: <cff004eda75a26c2-0-artemis@metatron>
+
+When computing fitness persistence, divide all values by the maximum fitness.
+That way it's possible to compare persistence diagrams for runs in different
+environments.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.issues/cff004eda75a26c2/new/1221008555.M591027P30017Q8.cole	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,8 @@
+From: Dmitriy Morozov <morozov@cs.duke.edu>
+Date: Fri, 14 Mar 2008 18:34:41 -0400
+Subject: properties changes (state)
+Message-Id: <cff004eda75a26c2-ad10cae14deb092d-artemis@metatron>
+References: <cff004eda75a26c2-0-artemis@metatron>
+In-Reply-To: <cff004eda75a26c2-0-artemis@metatron>
+
+state=fixed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.issues/d2ab07329c3588ca/new/1221008555.M528839P30017Q3.cole	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,8 @@
+From: Dmitriy Morozov <morozov@cs.duke.edu>
+Date: Wed, 27 Feb 2008 16:30:57 -0500
+State: fixed
+Subject: Segfault with topology/vineyard log enabled
+Message-Id: <d2ab07329c3588ca-0-artemis@metatron>
+
+The code segfaults in Vineyard::record_knee() if we subscribe to
+topology/vineyard log.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.issues/d2ab07329c3588ca/new/1221008555.M531575P30017Q4.cole	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,8 @@
+From: Dmitriy Morozov <morozov@cs.duke.edu>
+Date: Sat, 01 Mar 2008 04:46:46 -0500
+Subject: properties changes (state)
+Message-Id: <d2ab07329c3588ca-8c184b421f538482-artemis@metatron>
+References: <d2ab07329c3588ca-0-artemis@metatron>
+In-Reply-To: <d2ab07329c3588ca-0-artemis@metatron>
+
+state=fixed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.issues/d2ab07329c3588ca/new/1221008555.M533535P30017Q5.cole	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,8 @@
+From: Dmitriy Morozov <morozov@cs.duke.edu>
+Date: Sat, 01 Mar 2008 04:46:51 -0500
+Subject: Fixed in abba2950aced
+Message-Id: <d2ab07329c3588ca-fa65c35dfff6366f-artemis@metatron>
+References: <d2ab07329c3588ca-0-artemis@metatron>
+In-Reply-To: <d2ab07329c3588ca-0-artemis@metatron>
+
+Fixed in abba2950aced
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.issues/de674a2ac5f6c18c/new/1229837097.M859247P31105Q1.rufus	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,11 @@
+From: Dmitriy Morozov <dmitriy@mrzv.org>
+Date: Sat, 20 Dec 2008 21:21:53
+State: new
+Subject: Specialize ChainWrapper<C>::add() for linked lists
+Message-Id: <de674a2ac5f6c18c-0-artemis@rufus>
+category: functionality
+
+The current implementation of add() in ChainWrapper is container agnostic: it
+uses a temporary container, and then swaps it into place. There should be a
+specialized add() for linked lists (in particular, List from circular_list.h)
+since it is would likely be more efficient then the generic one.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.issues/de674a2ac5f6c18c/new/1239235533.M711045P10644Q1.cole	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,7 @@
+From: Dmitriy Morozov <dmitriy@mrzv.org>
+Date: Wed, 08 Apr 2009 17:05:33
+Subject: changed properties (category=functionality)
+Message-Id: <de674a2ac5f6c18c-ba280aee1f76cd3f-artemis@cole>
+References: <de674a2ac5f6c18c-0-artemis@rufus>
+In-Reply-To: <de674a2ac5f6c18c-0-artemis@rufus>
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.issues/e6d9deee8fbd81a5/new/1221008555.M541088P30017Q6.cole	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,7 @@
+From: Dmitriy Morozov <morozov@cs.duke.edu>
+Date: Wed, 06 Feb 2008 16:45:13 -0500
+State: new
+Subject: About section in README
+Message-Id: <e6d9deee8fbd81a5-0-artemis@metatron>
+
+Add "About" section to the README file.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.issues/e6f52c44ef26f4a7/new/1239399291.M841173P26652Q1.cole	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,10 @@
+From: Dmitriy Morozov <dmitriy@mrzv.org>
+Date: Fri, 10 Apr 2009 14:33:18
+State: new
+Subject: Intrusive containers for ZigzagPersistence
+Message-Id: <e6f52c44ef26f4a7-0-artemis@cole>
+category: efficiency
+
+Use Boost's intrusive containers to store rows in ZigzagPersistence. This
+should get rid of the inefficiencies associated with the simplex removal
+(through ZigzagPersistence::remove()).
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.issues/e8659770a6824e01/new/1221008555.M475248P30017Q1.cole	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,10 @@
+From: Dmitriy Morozov <morozov@cs.duke.edu>
+Date: Wed, 09 Jan 2008 13:57:57 -0500
+State: new
+Subject: Change cout to rlog
+Message-Id: <e8659770a6824e01-0-artemis@metatron>
+
+In examples/grid/grid2Dvineyard.hpp (and in examples in general),
+change the use of std::cout for logging information to rlog.
+Naturally, create appropriate channels even if they are of only local
+use.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.issues/ebda8db3f9908e33/new/1221008555.M637662P30017Q16.cole	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,9 @@
+From: Dmitriy Morozov <morozov@cs.duke.edu>
+Date: Mon, 25 Feb 2008 11:29:27 -0500
+State: resolved
+Subject: Efficient EventQueue
+Message-Id: <ebda8db3f9908e33-0-artemis@metatron>
+category: kinetic
+resolution: fixed
+
+Change EventQueue to an efficient implementation, e.g., using a Fibonacci heap.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.issues/ebda8db3f9908e33/new/1239235517.M200551P10643Q1.cole	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,7 @@
+From: Dmitriy Morozov <dmitriy@mrzv.org>
+Date: Wed, 08 Apr 2009 17:05:17
+Subject: changed properties (category=kinetic)
+Message-Id: <ebda8db3f9908e33-f094f3f4c111054c-artemis@cole>
+References: <ebda8db3f9908e33-0-artemis@metatron>
+In-Reply-To: <ebda8db3f9908e33-0-artemis@metatron>
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.issues/ebda8db3f9908e33/new/1265568370.M269870P17954Q1.vine	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,9 @@
+From: Dmitriy Morozov <dmitriy@mrzv.org>
+Date: Sun, 07 Feb 2010 10:45:04
+Subject: Switched to Boost's MultiIndex
+Message-Id: <ebda8db3f9908e33-e9c51216e26b5e19-artemis@vine>
+References: <ebda8db3f9908e33-0-artemis@metatron>
+In-Reply-To: <ebda8db3f9908e33-0-artemis@metatron>
+
+Switched EventQueue to Boost's MultiIndex with a sequence and ordered_non_unique
+indexing.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.issues/ebda8db3f9908e33/new/1265605942.M759644P4728Q1.vine	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,9 @@
+From: Dmitriy Morozov <dmitriy@mrzv.org>
+Date: Sun, 07 Feb 2010 21:11:12
+Subject: Binary heap
+Message-Id: <ebda8db3f9908e33-e780beb990f99293-artemis@vine>
+References: <ebda8db3f9908e33-0-artemis@metatron>
+In-Reply-To: <ebda8db3f9908e33-0-artemis@metatron>
+
+Changed EventQueue representation to a binary heap. Used code developed by Danny
+Tarlow and Yanbin Lu.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.issues/f6496b3e37275888/new/1229837161.M623187P31203Q1.rufus	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,11 @@
+From: Dmitriy Morozov <dmitriy@mrzv.org>
+Date: Sat, 20 Dec 2008 21:24:59
+State: new
+Subject: Add field arithmetic
+Message-Id: <f6496b3e37275888-0-artemis@rufus>
+category: functionality
+
+Add support for field arithmetic (i.e., not only Z_2 field as it is now).
+However, make sure that there is a specialization of ChainWrapper<C>::add() for
+Z_2 field (since it can be made much more efficient both in terms of space and
+time).
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.issues/f6496b3e37275888/new/1239235438.M855747P10635Q1.cole	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,7 @@
+From: Dmitriy Morozov <dmitriy@mrzv.org>
+Date: Wed, 08 Apr 2009 17:03:58
+Subject: changed properties (category=functionality)
+Message-Id: <f6496b3e37275888-937e7690680da5fe-artemis@cole>
+References: <f6496b3e37275888-0-artemis@rufus>
+In-Reply-To: <f6496b3e37275888-0-artemis@rufus>
+
--- a/CMakeLists.txt	Fri Aug 24 16:58:25 2007 -0400
+++ b/CMakeLists.txt	Tue Jun 27 09:37:05 2017 -0700
@@ -1,95 +1,88 @@
-project						(Dionysus)
+project                     (Dionysus)
+cmake_minimum_required      (VERSION 2.4)
 
-option						(debug				"Build Dionysus with debugging on" 		OFF)
-option						(counters			"Build Dionysus with counters on" 		OFF)
-option						(optimize			"Build Dionysus with optimization"		ON)
+option                      (logging            "Build Dionysus with logging on"        OFF)
+option                      (counters           "Build Dionysus with counters on"       OFF)
+option                      (debug              "Build Dionysus with debugging on"      OFF)
+option                      (optimize           "Build Dionysus with optimization"      ON)
+option                      (use_cgal           "Build examples and python bindings that use CGAL"       ON)
+option                      (use_dsrpdb         "Build examples that use DSR-PDB"       OFF)
+option                      (use_synaps         "Build examples that use SYNAPS"        OFF)
 
 # Find everything that's always required
-find_package				(Boost REQUIRED)
-find_package				(Doxygen)
-find_library				(dsrpdb_LIBRARY 			NAMES dsrpdb)
-find_path					(dsrpdb_INCLUDE_DIR 		dsrpdb/Protein.h)
-
-set							(libraries 					${libraries}
-														${dsrpdb_LIBRARY})
+find_package                (Boost REQUIRED COMPONENTS program_options python serialization signals)
+find_package                (Doxygen)
+if                          (use_dsrpdb)
+    find_library            (dsrpdb_LIBRARY             NAMES dsrpdb)
+    find_path               (dsrpdb_INCLUDE_DIR         dsrpdb/Protein.h)
+endif                       (use_dsrpdb)
 
-#CGAL
-execute_process				(COMMAND ${CMAKE_MAKE_PROGRAM} -f ${CMAKE_CURRENT_SOURCE_DIR}/FindCGAL.Makefile libpaths
-							 OUTPUT_VARIABLE cgal_libpaths)
-execute_process				(COMMAND ${CMAKE_MAKE_PROGRAM} -f ${CMAKE_CURRENT_SOURCE_DIR}/FindCGAL.Makefile ldflags
-							 OUTPUT_VARIABLE cgal_ldflags)
-execute_process				(COMMAND ${CMAKE_MAKE_PROGRAM} -f ${CMAKE_CURRENT_SOURCE_DIR}/FindCGAL.Makefile cxxflags
-							 OUTPUT_VARIABLE cgal_cxxflags)
-execute_process				(COMMAND ${CMAKE_MAKE_PROGRAM} -f ${CMAKE_CURRENT_SOURCE_DIR}/FindCGAL.Makefile libpath
-							 OUTPUT_VARIABLE cgal_libpath)
-#string						(REPLACE "\n" "" cgal_libpaths	${cgal_libpaths})
-#string						(REPLACE "\n" "" cgal_ldflags 	${cgal_ldflags})
-string						(REPLACE "\n" "" cgal_cxxflags 	${cgal_cxxflags})
-string						(REPLACE "\n" "" cgal_libpath 	${cgal_libpath})
-add_definitions				(${cgal_cxxflags})
-find_library				(cgal_LIBRARY				NAMES CGAL
-														PATHS ${cgal_libpath})
-find_library				(core_LIBRARY				NAMES CGALcore++
-														PATHS ${cgal_libpath})
-find_library				(mpfr_LIBRARY				NAMES mpfr)
-find_library				(gmp_LIBRARY				NAMES gmp)
-find_library				(gmpxx_LIBRARY				NAMES gmpxx)
-find_library				(m_LIBRARY					NAMES m)
-
-set							(cgal_libraries 			${cgal_LIBRARY} 
-														${core_LIBRARY}
-														${mpfr_LIBRARY} 
-														${gmp_LIBRARY} 
-														${gmpxx_LIBRARY} 
-														${m_LIBRARY})
+# CGAL
+if                          (use_cgal)
+    find_package            (CGAL QUIET)
+endif                       (use_cgal)
+#add_definitions             (-DCGAL_NO_ASSERTIONS -DCGAL_NO_PRECONDITIONS)
 
 # SYNAPS
-add_definitions				(-DBOOST_UBLAS_TYPE_CHECK=0)
-find_library				(synaps_LIBRARY				NAMES synaps)
-set							(synaps_libraries			${synaps_LIBRARY}
-														${gmp_LIBRARY}
-														${gmpxx_LIBRARY})
+if                          (use_synaps)
+    add_definitions         (-DBOOST_UBLAS_TYPE_CHECK=0)
+    find_library            (synaps_LIBRARY             NAMES synaps)
+    set                     (synaps_libraries           ${synaps_LIBRARY}
+                                                        ${gmp_LIBRARY}
+                                                        ${gmpxx_LIBRARY})
+endif                       (use_synaps)
 
 # Debugging
-if							(debug)
-	find_library			(cwd_LIBRARY				NAMES cwd)
-	find_path				(cwd_INCLUDE_DIR			libcwd/debug.h)
-	set 					(cwd_INCLUDE_DIR			${cwd_INCLUDE_DIR}/libcwd)
-	add_definitions			(-DCWDEBUG -g)
-	set						(external_sources			${CMAKE_CURRENT_SOURCE_DIR}/src/debug.cpp)
-	set						(libraries 					${libraries} ${cwd_LIBRARY})
-else						(debug)
-	add_definitions			(-DNDEBUG)
-endif						(debug)
+if                          (debug)
+    if                      (optimize)
+            set             (cxx_flags                  ${CMAKE_CXX_FLAGS_RELWITHDEBINFO})
+    else                    (optimize)
+            set             (cxx_flags                  ${CMAKE_CXX_FLAGS_DEBUG})
+    endif                   (optimize)
+else                        (debug)
+    if                      (optimize)
+            set             (cxx_flags                  ${CMAKE_CXX_FLAGS_RELEASE})
+    else                    (optimize)
+            set             (cxx_flags                  ${CMAKE_CXX_FLAGS})
+    endif                   (optimize)
+endif                       (debug)
+add_definitions             (${cxx_flags})
+
+# Fix the XCode bug
+add_definitions             (-ftemplate-depth=256)
+
+
+# Logging
+if                          (logging)
+    find_library            (rlog_LIBRARY               NAMES rlog)
+    find_path               (rlog_INCLUDE_DIR           rlog/rlog.h)
+    set                     (rlog_INCLUDE_DIR           ${rlog_INCLUDE_DIR})
+    add_definitions         (-DLOGGING -DRLOG_COMPONENT=dionysus)
+    set                     (libraries                  ${libraries} ${rlog_LIBRARY})
+endif                       (logging)
 
 # Counters
-if							(counters)
-	add_definitions			(-DCOUNTERS)
-endif						(counters)
-
-# Optimization
-if							(optimize GREATER 0)
-	add_definitions			(-O${optimize})
-elseif						(optimize)
-	add_definitions			(-O)
-endif						(optimize)
-endif						(optimize GREATER 0)
-
+if                          (counters)
+    add_definitions         (-DCOUNTERS)
+endif                       (counters)
 
 # Set includes
-include_directories			(${CMAKE_CURRENT_BINARY_DIR}
-							 ${CMAKE_CURRENT_SOURCE_DIR}/include
-							 ${Boost_INCLUDE_DIR}
-							 ${dsrpdb_INCLUDE_DIR}
-							 ${cwd_INCLUDE_DIR})
+include_directories         (${CMAKE_CURRENT_BINARY_DIR}
+                             ${CMAKE_CURRENT_SOURCE_DIR}/include
+                             ${Boost_INCLUDE_DIR}
+                             ${dsrpdb_INCLUDE_DIR}
+                             ${cwd_INCLUDE_DIR}
+                             ${rlog_INCLUDE_DIR})
 
 # Doxygen (FIXME)
-if							(DOXYGEN_FOUND)
-#	add_custom_target 		(docs ALL 
-#							${DOXYGEN_EXECUTABLE} Doxyfile
-#							DEPENDS Doxyfile)
-endif						(DOXYGEN_FOUND)
+if                          (DOXYGEN_FOUND)
+#   add_custom_target       (docs ALL
+#                           ${DOXYGEN_EXECUTABLE} Doxyfile
+#                           DEPENDS Doxyfile)
+endif                       (DOXYGEN_FOUND)
 
-# Set external sources
-add_subdirectory			(examples)
-add_subdirectory			(tests)
+# Process subdirectories
+add_subdirectory            (examples)
+add_subdirectory            (tests)
+add_subdirectory            (tools)
+add_subdirectory            (bindings)
--- a/FindCGAL.Makefile	Fri Aug 24 16:58:25 2007 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,15 +0,0 @@
-include $(CGAL_MAKEFILE)
-
-all: libpath libpaths ldflags cxxflags
-
-libpath:
-	@echo "$(CGAL_LIB_DIR)"
-
-libpaths:
-	@echo "$(CGAL_LIBPATHFLAGS)"
-
-ldflags:
-	@echo "$(CGAL_LDFLAGS)"
-
-cxxflags:
-	@echo "$(CGAL_CXXFLAGS)"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LEGAL	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,15 @@
+Copyright (C) 2006-2017  Dmitriy Morozov <dmitriy@mrzv.org>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LICENSE	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,280 @@
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                            NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                     END OF TERMS AND CONDITIONS
--- a/README	Fri Aug 24 16:58:25 2007 -0400
+++ b/README	Tue Jun 27 09:37:05 2017 -0700
@@ -1,28 +1,42 @@
-Dependencies
-  CGAL-3.3 -    for alpha-shapes and kinetic data structures
-  DSR-PDB -     for reading in PDB files
-  cmake -       for controlling the build process
-  boost -       great set of C++ libraries
-  Doxygen -     for building documentation
-  libcwd -      for debugging only (is not needed by default)
-  synaps -      for solving polynomial (for kinetic kernel), which in turn requires GMP
+% Dionysus README
+% Dmitriy Morozov
+
+## Dependencies
 
-Configuration
-  The path to CGAL's Makefile is expected to be set in $CGAL_MAKEFILE, the rest
-  is just usual CMake configuration
+  * [CGAL]-3.4 ---  for alpha-shapes and kinetic data structures
+  * [DSR-PDB] ---   for reading in PDB files (if use_dsrpdb is turned on in cmake)
+  * [CMake] ---     for controlling the build process
+  * [boost] ---     great set of C++ libraries
+  * [Doxygen] ---   for building documentation
+  * [rlog] ---      for logging only (is not needed by default)
+  * [SYNAPS] ---    for solving polynomials (for kinetic kernel), which in turn requires GMP
 
-Building
+[CGAL]:         http://www.cgal.org
+[DSR-PDB]:      http://www.salilab.org/~drussel/pdb/
+[CMake]:        http://www.cmake.org
+[boost]:        http://www.boost.org
+[Doxygen]:      http://www.stack.nl/~dimitri/doxygen/
+[rlog]:         http://www.arg0.net/rlog
+[SYNAPS]:       http://synaps.inria.fr/
+
+## Building
   To build examples, create a directory build (to keep everything in one place),
   go to that directory and run cmake and make:
-  mkdir build
-  cd build
-  cmake ..   (or "ccmake .." if you want a curses interface)
-  make
+
+    mkdir build
+    cd build
+    cmake ..   (or "ccmake .." if you want a curses interface)
+    make
   
-  In the cmake line you can provide -Ddebug:bool=on to turn on debugging,
-  -Dcounters:bool=on to turn on counters, -Doptimize:int=3 would set
-  optimization to -O3. All of this can be set using a text user interface by
-  running ccmake instead of cmake.
+  In the cmake line you can provide `-Ddebug:bool=on` to turn on debugging,
+  `-Dcounters:bool=on` to turn on counters, `-Doptimize:bool=on` to turn on
+  optimization, `-Duse_dsrpdb:bool=on` to turn on reading PDB files.  Depending on
+  the combination of debugging and optimization, a particular `CMAKE_CXX_FLAGS*`
+  is chosen.  All of this can be set using a text user interface by running
+  `ccmake` instead of `cmake`.
 
-Author
-  Dmitriy Morozov <morozov@cs.duke.edu>
+  When compiling on a 64 bit platform (with Boost 1.34) add
+  `-DBOOST_NO_INTRINSIC_INT64_T` to `CMAKE_CXX_FLAGS`.
+
+## Author
+  Dmitriy Morozov <dmitriy@mrzv.org>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bindings/CMakeLists.txt	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,1 @@
+add_subdirectory			(python)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bindings/python/CMakeLists.txt	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,53 @@
+find_package                (PythonLibs)
+link_libraries              (${PYTHON_LIBRARIES})
+include_directories         (${PYTHON_INCLUDE_PATH})
+link_libraries              (${Boost_PYTHON_LIBRARY})
+
+# currently can't build bindings with counters support, eventually FIXME
+remove_definitions          (-DCOUNTERS)
+set                         (sources
+                                                dionysus.cpp 
+                                                filtration.cpp
+                                                chain.cpp
+                                                static-persistence.cpp
+                                                dynamic-persistence.cpp
+                                                persistence-diagram.cpp
+                                                simplex.cpp
+                                                birthid.cpp
+                                                zigzag-persistence.cpp
+                                                cohomology-persistence.cpp
+                                                rips.cpp
+                                                distances.cpp
+                            )
+set                         (bindings_libraries ${libraries})
+
+if                          (CGAL_FOUND)
+    include                 (${CGAL_USE_FILE})
+
+    set                     (sources            ${sources}
+                                                alphashapes3d.cpp
+                                                alphashapes2d.cpp)
+    add_definitions         (${CGAL_CXX_FLAGS_INIT})
+    include_directories     (${CGAL_INCLUDE_DIRS})
+
+    link_libraries          (${CGAL_LIBRARY} ${CGAL_3RD_PARTY_LIBRARIES})
+else                            (CGAL_FOUND)
+    message(STATUS "CGAL not found, alphashape bindings will not be built")
+    add_definitions         (-DNO_CGAL)
+endif                       (CGAL_FOUND)
+
+add_library                 (_dionysus SHARED   ${sources})
+target_link_libraries       (_dionysus          ${libraries})
+
+
+# Python files and the symlink
+add_custom_target           (dionysus ALL
+                             ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/dionysus ${CMAKE_CURRENT_BINARY_DIR}/dionysus
+                             DEPENDS            dionysus/__init__.py
+                                                dionysus/distances.py
+                            )
+
+get_target_property         (_dionysus_location _dionysus LOCATION)
+add_custom_target           (dionysus-link ALL 
+                             ${CMAKE_COMMAND} -E create_symlink ${_dionysus_location} ${CMAKE_CURRENT_BINARY_DIR}/dionysus/_dionysus.so
+                             DEPENDS _dionysus)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bindings/python/alphashapes2d.cpp	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,44 @@
+// Wrap includes into namespaces to avoid nameclashes
+#include "../../examples/alphashapes/alphashapes2d.h" 
+
+#include <boost/python.hpp>
+#include <boost/python/stl_iterator.hpp>
+namespace bp = boost::python;
+
+#include "simplex.h"                // defines SimplexVD, Vertex, and Data
+namespace dp = dionysus::python;
+
+
+void fill_alpha2D_complex(bp::object points, bp::object complex)
+{
+    typedef     std::map<AlphaSimplex2D::Vertex, unsigned>      ASPointMap;
+
+    Delaunay2D  Dt;
+    ASPointMap  point_map;
+    unsigned i = 0;
+    for (bp::stl_input_iterator<bp::list> pt = points; pt != bp::stl_input_iterator<bp::list>(); ++pt)
+    {
+        double x = bp::extract<double>((*pt)[0]);
+        double y = bp::extract<double>((*pt)[1]);
+        point_map[Dt.insert(Point(x,y))] = i++;
+    }
+
+    AlphaSimplex2D::SimplexSet simplices;
+    fill_simplex_set(Dt, simplices);
+
+    for (AlphaSimplex2D::SimplexSet::const_iterator cur = simplices.begin(); cur != simplices.end(); ++cur)
+    {
+        dp::SimplexVD s;
+        for (AlphaSimplex2D::VertexContainer::const_iterator vcur  = cur->vertices().begin(); 
+                                                             vcur != cur->vertices().end(); ++vcur)
+            s.add(point_map[*vcur]);
+        
+        s.data() = bp::object(std::make_pair(cur->value(), !cur->attached()));      // regular/critical rather than attached
+        complex.attr("append")(s);
+    }
+}
+
+void export_alphashapes2d()
+{
+    bp::def("fill_alpha2D_complex",       &fill_alpha2D_complex);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bindings/python/alphashapes3d.cpp	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,48 @@
+// Wrap includes into namespaces to avoid nameclashes
+#include "../../examples/alphashapes/alphashapes3d.h" 
+
+#include <boost/shared_ptr.hpp>
+#include <boost/python.hpp>
+#include <boost/python/stl_iterator.hpp>
+namespace bp = boost::python;
+
+#include "utils.h"
+#include "simplex.h"                // defines SimplexVD, Vertex, and Data
+namespace dp = dionysus::python;
+
+
+void fill_alpha3D_complex(bp::object points, bp::object complex)
+{
+    typedef     std::map<AlphaSimplex3D::Vertex, unsigned>      ASPointMap;
+
+    Delaunay3D  Dt;
+    ASPointMap  point_map;
+    unsigned i = 0;
+    for (bp::stl_input_iterator<bp::list> pt = points; pt != bp::stl_input_iterator<bp::list>(); ++pt)
+    {
+        double x = bp::extract<double>((*pt)[0]);
+        double y = bp::extract<double>((*pt)[1]);
+        double z = bp::extract<double>((*pt)[2]);
+        point_map[Dt.insert(Point(x,y,z))] = i++;
+    }
+
+    AlphaSimplex3D::SimplexSet simplices;
+    fill_simplex_set(Dt, simplices);
+
+    for (AlphaSimplex3D::SimplexSet::const_iterator cur = simplices.begin(); cur != simplices.end(); ++cur)
+    {
+        
+        dp::SimplexVD s;
+        for (AlphaSimplex3D::VertexContainer::const_iterator vcur  = cur->vertices().begin(); 
+                                                             vcur != cur->vertices().end(); ++vcur)
+            s.add(point_map[*vcur]);
+        
+        s.data() = bp::object(std::make_pair(cur->value(), !cur->attached()));      // regular/critical rather than attached
+        complex.attr("append")(s);
+    }
+}
+
+void export_alphashapes3d()
+{
+    bp::def("fill_alpha3D_complex",       &fill_alpha3D_complex);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bindings/python/birthid.cpp	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,10 @@
+#include "birthid.h"
+#include "optional.h"
+
+namespace dp = dionysus::python;
+
+void export_birthid()
+{
+    python_optional<dp::BirthID>();   
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bindings/python/birthid.h	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,15 @@
+#ifndef __PYTHON_BIRTHID_H__
+#define __PYTHON_BIRTHID_H__
+
+#include <boost/python.hpp>
+
+namespace dionysus {
+namespace python   {
+
+//typedef         int                             BirthID;
+//typedef         boost::python::long_            BirthID;
+typedef         boost::python::object           BirthID;
+
+} } // namespace dionysus::python
+
+#endif // __PYTHON_BIRTHID_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bindings/python/chain.cpp	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,29 @@
+#include <boost/iterator/indirect_iterator.hpp>
+
+#include <boost/python.hpp>
+#include <boost/python/iterator.hpp>
+#include <boost/python/return_internal_reference.hpp>
+namespace bp = boost::python;
+
+#include "chain.h"
+namespace dp = dionysus::python;
+
+
+template<class Chain>
+boost::indirect_iterator<typename Chain::const_iterator>    chain_begin(Chain& c)                  { return boost::make_indirect_iterator(c.begin()); }
+
+template<class Chain>
+boost::indirect_iterator<typename Chain::const_iterator>    chain_end(Chain& c)                    { return boost::make_indirect_iterator(c.end()); }
+
+void export_chain()
+{
+    bp::class_<dp::VSPChain>("SPChain")
+        .def("__iter__",    bp::range<bp::return_internal_reference<1> >(&chain_begin<dp::VSPChain>, &chain_end<dp::VSPChain>))
+        .def("__len__",     &dp::VSPChain::size)
+    ;
+    
+    bp::class_<dp::VDPChain>("DPChain")
+        .def("__iter__",    bp::range<bp::return_internal_reference<1> >(&chain_begin<dp::VDPChain>, &chain_end<dp::VDPChain>))
+        .def("__len__",     &dp::VDPChain::size)
+    ;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bindings/python/chain.h	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,11 @@
+#include <topology/chain.h>
+#include "static-persistence.h"
+#include "dynamic-persistence.h"
+
+namespace dionysus { 
+namespace python   {
+
+typedef     SPersistence::Chain                     VSPChain;
+typedef     DPersistenceChains::Chain               VDPChain;
+
+} }     // namespace dionysus::python
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bindings/python/cohomology-persistence.cpp	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,112 @@
+#include <topology/cohomology-persistence.h>
+
+#include <boost/python.hpp>
+#include <boost/python/stl_iterator.hpp>
+#include <boost/python/overloads.hpp>
+#include <boost/shared_ptr.hpp>
+namespace bp = boost::python;
+
+#include "cohomology-persistence.h"             // defines CohomPersistence
+#include "optional.h"
+namespace dp = dionysus::python;
+
+
+// CohomPersistence
+boost::shared_ptr<dp::CohomPersistence>     init_from_prime(unsigned p)
+{
+    dp::CohomPersistence::Field field(p);       // Zp
+
+    boost::shared_ptr<dp::CohomPersistence> chp(new dp::CohomPersistence(field));
+    return chp;
+}
+
+boost::shared_ptr<dp::CohomPersistence>     init()
+{
+    return init_from_prime(11);
+}
+
+
+bp::tuple                                   chp_add(dp::CohomPersistence& chp,
+                                                    bp::object bdry,
+                                                    dp::BirthID birth,
+                                                    bool store,
+                                                    bool image,
+                                                    bp::object coefficients)
+{
+    dp::CohomPersistence::SimplexIndex      i;
+    dp::CohomPersistence::Death             d;
+    dp::CohomPersistence::CocyclePtr        ccl;
+
+    if (coefficients)
+    {
+        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);
+    } 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);
+    }
+
+    return bp::make_tuple(i,d, 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)
+{ return ccl.zcolumn.end(); }
+
+// SimplexIndex
+template<class T>
+unsigned                            si_order(T& si)
+{
+    return si->order;
+}
+
+
+BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(add_overloads, add, 2, 4)
+
+void export_cohomology_persistence()
+{
+    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)
+    ;
+
+    bp::class_<dp::CohomPersistence>("CohomologyPersistence", bp::no_init)
+        .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)
+    ;
+
+    bp::class_<dp::CohomPersistence::Cocycle>("Cocycle", bp::no_init)
+        .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))
+    ;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bindings/python/cohomology-persistence.h	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,16 @@
+#ifndef __PYTHON_ZIGZAG_PERSISTENCE_H__
+#define __PYTHON_ZIGZAG_PERSISTENCE_H__
+
+#include <topology/cohomology-persistence.h>
+#include <boost/python.hpp>
+
+#include "birthid.h"
+
+namespace dionysus {
+namespace python   {
+
+typedef         CohomologyPersistence<BirthID>  CohomPersistence;
+
+} } // namespace dionysus::python
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bindings/python/dionysus.cpp	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,61 @@
+#include <utilities/log.h>
+#include <boost/python.hpp>
+#include "utils.h"
+
+namespace bp = boost::python;
+namespace dp = dionysus::python;
+
+void export_simplex();
+void export_filtration();
+void export_static_persistence();
+void export_dynamic_persistence_chains();
+void export_chain();
+void export_birthid();
+void export_zigzag_persistence();
+void export_cohomology_persistence();
+void export_point();
+void export_persistence_diagram();
+
+void export_rips();
+void export_pairwise_distances();
+
+#ifndef NO_CGAL
+void export_alphashapes2d();
+void export_alphashapes3d();
+#endif
+
+#ifdef LOGGING
+void            enable_log(std::string s)
+{
+    stdoutLog.subscribeTo(RLOG_CHANNEL(s.c_str()));
+}
+#endif
+
+BOOST_PYTHON_MODULE(_dionysus)
+{
+    bp::to_python_converter<std::pair<double, bool>, dp::PairToTupleConverter<double, bool> >();
+
+    export_simplex();
+    export_filtration();
+    export_static_persistence();
+    export_dynamic_persistence_chains();
+    export_chain();
+    export_point();
+    export_persistence_diagram();
+
+    export_birthid();
+    export_zigzag_persistence();
+    export_cohomology_persistence();
+
+    export_rips();
+    export_pairwise_distances();
+
+#ifndef NO_CGAL
+    export_alphashapes2d();
+    export_alphashapes3d();
+#endif
+
+#ifdef LOGGING
+    bp::def("enable_log",           &enable_log);
+#endif
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bindings/python/dionysus/__init__.py	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,69 @@
+from    _dionysus   import *
+from    distances   import l2, ExplicitDistances, points_file
+from    zigzag      import *
+from    adaptor     import *
+import  circular
+
+def init_with_none(self, iter, data = None):        # convenience: data defaults to None
+    self._cpp_init_(iter, data)
+
+def repr_with_data(self):
+    str = self._cpp_repr_()
+    if type(self.data) == float:
+        str += ' %f' % self.data
+    return str
+
+Simplex._cpp_init_ =    Simplex.__init__
+Simplex.__init__   =    init_with_none
+Simplex._cpp_repr_ =    Simplex.__repr__
+Simplex.__repr__   =    repr_with_data
+
+def Simplex_getinitargs(self):
+    return ([v for v in self.vertices], self.data)
+
+Simplex.__getinitargs__ = Simplex_getinitargs
+
+def data_cmp(s1, s2):
+    return cmp(s1.data, s2.data)
+
+def data_dim_cmp(s1,s2):
+    return cmp(s1.dimension(), s2.dimension()) or data_cmp(s1,s2)
+
+def dim_data_cmp(s1,s2):
+    return data_cmp(s1,s2) or cmp(s1.dimension(), s2.dimension())
+
+def vertex_dim_cmp(s1, s2):
+    return cmp(s1.dimension(), s2.dimension()) or vertex_cmp(s1, s2)
+
+def dim_cmp(s1, s2):
+    return cmp(s1.dimension(), s2.dimension())
+
+def fill_alpha_complex(points, simplices):
+    if   len(points[0]) == 2:           # 2D
+        fill_alpha2D_complex(points, simplices)
+    elif len(points[0]) == 3:           # 3D
+        fill_alpha3D_complex(points, simplices)
+
+def closure(simplices, k):
+    """Compute the k-skeleton of the closure of the list of simplices."""
+
+    res = set()
+
+    from    itertools   import combinations
+    for s in simplices:
+        for kk in xrange(1, k+2):
+            for face in combinations(s.vertices, min(s.dimension() + 1, kk)):
+                res.add(Simplex(face, s.data))
+
+    return list(res)
+
+_init_diagrams = init_diagrams
+
+def init_diagrams(p, f, evaluator = None, data = None):
+    if isinstance(p, StaticCohomologyPersistence):
+        return init_diagrams_from_adaptor(p,f, evaluator, data)
+
+    return _init_diagrams(p,f, evaluator, data)
+
+def read_points(filename):
+    return [p for p in points_file(filename)]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bindings/python/dionysus/adaptor.py	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,114 @@
+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 = []
+
+    def pair_simplices(self):
+        indices = []
+        for i,s in enumerate(self.filtration):
+            sc = self.subcomplex(s)
+            boundary = (indices[self.filtration(ss)] for ss in s.boundary)
+            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] = 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
+
+    def __len__(self):
+        return len(self.pairs)
+
+    def __iter__(self):
+        for i, (pair, subcomplex, cocycle) in enumerate(self.pairs):
+            if pair == i:       # unpaired
+                if subcomplex:
+                    yield APNode(i, self.pairs)
+            else:
+                if pair > i and subcomplex:
+                    yield APNode(i, self.pairs)
+                elif pair < i:
+                    pair_pair, pair_subcomplex, pair_cocycle = self.pairs[pair]
+                    if pair_subcomplex:
+                        yield APNode(i, self.pairs)
+
+    def make_simplex_map(self, filtration):
+        return APSimplexMap(filtration)
+
+class ImagePersistence(StaticCohomologyPersistence):
+    def __init__(self, filtration, subcomplex):
+        super(ImagePersistence, self).__init__(filtration, subcomplex = subcomplex)
+
+# Remaps APNodes into Simplices
+class APSimplexMap:
+    def __init__(self, filtration):
+        self.filtration = filtration
+
+    def __getitem__(self, n):
+        return self.filtration[n.i]
+
+class APNode:
+    def __init__(self, i, pairs):
+        self.i = i
+        self.pairs = pairs
+
+    def sign(self):
+        return self.unpaired() or self.i < self._pair()
+
+    def unpaired(self):
+        return self.i == self._pair()
+
+    def _pair(self):
+        return self.pairs[self.i][0]
+
+    def pair(self):
+        return APNode(self._pair(), self.pairs)
+
+    @property
+    def cocycle(self):
+        return self.pairs[self.i][2]
+
+def init_diagrams_from_adaptor(p, f, evaluator, data):
+    if not evaluator:
+        evaluator = lambda s: s.data
+
+    if not data:
+        data = lambda i: None
+
+    dgms = []
+    smap = p.make_simplex_map(f)
+    for n in p:
+        if not n.sign(): continue
+
+        dim = smap[n].dimension()
+        if dim + 1 > len(dgms):
+            dgms.append(PersistenceDiagram(dim))
+
+        b = evaluator(smap[n])
+        d = evaluator(smap[n.pair()]) if not n.unpaired() else float('inf')
+        if b == d: continue
+
+        dgms[dim].append((b,d, data(n)))
+
+    return dgms
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bindings/python/dionysus/circular/__init__.py	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,66 @@
+def smooth(filtration, cocycle):
+    from    cvxopt          import spmatrix, matrix
+    from    cvxopt.blas     import copy
+    from    lsqr            import lsqr
+
+    coefficient = []
+    coface_indices = []
+    face_indices = []
+    for i,s in enumerate(filtration):
+        if s.dimension() > 2: continue
+
+        c = 1
+        for sb in s.boundary:
+            j = filtration(sb)
+            coefficient.append(c)
+            coface_indices.append(i)
+            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), cocycle_max) + 1
+    D = spmatrix(coefficient, coface_indices, face_indices, (dimension, dimension))
+
+    z = spmatrix([zz[0] for zz in cocycle],
+                 [zz[1] for zz in cocycle],
+                 [0     for zz in cocycle], (dimension, 1))
+
+    v1 = D * z
+    if bool(D*D):
+        raise Exception('D^2 is not 0')
+    if bool(v1):
+        raise Exception('Expected a cocycle as input')
+    z = matrix(z)
+
+    def Dfun(x,y,trans = 'N'):
+        if trans == 'N':
+            copy(D * x, y)
+        elif trans == 'T':
+            copy(D.T * x, y)
+        else:
+            assert False, "Unexpected trans parameter"
+
+    tol = 1e-10
+    show = False
+    maxit = None
+    solution = lsqr(Dfun, matrix(z), show = show, atol = tol, btol = tol, itnlim = maxit)
+
+    z_smooth = z - D*solution[0]
+
+    # print sum(z_smooth**2)
+    # assert sum((D*z_smooth)**2) < tol and sum((D.T*z_smooth)**2) < tol, "Expected a harmonic cocycle"
+    if not (sum((D*z_smooth)**2) < tol and sum((D.T*z_smooth)**2) < tol):
+        raise Exception("Expected a harmonic cocycle: %f %f" % (sum((D*z_smooth)**2), sum((D.T*z_smooth)**2)))
+
+    values = []
+    vertices = ((i,s) for (i,s) in enumerate(filtration) if s.dimension() == 0)
+    for i,s in vertices:
+        v = [v for v in s.vertices][0]
+        if v >= len(values):
+            values.extend((None for i in xrange(len(values), v+1)))
+        values[v] = solution[0][i]
+
+    return values
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bindings/python/dionysus/circular/lsqr.py	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,408 @@
+# LSQR solver from http://pages.cs.wisc.edu/~kline/cvxopt/
+
+from cvxopt import matrix
+from cvxopt.lapack import *
+from cvxopt.blas import *
+from math import sqrt
+
+"""
+a,b are scalars
+
+On exit, returns scalars c,s,r
+"""
+def SymOrtho(a,b):
+    aa=abs(a)
+    ab=abs(b)
+    if b==0.:
+        s=0.
+        r=aa
+        if aa==0.:
+            c=1.
+        else:
+            c=a/aa
+    elif a==0.:
+        c=0.
+        s=b/ab
+        r=ab
+    elif ab>=aa:
+        sb=1
+        if b<0: sb=-1
+        tau=a/b
+        s=sb*(1+tau**2)**-0.5
+        c=s*tau
+        r=b/s
+    elif aa>ab:
+        sa=1
+        if a<0: sa=-1
+        tau=b/a
+        c=sa*(1+tau**2)**-0.5
+        s=c*tau
+        r=a/c
+
+    return c,s,r
+
+"""
+
+It is usually recommended to use SYMMLQ for symmetric matrices
+
+Requires the syntax
+                   A(x,y)   == y:=[A]*x
+and
+           A(x,y,trans='T') == y:=[A.T]*x
+
+comments with '###' are followed by the intent of the original matlab
+code. This may be useful for debugging.
+
+"""
+
+def lsqr(  A, b, damp=0.0, atol=1e-8, btol=1e-8, conlim=1e8, itnlim=None, show=False, wantvar=False):
+    """
+
+    [ x, istop, itn, r1norm, r2norm, anorm, acond, arnorm, xnorm, var ]...
+     = lsqr( m, n,  'aprod',  iw, rw, b, damp, atol, btol, conlim, itnlim, show );
+
+     LSQR solves  Ax = b  or  min ||b - Ax||_2  if damp = 0,
+     or   min || (b)  -  (  A   )x ||   otherwise.
+              || (0)     (damp I)  ||2
+     A  is an m by n matrix defined by  y = aprod( mode,m,n,x,iw,rw ),
+     where the parameter 'aprodname' refers to a function 'aprod' that
+     performs the matrix-vector operations.
+     If mode = 1,   aprod  must return  y = Ax   without altering x.
+     If mode = 2,   aprod  must return  y = A'x  without altering x.
+     WARNING:   The file containing the function 'aprod'
+                must not be called aprodname.m !!!!
+
+    -----------------------------------------------------------------------
+     LSQR uses an iterative (conjugate-gradient-like) method.
+     For further information, see
+     1. C. C. Paige and M. A. Saunders (1982a).
+        LSQR: An algorithm for sparse linear equations and sparse least squares,
+        ACM TOMS 8(1), 43-71.
+     2. C. C. Paige and M. A. Saunders (1982b).
+        Algorithm 583.  LSQR: Sparse linear equations and least squares problems,
+        ACM TOMS 8(2), 195-209.
+     3. M. A. Saunders (1995).  Solution of sparse rectangular systems using
+        LSQR and CRAIG, BIT 35, 588-604.
+
+     Input parameters:
+     iw, rw      are not used by lsqr, but are passed to aprod.
+     atol, btol  are stopping tolerances.  If both are 1.0e-9 (say),
+                 the final residual norm should be accurate to about 9 digits.
+                 (The final x will usually have fewer correct digits,
+                 depending on cond(A) and the size of damp.)
+     conlim      is also a stopping tolerance.  lsqr terminates if an estimate
+                 of cond(A) exceeds conlim.  For compatible systems Ax = b,
+                 conlim could be as large as 1.0e+12 (say).  For least-squares
+                 problems, conlim should be less than 1.0e+8.
+                 Maximum precision can be obtained by setting
+                 atol = btol = conlim = zero, but the number of iterations
+                 may then be excessive.
+     itnlim      is an explicit limit on iterations (for safety).
+     show = 1    gives an iteration log,
+     show = 0    suppresses output.
+
+     Output parameters:
+     x           is the final solution.
+     istop       gives the reason for termination.
+     istop       = 1 means x is an approximate solution to Ax = b.
+                 = 2 means x approximately solves the least-squares problem.
+     r1norm      = norm(r), where r = b - Ax.
+     r2norm      = sqrt( norm(r)^2  +  damp^2 * norm(x)^2 )
+                 = r1norm if damp = 0.
+     anorm       = estimate of Frobenius norm of Abar = [  A   ].
+                                                        [damp*I]
+     acond       = estimate of cond(Abar).
+     arnorm      = estimate of norm(A'*r - damp^2*x).
+     xnorm       = norm(x).
+     var         (if present) estimates all diagonals of (A'A)^{-1} (if damp=0)
+                 or more generally (A'A + damp^2*I)^{-1}.
+                 This is well defined if A has full column rank or damp > 0.
+                 (Not sure what var means if rank(A) < n and damp = 0.)
+
+
+            1990: Derived from Fortran 77 version of LSQR.
+     22 May 1992: bbnorm was used incorrectly.  Replaced by anorm.
+     26 Oct 1992: More input and output parameters added.
+     01 Sep 1994: Matrix-vector routine is now a parameter 'aprodname'.
+                  Print log reformatted.
+     14 Jun 1997: show  added to allow printing or not.
+     30 Jun 1997: var   added as an optional output parameter.
+     07 Aug 2002: Output parameter rnorm replaced by r1norm and r2norm.
+                  Michael Saunders, Systems Optimization Laboratory,
+                  Dept of MS&E, Stanford University.
+    -----------------------------------------------------------------------
+    """
+    """
+         Initialize.
+    """
+    n=len(b)
+    m=n
+    if itnlim is None: itnlim=2*n
+
+    msg=('The exact solution is  x = 0                              ',
+         'Ax - b is small enough, given atol, btol                  ',
+         'The least-squares solution is good enough, given atol     ',
+         'The estimate of cond(Abar) has exceeded conlim            ',
+         'Ax - b is small enough for this machine                   ',
+         'The least-squares solution is good enough for this machine',
+         'Cond(Abar) seems to be too large for this machine         ',
+         'The iteration limit has been reached                      ');
+
+    var = matrix(0.,(n,1));
+
+    if show:
+        print ' '
+        print 'LSQR            Least-squares solution of  Ax = b'
+        str1 = 'The matrix A has %8g rows  and %8g cols' % (m, n)
+        str2 = 'damp = %20.14e    wantvar = %8g' %( damp,wantvar)
+        str3 = 'atol = %8.2e                 conlim = %8.2e'%( atol, conlim)
+        str4 = 'btol = %8.2e                 itnlim = %8g'  %( btol, itnlim)
+        print str1
+        print str2
+        print str3
+        print str4
+
+    itn    = 0;		istop  = 0;		nstop  = 0;
+    ctol   = 0;
+    if conlim > 0: ctol = 1/conlim
+    anorm  = 0;		acond  = 0;
+    dampsq = damp**2;	ddnorm = 0;		res2   = 0;
+    xnorm  = 0;		xxnorm = 0;		z      = 0;
+    cs2    = -1;		sn2    = 0;
+
+    """
+    Set up the first vectors u and v for the bidiagonalization.
+     These satisfy  beta*u = b,  alfa*v = A'u.
+    """
+    __x    = matrix(0., (n,1)) # a matrix for temporary holding
+    v      = matrix(0., (n,1))
+    u      = +b;
+    x      = matrix(0., (n,1))
+    alfa   = 0;
+    beta = nrm2( u );
+    w      = matrix(0., (n,1))
+
+    if beta > 0:
+        ### u = (1/beta) * u;
+        ### v = feval( aprodname, 2, m, n, u, iw, rw );
+        scal(1/beta,u)
+	A(u,v,trans='T'); #v = feval( aprodname, 2, m, n, u, iw, rw );
+        alfa = nrm2( v );
+
+    if alfa > 0:
+        ### v = (1/alfa) * v;
+        scal(1/alfa,v)
+        copy(v,w)
+
+
+    rhobar = alfa;		phibar = beta;		bnorm  = beta;
+    rnorm  = beta;
+    r1norm = rnorm;
+    r2norm = rnorm;
+
+    # reverse the order here from the original matlab code because
+    # there was an error on return when arnorm==0
+    arnorm = alfa * beta;
+    if arnorm == 0:
+        print msg[0];
+        return x, istop, itn, r1norm, r2norm, anorm, acond, arnorm, xnorm, var
+
+    head1  = '   Itn      x[0]       r1norm     r2norm ';
+    head2  = ' Compatible   LS      Norm A   Cond A';
+
+    if show:
+        print ' '
+        print head1, head2
+        test1  = 1;		test2  = alfa / beta;
+        str1   = '%6g %12.5e'    %(    itn,   x[0] );
+        str2   = ' %10.3e %10.3e'%( r1norm, r2norm );
+        str3   = '  %8.1e %8.1e' %(  test1,  test2 );
+        print str1, str2, str3
+
+    """
+    %------------------------------------------------------------------
+    %     Main iteration loop.
+    %------------------------------------------------------------------
+    """
+    while itn < itnlim:
+        itn = itn + 1;
+        """
+        %     Perform the next step of the bidiagonalization to obtain the
+        %     next  beta, u, alfa, v.  These satisfy the relations
+        %                beta*u  =  a*v   -  alfa*u,
+        %                alfa*v  =  A'*u  -  beta*v.
+        """
+        ### u    = feval( aprodname, 1, m, n, v, iw, rw )  -  alfa*u;
+        copy(u, __x)
+        A(v,u)
+        axpy(__x,u,-alfa)
+
+        beta = nrm2( u );
+        if beta > 0:
+            ### u     = (1/beta) * u;
+            scal(1/beta,u)
+            anorm = sqrt(anorm**2 + alfa**2 + beta**2 + damp**2);
+            ### v     = feval( aprodname, 2, m, n, u, iw, rw )  -  beta*v;
+            copy(v,__x)
+            A(u,v,trans='T')
+            axpy(__x,v,-beta)
+
+            alfa  = nrm2( v );
+            if alfa > 0:
+                ### v = (1/alfa) * v;
+                scal(1/alfa, v)
+
+        """
+        %     Use a plane rotation to eliminate the damping parameter.
+        %     This alters the diagonal (rhobar) of the lower-bidiagonal matrix.
+        """
+
+        rhobar1 = sqrt(rhobar**2 + damp**2);
+        cs1     = rhobar / rhobar1;
+        sn1     = damp   / rhobar1;
+        psi     = sn1 * phibar;
+        phibar  = cs1 * phibar;
+        """
+        %     Use a plane rotation to eliminate the subdiagonal element (beta)
+        %     of the lower-bidiagonal matrix, giving an upper-bidiagonal matrix.
+        """
+
+
+        ###cs      =   rhobar1/ rho;
+        ###sn      =   beta   / rho;
+        cs,sn,rho = SymOrtho(rhobar1,beta)
+
+        theta   =   sn * alfa;
+        rhobar  = - cs * alfa;
+        phi     =   cs * phibar;
+        phibar  =   sn * phibar;
+        tau     =   sn * phi;
+        """
+        %     Update x and w.
+        """
+        t1      =   phi  /rho;
+        t2      = - theta/rho;
+        dk      =   (1/rho)*w;
+
+        ### x       = x      +  t1*w;
+        axpy(w,x,t1)
+        ### w       = v      +  t2*w;
+        scal(t2,w)
+        axpy(v,w)
+        ddnorm  = ddnorm +  nrm2(dk)**2;
+        if wantvar:
+            ### var = var  +  dk.*dk;
+            axpy(dk**2, var)
+        """
+        %     Use a plane rotation on the right to eliminate the
+        %     super-diagonal element (theta) of the upper-bidiagonal matrix.
+        %     Then use the result to estimate  norm(x).
+        """
+
+        delta   =   sn2 * rho;
+        gambar  = - cs2 * rho;
+        rhs     =   phi  -  delta * z;
+        zbar    =   rhs / gambar;
+        xnorm   =   sqrt(xxnorm + zbar**2);
+        gamma   =   sqrt(gambar**2 +theta**2);
+        cs2     =   gambar / gamma;
+        sn2     =   theta  / gamma;
+        z       =   rhs    / gamma;
+        xxnorm  =   xxnorm  +  z**2;
+        """
+        %     Test for convergence.
+        %     First, estimate the condition of the matrix  Abar,
+        %     and the norms of  rbar  and  Abar'rbar.
+        """
+        acond   =   anorm * sqrt(ddnorm);
+        res1    =   phibar**2;
+        res2    =   res2  +  psi**2;
+        rnorm   =   sqrt( res1 + res2 );
+        arnorm  =   alfa * abs( tau );
+        """
+        %     07 Aug 2002:
+        %     Distinguish between
+        %        r1norm = ||b - Ax|| and
+        %        r2norm = rnorm in current code
+        %               = sqrt(r1norm^2 + damp^2*||x||^2).
+        %        Estimate r1norm from
+        %        r1norm = sqrt(r2norm^2 - damp^2*||x||^2).
+        %     Although there is cancellation, it might be accurate enough.
+        """
+        r1sq    =   rnorm**2  -  dampsq * xxnorm;
+        r1norm  =   sqrt( abs(r1sq) );
+        if r1sq < 0: r1norm = - r1norm;
+        r2norm  =   rnorm;
+        """
+        %     Now use these norms to estimate certain other quantities,
+        %     some of which will be small near a solution.
+        """
+        test1   =   rnorm / bnorm;
+        test2   =   arnorm/( anorm * rnorm );
+        test3   =       1 / acond;
+        t1      =   test1 / (1    +  anorm * xnorm / bnorm);
+        rtol    =   btol  +  atol *  anorm * xnorm / bnorm;
+        """
+        %     The following tests guard against extremely small values of
+        %     atol, btol  or  ctol.  (The user may have set any or all of
+        %     the parameters  atol, btol, conlim  to 0.)
+        %     The effect is equivalent to the normal tests using
+        %     atol = eps,  btol = eps,  conlim = 1/eps.
+        """
+        if itn >= itnlim  : istop = 7;
+        if 1 + test3  <= 1: istop = 6;
+        if 1 + test2  <= 1: istop = 5;
+        if 1 + t1     <= 1: istop = 4;
+        """
+        %     Allow for tolerances set by the user.
+        """
+        if  test3 <= ctol:  istop = 3;
+        if  test2 <= atol:  istop = 2;
+        if  test1 <= rtol:  istop = 1;
+        """
+        %     See if it is time to print something.
+        """
+        prnt = False;
+        if n     <= 40       : prnt = True;
+        if itn   <= 10       : prnt = True;
+        if itn   >= itnlim-10: prnt = True;
+        # if itn%10 == 0       : prnt = True;
+        if test3 <=  2*ctol  : prnt = True;
+        if test2 <= 10*atol  : prnt = True;
+        if test1 <= 10*rtol  : prnt = True;
+        if istop !=  0       : prnt = True;
+
+        if prnt:
+            if show:
+                str1 = '%6g %12.5e'%        (itn,   x[0] );
+                str2 = ' %10.3e %10.3e'% (r1norm, r2norm );
+                str3 = '  %8.1e %8.1e'%  ( test1,  test2 );
+                str4 = ' %8.1e %8.1e'%   ( anorm,  acond );
+                print str1, str2, str3, str4
+
+        if istop != 0: break
+
+    """
+    %     End of iteration loop.
+    %     Print the stopping condition.
+    """
+    if show:
+        print ' '
+        print 'LSQR finished'
+        print msg[istop]
+        print ' '
+        str1 = 'istop =%8g   r1norm =%8.1e'%  ( istop, r1norm );
+        str2 = 'anorm =%8.1e   arnorm =%8.1e'%( anorm, arnorm );
+        str3 = 'itn   =%8g   r2norm =%8.1e'%  (   itn, r2norm );
+        str4 = 'acond =%8.1e   xnorm  =%8.1e'%( acond, xnorm  );
+        print str1+ '   ' +str2
+        print str3+ '   ' +str4
+        print ' '
+
+    return x, istop, itn, r1norm, r2norm, anorm, acond, arnorm, xnorm, var
+
+    """
+    %-----------------------------------------------------------------------
+    % End of lsqr.m
+    %-----------------------------------------------------------------------
+    """
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bindings/python/dionysus/distances.py	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,40 @@
+from    math        import sqrt
+
+def l2(p):
+    return sqrt(sum((x**2 for x in p)))
+
+# Pairwise distances between the elements of `points` with respect to some `norm`
+class PairwiseDistances:
+    def __init__(self, points, norm = l2):
+        self.points = points
+        self.norm = norm
+
+    def __len__(self):
+        return len(self.points)
+
+    def __call__(self, p1, p2):
+        return self.norm((x - y for (x,y) in zip(self.points[p1], self.points[p2])))
+
+# Caches all distances specified by `distances`
+class ExplicitDistances:
+    def __init__(self, distances):
+        self.len = len(distances)
+        self.distances = []
+        for i in xrange(self.len): 
+            self.distances.append([])
+            for j in xrange(self.len):
+                self.distances[-1].append(distances(i,j))
+
+    def __len__(self):
+        return self.len
+
+    def __call__(self, p1, p2):
+        return self.distances[p1][p2]
+
+# Generator of all points in a file `filename` with one point per line
+def points_file(filename):
+    fd = open(filename)
+    for line in fd.xreadlines():
+        if line.startswith('#'): continue
+        yield map(float, line.strip().split())
+    fd.close()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bindings/python/dionysus/viewer/PyGLWidget.py	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,309 @@
+# -*- coding: utf-8 -*-
+#===============================================================================
+#
+# PyGLWidget.py
+#
+# A simple GL Viewer.
+#
+# Copyright (c) 2011, Arne Schmitz <arne.schmitz@gmx.net>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#     * Redistributions of source code must retain the above copyright
+#       notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above copyright
+#       notice, this list of conditions and the following disclaimer in the
+#       documentation and/or other materials provided with the distribution.
+#     * Neither the name of the <organization> nor the
+#       names of its contributors may be used to endorse or promote products
+#       derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#===============================================================================
+
+from PyQt4 import QtCore, QtGui, QtOpenGL
+import math
+import numpy
+import numpy.linalg as linalg
+import OpenGL
+OpenGL.ERROR_CHECKING = False
+from OpenGL.GL import *
+from OpenGL.GLU import *
+
+class PyGLWidget(QtOpenGL.QGLWidget):
+
+    # Qt signals
+    signalGLMatrixChanged = QtCore.pyqtSignal()
+    rotationBeginEvent = QtCore.pyqtSignal()
+    rotationEndEvent = QtCore.pyqtSignal()
+
+    def __init__(self, parent = None):
+        format = QtOpenGL.QGLFormat()
+        format.setSampleBuffers(True)
+        QtOpenGL.QGLWidget.__init__(self, format, parent)
+        self.setCursor(QtCore.Qt.OpenHandCursor)
+        self.setMouseTracking(True)
+
+        self.modelview_matrix_  = []
+        self.translate_vector_  = [0.0, 0.0, 0.0]
+        self.viewport_matrix_   = []
+        self.projection_matrix_ = []
+        self.near_   = 0.1
+        self.far_    = 100.0
+        self.fovy_   = 45.0
+        self.radius_ = 5.0
+        self.last_point_2D_ = QtCore.QPoint()
+        self.last_point_ok_ = False
+        self.last_point_3D_ = [1.0, 0.0, 0.0]
+        self.isInRotation_  = False
+
+        # connections
+        #self.signalGLMatrixChanged.connect(self.printModelViewMatrix)
+
+    @QtCore.pyqtSlot()
+    def printModelViewMatrix(self):
+        print self.modelview_matrix_
+
+    def initializeGL(self):
+        # OpenGL state
+        glClearColor(1.0, 1.0, 1.0, 0.0)
+        glEnable(GL_DEPTH_TEST)
+        self.reset_view()
+
+    def resizeGL(self, width, height):
+        glViewport( 0, 0, width, height );
+        self.set_projection( self.near_, self.far_, self.fovy_ );
+        self.updateGL()
+
+    def paintGL(self):
+        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
+
+        glMatrixMode(GL_MODELVIEW)
+        glLoadMatrixd(self.modelview_matrix_)
+
+    def set_projection(self, _near, _far, _fovy):
+        self.near_ = _near
+        self.far_ = _far
+        self.fovy_ = _fovy
+        self.makeCurrent()
+        glMatrixMode( GL_PROJECTION )
+        glLoadIdentity()
+        gluPerspective( self.fovy_, float(self.width()) / float(self.height()),
+                        self.near_, self.far_ )
+        self.updateGL()
+
+    def set_center(self, _cog):
+        self.center_ = _cog
+        self.view_all()
+
+    def set_radius(self, _radius):
+        self.radius_ = _radius
+        self.set_projection(_radius / 100.0, _radius * 100.0, self.fovy_)
+        self.reset_view()
+        self.translate([0, 0, -_radius * 2.0])
+        self.view_all()
+        self.updateGL()
+
+    def reset_view(self):
+        # scene pos and size
+        glMatrixMode( GL_MODELVIEW )
+        glLoadIdentity();
+        self.modelview_matrix_ = glGetDoublev( GL_MODELVIEW_MATRIX )
+        self.set_center([0.0, 0.0, 0.0])
+
+    def reset_rotation(self):
+        self.modelview_matrix_[0] = [1.0, 0.0, 0.0, 0.0]
+        self.modelview_matrix_[1] = [0.0, 1.0, 0.0, 0.0]
+        self.modelview_matrix_[2] = [0.0, 0.0, 1.0, 0.0]
+        glMatrixMode(GL_MODELVIEW)
+        glLoadMatrixd(self.modelview_matrix_)
+        self.updateGL()
+
+    def translate(self, _trans):
+        # Translate the object by _trans
+        # Update modelview_matrix_
+        self.makeCurrent()
+        glMatrixMode(GL_MODELVIEW)
+        glLoadIdentity()
+        glTranslated(_trans[0], _trans[1], _trans[2])
+        glMultMatrixd(self.modelview_matrix_)
+        self.modelview_matrix_ = glGetDoublev(GL_MODELVIEW_MATRIX)
+        self.translate_vector_[0] = self.modelview_matrix_[3][0]
+        self.translate_vector_[1] = self.modelview_matrix_[3][1]
+        self.translate_vector_[2] = self.modelview_matrix_[3][2]
+        self.signalGLMatrixChanged.emit()
+
+    def rotate(self, _axis, _angle):
+        t = [self.modelview_matrix_[0][0] * self.center_[0] +
+             self.modelview_matrix_[1][0] * self.center_[1] +
+             self.modelview_matrix_[2][0] * self.center_[2] +
+             self.modelview_matrix_[3][0],
+             self.modelview_matrix_[0][1] * self.center_[0] +
+             self.modelview_matrix_[1][1] * self.center_[1] +
+             self.modelview_matrix_[2][1] * self.center_[2] +
+             self.modelview_matrix_[3][1],
+             self.modelview_matrix_[0][2] * self.center_[0] +
+             self.modelview_matrix_[1][2] * self.center_[1] +
+             self.modelview_matrix_[2][2] * self.center_[2] +
+             self.modelview_matrix_[3][2]]
+
+        self.makeCurrent()
+        glLoadIdentity()
+        glTranslatef(t[0], t[1], t[2])
+        glRotated(_angle, _axis[0], _axis[1], _axis[2])
+        glTranslatef(-t[0], -t[1], -t[2])
+        glMultMatrixd(self.modelview_matrix_)
+        self.modelview_matrix_ = glGetDoublev(GL_MODELVIEW_MATRIX)
+        self.signalGLMatrixChanged.emit()
+
+    def view_all(self):
+        self.translate( [ -( self.modelview_matrix_[0][0] * self.center_[0] +
+                             self.modelview_matrix_[0][1] * self.center_[1] +
+                             self.modelview_matrix_[0][2] * self.center_[2] +
+                             self.modelview_matrix_[0][3]),
+                           -( self.modelview_matrix_[1][0] * self.center_[0] +
+                              self.modelview_matrix_[1][1] * self.center_[1] +
+                              self.modelview_matrix_[1][2] * self.center_[2] +
+                              self.modelview_matrix_[1][3]),
+                           -( self.modelview_matrix_[2][0] * self.center_[0] +
+                              self.modelview_matrix_[2][1] * self.center_[1] +
+                              self.modelview_matrix_[2][2] * self.center_[2] +
+                              self.modelview_matrix_[2][3] +
+                              self.radius_ / 2.0 )])
+
+    def map_to_sphere(self, _v2D):
+        _v3D = [0.0, 0.0, 0.0]
+        # inside Widget?
+        if (( _v2D.x() >= 0 ) and ( _v2D.x() <= self.width() ) and
+            ( _v2D.y() >= 0 ) and ( _v2D.y() <= self.height() ) ):
+            # map Qt Coordinates to the centered unit square [-0.5..0.5]x[-0.5..0.5]
+            x  = float( _v2D.x() - 0.5 * self.width())  / self.width()
+            y  = float( 0.5 * self.height() - _v2D.y()) / self.height()
+
+            _v3D[0] = x;
+            _v3D[1] = y;
+            # use Pythagoras to comp z-coord (the sphere has radius sqrt(2.0*0.5*0.5))
+            z2 = 2.0*0.5*0.5-x*x-y*y;
+            # numerical robust sqrt
+            _v3D[2] = math.sqrt(max( z2, 0.0 ))
+
+            # normalize direction to unit sphere
+            n = linalg.norm(_v3D)
+            _v3D = numpy.array(_v3D) / n
+
+            return True, _v3D
+        else:
+            return False, _v3D
+
+    def wheelEvent(self, _event):
+        # Use the mouse wheel to zoom in/out
+
+        d = - float(_event.delta()) / 200.0 * self.radius_
+        self.translate([0.0, 0.0, d])
+        self.updateGL()
+        _event.accept()
+
+    def mousePressEvent(self, _event):
+        self.last_point_2D_ = _event.pos()
+        self.last_point_ok_, self.last_point_3D_ = self.map_to_sphere(self.last_point_2D_)
+
+    def mouseMoveEvent(self, _event):
+        newPoint2D = _event.pos()
+
+        if ((newPoint2D.x() < 0) or (newPoint2D.x() > self.width()) or
+            (newPoint2D.y() < 0) or (newPoint2D.y() > self.height())):
+            return
+
+        # Left button: rotate around center_
+        # Middle button: translate object
+        # Left & middle button: zoom in/out
+
+        value_y = 0
+        newPoint_hitSphere, newPoint3D = self.map_to_sphere(newPoint2D)
+
+        dx = float(newPoint2D.x() - self.last_point_2D_.x())
+        dy = float(newPoint2D.y() - self.last_point_2D_.y())
+
+        w  = float(self.width())
+        h  = float(self.height())
+
+        # enable GL context
+        self.makeCurrent()
+
+        # move in z direction
+        if (((_event.buttons() & QtCore.Qt.LeftButton) and (_event.buttons() & QtCore.Qt.MidButton))
+            or (_event.buttons() & QtCore.Qt.LeftButton and _event.modifiers() & QtCore.Qt.ControlModifier)):
+            value_y = self.radius_ * dy * 2.0 / h;
+            self.translate([0.0, 0.0, value_y])
+        # move in x,y direction
+        elif (_event.buttons() & QtCore.Qt.MidButton
+              or (_event.buttons() & QtCore.Qt.LeftButton and _event.modifiers() & QtCore.Qt.ShiftModifier)):
+            z = - (self.modelview_matrix_[0][2] * self.center_[0] +
+                   self.modelview_matrix_[1][2] * self.center_[1] +
+                   self.modelview_matrix_[2][2] * self.center_[2] +
+                   self.modelview_matrix_[3][2]) / (self.modelview_matrix_[0][3] * self.center_[0] +
+                                                    self.modelview_matrix_[1][3] * self.center_[1] +
+                                                    self.modelview_matrix_[2][3] * self.center_[2] +
+                                                    self.modelview_matrix_[3][3])
+
+            fovy   = 45.0
+            aspect = w / h
+            n      = 0.01 * self.radius_
+            up     = math.tan(fovy / 2.0 * math.pi / 180.0) * n
+            right  = aspect * up
+
+            self.translate( [2.0 * dx / w * right / n * z,
+                             -2.0 * dy / h * up / n * z,
+                             0.0] )
+
+
+        # rotate
+        elif (_event.buttons() & QtCore.Qt.LeftButton):
+            if (not self.isInRotation_):
+                self.isInRotation_ = True
+                self.rotationBeginEvent.emit()
+
+            axis = [0.0, 0.0, 0.0]
+            angle = 0.0
+
+            if (self.last_point_ok_ and newPoint_hitSphere):
+                axis = numpy.cross(self.last_point_3D_, newPoint3D)
+                cos_angle = numpy.dot(self.last_point_3D_, newPoint3D)
+                if (abs(cos_angle) < 1.0):
+                    angle = math.acos(cos_angle) * 180.0 / math.pi
+                    angle *= 2.0
+                self.rotate(axis, angle)
+
+        # remember this point
+        self.last_point_2D_ = newPoint2D
+        self.last_point_3D_ = newPoint3D
+        self.last_point_ok_ = newPoint_hitSphere
+
+        # trigger redraw
+        self.updateGL()
+
+        def mouseReleaseEvent(self, _event):
+            if (isInRotation_):
+                isInRotation_ = false
+                self.rotationEndEvent.emit()
+            last_point_ok_ = False
+
+#===============================================================================
+#
+# Local Variables:
+# mode: Python
+# indent-tabs-mode: nil
+# End:
+#
+#===============================================================================
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bindings/python/dionysus/viewer/__init__.py	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,16 @@
+from    diagram     import show_diagram as _show_diagram
+from    complex2d   import show_complex_2D as _show_complex_2D
+from    complex3d   import show_complex_3D as _show_complex_3D
+
+from    PyQt4       import QtGui
+
+_app = QtGui.QApplication([])
+
+def show_complex(points, complex = None, values = None, subcomplex = None, **kwargs):
+    if len(points[0]) == 2:
+        _show_complex_2D(points, complex, values, subcomplex, app = _app, **kwargs)
+    if len(points[0]) == 3:
+        _show_complex_3D(points, complex, values, subcomplex, app = _app, **kwargs)
+
+def show_diagram(dgm, noise = 0):
+    return _show_diagram(dgm, noise, _app)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bindings/python/dionysus/viewer/complex2d.py	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,117 @@
+from    PyQt4       import QtGui, QtCore
+from    dionysus    import Simplex
+
+class ComplexViewer2D(QtGui.QGraphicsView):
+    def __init__(self, points, complex = None, values = None, subcomplex = None):
+        super(QtGui.QGraphicsView, self).__init__()
+        self._pan = False
+
+        self.points = points
+        if complex:
+            complex = [s for s in complex]
+        else:
+            # Create vertex simplices if no complex provided
+            complex = [Simplex([i]) for i in xrange(len(self.points))]
+
+        if not subcomplex:
+            subcomplex = []
+
+        if not values:
+            values = [0]*len(self.points)
+        self.values = values
+        self.maxval, self.minval = max(values), min(values)
+
+        self.setRenderHint(QtGui.QPainter.Antialiasing)
+        self.scene = QtGui.QGraphicsScene(self)
+        self.setScene(self.scene)
+
+        minx = min(p[0] for p in points)
+        miny = min(p[1] for p in points)
+        maxx = max(p[0] for p in points)
+        maxy = max(p[1] for p in points)
+
+        radius = min(maxx - minx, maxy - miny)/100
+        self.scene.setSceneRect(minx - 10*radius, miny - 10*radius, (maxx - minx) + 20*radius, (maxy - miny) + 20*radius)
+
+        self.draw_complex(complex, radius, colormap = self.colormap)
+        self.draw_complex(subcomplex, 3*radius, colormap = lambda v: QtCore.Qt.green, line_color = QtCore.Qt.green)
+
+        # Flip y-axis
+        self.scale(1,-1)
+
+        # Set the correct view
+        rect = self.scene.itemsBoundingRect()
+        self.fitInView(rect, QtCore.Qt.KeepAspectRatio)
+
+    def draw_complex(self, complex, radius, colormap, line_color = QtCore.Qt.black):
+        complex.sort(lambda s1, s2: -cmp(s1.dimension(), s2.dimension()))
+        for s in complex:
+            vertices = [v for v in s.vertices]
+            if s.dimension() == 0:              # point
+                p = self.points[vertices[0]]
+                v = self.values[vertices[0]]
+                item = QtGui.QGraphicsEllipseItem(p[0] - radius/2,p[1] - radius/2,radius,radius)
+                color = colormap(v)
+                item.setBrush(QtGui.QBrush(color))
+                item.setPen(QtGui.QPen(color))
+            elif s.dimension() == 1:            # edge
+                p0 = self.points[vertices[0]]
+                p1 = self.points[vertices[1]]
+                item = QtGui.QGraphicsLineItem(p0[0], p0[1], p1[0], p1[1])
+                item.setPen(QtGui.QPen(line_color))
+            else:                               # higher-d simplex
+                pts = [QtCore.QPointF(self.points[v][0], self.points[v][1]) for v in vertices]
+                item = QtGui.QGraphicsPolygonItem(QtGui.QPolygonF(pts))
+                item.setBrush(QtCore.Qt.blue)
+
+            self.scene.addItem(item)
+
+    def colormap(self, v):
+        if self.maxval <= self.minval:
+            t = 0
+        else:
+            t = (v - self.minval)/(self.maxval - self.minval)
+        c = QtGui.QColor()
+        c.setHsv(int(t*255), 255, 255)
+        return c
+
+    def wheelEvent(self, event):
+        delta = 1 + float(event.delta())/100
+        if delta < 0:
+            event.ignore()
+            return
+        self.scale(delta, delta)
+        event.accept()
+
+    def mousePressEvent(self, event):
+        if event.button() == QtCore.Qt.RightButton:
+            self._pan = True
+            self._panStartX = event.x()
+            self._panStartY = event.y()
+            self.setCursor(QtCore.Qt.ClosedHandCursor)
+            event.accept()
+
+    def mouseReleaseEvent(self, event):
+        if event.button() == QtCore.Qt.RightButton:
+            self._pan = False
+            self.setCursor(QtCore.Qt.ArrowCursor)
+            event.accept()
+            return
+        event.ignore()
+
+    def mouseMoveEvent(self, event):
+        if self._pan:
+            self.horizontalScrollBar().setValue(self.horizontalScrollBar().value() - (event.x() - self._panStartX))
+            self.verticalScrollBar().setValue(self.verticalScrollBar().value() - (event.y() - self._panStartY))
+            self._panStartX = event.x()
+            self._panStartY = event.y()
+            event.accept()
+            return
+        event.ignore()
+
+def show_complex_2D(points, complex = None, values = None, subcomplex = None, app = None):
+    #app = QtGui.QApplication([])
+    view = ComplexViewer2D(points, complex, values, subcomplex)
+    view.show()
+    view.raise_()
+    app.exec_()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bindings/python/dionysus/viewer/complex3d.py	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,118 @@
+from    PyQt4       import QtGui, QtCore
+from    PyGLWidget  import PyGLWidget
+from    OpenGL.GL   import *
+from    dionysus    import Simplex
+from    math        import sqrt
+
+class ComplexViewer3D(PyGLWidget):
+    def __init__(self, points, complex = None, values = None, subcomplex = 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]
+        else:
+            # Create vertex simplices if no complex provided
+            self.complex = [Simplex([i]) for i in xrange(len(self.points))]
+
+        if subcomplex:
+            self.subcomplex = subcomplex
+        else:
+            self.subcomplex = []
+
+        self.values = values
+        if not values:
+            self.values = [0]*len(self.points)
+        self.maxval, self.minval = max(self.values), min(self.values)
+
+        center, radius = self.center_radius()
+        self.set_radius(radius)
+        self.set_center(center)
+
+        self.make_display_list()
+
+    def center_radius(self):
+        c = [0,0,0]
+        for p in self.points:
+            for i in xrange(3): c[i] += p[i]
+        for i in xrange(3): c[i] /= len(self.points)
+
+        r = 0
+        for p in self.points:
+            d = sqrt((p[0] - c[0])**2 + (p[1] - c[1])**2 + (p[2] - c[2])**2)
+            if d > r: r = d
+        return c,r
+
+    def paintGL(self):
+        PyGLWidget.paintGL(self)
+        if self.display_list:
+            glCallList(self.display_list)
+
+    def make_display_list(self):
+        self.display_list = glGenLists(1)
+        glNewList(self.display_list, GL_COMPILE)
+        self.draw_complex(self.complex,    self.point_size,   2., self.colormap)
+        self.draw_complex(self.subcomplex, 2*self.point_size, 4., colormap = lambda v: (0,1.,0), line_color = (0,1.,0))
+        glEndList()
+
+
+    def draw_complex(self, complex, point_size, line_size, colormap, line_color = (0,0,1.)):
+        glPointSize(point_size)
+        glLineWidth(line_size)
+        complex.sort(lambda s1, s2: -cmp(s1.dimension(), s2.dimension()))
+        for s in complex:
+            vertices = [v for v in s.vertices]
+            if s.dimension() == 0:              # point
+                p = self.points[vertices[0]]
+                v = self.values[vertices[0]]
+
+                c = self.colormap(v)
+                glColor3f(*c)
+                glBegin(GL_POINTS)
+                glVertex3f(p[0],p[1],p[2])
+                glEnd()
+            if s.dimension() == 1:            # edge
+                p0 = self.points[vertices[0]]
+                p1 = self.points[vertices[1]]
+
+                glColor3f(*line_color)
+                glBegin(GL_LINES)
+                glVertex3f(p0[0],p0[1],p0[2])
+                glVertex3f(p1[0],p1[1],p1[2])
+                glEnd()
+            elif s.dimension() == 2:
+                p0 = self.points[vertices[0]]
+                p1 = self.points[vertices[1]]
+                p2 = self.points[vertices[2]]
+
+                glColor3f(1,1,0)
+                glBegin(GL_TRIANGLES)
+                glVertex3f(p0[0],p0[1],p0[2])
+                glVertex3f(p1[0],p1[1],p1[2])
+                glVertex3f(p2[0],p2[1],p2[2])
+                glEnd()
+
+    def colormap(self, v):
+        if self.maxval <= self.minval:
+            t = 0
+        else:
+            t = (v - self.minval)/(self.maxval - self.minval)
+        c = QtGui.QColor()
+        c.setHsv(int(t*255), 255, 255)
+        cr = float(c.red())/255
+        cg = float(c.green())/255
+        cb = float(c.blue())/255
+        return (cr,cg,cb)
+
+def show_complex_3D(points, complex = None, values = None, subcomplex = None, app = None, point_size = 3.):
+    #app = QtGui.QApplication([])
+    view = ComplexViewer3D(points, complex, values, subcomplex, point_size)
+    view.show()
+    view.raise_()
+    app.exec_()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bindings/python/dionysus/viewer/diagram.py	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,156 @@
+from    PyQt4       import QtGui, QtCore
+from    math        import fabs
+
+class DiagramPoint(QtGui.QGraphicsEllipseItem):
+    def __init__(self,x,y, p, infty = False, color = 0):
+        super(QtGui.QGraphicsEllipseItem, self).__init__()
+        c = self.color(color)
+        self.setBrush(QtGui.QBrush(c[0]))
+        self.setPen(QtGui.QPen(c[1]))
+        self.radius = .075
+        if infty:
+            self.radius *= 2
+        self.x, self.y = x,y
+        self.scale(1)
+        self.p = p
+
+    def scale(self, delta):
+        self.radius *= delta
+        self.setRect(self.x - self.radius, self.y - self.radius, 2*self.radius, 2*self.radius)
+
+    def color(self, i):
+        return self._colors[i % len(self._colors)]
+
+    # (fill, border) pairs
+    _colors = [(QtCore.Qt.red,   QtGui.QColor(225, 0, 0)),
+               (QtCore.Qt.blue,  QtGui.QColor(0, 0, 225)),
+               (QtCore.Qt.green, QtGui.QColor(0, 225, 0)),
+              ]
+
+class DiagramViewer(QtGui.QGraphicsView):
+    def __init__(self, dgm, noise):
+        super(QtGui.QGraphicsView, self).__init__()
+
+        self.selection = None
+        self._pan = False
+
+        self.setRenderHint(QtGui.QPainter.Antialiasing)
+        self.scene = QtGui.QGraphicsScene(self)
+        self.setScene(self.scene)
+
+        if not isinstance(dgm, list):
+            # Assume it's just a single diagram
+            dgms = [dgm]
+        else:
+            dgms = dgm
+
+        inf = float('inf')
+        xs = [p[0] for d in dgms for p in d]
+        ys = [p[1] for d in dgms for p in d]
+        minx = min(0, min(xs) if xs else 0)
+        miny = min(0, min(ys) if ys else 0)
+        xs = [x for x in xs if x != inf]
+        ys = [y for y in ys if y != inf]
+        maxx = max(0, max(xs) if xs else 0)
+        maxy = max(0, max(ys) if ys else 0)
+
+        self.draw_axes(minx,miny,maxx,maxy)
+
+        for i, dgm in enumerate(dgms):
+            for p in dgm:
+                x,y = p[0],p[1]
+                if fabs(y - x) < noise:
+                    continue
+                if fabs(x) == inf or fabs(y) == inf:
+                    if x == inf: x = maxx + 2
+                    if y == inf: y = maxy + 2
+                    if x == -inf: x = minx - 2
+                    if y == -inf: y = miny - 2
+                    item = DiagramPoint(x,y,p, infty = True, color = i)
+                else:
+                    item = DiagramPoint(x,y,p, color = i)
+                self.scene.addItem(item)
+
+        # Flip y-axis
+        self.scale(1, -1)
+
+        # Set the correct view
+        rect = self.scene.itemsBoundingRect()
+        self.fitInView(rect, QtCore.Qt.KeepAspectRatio)
+
+    def mousePressEvent(self, event):
+        if event.button() == QtCore.Qt.RightButton:
+            self._pan = True
+            self._panStartX = event.x()
+            self._panStartY = event.y()
+            self.setCursor(QtCore.Qt.ClosedHandCursor)
+            event.accept()
+        else:
+            p = self.mapToScene(event.pos())
+            item = self.scene.itemAt(p)
+            if isinstance(item, DiagramPoint):
+                self.selection = item.p
+                self.close()
+
+    def mouseReleaseEvent(self, event):
+        if event.button() == QtCore.Qt.RightButton:
+            self._pan = False
+            self.setCursor(QtCore.Qt.ArrowCursor)
+            event.accept()
+            return
+        event.ignore()
+
+    def mouseMoveEvent(self, event):
+        if self._pan:
+            self.horizontalScrollBar().setValue(self.horizontalScrollBar().value() - (event.x() - self._panStartX))
+            self.verticalScrollBar().setValue(self.verticalScrollBar().value() - (event.y() - self._panStartY))
+            self._panStartX = event.x()
+            self._panStartY = event.y()
+            event.accept()
+            return
+        event.ignore()
+
+    def wheelEvent(self, event):
+        delta = 1 + float(event.delta())/100
+        if delta < 0:
+            event.ignore()
+            return
+        self.scale(delta, delta)
+        for item in self.scene.items():
+            if isinstance(item, DiagramPoint):
+                item.scale(1/delta)
+        event.accept()
+
+    def draw_axes(self, minx, miny, maxx, maxy):
+        # Draw axes and diagonal
+        if maxx > 0:
+            self.scene.addItem(QtGui.QGraphicsLineItem(0,0, maxx, 0))
+        if minx < 0:
+            self.scene.addItem(QtGui.QGraphicsLineItem(minx,0, 0, 0))
+        if maxy > 0:
+            self.scene.addItem(QtGui.QGraphicsLineItem(0,0, 0, maxy))
+        if miny < 0:
+            self.scene.addItem(QtGui.QGraphicsLineItem(0,miny, 0, 0))
+        self.scene.addItem(QtGui.QGraphicsLineItem(0,0, min(maxx, maxy), min(maxx, maxy)))
+        self.scene.addItem(QtGui.QGraphicsLineItem(max(minx,miny), max(minx,miny), 0,0))
+
+        # Dashed, gray integer lattice
+        pen = QtGui.QPen(QtCore.Qt.DashLine)
+        pen.setColor(QtCore.Qt.gray)
+        for i in xrange(min(0, int(minx)) + 1, max(0,int(maxx)) + 1):
+            line = QtGui.QGraphicsLineItem(i,0, i, maxy)
+            line.setPen(pen)
+            self.scene.addItem(line)
+        for i in xrange(min(0, int(miny)) + 1, max(0, int(maxy)) + 1):
+            line = QtGui.QGraphicsLineItem(0,i, maxx, i)
+            line.setPen(pen)
+            self.scene.addItem(line)
+
+
+def show_diagram(dgm, noise, app):
+    #app = QtGui.QApplication([])
+    view = DiagramViewer(dgm, noise)
+    view.show()
+    view.raise_()
+    app.exec_()
+    return view.selection
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bindings/python/dionysus/zigzag.py	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,20 @@
+def add_simplices(zz, simplices, complex, birth, report_local = False):
+    deaths = []
+    for s in simplices:
+        i,d = zz.add([complex[sb] for sb in s.boundary], (s.dimension(), birth))
+        complex[s] = i
+        if d is not None:
+            if report_local or not d[1] == birth:
+                deaths.append(d)
+    return deaths
+            
+
+def remove_simplices(zz, simplices, complex, birth, report_local = False):
+    deaths = []
+    for s in simplices:
+        d = zz.remove(complex[s], (s.dimension() - 1, birth))
+        complex[s] = None
+        if d is not None:
+            if report_local or not d[1] == birth:
+                deaths.append(d)
+    return deaths
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bindings/python/distances.cpp	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,21 @@
+#include <boost/python.hpp>
+namespace bp = boost::python;
+
+#include "distances.h"
+namespace dp = dionysus::python;
+
+boost::shared_ptr<dp::ListPointPairwiseDistances>       init_from_list(bp::list lst)
+{
+    boost::shared_ptr<dp::ListPointPairwiseDistances>   p(new dp::ListPointPairwiseDistances(lst));
+    return p;
+}
+
+void export_pairwise_distances()
+{
+    bp::class_<dp::ListPointPairwiseDistances>("PairwiseDistances", bp::no_init)
+        .def("__init__",        bp::make_constructor(&init_from_list))
+        .def("__len__",         &dp::ListPointPairwiseDistances::size)
+        .def("__call__",        &dp::ListPointPairwiseDistances::operator())
+    ;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bindings/python/distances.h	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,54 @@
+#include <utilities/log.h>
+
+#include <boost/python.hpp>
+namespace bp = boost::python;
+
+namespace dionysus { 
+namespace python   {
+
+typedef     bp::list            ListPoint;
+
+struct ListPointL2Distance:
+    public std::binary_function<bp::object, bp::object, double>
+{
+    result_type     operator()(bp::object p1, bp::object p2) const
+    {
+        ListPoint lp1 = bp::extract<ListPoint>(p1), lp2 = bp::extract<ListPoint>(p2);
+
+        AssertMsg(bp::len(lp1) == bp::len(lp2), "Points must be in the same dimension (in L2Distance): dim1=%d, dim2=%d", bp::len(lp1), bp::len(lp2));
+        result_type sum = 0;
+        for (size_t i = 0; i < bp::len(lp1); ++i)
+        {
+            double diff = bp::extract<double>(lp1[i]) - bp::extract<double>(lp2[i]);
+            sum += diff*diff;
+        }
+
+        return sqrt(sum);
+    }
+};
+
+class ListPointPairwiseDistances
+{
+    public:
+        typedef             bp::list                                        Container;
+        typedef             ListPointL2Distance                             Distance;
+        typedef             unsigned                                        IndexType;
+        typedef             Distance::result_type                           DistanceType;
+
+
+                            ListPointPairwiseDistances(Container container): 
+                                container_(container)                       {}
+
+        DistanceType        operator()(IndexType a, IndexType b) const      { return distance_(container_[a], container_[b]); }
+
+        size_t              size() const                                    { return bp::len(container_); }
+        IndexType           begin() const                                   { return 0; }
+        IndexType           end() const                                     { return size(); }
+
+    private:
+        Container           container_;
+        Distance            distance_;
+};
+
+} }     // namespace dionysus::python
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bindings/python/dynamic-persistence.cpp	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,41 @@
+#include <topology/dynamic-persistence.h>
+
+#include <boost/python.hpp>
+#include <boost/python/iterator.hpp>
+#include <boost/python/return_internal_reference.hpp>
+namespace bp = boost::python;
+
+#include "filtration.h"
+#include "dynamic-persistence.h"
+#include "chain.h"
+namespace dp = dionysus::python;
+
+
+dp::DPersistenceChains::iterator        dpc_begin(dp::DPersistenceChains& dpc)          { return dpc.begin(); }
+dp::DPersistenceChains::iterator        dpc_end(dp::DPersistenceChains& dpc)            { return dpc.end(); }
+
+void export_dynamic_persistence_chains()
+{
+    bp::class_<dp::DPersistenceChainsNode>("DPCNode", bp::no_init)
+        .def("pair",            &dp::pair<dp::DPersistenceChainsNode>,      bp::return_internal_reference<1>())
+        .add_property("cycle",  &dp::DPersistenceChainsNode::cycle)
+        .add_property("chain",  &dp::DPersistenceChainsNode::chain)
+        .def("sign",            &dp::DPersistenceChainsNode::sign)
+        .def("unpaired",        &dp::DPersistenceChainsNode::unpaired)
+    ;
+
+    bp::class_<dp::DPersistenceChains>("DynamicPersistenceChains", bp::no_init)
+        .def("__init__",        bp::make_constructor(&dp::init_from_filtration<dp::DPersistenceChains>))
+        
+        .def("pair_simplices",  &dp::DPersistenceChains::pair_simplices)
+        .def("__call__",        &dp::distance<dp::DPersistenceChains, dp::DPersistenceChainsIndex>)
+        .def("make_simplex_map",&dp::DPersistenceChains::make_simplex_map<dp::PythonFiltration>)
+
+        .def("__iter__",        bp::range<bp::return_internal_reference<1> >(dpc_begin, dpc_end))
+        .def("__len__",         &dp::DPersistenceChains::size)
+    ;
+
+    bp::class_<dp::DPersistenceChainsSimplexMap>("DPersistenceChainsSimplexMap", bp::no_init)
+        .def("__getitem__",     &dp::psmap_getitem<dp::DPersistenceChainsSimplexMap, dp::DPersistenceChainsIndex>,  bp::return_internal_reference<1>())
+    ;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bindings/python/dynamic-persistence.h	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,17 @@
+#ifndef __PYTHON_DYNAMIC_PERSISTENCE_CHAINS_H__
+#define __PYTHON_DYNAMIC_PERSISTENCE_CHAINS_H__
+
+#include <topology/dynamic-persistence.h>
+#include "static-persistence.h"
+
+namespace dionysus {
+namespace python   {
+
+typedef         DynamicPersistenceChains<>          DPersistenceChains;
+typedef         DPersistenceChains::OrderElement    DPersistenceChainsNode;
+typedef         DPersistenceChains::OrderIndex      DPersistenceChainsIndex;
+typedef         DPersistenceChains::SimplexMap<PythonFiltration>        
+                                                    DPersistenceChainsSimplexMap;
+} } // namespace dionysus::python
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bindings/python/filtration.cpp	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,60 @@
+#include <topology/filtration.h>
+
+#include <boost/python.hpp>
+#include <boost/iterator.hpp>
+#include <boost/python/return_internal_reference.hpp>
+namespace bp = boost::python;
+
+
+#include "simplex.h"
+#include "filtration.h"      // defines PythonFiltration
+#include "utils.h"           // defines PythonCmp
+namespace dp = dionysus::python;
+
+boost::shared_ptr<dp::PythonFiltration>     init_from_iterator(bp::object iter)
+{
+    typedef     dp::PythonFiltration::Simplex   Smplx;
+    boost::shared_ptr<dp::PythonFiltration>     p(new dp::PythonFiltration(bp::stl_input_iterator<Smplx>(iter), 
+                                                                           bp::stl_input_iterator<Smplx>()));
+    return p;
+}
+
+boost::shared_ptr<dp::PythonFiltration>     init_from_iterator_cmp(bp::object iter, bp::object cmp)
+{
+    typedef     dp::PythonFiltration::Simplex   Smplx;
+    boost::shared_ptr<dp::PythonFiltration>     p(new dp::PythonFiltration(bp::stl_input_iterator<Smplx>(iter), 
+                                                                           bp::stl_input_iterator<Smplx>(),
+                                                                           dp::PythonCmp(cmp)));
+    return p;
+}
+
+void                                        filtration_sort(dp::PythonFiltration& f, bp::object cmp)
+{ f.sort(dp::PythonCmp(cmp)); }
+
+const dp::PythonFiltration::Simplex&        f_getitem(const dp::PythonFiltration& f, int i)
+{ 
+    if (i >= 0)
+        return f.simplex(f.begin() + i); 
+    else
+        return f.simplex(f.end() + i);
+}
+
+unsigned                                    f_call(const dp::PythonFiltration& f, const dp::PythonFiltration::Simplex& s)
+{ return f.find(s) - f.begin(); }
+
+
+void export_filtration()
+{
+    bp::class_<dp::PythonFiltration>("Filtration")
+        .def("__init__",        bp::make_constructor(&init_from_iterator))
+        .def("__init__",        bp::make_constructor(&init_from_iterator_cmp))
+
+        .def("append",          &dp::PythonFiltration::push_back)
+        .def("sort",            &filtration_sort)
+
+        .def("__getitem__",     &f_getitem,      bp::return_internal_reference<1>())
+        .def("__call__",        &f_call)
+        .def("__iter__",        bp::range<bp::return_internal_reference<1> >(&dp::PythonFiltration::begin, &dp::PythonFiltration::end))
+        .def("__len__",         &dp::PythonFiltration::size)
+    ;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bindings/python/filtration.h	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,18 @@
+#ifndef __PYTHON_FILTRATION_H__
+#define __PYTHON_FILTRATION_H__
+
+#include <topology/filtration.h>
+#include <boost/python.hpp>
+#include "simplex.h"
+#include "utils.h"                      // for ListRandomAccessIterator
+
+namespace bp = boost::python;
+
+namespace dionysus {
+namespace python   {
+
+typedef         Filtration<SimplexVD>                       PythonFiltration;
+
+} } // namespace dionysus::python
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bindings/python/optional.h	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,85 @@
+#ifndef __PYTHON_OPTIONAL_H__
+#define __PYTHON_OPTIONAL_H__
+
+#include <boost/python.hpp>
+#include <boost/optional.hpp>
+#include <boost/utility.hpp>
+
+// Taken from an email by John Wiegley; 
+// http://mail.python.org/pipermail/cplusplus-sig/2007-May/012003.html
+
+template <typename T, typename TfromPy>
+struct object_from_python
+{
+    object_from_python() 
+    {
+        boost::python::converter::registry::push_back(&TfromPy::convertible, 
+                                                      &TfromPy::construct, 
+                                                      boost::python::type_id<T>());
+    }
+};
+
+template <typename T, typename TtoPy, typename TfromPy>
+struct register_python_conversion
+{
+    register_python_conversion() 
+    {
+        boost::python::to_python_converter<T, TtoPy>();
+        object_from_python<T, TfromPy>();
+    }
+};
+
+template <typename T>
+struct python_optional : public boost::noncopyable
+{
+    struct optional_to_python
+    {
+        static PyObject * convert(const boost::optional<T>& value)
+        {
+            return (value ? boost::python::to_python_value<T>()(*value) :
+                            boost::python::detail::none());
+        }
+    };
+
+    struct optional_from_python
+    {
+        static void * convertible(PyObject * source)
+        {
+            using namespace boost::python::converter;
+
+            if (source == Py_None)
+                return source;
+
+            const registration& converters(registered<T>::converters);
+
+            if (implicit_rvalue_convertible_from_python(source, converters)) 
+            {
+                rvalue_from_python_stage1_data data = rvalue_from_python_stage1(source, converters);
+                return rvalue_from_python_stage2(source, data, converters);
+            }
+            return NULL;
+        }
+
+        static void construct(PyObject * source,
+                              boost::python::converter::rvalue_from_python_stage1_data * data)
+        {
+            using namespace boost::python::converter;
+
+            void * const storage = ((rvalue_from_python_storage<T> *) data)->storage.bytes;
+
+            if (data->convertible == source)     // == None
+                new (storage) boost::optional<T>(); // A Boost uninitialized value
+            else
+                new (storage) boost::optional<T>(*static_cast<T *>(data->convertible));
+
+            data->convertible = storage;
+        }
+    };
+
+    explicit python_optional() 
+    {
+        register_python_conversion<boost::optional<T>, optional_to_python, optional_from_python>();
+    }
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bindings/python/persistence-diagram.cpp	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,229 @@
+#include<topology/persistence-diagram.h>
+#include<utilities/types.h>
+
+#include "filtration.h"
+#include "simplex.h"
+#include "static-persistence.h"
+#include "dynamic-persistence.h"
+
+#include <boost/foreach.hpp>
+
+#include<boost/python.hpp>
+#include<boost/python/init.hpp>
+#include<boost/shared_ptr.hpp>
+#include<boost/python/stl_iterator.hpp>
+#include<boost/python/def.hpp>
+#include<boost/python/register_ptr_to_python.hpp>
+namespace bp = boost::python;
+
+
+namespace dionysus{
+namespace python{
+
+typedef     bp::object                  Data;
+typedef     PersistenceDiagram<Data>    PersistenceDiagramD;
+typedef     PersistenceDiagramD::Point  PointD;
+typedef     boost::shared_ptr<PersistenceDiagramD>  PDgmPtr;
+
+} } //namespace dionysus::python
+
+namespace dp = dionysus::python;
+
+struct PointFromTupleConverter
+{
+    PointFromTupleConverter()
+    {
+        boost::python::converter::registry::push_back(&convertible,
+                                                      &construct,
+                                                      boost::python::type_id<dp::PointD>());
+    }
+
+    static void* convertible(PyObject* obj_ptr)
+    {
+        if (!PyTuple_Check(obj_ptr)) return 0;
+        if (PyTuple_Size(obj_ptr) < 2) return 0;
+        return obj_ptr;
+    }
+
+    static void construct(PyObject* obj_ptr,
+                          boost::python::converter::rvalue_from_python_stage1_data* data)
+    {
+        //const char* value = PyString_AsString(obj_ptr);
+        //if (value == 0) boost::python::throw_error_already_set();
+
+        // Grab pointer to memory into which to construct the new T
+        void* storage = ( (boost::python::converter::rvalue_from_python_storage<dp::PointD>*) data)->storage.bytes;
+
+        RealType x = bp::extract<RealType>(PyTuple_GetItem(obj_ptr, 0));
+        RealType y = bp::extract<RealType>(PyTuple_GetItem(obj_ptr, 1));
+
+        // in-place construct the new T using the character data extraced from the python object
+        dp::PointD* p = new (storage) dp::PointD(x,y);
+
+        if (PyTuple_Size(obj_ptr) > 2)
+            p->data() = bp::extract<bp::object>(PyTuple_GetItem(obj_ptr, 2));
+
+        // Stash the memory chunk pointer for later use by boost.python
+        data->convertible = storage;
+    }
+};
+
+struct PointToTupleConverter
+{
+    static PyObject* convert(const dp::PointD& p)
+    {
+        if (p.data().ptr() == bp::object().ptr())
+            return bp::incref(bp::make_tuple(p.x(), p.y()).ptr());
+        else
+            return bp::incref(bp::make_tuple(p.x(), p.y(), p.data()).ptr());
+    }
+};
+
+
+void export_point( )
+{
+    PointFromTupleConverter();
+    bp::to_python_converter<dp::PointD, PointToTupleConverter>();
+}
+
+
+boost::shared_ptr<dp::PersistenceDiagramD>      init_from_points_sequence(Dimension dimension, bp::object point_sequence)
+{
+    typedef     bp::stl_input_iterator<dp::PointD>  PointIterator;
+
+    PointIterator beg = PointIterator(point_sequence), end = PointIterator();
+    boost::shared_ptr<dp::PersistenceDiagramD> p(new dp::PersistenceDiagramD(dimension));
+
+    for(PointIterator cur = beg; cur != end; cur++)
+        (*p).push_back(*cur);
+    return p;
+
+}
+
+RealType    bottleneck_distance_adapter(const dp::PersistenceDiagramD& dgm1, const dp::PersistenceDiagramD& dgm2)
+{
+    return bottleneck_distance(dgm1, dgm2);
+}
+
+
+template<class Persistence>
+struct InitDiagrams
+{
+    typedef             std::map<int, dp::PDgmPtr>                                          DiagramMap;
+    typedef             typename Persistence::template SimplexMap<dp::PythonFiltration>     SMap;
+
+    struct DataEvaluator
+    {
+                            DataEvaluator(const SMap& smap_):
+                                smap(smap_)                         {}
+
+        template<class Key>
+        RealType            operator()(Key k) const                 { return bp::extract<RealType>(smap[k].data()); }
+
+        const SMap& smap;
+    };
+
+    struct PythonEvaluator
+    {
+                            PythonEvaluator(const SMap& smap_, bp::object eval_):
+                                smap(smap_), eval(eval_)            {}
+
+        template<class Key>
+        RealType            operator()(Key k) const                 { return bp::extract<RealType>(eval(smap[k])); }
+
+        const SMap& smap;
+        bp::object  eval;
+    };
+
+    // A hack
+    struct DiagramMapOwner: public DiagramMap
+    {
+        typedef             dp::PersistenceDiagramD                 mapped_type;
+
+        mapped_type&        operator[](Dimension d)
+        {
+            if (this->find(d) == this->end())
+                this->insert(std::make_pair(d, dp::PDgmPtr(new dp::PersistenceDiagramD(d))));
+            return *DiagramMap::operator[](d);
+        }
+    };
+
+    static
+    bp::list    extract_list(const DiagramMapOwner& dgms)
+    {
+        bp::list result;
+        size_t dim = 0;
+        typedef         typename DiagramMapOwner::value_type         ValType;
+        BOOST_FOREACH(const ValType& dim_dgm, dgms)
+        {
+            while (dim_dgm.first > dim)
+            {
+                result.append(dp::PDgmPtr(new dp::PersistenceDiagramD));
+                ++dim;
+            }
+
+            // dim_dgm.first == dim
+            result.append(dim_dgm.second);
+            dim++;
+        }
+
+        return result;
+    }
+
+    struct PointDataVisitor
+    {
+                PointDataVisitor(bp::object data_): data(data_)                                 {}
+        void    point(const typename Persistence::iterator& i, dp::PointD& p) const             { p.data() = data(*i); }
+        bp::object data;
+    };
+
+    static
+    bp::list    init(const Persistence& p, const dp::PythonFiltration& f, bp::object eval, bp::object data)
+    {
+
+        DiagramMapOwner dgms;
+        SMap            smap = p.make_simplex_map(f);
+        if (eval == bp::object())
+            init_diagrams(dgms, p.begin(), p.end(),
+                          DataEvaluator(smap),
+                          evaluate_through_map(smap, dp::SimplexVD::DimensionExtractor()));
+        else if (data == bp::object())
+            init_diagrams(dgms, p.begin(), p.end(),
+                          PythonEvaluator(smap, eval),
+                          evaluate_through_map(smap, dp::SimplexVD::DimensionExtractor()));
+        else
+            init_diagrams(dgms, p.begin(), p.end(),
+                          PythonEvaluator(smap, eval),
+                          evaluate_through_map(smap, dp::SimplexVD::DimensionExtractor()),
+                          PointDataVisitor(data));
+        return extract_list(dgms);
+    }
+};
+
+void export_persistence_diagram()
+{
+    bp::class_<dp::PersistenceDiagramD, dp::PDgmPtr>("PersistenceDiagram")
+        .def("__init__",            bp::make_constructor(&init_from_points_sequence))
+        .def(                       bp::init<Dimension>())
+        .def("append",              &dp::PersistenceDiagramD::push_back)
+        .add_property("dimension",  &dp::PersistenceDiagramD::dimension)
+        .def(                       repr(bp::self))
+        .def("__iter__",            bp::range(&dp::PersistenceDiagramD::begin, &dp::PersistenceDiagramD::end))
+        .def("__len__",             &dp::PersistenceDiagramD::size)
+    ;
+    bp::register_ptr_to_python<dp::PDgmPtr>();
+
+    bp::def("init_diagrams",        &InitDiagrams<dp::SPersistence>::init,
+                                     (bp::arg("persistence"),
+                                      bp::arg("filtration"),
+                                      bp::arg("eval")=bp::object(),
+                                      bp::arg("data")=bp::object()));
+    bp::def("init_diagrams",        &InitDiagrams<dp::DPersistenceChains>::init,
+                                     (bp::arg("persistence"),
+                                      bp::arg("filtration"),
+                                      bp::arg("eval")=bp::object(),
+                                      bp::arg("data")=bp::object()));
+
+    bp::def("bottleneck_distance",  &bottleneck_distance_adapter);
+    bp::def("wasserstein_distance", &wasserstein_distance<dp::PersistenceDiagramD>);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bindings/python/rips.cpp	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,35 @@
+#include <topology/rips.h>
+#include <boost/python.hpp>
+namespace bp = boost::python;
+
+#include "rips.h"                   // defines RipsWithDistances
+namespace dp = dionysus::python;
+
+#include <iostream>
+
+
+/* Various wrappers for exposing Rips to Python */
+// Constructor from distances
+boost::shared_ptr<dp::RipsWithDistances>        init_from_distances(bp::object distances)
+{ 
+    boost::shared_ptr<dp::RipsWithDistances>    p(new dp::RipsWithDistances(distances));
+    return p;
+}
+
+void export_rips()
+{
+    bp::class_<dp::RipsWithDistances>("Rips", bp::no_init)
+        .def("__init__",            bp::make_constructor(&init_from_distances))
+        .def("generate",            &dp::RipsWithDistances::generate)
+        .def("generate",            &dp::RipsWithDistances::generate_candidates)
+        .def("vertex_cofaces",      &dp::RipsWithDistances::vertex_cofaces)
+        .def("vertex_cofaces",      &dp::RipsWithDistances::vertex_cofaces_candidate)
+        .def("edge_cofaces",        &dp::RipsWithDistances::edge_cofaces)
+        .def("edge_cofaces",        &dp::RipsWithDistances::edge_cofaces_candidates)
+
+        .def("cmp",                 &dp::RipsWithDistances::cmp)
+        .def("cmp",                 &dp::RipsWithDistances::cmp_native)
+        .def("eval",                &dp::RipsWithDistances::eval)
+        .def("eval",                &dp::RipsWithDistances::eval_native)
+    ;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bindings/python/rips.h	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,112 @@
+#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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bindings/python/simplex.cpp	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,98 @@
+#include <topology/simplex.h>
+#include <utilities/indirect.h>
+#include <iostream>
+
+#include <boost/python.hpp>
+#include <boost/python/stl_iterator.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/functional/hash.hpp>
+namespace bp = boost::python;
+
+#include "simplex.h"                // defines SimplexVD, Vertex, and Data
+namespace dp = dionysus::python;
+
+
+/* Various wrappers for exposing Simplex to Python */
+// `vertices` property
+template<class V, class T>
+typename Simplex<V,T>::VertexContainer::const_iterator
+                                    vertices_begin(const Simplex<V,T>& s)       { return s.vertices().begin(); }
+template<class V, class T>
+typename Simplex<V,T>::VertexContainer::const_iterator
+                                    vertices_end(const Simplex<V,T>& s)         { return s.vertices().end(); }
+
+// Constructor from iterator        TODO: the default argument is not working yet
+template<class V, class T>
+boost::shared_ptr<Simplex<V,T> >    init_from_iterator(bp::object iter, bp::object d)
+{ 
+    boost::shared_ptr<Simplex<V,T> > p(new Simplex<V,T>(bp::stl_input_iterator<V>(iter), bp::stl_input_iterator<V>(), d));
+    return p;
+}
+
+
+// Simplex hash
+template<class V, class T>
+size_t                              hash_simplex(const Simplex<V,T>& s)
+{
+    return boost::hash_range(s.vertices().begin(), s.vertices().end());
+}
+
+template<class V, class T>
+size_t                              eq_simplex(const Simplex<V,T>& a, const Simplex<V,T>& b)
+{
+    return vertex_comparison(a,b) == 0;
+}
+
+template<class S>
+bool                                contains(const S& s, const S& other)
+{ 
+    return s.contains(other);
+}
+
+template<class S>
+dp::Data                            get_data(const S& s)
+{
+    return s.data();
+}
+
+template<class S>
+void                                set_data(S& s, dp::Data d)
+{
+    s.data() = d;
+}
+
+/* Comparisons */
+// VertexComparison
+template<class V, class T>
+int                                 vertex_comparison(const Simplex<V,T>& a, const Simplex<V,T>& b)
+{
+    return ThreeOutcomeCompare<typename Simplex<V,T>::VertexComparison>().compare(a,b);
+}
+
+
+void export_simplex()
+{
+    bp::class_<dp::SimplexVD>("Simplex")
+        .def("__init__",            bp::make_constructor(&init_from_iterator<dp::Vertex, dp::Data>))
+
+        .def("add",                 &dp::SimplexVD::add)
+        .add_property("boundary",   bp::range(&dp::SimplexVD::boundary_begin, &dp::SimplexVD::boundary_end))
+        .def("contains",            &contains<dp::SimplexVD>)
+        .def("join",                (void (dp::SimplexVD::*)(const dp::SimplexVD&)) &dp::SimplexVD::join)
+        .def("dimension",           &dp::SimplexVD::dimension)
+        .add_property("data",       &get_data<dp::SimplexVD>, &set_data<dp::SimplexVD>)
+        
+        .add_property("vertices",   bp::range(&vertices_begin<dp::Vertex, dp::Data>, &vertices_end<dp::Vertex, dp::Data>))
+        .def(repr(bp::self))
+
+        .def("__hash__",            &hash_simplex<dp::Vertex, dp::Data>)
+        .def("__eq__",              &eq_simplex<dp::Vertex, dp::Data>)
+        .enable_pickling()
+    ;
+
+    bp::class_<dp::SimplexObject>("SimplexObject")
+        .def("__getattribute__",    &dp::SimplexObject::getattribute)
+    ;
+
+    bp::def("vertex_cmp",           &vertex_comparison<dp::Vertex, dp::Data>);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bindings/python/simplex.h	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,65 @@
+#ifndef __PYTHON_SIMPLEX_H__
+#define __PYTHON_SIMPLEX_H__
+
+#include <topology/simplex.h>
+
+#include <boost/python.hpp>
+#include <boost/python/stl_iterator.hpp>
+namespace bp = boost::python;
+
+
+namespace dionysus {
+namespace python   {
+
+/**
+ * SimplexVD is a base class for Python simplices (it's exposed to python as Simplex)
+ *
+ * SimplexObject is the representation of Python simplices in C++; i.e. it wraps bp::object and exposes a simplex-like interface.
+ */
+typedef                             int                                         Vertex;
+typedef                             bp::object                                  Data;
+typedef                             Simplex<Vertex, Data>                       SimplexVD;
+
+
+// Wrapper around bp::object that acts like a simplex
+class SimplexObject: public bp::object
+{
+    public:
+        typedef                 SimplexObject                                   Self;
+        typedef                 bp::object                                      Parent;
+        typedef                 bp::stl_input_iterator<Self>                    BoundaryIterator;
+
+
+                                SimplexObject(Parent o = Parent()): Parent(o)   {}
+
+        BoundaryIterator        boundary_begin() const                          { return bp::stl_input_iterator<Self>(this->attr("boundary")); }
+        BoundaryIterator        boundary_end() const                            { return bp::stl_input_iterator<Self>(); }
+
+                                operator SimplexVD() const                      { return bp::extract<const SimplexVD&>(*this); }
+                                operator bp::object() const                     { return *this; }
+
+        bp::object              getattribute(const char* name) const            { return this->attr(name); }
+
+        class                   VertexComparison: public SimplexVD::VertexComparison
+        {
+            public:
+                typedef         Self                                            first_argument_type;
+                typedef         Self                                            second_argument_type;
+                typedef         bool                                            result_type;
+
+                bool            operator()(const SimplexObject& s1, const SimplexObject& s2) const  
+                { return SimplexVD::VertexComparison::operator()(bp::extract<const SimplexVD&>(s1), bp::extract<const SimplexVD&>(s2)); }
+        };
+};
+
+struct SimplexObjectToSimplexVD
+{
+    static PyObject* convert (const SimplexObject& so)
+    {
+        return (PyObject*) &so;
+    }
+};
+
+} } // namespace dionysus::python
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bindings/python/static-persistence.cpp	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,44 @@
+#include <topology/static-persistence.h>
+
+#include <boost/python.hpp>
+#include <boost/python/iterator.hpp>
+#include <boost/python/return_internal_reference.hpp>
+namespace bp = boost::python;
+
+#include "filtration.h"
+#include "static-persistence.h"
+#include "chain.h"
+namespace dp = dionysus::python;
+
+
+void            pair_simplices(dp::SPersistence& sp, bool store_negative)
+{
+    dp::SPersistence::PairVisitorNoProgress visitor;
+    sp.pair_simplices(sp.begin(), sp.end(), store_negative, visitor);
+}
+
+
+void export_static_persistence()
+{
+    bp::class_<dp::SPersistenceNode>("SPNode", bp::no_init)
+        .def("pair",            &dp::pair<dp::SPersistenceNode>,        bp::return_internal_reference<1>())
+        .add_property("cycle",  &dp::SPersistenceNode::cycle)
+        .def("sign",            &dp::SPersistenceNode::sign)
+        .def("unpaired",        &dp::SPersistenceNode::unpaired)
+    ;
+
+    bp::class_<dp::SPersistence>("StaticPersistence", bp::no_init)
+        .def("__init__",        bp::make_constructor(&dp::init_from_filtration<dp::SPersistence>))
+
+        .def("pair_simplices",  &pair_simplices, (bp::args("store_negative")=false))
+        .def("__call__",        &dp::distance<dp::SPersistence, dp::SPersistenceIndex>)
+        .def("make_simplex_map",&dp::SPersistence::make_simplex_map<dp::PythonFiltration>)
+
+        .def("__iter__",        bp::range<bp::return_internal_reference<1> >(&dp::SPersistence::begin, &dp::SPersistence::end))
+        .def("__len__",         &dp::SPersistence::size)
+    ;
+
+    bp::class_<dp::SPersistenceSimplexMap>("SPersistenceSimplexMap", bp::no_init)
+        .def("__getitem__",     &dp::psmap_getitem<dp::SPersistenceSimplexMap, dp::SPersistenceIndex>,  bp::return_internal_reference<1>())
+    ;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bindings/python/static-persistence.h	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,44 @@
+#ifndef __PYTHON_STATIC_PERSISTENCE_H__
+#define __PYTHON_STATIC_PERSISTENCE_H__
+
+#include <topology/static-persistence.h>
+
+#include "filtration.h"
+
+namespace dionysus {
+namespace python   {
+
+typedef         StaticPersistence<>             SPersistence;
+typedef         SPersistence::OrderElement      SPersistenceNode;
+typedef         SPersistence::OrderIndex        SPersistenceIndex;
+typedef         SPersistence::SimplexMap<PythonFiltration>        
+                                                SPersistenceSimplexMap;
+
+
+/* Persistence */
+template<class Persistence>
+boost::shared_ptr<Persistence>          init_from_filtration(bp::object f)
+{
+    PythonFiltration& sf = bp::extract<PythonFiltration&>(f);
+    boost::shared_ptr<Persistence> p(new Persistence(sf));
+    return p;
+}
+
+template<class Persistence, class PersistenceIndex>
+unsigned                                distance(Persistence& p, 
+                                                 const PersistenceIndex& i)             { return p.iterator_to(i) - p.begin(); }
+
+/* SPNode */
+template<class PNode>
+const PNode&                            pair(const PNode& n)                            { return *n.pair; }
+
+
+/* PersistenceSimplexMap */
+template<class PersistenceSimplexMap, class PersistenceIndex>
+const SimplexVD&                        psmap_getitem(const PersistenceSimplexMap& psmap, 
+                                                      const PersistenceIndex& i)        { return psmap[i]; }
+
+
+} } // namespace dionysus::python
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bindings/python/utils.h	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,62 @@
+#ifndef __PYTHON_UTILS_H__
+#define __PYTHON_UTILS_H__
+
+#include <boost/python.hpp>
+#include <boost/iterator/counting_iterator.hpp>
+namespace bp = boost::python;
+
+namespace dionysus {
+namespace python   {
+
+// Random access iterator into python's list (using integer indices)
+template<class Value>
+class ListRandomAccessIterator:
+    public boost::iterator_adaptor<ListRandomAccessIterator<Value>,         // Derived
+                                   boost::counting_iterator<unsigned>,      // Base
+                                   Value,                                   // Value
+                                   boost::use_default,
+                                   Value>
+{
+    public:
+        typedef                 ListRandomAccessIterator                                        Self;
+        typedef                 boost::iterator_adaptor<ListRandomAccessIterator,           
+                                                        boost::counting_iterator<unsigned>,     
+                                                        Value,
+                                                        boost::use_default,
+                                                        Value>                                  Parent;
+                    
+                                ListRandomAccessIterator()                                      {}
+
+                                ListRandomAccessIterator(bp::list l, unsigned i):
+                                    Parent(i), l_(l)                                            {}
+
+    private:
+        friend class boost::iterator_core_access;
+        friend class FiltrationPythonIterator;
+
+        typename Parent::reference       
+                                dereference() const                                             { return bp::object(l_[*(this->base())]); }
+
+        bp::list                l_;
+};
+
+// Adaptor of a Pyhon object to act as a C++-style comparison functor
+struct PythonCmp
+{
+    template<class T>
+    bool            operator()(T x1, T x2) const            { return cmp_(x1, x2) < 0; }
+
+                    PythonCmp(bp::object cmp): cmp_(cmp)    {}
+
+    bp::object      cmp_;
+};
+
+template<class T1, class T2>
+struct PairToTupleConverter 
+{
+    static PyObject* convert(const std::pair<T1, T2>& pair) { return bp::incref(bp::make_tuple(pair.first, pair.second).ptr()); }
+};
+
+} } // namespace dionysus::python
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bindings/python/zigzag-persistence.cpp	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,128 @@
+#include <topology/zigzag-persistence.h>
+#include <topology/image-zigzag-persistence.h>
+
+#include <boost/python.hpp>
+#include <boost/python/stl_iterator.hpp>
+#include <boost/shared_ptr.hpp>
+namespace bp = boost::python;
+
+#include "zigzag-persistence.h"             // defines ZZPersistence, IZZPersistence
+#include "optional.h"
+namespace dp = dionysus::python;
+
+#include <sstream>
+#include <string>
+
+
+// ZigzagPersistence
+bp::tuple                           zzp_add(dp::ZZPersistence& zzp, bp::object bdry, dp::BirthID birth)
+{
+    // Make ZColumn
+    // NB: it's extremely weird that I have to do it this way,
+    //     but for some reason I cannot just create boundary on the stack
+    boost::shared_ptr<dp::ZZPersistence::ZColumn>
+                                            boundary(new dp::ZZPersistence::ZColumn(bp::stl_input_iterator<dp::ZZPersistence::SimplexIndex>(bdry),
+                                                                                    bp::stl_input_iterator<dp::ZZPersistence::SimplexIndex>()));
+    boundary->sort(zzp.cmp);
+
+    dp::ZZPersistence::SimplexIndex         i;
+    dp::ZZPersistence::Death                d;
+    boost::tie(i,d)                                 = zzp.add(*boundary, birth);
+    return bp::make_tuple(i,d);
+}
+
+dp::ZZPersistence::Death            zzp_remove(dp::ZZPersistence& zzp, dp::ZZPersistence::SimplexIndex s, dp::ZZPersistence::BirthID birth)
+{
+    return zzp.remove(s, birth);
+}
+
+bool                                zzp_is_alive(dp::ZZPersistence& zzp, const dp::ZZPersistence::ZNode& zn)
+{
+    return zzp.is_alive(zn);
+}
+
+// ImageZigzagPersistence
+bp::tuple                           izzp_add(dp::IZZPersistence& izzp, bp::object bdry, bool subcomplex, dp::BirthID birth)
+{
+    // Make ZColumn
+    // NB: it's extremely weird that I have to do it this way,
+    //     but for some reason I cannot just create boundary on the stack
+    boost::shared_ptr<dp::IZZPersistence::ZColumn>
+                                            boundary(new dp::IZZPersistence::ZColumn(bp::stl_input_iterator<dp::IZZPersistence::SimplexIndex>(bdry),
+                                                                                     bp::stl_input_iterator<dp::IZZPersistence::SimplexIndex>()));
+    boundary->sort(izzp.cmp);
+
+    dp::IZZPersistence::SimplexIndex            i;
+    dp::IZZPersistence::Death                   d;
+    boost::tie(i,d)                                 = izzp.add(*boundary, subcomplex, birth);
+    return bp::make_tuple(i,d);
+}
+
+dp::IZZPersistence::Death           izzp_remove(dp::IZZPersistence& izzp, dp::IZZPersistence::SimplexIndex s, dp::IZZPersistence::BirthID birth)
+{
+    return izzp.remove(s, birth);
+}
+
+
+// SimplexIndex
+template<class T>
+unsigned                            si_order(T& si)
+{
+    return si->order;
+}
+
+template<class T>
+std::string                         si_repr(T& si)
+{
+    std::ostringstream out; out << "SimplexIndex <" << si->order << ">";
+    return out.str();
+}
+
+// ZNode
+template<class Persistence>
+typename Persistence::ZColumn::const_iterator
+znode_zcolumn_begin(typename Persistence::ZNode& zn)
+{ return zn.z_column.begin(); }
+
+template<class Persistence>
+typename Persistence::ZColumn::const_iterator
+znode_zcolumn_end(typename Persistence::ZNode& zn)
+{ return zn.z_column.end(); }
+
+
+
+void export_zigzag_persistence()
+{
+    bp::class_<dp::ZZPersistence::SimplexIndex>("ZZSimplexIndex")
+        .def("order",           &si_order<dp::ZZPersistence::SimplexIndex>)
+        .def("__repr__",        &si_repr<dp::ZZPersistence::SimplexIndex>)
+    ;
+
+    bp::class_<dp::IZZPersistence::SimplexIndex>("IZZSimplexIndex")
+        .def("order",           &si_order<dp::IZZPersistence::SimplexIndex>)
+        .def("__repr__",        &si_repr<dp::IZZPersistence::SimplexIndex>)
+    ;
+
+    bp::class_<dp::ZZPersistence>("ZigzagPersistence")
+        .def("add",             &zzp_add)
+        .def("remove",          &zzp_remove)
+        .def("is_alive",        &zzp_is_alive)
+        .def("__iter__",        bp::range(&dp::ZZPersistence::begin, &dp::ZZPersistence::end))
+    ;
+
+    bp::class_<dp::IZZPersistence>("ImageZigzagPersistence")
+        .def("add",             &izzp_add)
+        .def("remove",          &izzp_remove)
+        .def("__iter__",        bp::range(&dp::IZZPersistence::image_begin, &dp::IZZPersistence::image_end))
+    ;
+
+    bp::class_<dp::ZZPersistence::ZNode>("ZNode", bp::no_init)
+        .add_property("birth",  &dp::ZZPersistence::ZNode::birth)
+        .def("__iter__",        bp::range(&znode_zcolumn_begin<dp::ZZPersistence>, &znode_zcolumn_end<dp::ZZPersistence>))
+    ;
+
+    bp::class_<dp::IZZPersistence::ZNode>("IZNode", bp::no_init)
+        .add_property("birth",  &dp::IZZPersistence::ZNode::birth)
+        .def("__iter__",        bp::range(&znode_zcolumn_begin<dp::IZZPersistence>, &znode_zcolumn_end<dp::IZZPersistence>))
+    ;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bindings/python/zigzag-persistence.h	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,18 @@
+#ifndef __PYTHON_ZIGZAG_PERSISTENCE_H__
+#define __PYTHON_ZIGZAG_PERSISTENCE_H__
+
+#include <topology/zigzag-persistence.h>
+#include <topology/image-zigzag-persistence.h>
+#include <boost/python.hpp>
+
+#include "birthid.h"
+
+namespace dionysus {
+namespace python   {
+
+typedef         ZigzagPersistence<BirthID>      ZZPersistence;
+typedef         ImageZigzagPersistence<BirthID> IZZPersistence;
+
+} } // namespace dionysus::python
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/Makefile	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,75 @@
+# Makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line.
+SPHINXOPTS    =
+SPHINXBUILD   = sphinx-build
+PAPER         =
+
+# Internal variables.
+PAPEROPT_a4     = -D latex_paper_size=a4
+PAPEROPT_letter = -D latex_paper_size=letter
+ALLSPHINXOPTS   = -d .build/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+
+.PHONY: help clean html web pickle htmlhelp latex changes linkcheck
+
+help:
+	@echo "Please use \`make <target>' where <target> is one of"
+	@echo "  html      to make standalone HTML files"
+	@echo "  pickle    to make pickle files"
+	@echo "  json      to make JSON files"
+	@echo "  htmlhelp  to make HTML files and a HTML help project"
+	@echo "  latex     to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
+	@echo "  changes   to make an overview over all changed/added/deprecated items"
+	@echo "  linkcheck to check all external links for integrity"
+
+clean:
+	-rm -rf .build/*
+
+html:
+	mkdir -p .build/html .build/doctrees
+	$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) .build/html
+	@echo
+	@echo "Build finished. The HTML pages are in .build/html."
+
+pickle:
+	mkdir -p .build/pickle .build/doctrees
+	$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) .build/pickle
+	@echo
+	@echo "Build finished; now you can process the pickle files."
+
+web: pickle
+
+json:
+	mkdir -p .build/json .build/doctrees
+	$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) .build/json
+	@echo
+	@echo "Build finished; now you can process the JSON files."
+
+htmlhelp:
+	mkdir -p .build/htmlhelp .build/doctrees
+	$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) .build/htmlhelp
+	@echo
+	@echo "Build finished; now you can run HTML Help Workshop with the" \
+	      ".hhp project file in .build/htmlhelp."
+
+latex:
+	mkdir -p .build/latex .build/doctrees
+	$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) .build/latex
+	@echo
+	@echo "Build finished; the LaTeX files are in .build/latex."
+	@echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \
+	      "run these through (pdf)latex."
+
+changes:
+	mkdir -p .build/changes .build/doctrees
+	$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) .build/changes
+	@echo
+	@echo "The overview file is in .build/changes."
+
+linkcheck:
+	mkdir -p .build/linkcheck .build/doctrees
+	$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) .build/linkcheck
+	@echo
+	@echo "Link check complete; look for any errors in the above output " \
+	      "or in .build/linkcheck/output.txt."
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/bibliography.rst	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,34 @@
+Bibliography
+============
+
+.. |edels|      replace:: Herbert Edelsbrunner
+.. .. _edels:      http://www.cs.duke.edu/~edels/
+.. |david|      replace:: David Cohen-Steiner
+.. .. _david:      http://www-sop.inria.fr/geometrica/team/David.Cohen-Steiner/
+.. |morozov|    replace:: Dmitriy Morozov
+.. .. _morozov:    http://www.mrzv.org/
+.. |afra|       replace:: Afra Zomorodian
+.. .. _afra:       http://www.cs.dartmouth.edu/~afra/
+.. |letscher|   replace:: David Letscher
+.. |gunnar|     replace:: Gunnar Carlsson
+.. .. _gunnar:     http://math.stanford.edu/~gunnar/
+.. |vin|        replace:: Vin de Silva
+.. .. _vin:        http://pages.pomona.edu/~vds04747/
+.. |mikael|     replace:: Mikael Vejdemo Johansson 
+
+.. [CdSM09] |gunnar|, |vin|, and |morozov|.
+            `Zigzag Persistent Homology and Real-valued Functions
+            <http://www.mrzv.org/publications/zigzags/>`__.
+
+.. [CEM06] |david|, |edels|, and |morozov|. 
+           `Vines and Vineyards by Updating Persistence in Linear Time 
+           <http://www.mrzv.org/publications/vineyards/>`__.
+
+.. [dSVJ09] |vin|, |mikael|.
+            Persistent Cohomology and Circular Coordinates.
+
+.. [ELZ02] |edels|, |letscher|, and |afra|. 
+           Topological Persistence and Simplification.
+
+.. [ZC05]  |afra| and |gunnar|.
+           Computing Persistent Homology.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/conf.py	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,205 @@
+# -*- coding: utf-8 -*-
+#
+# Dionysus documentation build configuration file, created by
+# sphinx-quickstart on Tue Dec  9 10:21:40 2008.
+#
+# This file is execfile()d with the current directory set to its containing dir.
+#
+# The contents of this file are pickled, so don't put values in the namespace
+# that aren't pickleable (module imports are okay, they're removed automatically).
+#
+# All configuration values have a default; values that are commented out
+# serve to show the default.
+
+import sys, os
+
+# If your extensions are in another directory, add it here. If the directory
+# is relative to the documentation root, use os.path.abspath to make it
+# absolute, like shown here.
+#sys.path.append(os.path.abspath('.'))
+
+# General configuration
+# ---------------------
+
+# Add any Sphinx extension module names here, as strings. They can be extensions
+# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
+sys.path.append('.')
+
+extensions = ['sphinx.ext.autodoc', 'sphinx.ext.todo', 
+              #'sphinx.ext.jsmath',  'ext.sprite_jsmath', 
+              'sphinx.ext.pngmath',
+              'ext.sfile']
+todo_include_todos = True
+
+jsmath_path = 'jsMath/easy/load.js'
+
+# Base URI for sfile extension
+sfile_base_uri = 'http://hg.mrzv.org/Dionysus/file/tip/'
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['.templates']
+
+# The suffix of source filenames.
+source_suffix = '.rst'
+
+# The encoding of source files.
+#source_encoding = 'utf-8'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General information about the project.
+project = u'Dionysus'
+copyright = u'2005--2009, Dmitriy Morozov'
+
+# The version info for the project you're documenting, acts as replacement for
+# |version| and |release|, also used in various other places throughout the
+# built documents.
+#
+# The short X.Y version.
+version = '3'
+# The full version, including alpha/beta/rc tags.
+release = '3'
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+#language = None
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+#today = ''
+# Else, today_fmt is used as the format for a strftime call.
+#today_fmt = '%B %d, %Y'
+
+# List of documents that shouldn't be included in the build.
+#unused_docs = []
+
+# List of directories, relative to source directory, that shouldn't be searched
+# for source files.
+exclude_trees = ['.build']
+
+# The reST default role (used for this markup: `text`) to use for all documents.
+#default_role = None
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+#add_function_parentheses = True
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+#add_module_names = True
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+#show_authors = False
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+
+# Options for HTML output
+# -----------------------
+
+# The theme to use for HTML and HTML Help pages.  Major themes that come with
+# Sphinx are currently 'default' and 'sphinxdoc'.
+html_theme = 'default'
+
+# Theme options are theme-specific and customize the look and feel of a theme
+# further.  For a list of options available for each theme, see the
+# documentation.
+#html_theme_options = {}
+
+# Add any paths that contain custom themes here, relative to this directory.
+#html_theme_path = []
+
+# The name for this set of Sphinx documents.  If None, it defaults to
+# "<project> v<release> documentation".
+html_title = 'Dionysus'
+
+# A shorter title for the navigation bar.  Default is the same as html_title.
+#html_short_title = None
+
+# The name of an image file (relative to this directory) to place at the top
+# of the sidebar.
+#html_logo = None
+
+# The name of an image file (within the static path) to use as favicon of the
+# docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32
+# pixels large.
+#html_favicon = None
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ['.static']
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+html_last_updated_fmt = '%b %d, %Y'
+
+# If true, SmartyPants will be used to convert quotes and dashes to
+# typographically correct entities.
+html_use_smartypants = True
+
+# Custom sidebar templates, maps document names to template names.
+#html_sidebars = {}
+
+# Additional templates that should be rendered to pages, maps page names to
+# template names.
+#html_additional_pages = {}
+
+# If false, no module index is generated.
+#html_use_modindex = True
+
+# If false, no index is generated.
+#html_use_index = True
+
+# If true, the index is split into individual pages for each letter.
+#html_split_index = False
+
+# If true, the reST sources are included in the HTML build as _sources/<name>.
+#html_copy_source = True
+
+# If true, an OpenSearch description file will be output, and all pages will
+# contain a <link> tag referring to it.  The value of this option must be the
+# base URL from which the finished HTML is served.
+#html_use_opensearch = ''
+
+# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml").
+#html_file_suffix = ''
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'Dionysusdoc'
+
+
+# Options for LaTeX output
+# ------------------------
+
+# The paper size ('letter' or 'a4').
+#latex_paper_size = 'letter'
+
+# The font size ('10pt', '11pt' or '12pt').
+#latex_font_size = '10pt'
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title, author, document class [howto/manual]).
+latex_documents = [
+  ('index', 'Dionysus.tex', ur'Dionysus Documentation',
+   ur'Dmitriy Morozov', 'manual'),
+]
+
+# The name of an image file (relative to this directory) to place at the top of
+# the title page.
+#latex_logo = None
+
+# For "manual" documents, if this is true, then toplevel headings are parts,
+# not chapters.
+#latex_use_parts = False
+
+# Additional stuff for the LaTeX preamble.
+#latex_preamble = ''
+
+# Documents to append as an appendix to all manuals.
+#latex_appendices = []
+
+# If false, no module index is generated.
+#latex_use_modindex = True
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/examples/alphashape.rst	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,36 @@
+.. _alpha-shape-example:
+
+Alpha shape example
+===================
+
+The example given in :sfile:`examples/alphashapes/alphashapes.py` takes a
+filename containing points in 2D or 3D on the command line. It generates the
+alpha shape filtration of those points, and computes its persistence. It then
+outputs the persistence diagram in the format of a point (dimension, birth,
+death) per line.
+
+.. literalinclude:: ../../examples/alphashapes/alphashapes.py
+   :language: python
+
+After the points are read into the list ``points``, the functions
+:ref:`fill_alpha*_complex <alphashapes>` fill the :class:`Filtration` with the
+simplices of the Delaunay triangulation. Each one has its :attr:`~Simplex.data`
+attribute set to the tuple consisting of its alpha shape value (the minimum value of the squared
+distance function on its dual Voronoi cell) and whether the simplex is regular
+or critical.
+
+The filtration then sorts the simplices with
+respect to their data and dimension (via :func:`data_dim_cmp`)::
+
+    f = Filtration()
+    fill_alpha*_complex(points, f)
+    f.sort(data_dim_cmp)
+
+We initialize :class:`StaticPersistence`, and pair the simplices::
+
+    p = StaticPersistence(f)
+    p.pair_simplices()
+    
+Iterating over the :class:`StaticPersistence`, we output the points of the
+persistence diagram (dimension, birth, death) in the last for loop. If the
+simplex is unpaired (``i.unpaired()``), the class it creates survives till infinity.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/examples/cohomology.rst	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,129 @@
+.. _cohomology-parametrization:
+
+Parametrizing a point set using circle valued functions
+=======================================================
+
+The procedure described below is explained in detail in [dSVJ09]_.
+
+.. program:: rips-pairwise-cohomology
+
+One can use :sfile:`examples/cohomology/rips-pairwise-cohomology.cpp` to compute
+persistent pairing of the Rips filtration using the persistent cohomology
+algorithm. It takes as input a file containing a point set in Euclidean space
+(one per line) as well as the following command-line flags:
+
+.. cmdoption:: -p, --prime
+
+    The prime to use in the computation (defaults to 11).
+
+.. cmdoption:: -m, --max-distance
+
+    Maximum cutoff parameter up to which to compute the complex.
+
+.. cmdoption:: -s, --skeleton-dimension
+
+    Skeleton to compute; persistent pairs output will be this number minus 1
+    (defaults to 2).
+
+.. cmdoption:: -b, --boundary
+
+    Filename where to output the boundary matrix.
+
+.. cmdoption:: -c, --cocycle
+
+    Prefix of the filenames where to output the 1-dimensional cocycles.
+
+.. cmdoption:: -v, --vertices
+
+    Filename where to output the simplex vertex mapping.
+
+.. cmdoption:: -d, --diagram
+
+    Filename where to output the persistence diagram.
+
+
+For example::
+
+    rips-pairwise-cohomology points.txt -m 1 -b points.bdry -c points -v points.vrt -d points.dgm
+
+Assuming that at the threshold value of 1 (``-m 1`` above) Rips complex contains
+1-dimensional cocycles, they will be output into filenames of the form
+``points-0.ccl``, ``points-1.ccl``, etc.
+
+Subsequently one can use :sfile:`examples/cohomology/cocycle.py` to assign to
+each vertex of the input point set a circle-valued function. It takes the
+boundary matrix, cocycle, and simplex-vertex map as an input (all produced at
+the previous step)::
+
+    cocycle.py points.bdry points-0.ccl points.vrt
+
+The above command outputs a file ``points-0.val`` which contains values assigned
+to the input points (the lines match the lines of the input file
+``points.txt``, but also contains the indices).
+
+
+Plotting
+--------
+
+Two auxilliary tools allow one to visualize the values assigned to the points
+(using Matplotlib_): :sfile:`tools/plot-values/plot.py` and
+:sfile:`tools/plot-values/scatter.py`::
+    
+    plot.py points-0.val points.txt scatter.py points-0.val points-1.val
+
+.. _Matplotlib:                             http://matplotlib.sourceforge.net/    
+
+
+Dependency
+----------
+
+The Python `LSQR code`_ (ported from the `Stanford MATLAB implementation`_ to
+Python by `Jeffery Kline`_) included with Dionysus, and used in
+:sfile:`examples/cohomology/cocycle.py`, requires CVXOPT_.
+
+.. _`LSQR code`:                            http://pages.cs.wisc.edu/~kline/cvxopt/
+.. _CVXOPT:                                 http://abel.ee.ucla.edu/cvxopt/
+.. _`Stanford MATLAB implementation`:       http://www.stanford.edu/group/SOL/software/lsqr.html
+.. _`Jeffery Kline`:                        http://pages.cs.wisc.edu/~kline/
+
+
+.. _rips-pairwise-cohomology:
+
+Python cohomology computation
+-----------------------------
+
+:sfile:`examples/cohomology/rips-pairwise-cohomology.py` gives an example of the
+same computation performed in Python (but with the output in a different format).
+
+After the simplicial complex is computed in a list `simplices`, and the list is
+sorted with respect to the Rips filtration order, the simplices are inserted
+into the :class:`CohomologyPersistence` one by one::
+
+    # list simplices is created
+
+    ch = CohomologyPersistence(prime)
+    complex = {}
+
+    for s in simplices:
+        i,d = ch.add([complex[sb] for sb in s.boundary], (s.dimension(), s.data))
+        complex[s] = i
+        if d: 
+            dimension, birth = d
+            print dimension, birth, s.data
+        # else birth
+
+Above dictionary `complex` maintains the map of simplices to indices returned by
+:meth:`CohomologyPersistence.add`.  The pair `(dimension, data)` is used as the
+birth value. Here `data` is the value associated with the simplex in the Rips
+filtration. The pair is returned back if a death occurs, and is printed on the
+standard output. After the for loop finishes, one may output infinite
+persistence classes with the following for loop::
+
+    for ccl in ch:
+        dimension, birth = ccl.birth
+        if dimension >= skeleton: continue
+        print dimension, birth, 'inf'         # dimension, simplex data = birth
+    
+Naturally one may iterate over `ccl` which is of type :class:`Cocycle` and
+extract more information. For example, this is necessary to get the coefficients
+that serve as the input for :sfile:`examples/cohomology/cocycle.py`.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/examples/index.rst	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,55 @@
+.. _examples:
+
+Examples
+========
+
+The most basic example and therefore a good place to start getting acquainted
+with the library is the :ref:`triangle-example`. It adds simplices of a triangle
+one by one, and then (in case of a :ref:`triangle-zigzag-example`), removes them
+one by one.
+
+.. toctree::
+    
+    triangle
+    triangle-zigzag
+    
+The simplest example that instead of specifying the complex explicitly,
+constructs it from the input point set is the :ref:`alpha-shape-example`. The
+example reads points from a file, determines their dimension dynamically (based
+on the number of coordinates in the first line of the file), and then constructs
+an alpha shape and outputs its persistence diagram.
+
+.. toctree::
+
+    alphashape
+
+Another example that follows a similar strategy is the computation of the
+Vietoris-Rips complex. Since only pairwise distances are required it works with
+points in arbitrary dimension. (Of course, in dimensions 2 and 3 the complexes
+are much larger than those for the :ref:`alpha-shape-example`).
+
+.. toctree::
+    :maxdepth: 1
+
+    rips
+
+One may use persistent cohomology algorithm to extract persistent cocycles,
+turn them into harmonic cocycles, and use them to parametrize the input point
+set; for details see [dSVJ09]_. The explanation of how to use Dionysus to
+achieve this is available.
+
+.. toctree::
+    :maxdepth: 1
+
+    cohomology
+
+A simple example of computing persistence of a lower-star filtration is in
+:sfile:`examples/pl-functions/lsfiltration.py`.
+
+A C++-only, but useful example is computation of a vineyard of piecewise
+straight-line homotopy of piecewise-linear functions.
+
+.. toctree::
+    :maxdepth: 1
+
+    pl-vineyard
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/examples/pl-vineyard.rst	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,72 @@
+.. _pl-vineyard:
+
+Piecewise-Linear Vineyard
+=========================
+
+Given a simplicial complex :math:`K`, and a sequence of values on each one of
+its vertices, one may construct a homotopy of PL functions on the complex that
+interpolates linearly between the values. For any given time in the homotopy, we
+get a function from the simplicial complex to the real line, and we can compute
+its persistence diagram. Stacking all such diagrams together we get a
+persistence vineyard [CEM06]_. An example that computes such a vineyard is in 
+:sfile:`examples/pl-functions/pl-vineyard.cpp`. 
+
+.. program:: pl-vineyard
+
+Once compiled, it takes three files as the input::
+    
+    pl-vineyard complex values output-prefix
+
+``complex`` lists the simplices of the simplicial complex :math:`K`, one
+per-line::
+
+    0
+    1
+    0 1
+    2
+    0 2
+    ...
+
+``values`` lists the vertex values of the consequtive "frames" of the homotopy.
+Each line is a sequence of as many numbers as there are vertices in the complex.
+It describes a single frame. :program:`pl-vineayrd` constructs the homotopy over
+the interval :math:`[0,k-1]`, where :math:`k` is the number of frames. As an
+example of ``values`` input::
+
+    3.3   6    2
+    1.2   3    10
+    7.5   2.1  0
+
+This input means: :math:`f_0(0) = 3.3, f_1(0) = 1.2, f_2(0) = 7.5`. Similarly, 
+:math:`f_0(1) = 6, f_1(1) = 3, f_2(1) = 2.1`; 
+:math:`f_0(2) = 2, f_1(2) = 10, f_2(2) = 0`.
+
+The vineyard is saved to the files prefixed with ``output-prefix``, followed by
+the dimension and extension, e.g. ``myfunction1.vin`` or ``myfunction1.edg``,
+depending on the format. The two formats are vines and edges. The former saves
+one vine per line, listed as a stream of triplets BIRTH DEATH TIME::
+
+    4 5 0 3.4 5.6 0.4 3 6 1 ...
+
+The edge format represents the vine as a sequence of edges, each given as a
+start and end point. So the above vine would appear as::
+
+    4 5 0
+    3.4 5.6 0.4
+    3.4 5.6 0.4
+    3 6 1
+    ...
+
+:program:`pl-vineyard` takes additional options:
+
+.. cmdoption:: -s, --skip-infinite
+
+    Do not output infinite vines.
+
+.. cmdoption:: -v, --save-vines
+
+    Output vines, instead of the default edge format.
+
+.. cmdoption:: -e, --explicit-events
+
+    Go through the events one by one (useful for the debugging).
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/examples/rips.rst	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,71 @@
+.. _rips-example:
+
+Rips complex example
+====================
+
+.. todo::
+   Explain `Vietoris-Rips complex`_.
+
+There is an elementary example in :sfile:`examples/rips/rips.py` that computes a
+Rips complex of a few points with integer coordinates on a line. It illustrates
+the use of Rips complexes and in particular of defining your own notion of a
+:ref:`Distance <Distances>` based on which the Rips complex is constructed.
+
+A more useful example is given in :sfile:`examples/rips/rips-pairwise.py` (and
+its C++ counterpart in :sfile:`examples/rips/rips-pairwise.cpp`). The example
+takes on the command line the filename of a file with points in Euclidean space
+(one point per line), and a cut off parameters for the skeleton and the
+:math:`\epsilon` parameter for the Rips complex construction. It then constructs
+the Rips complex up to these cutoff parameters, computes its persistence, and
+outputs the persistence diagram (one point per line).
+
+.. literalinclude:: ../../examples/rips/rips-pairwise.py
+
+The bit that sets up the Rips complex is::
+
+    distances = PairwiseDistances(points)
+    rips = Rips(distances)
+    simplices = Filtration()
+    rips.generate(skeleton, max, simplices.append)
+
+The computation of persistence and output of the persistence diagram are the
+same as in the :ref:`alpha-shape-example`. The example also incorporates 
+the :ref:`speed-up-suggestions` given in the :ref:`tutorial`.
+
+
+
+C++ sketch
+----------
+.. highlight:: cpp
+
+.. warning:: This section is not finished.
+
+The example given in :sfile:`examples/rips/rips.cpp` illustrates how one can use
+the library to compute persistence of a `Vietoris-Rips complex`_ for a given set of
+distances. At the top of the file a `struct Distances` is defined. The
+particular distances in the example are trivial (they are points with integer
+coordinates on a real line), however, the `struct` illustrates the basic
+requirements of any such class to be passed to the `Rips<Distances>` class.
+
+.. _`Vietoris-Rips complex`:        http://en.wikipedia.org/wiki/Vietoris-Rips_complex
+
+The Rips complex itself is generated in the line::
+
+    rips.generate(2, 50, make_push_back_functor(complex));
+
+which tells it to generate a 2-skeleton of the Rips complex up to 
+distance value of 50, and insert the simplices into the previously defined
+vector `complex`. 
+
+Subsequent sort is unnecessary since Bron-Kerbosch algorithm that generates the
+complex will actually generate the simplices in lexicographic order; it's there
+for illustration purposes only (the simplices must be sorted
+lexicographically). 
+
+The following "paragraph" sets up the filtration with respect to simplex sizes
+(specified by `Generator::Comparison(distances)`), and computes its persistence::
+
+    // Generate filtration with respect to distance and compute its persistence
+    Fltr f(complex.begin(), complex.end(), Generator::Comparison(distances));
+    Persistence p(f);
+    p.pair_simplices();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/examples/triangle-zigzag.rst	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,38 @@
+.. _triangle-zigzag-example:
+
+Triangle zigzag example
+=======================
+
+Simple example of a filtered triangle where simplices are first inserted in a
+given order, and then removed in the reverse order is in
+:sfile:`examples/triangle/triangle-zigzag.cpp`. Its Python equivalent
+(:sfile:`examples/triangle/triangle-zigzag.py`) is described next.
+
+.. literalinclude:: ../../examples/triangle/triangle-zigzag.py
+   :language: python
+
+Unlike the :ref:`triangle-example`, here we use :class:`ZigzagPersistence` to
+compute the pairings, and therefore need to store the internal representations
+of the simplicies used by the class. These representation are stored in the
+dictionary ``complex``, which maps the simplices to their representations for
+:class:`ZigzagPersistence`.
+
+The first for loop processes the simplices sorted with respect to
+:func:`data_cmp`. :meth:`ZigzagPersistence.add` invoked within the loop accepts
+the boundary of the newly added cell in its internal representation, which is
+computed by looking up each simplex in the dictionary ``complex``:
+``[complex[ss] for ss in s.boundary]``. If there is a birth, the value to be
+associated with the newly created class is ``b`` (which in this case is simply a
+counter).  :meth:`~ZigzagPersistence.add` returns a pair ``(i,d)``. The former
+is an internal representation of the newly added cell, which we immediately
+record with ``complex[s] = i``. The latter is an indicator of whether a death
+has occurred, which happens iff ``d is not None``, in which case ``d`` is the
+birth value passed to :meth:`~ZigzagPersistence.add` whenever the class that
+just died was born. If the death occurred, then we outut the interval ``(d,
+b-1)``.
+
+The second for loop removes simplices in the reverse order of their insertion.
+:meth:`~ZigzagPersistence.remove` takes the index of the cells to be removed
+(looked up in the ``complex`` dictionary: ``complex[s]``), and takes a birth
+value in case a class is born. It return only a death indicator (which again is
+``None`` if no death occurred).
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/examples/triangle.rst	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,37 @@
+.. _triangle-example:
+
+Triangle example
+================
+
+Simple example of a filtered triangle is given in
+:sfile:`examples/triangle/triangle.cpp`. Its equivalent in Python appears in
+:sfile:`examples/triangle/triangle.py`, and we describe it next.
+
+.. literalinclude:: ../../examples/triangle/triangle.py
+   :language: python
+
+After the necessary imports, the ``complex`` is setup explicitly as a list of
+simplices. Each :class:`Simplex` constructor takes an iterable sequence of
+vertices, and optionally a data value.
+
+A filtration ``f`` is initialized using the :class:`Filtration` class, which
+takes a list of simplices (or anything iterable) and a comparison that defines
+in what order the simplices should come in the filtration. In this case we use
+:func:`data_cmp`, which simply compares simplices' :attr:`~Simplex.data`
+attributes.
+
+:class:`StaticPersistence` is initialized with the filtration, and its method
+:meth:`~StaticPersistence.pair_simplices` pairs the simplices of the
+filtration::
+
+    p = StaticPersistence(f)
+    p.pair_simplices()
+
+Subsequently, we iterate over ``p`` to access a representation of each simplex
+in the filtration order. We output each simplex, its sign, and its pair. The auxilliary 
+``smap = p.make_simplex_map(f)`` remaps the indices of :class:`StaticPersistence` into 
+the simplices in the filtration.
+Naturally, one could use this to access the
+:attr:`~Simplex.data` attribute of the simplices to output the actual
+persistence diagram, as is done in the :ref:`alpha-shape-example` and the
+:ref:`rips-example`.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/ext/cppdocs.py	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,202 @@
+from docutils               import nodes, utils
+from docutils.parsers.rst   import directives
+from sphinx                 import addnodes
+from sphinx.util.compat     import Directive
+
+from sphinx.directives.desc import CDesc
+
+############
+# CppClass #
+############
+class CppClass(nodes.Part, nodes.Element):
+    @staticmethod
+    def html_visit(visitor, node):
+        visitor.body.append('<dl class="class">')
+        visitor.body.append(visitor.starttag(node, 'dt'))
+        if node['tparams']:
+            visitor.body.append('<em class="property">template</em> &lt;')
+            tparam_names = ['class ' + tp[0] for tp in node['tparams']]
+            visitor.body.append(', '.join(tparam_names))
+            visitor.body.append('&gt;<br/>')
+            
+        visitor.body.append('<em class="property">class</em> ')
+        visitor.body.append('<tt class="descname">' + node['name'] + '</tt>')
+        visitor.body.append(u'<a class="headerlink" href="#%s" title="%s">\u00B6</a>' % 
+                              ('cppclass-'+node['name'], _('Permalink to this class')))
+        visitor.body.append('</dt>')
+        visitor.body.append('<dd>')
+
+        if node['derives']:
+            visitor.body.append('<p>Derives from ')
+            for d in node['derives'].split(','):
+                dnode ={ 'type': 'cppclass', 'target': d.strip() } 
+                Ref.html_visit(visitor, dnode)
+                visitor.body.append(d)
+                Ref.html_depart(visitor, dnode)
+            visitor.body.append('.</p>')
+
+        visitor.body.append('<p>')
+        for name, desc in node['tparams']:
+            visitor.body.append(name + ' &mdash; ' + desc + '<br/>')
+        visitor.body.append('</p>')
+
+
+    @staticmethod
+    def html_depart(visitor, node):
+        visitor.body.append('</dd></dl>')
+
+
+class CppClassDirective(Directive):
+    has_content = True
+    required_arguments = 1
+    final_argument_whitespace = True
+    option_spec = { 'derives': directives.unchanged,
+                    'tparam':  directives.unchanged }
+
+    def run(self):
+        env = self.state.document.settings.env
+
+        cppclass = CppClass()
+        cppclass['name'] = self.arguments[0]
+        cppclass['derives'] = self.options.get('derives')
+
+        targetname = '%s-%s' % ('cppclass', cppclass['name'])
+        targetnode = nodes.target('', '', ids=[targetname])
+        self.state.document.note_explicit_target(targetnode)
+
+        indextext = _('%s (C++ class)') % cppclass['name']
+        inode = addnodes.index(entries = [('single', indextext, 
+                                           'cppclass-' + cppclass['name'], 
+                                           cppclass['name'])])
+
+        self.state.nested_parse(self.content, self.content_offset, cppclass)
+
+        return [inode, targetnode, cppclass]
+
+class TParam(nodes.Element):
+    pass
+
+class TParamDirective(Directive):
+    required_arguments = 1
+    optional_arguments = 1
+    final_argument_whitespace = True
+
+    def run(self):
+        tparam = TParam()
+
+        tparam['name'] = self.arguments[0]
+        if len(self.arguments) > 1:
+            tparam['description'] = self.arguments[1]
+
+        return [tparam]
+
+
+#############
+# CppMethod #
+#############
+class CppMethod(nodes.Part, nodes.Element):
+    @staticmethod
+    def html_visit(visitor, node):
+        visitor.body.append(visitor.starttag(node, 'dt'))
+        visitor.body.append(node['name'])
+        visitor.body.append(u'<a class="headerlink" href="#%s" title="%s">\u00B6</a>' % 
+                             ('cppmethod-' + node['classname'] + '::' + node['name'], _('Permalink to this class')))
+        visitor.body.append('</dt>')
+        visitor.body.append('<dd>')
+
+    @staticmethod
+    def html_depart(visitor, node):
+        visitor.body.append('</dd></dl>')
+
+
+class CppMethodDirective(Directive):
+    has_content = True
+    required_arguments = 1
+    final_argument_whitespace = True
+
+    def run(self):
+        env = self.state.document.settings.env
+
+        cppmethod = CppMethod()
+        cppmethod['name'] = self.arguments[0]            # TODO: parse name
+
+        targetname = '%s-%s' % ('cppmethod', cppmethod['name'])
+        targetnode = nodes.target('', '', ids=[targetname])
+        self.state.document.note_explicit_target(targetnode)
+
+        indextext = _('%s (C++ method)') % cppmethod['name']
+        inode = addnodes.index(entries = [('single', indextext, 
+                                           'cppmethod-' + cppmethod['name'], 
+                                           cppmethod['name'])])
+
+        self.state.nested_parse(self.content, self.content_offset, cppmethod)
+
+        return [inode, targetnode, cppmethod]
+
+
+class Ref(nodes.Inline, nodes.TextElement):
+    @staticmethod
+    def html_visit(visitor, node):
+        if node['type'] == 'cppclass':
+            visitor.body.append('<a href="#%s-%s">' % (node['type'], node['target']))
+        elif node['type'] == 'cppmethod':
+            # TODO: check if the name is not fully qualified, and has a parent CppClass node, 
+            #       in that case, prepend the name, otherwise
+            visitor.body.append('<a href="#%s-%s::%s">' % (node['type'], node['classname'], node['target']))
+
+
+    @staticmethod
+    def html_depart(visitor, node):
+        visitor.body.append('</a>')
+
+def cppclass_role(role, rawtext ,text, lineno, inliner, options={}, content=[]):
+    text = utils.unescape(text)
+    node = Ref(text, text, target=text, type='cppclass')
+    node['docname'] = inliner.document.settings.env.docname
+    return [node], []
+
+def cppmethod_role(role, rawtext ,text, lineno, inliner, options={}, content=[]):
+    text = utils.unescape(text)
+    node = Ref(text, text, target=text, type='cppmethod')
+    node['docname'] = inliner.document.settings.env.docname
+    return [node], []
+
+
+def process_classnames(app, doctree, fromdocname):
+    for node in doctree.traverse(CppClass):
+        for method in node.traverse(CppMethod):
+            method['classname'] = node['name']
+        for ref in node.traverse(Ref):
+            if ref['type'] == 'cppmethod':
+                ref['classname'] = node['name']
+
+def process_tparams(app, doctree, fromdocname):
+    for node in doctree.traverse(CppClass):
+        node['tparams'] = []
+        for tparam in node.traverse(TParam):
+            node['tparams'].append((tparam['name'], tparam['description']))
+
+
+def process_cfunction_scope(app, doctree, fromdocname):
+    for node in doctree.traverse():
+        if 'ctype' in node: print node
+        if 'cfunction' in node: print node
+        
+def setup(app):
+    app.add_node(Ref,               html=(Ref.html_visit, Ref.html_depart))
+
+    app.add_directive('cppclass',   CppClassDirective)
+    app.add_node(CppClass,          html=(CppClass.html_visit, CppClass.html_depart))
+    app.add_role('cppclass',        cppclass_role)
+    
+    app.add_directive('tparam',     TParamDirective)
+    app.add_node(TParam,            html=(lambda v,n: '', lambda v,n: ''))
+    
+    app.add_directive('cppmethod',  CppMethodDirective)
+    app.add_node(CppMethod,         html=(CppMethod.html_visit, CppMethod.html_depart))
+    app.add_role('cppmethod',       cppmethod_role)
+
+    app.connect('doctree-resolved', process_classnames)
+    app.connect('doctree-resolved', process_tparams)
+    
+    app.connect('doctree-resolved', process_cfunction_scope)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/ext/sfile.py	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,14 @@
+from docutils import nodes, utils
+import posixpath
+
+def sfile_role(typ, rawtext, etext, lineno, inliner, options={}, content=[]):
+    env = inliner.document.settings.env
+    baseuri = env.config.sfile_base_uri
+    text = utils.unescape(etext)
+    refnode = nodes.reference('', '', refuri=posixpath.join(baseuri, text))
+    refnode += nodes.literal(text, text)
+    return [refnode], []
+
+def setup(app):
+    app.add_role('sfile', sfile_role)
+    app.add_config_value('sfile_base_uri', 'http://example.com/source', True) 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/ext/sprite_jsmath.py	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,2 @@
+def setup(app):
+    app.add_javascript('jsMath/plugins/spriteImageFonts.js')
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/get-build-install.rst	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,135 @@
+.. _download:
+
+Get, Build, Install
+===================
+
+The most up to date code is available from
+`my Mercurial repository`_.
+If you have Mercurial_, the easiest way to obtain the code is by cloning it:
+
+.. parsed-literal::
+
+  hg clone |dionysus-url|
+  cd Dionysus
+  hg up tip
+
+If you don't have time or desire to deal with Mercurial, you can download the
+`tarball of the entire repository`_. The advantage of using Mercurial is that it
+makes it very easy to keep up with the updates that are periodically committed
+to the repository::
+
+  hg pull -u
+
+
+.. |dionysus-url|   replace:: http://hg.mrzv.org/Dionysus/
+
+.. _Mercurial:      http://www.selenic.com/mercurial/
+
+.. _`tarball of the entire repository`:     http://hg.mrzv.org/Dionysus/archive/tip.tar.gz
+.. _`my Mercurial repository`:              http://hg.mrzv.org/Dionysus/
+
+
+Dependencies
+------------
+Dionysus requires the following software:
+
+  :CMake_:              for building (version :math:`\geq` 2.6)
+  :Boost_:              C++ utilities (version :math:`\geq` 1.36; including Boost.Python used to create
+                        Python bindings)
+
+Optional dependencies:
+
+  :CGAL_:               for alpha shapes   (version :math:`\geq` 3.4)
+  :CVXOPT_:             for :ref:`circle-valued parametrization <cohomology-parametrization>` using LSQR
+  :PyQt4_:              for :mod:`viewer` module
+  :PyOpenGL_, NumPy_:   for 3D visualization in :mod:`viewer` module
+  :PyX_:                :sfile:`tools/draw-diagram/draw.py` uses `PyX`_ to
+                        produce a PDF of the diagram
+  :rlog_:               used for logging only (not needed by default)
+
+..  :dsrpdb_:             for reading PDB files
+    :SYNAPS_:             for solving polynomials (for kinetic kernel), which in
+                        turn requires GMP_
+
+.. _CMake:          http://www.cmake.org
+.. _Boost:          http://www.boost.org
+.. _CGAL:           http://www.cgal.org
+.. _CVXOPT:         http://abel.ee.ucla.edu/cvxopt/
+.. _PyQt4:          http://www.riverbankcomputing.co.uk/software/pyqt/intro
+.. _PyOpenGL:       http://pyopengl.sourceforge.net/
+.. _NumPy:          http://numpy.scipy.org/
+.. _PyX:            http://pyx.sourceforge.net/
+.. _rlog:           http://www.arg0.net/rlog
+.. _dsrpdb:         http://www.salilab.org/~drussel/pdb/
+.. _SYNAPS:         http://www-sop.inria.fr/galaad/synaps/
+.. _GMP:            http://gmplib.org/
+
+
+Building
+--------
+To build the examples as well as the :ref:`Python bindings <python-bindings>`,
+create a directory ``build``. Inside that directory run ``cmake`` and ``make``::
+
+  mkdir build
+  cd build
+  cmake ..
+  make
+
+.. tip::
+
+   To use GCC 4.2 on a Mac one can try ``CXX=g++-4.2 cmake ..`` instead of
+   ``cmake ..``.
+
+Instead of ``cmake``, one can run ``ccmake`` for a curses interface. The
+following configuration options are available. One can set them either through
+the curses interface or by passing a flag of the form ``-Doptimize:bool=on`` to
+``cmake``.
+
+  :debug:         Turns on debugging compilation
+  :optimize:      Turns on compiler optimizations (`on` by default)
+  :logging:       Turns on logging facilities
+  :counters:      Turns on various built-in counters
+
+Depending on the combination of debugging and optimization, a particular
+``CMAKE_CXX_FLAGS*`` is chosen.
+
+.. tip::    The default settings work fine unless you want to dive into the
+            library's internals with logging or study the performance of various
+            algorithms with counters.
+
+.. todo::       Write sections on logging and counters.
+
+Some parts of Dionysus understand the ``DEBUG_CONTAINERS`` definition which can
+be appended to ``CMAKE_CXX_FLAGS``. If set, the library will use GCC STL's
+debugging containers (from the ``std::__debug`` namespace defined in ``debug/*``
+header files). These containers return safe iterators (the kind that check
+whether they are singular when compared, or additionally whether they are out of
+bounds when dereferenced).
+
+.. todo:: ``ZIGZAG_CONSISTENCY`` definition
+
+
+Install
+-------
+
+At the moment there are no installation procedures. To run the Python code you
+need to have ``.../build/bindings/python`` somewhere in your ``PYTHONPATH``.
+I.e. add::
+
+    export PYTHONPATH=.../build/bindings/python
+
+to your ``~/.bashrc`` (assuming you are using Bash_). Alternatively, run the
+python examples from within ``.../build/bindings/python``::
+
+    python .../Dionysus/examples/triangle/triangle.py
+
+The C++ examples can be run from anywhere. The C++ library consists only of
+header files (no library actually needs to be built), so to compile against it,
+it suffices to add ``-I .../Dionysus/include`` to your ``g++`` flags::
+
+    g++ your-code.cpp -o your-code -I .../Dionysus/include
+
+Proper installation procedures (with ``make install``) will be added in the
+future.
+
+.. _Bash:       http://www.gnu.org/software/bash/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/index.rst	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,60 @@
+Welcome to Dionysus' documentation!
+===================================
+
+Dionysus is a C++ library for computing persistent homology. It provides
+implementations of the following algorithms:
+
+.. sidebar:: Contents
+   
+   .. toctree::
+      :maxdepth: 1
+   
+      get-build-install
+      tutorial
+      examples/index
+      python/overview
+      bibliography
+
+* Persistent homology computation [ELZ02]_ [ZC05]_
+* Vineyards [CEM06]_    |cpp-only|
+* Persistent cohomology computation (described in [dSVJ09]_)
+* Zigzag persistent homology [CdSM09]_
+* :ref:`examples` provide useful functionality in and of themselves:
+  
+  * :ref:`Alpha shape construction <alpha-shape-example>` in 2D and 3D
+  * :ref:`Rips complex construction <rips-example>`
+  * Cech complex construction       |cpp-only|
+  * :ref:`Circle-valued parametrization <cohomology-parametrization>`
+  * :ref:`Piecewise-linear vineyards <pl-vineyard>`
+
+.. todo:: 
+   Document more examples.
+
+The C++ API is currently very poorly documented. One's best source for its
+documentation is its usage in various :ref:`examples` (located in
+:sfile:`examples/`).
+
+The :ref:`Python bindings <python-bindings>` provide both a simple interface to
+the low-level C++ functionality as well as high-level auxilliary routines. Their
+"thinness" is meant to provide the efficiency benefits of C++ together with the
+simplicity, elegance, and interactivity of Python. Since they mimick the C++
+functionality, their documentation may be a helpful resource for the latter.
+
+:ref:`Download <download>` the software, or read a :ref:`tutorial` to
+get acquainted with its structure.
+
+The library is distributed under the GPL_ license.
+
+.. _GPL: http://www.gnu.org/licenses/gpl.html
+
+.. include::    substitutions.aux
+
+
+..
+    Indices and tables
+    ==================
+
+    * :ref:`genindex`
+    * :ref:`modindex`
+    * :ref:`search`
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/python/alphashapes.rst	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,47 @@
+.. _alphashapes:
+
+Alpha shapes
+============
+
+There are two functions provided to compute alpha shapes. One in 2D and one in
+3D. Both take a list of points (each a list of coordinates) as input, and fill a
+list with the simplices of the `Delaunay triangulation`_. Each such simplex is
+said to be *attached* (or *regular*) if its dual Voronoi cell does not contain a
+critical point of the distance function to the point set. The smallest value of
+the squared distance function on the dual Voronoi cell of the Delaunay simplex
+is the alpha shape value assigned to it. This value is stored in the simplex's
+`data` attribute; whether it is attached is stored in the `attached` attribute.
+
+.. _`Delaunay triangulation`:   http://en.wikipedia.org/wiki/Delaunay_triangulation
+
+
+.. function:: fill_alpha_complex(points, complex)
+
+    Based on the dimension of the first point, decides which of the two functions
+    below to call.
+
+.. function:: fill_alpha2D_complex(points, complex)
+
+    Appends to the `complex` the simplices of the 2D Delaunay triangulation
+    on the `points`.
+
+.. function:: fill_alpha3D_complex(points, complex)
+
+    Appends to the `complex` the simplices of the 3D Delaunay triangulation
+    on the `points`.
+
+
+Example
+-------
+
+The following example generates 10 points on a circle, and computes their
+Delaunay triangulation with corresponding alpha shape values::
+
+    from math import sin, cos, pi
+    points = [[cos(2*pi*t/10), sin(2*pi*t/10)] for t in xrange(10)]
+    complex = Filtration()
+    fill_alpha2D_complex(points, complex)
+
+One can extract any given alpha shape with the usual Python list notation::
+
+    alphashape = [s for s in complex if s.data[0] <= .5]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/python/cohomology-persistence.rst	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,175 @@
+:class:`CohomologyPersistence` class
+====================================
+
+The :ref:`rips-pairwise-cohomology` illustrates the use of :class:`CohomologyPersistence`.
+
+.. class:: CohomologyPersistence
+
+    .. method:: __init__(prime = 11)
+
+        Initializes :class:`CohomologyPersistence` with the given `prime`; from
+        this point on all the computation will be performed with coefficients
+        in :math:`\mathbb{Z}/prime \mathbb{Z}`.
+
+    .. method:: add(boundary, birth, [store = True], [image = True], [coefficients = []])
+
+        Adds a simplex with the given `boundary` to the complex, i.e.
+        :math:`K_{i+1} = K_i \cup \sigma` and `boundary` = :math:`\partial \sigma`.
+        If a new class is born as a result of the addition, `birth` is stored with
+        it for future reference.
+
+        If `store` is ``False`` and a class is born, it will not be stored in
+        :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.
+
+        The `image` parameter allows one to work with a case of a space
+        :math:`L \subseteq K` where the filtration of :math:`K` induces a
+        filtration of :math:`L`. In this case, one may want to compute **image
+        persistence** (i.e. the persistence of the sequences of the images given
+        by the inclusion of :math:`L` in :math:`K`). `image` indicates whether
+        the simplex added belongs to :math:`L` or not.
+
+        If given, `coefficients` is a list parallel to `boundary` that provides
+        coefficients for the corresponding boundary elements. If empty, it is
+        assumed to be :math:`(-1)^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 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__()
+
+        Iterator over the live cocycles stored in
+        :class:`CohomologyPersistence`. The returned elements are of the type
+        :class:`Cocycle` below.
+
+
+.. class:: Cocycle
+
+    .. attribute:: birth
+
+        The birth value associated with the cocycle. It is passed to
+        :class:`CohomologyPersistence` in method
+        :meth:`~CohomologyPersistence.add`.
+
+    .. method:: __iter__()
+
+        Iterator over the individual nodes (simplices) of the cocycle, each of type
+        :class:`CHSNode`.
+
+.. class:: CHSNode
+
+    .. attribute:: si
+
+        The index of the simplex, of type :class:`CHSimplexIndex`.
+
+    .. attribute:: coefficient
+
+        Coefficient in :math:`\mathbb{Z}/prime \mathbb{Z}` associated with the
+        simplex.
+
+
+.. class:: CHSimplexIndex
+
+    .. attribute:: order
+
+        The count associated with the simplex when it is inserted into
+        :class:`CohomologyPersistence`.
+
+
+Adaptor
+-------
+
+:class:`StaticCohomologyPersistence` provides a wrapper around
+class :class:`CohomologyPersistence` that's compatible with :class:`StaticPersistence`.
+See the documentation of the latter class for details.
+
+
+.. class:: StaticCohomologyPersistence
+
+   .. method:: __init__(filtration, prime = 2)
+
+        Initializes :class:`StaticCohomologyPersistence` with the given
+        :class:`Filtration`. `prime` is passed straight to the wrapped
+        :class:`CohomologyPersistence` class.
+
+   .. method:: pair_simplices()
+
+        Pairs simplices using :class:`CohomologyPersistence` class.
+
+   .. method:: __call__(i)
+
+        Given a node in the internal representation, the method returns its
+        integer offset from the beginning of the filtration.
+
+   .. method:: make_simplex_map(filtration)
+
+        Creates an auxilliary map from the nodes to the simplices::
+
+            smap = persistence.make_simplex_map(filtration)
+            for i in persistence:
+                if i.unpaired(): print smap[i]
+
+   .. method:: __iter__()
+
+        Iterator over the nodes (representing individual simplices). See
+        :class:`APNode`.
+
+   .. method:: __len__()
+
+        Returns the number of nodes (i.e. the number of simplices).
+
+.. class:: APNode
+
+    The following methods behave the same way as they do in :class:`SPNode`.
+
+    .. method:: sign()
+
+    .. method:: pair()
+
+    .. method:: unpaired()
+
+    The only crucial distinction in the behavior comes with the attribute
+    :attr:`cocycle`.
+
+    .. attribute:: cocycle
+
+        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.
+        ::
+
+            for i in persistence:
+                if i.sign(): print i.cocycle
+
+
+.. class:: ImagePersistence
+
+    This class is another wrapper around :class:`CohomologyPersistence` that can
+    compute image persistence induced by inclusion of a subcomplex. Its
+    interface is the same as :class:`StaticCohomologyPersistence` above, except
+    for the constructor:
+
+    .. method:: __init__(filtration, subcomplex)
+
+       `subcomplex` is a function called with every simplex. It should return
+       ``True`` if the simplex belong to the subcomplex; ``False`` otherwise.
+
+
+Circular coordinates
+--------------------
+
+.. function:: circular.smooth(filtration, cocycle)
+
+   Returns a map from the vertices of the simplicial complex `filtration` to a circle :math:`[-.5, .5]`,
+   where the opposite ends of the interval are identified.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/python/filtration.rst	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,43 @@
+:class:`Filtration` class
+=========================
+
+.. class:: Filtration
+    
+    This class serves as a representation of the simplicial complex. It knows both 
+    how to perform a fast lookup of a given simplex, as well as how to 
+    iterate over the simplices in a sorted order.
+
+    .. method:: __init__()
+    .. method:: __init__(simplices, cmp)
+    
+        Initializes :class:`Filtration` by internally storing the elements of the sequence
+        `simplices`, and  in the order sorted with respect to `cmp`.
+
+    .. method:: append(s)
+        
+        Appends the given simplex `s` to the filtration.
+
+    .. method:: sort(cmp)
+
+        Sorts the filtration with respect to the comparison `cmp`.
+
+    .. method:: __getitem__(i)
+
+        Random access to the elements of the filtration.
+
+    .. method:: __call__(s)
+        
+        Finds the integer index of the given simplex in the sorted order of the filtration.
+
+    .. method:: __iter__()
+ 
+        Iterator over the elements of the filtration sorted with respect
+        to the comparison `cmp`. E.g.::
+
+            simplices = [Simplex([0], 2), ..., Simplex([3,4,5], 3.5)]
+            f = Filtration(simplices, data_dim_cmp)
+            for s in f: print s
+
+    .. method:: __len__()
+
+        Size of the filtration.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/python/overview.rst	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,24 @@
+.. _python-bindings:
+
+Python bindings: module :mod:`dionysus`
+=======================================
+
+.. module::         dionysus
+.. moduleauthor::   Dmitriy Morozov <dmitriy@mrzv.org>
+
+The :ref:`tutorial` describes how to use the bindings. The pages in this section
+document the API of various classes and functions.
+
+The following classes are available in the module:
+
+.. toctree::
+    :maxdepth: 1
+
+    simplex.rst
+    filtration.rst
+    static-persistence.rst
+    cohomology-persistence.rst
+    alphashapes.rst
+    rips.rst
+    zigzag-persistence.rst
+    persistence-diagram.rst
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/python/persistence-diagram.rst	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,67 @@
+:class:`PersistenceDiagram` class
+==================================
+
+.. class:: PersistenceDiagram
+
+    .. method:: __init__( dimension )
+
+        Initializes : an empty( no points ) :class:`PersistenceDiagram` object and sets
+        the :attr:`~PersistenceDiagram.dimension` attribute( must be integer ) e.g.::
+
+            dia = PersistenceDiagram( 1 )
+
+    .. method:: __init__( dimension, point_seq )
+
+        Initializes :class:`PersistenceDiagram` of specified dimension from the given sequence `seq` of tuples, e.g.::
+
+            dia = PersistenceDiagram( 1, (1,2) )
+
+        The tuples must have at least 2 elements ``(birth, death)``.
+        If there is a third element, it is stored as extra data associated to
+        a point.
+
+    .. method:: append( p )
+
+        Adds point `p` to the persistence diagram.
+
+    .. attribute:: dimension
+
+        Dimension of the persistence diagram. Must be an integer. Must be set at initialization.
+
+    .. method:: __iter__( )
+
+        Iterator over the points in the persistence diagram,
+        e.g.::
+
+            for p in dia: print p
+
+    .. method:: __len__( )
+
+        :returns: The number of points in the diagram.
+
+
+
+Utility functions for persistence diagrams
+--------------------------------------------
+
+.. function:: init_diagrams(persistence, filtration[, eval = lambda s: s.data[, data = lambda i: None]])
+
+    Initializes a collection of :class:`PersistenceDiagram` instances from `persistence`
+    and `filtration`. Optional `eval` can determine how to extract birth and
+    death values from a simplex. For example, if `filtration` was filled using
+    :func:`fill_alpha_complex()`, the :attr:`~Simplex.data` contains a pair ``(value, critical)``.
+    We can extract the ``value`` from the tuple::
+
+        init_diagrams(persistence, filtration, lambda s: s.data[0])
+
+    Optional `data` argument can return arbitrary data to associate with each point,
+    given an node of `persistence`.
+
+.. function:: bottleneck_distance(dia1, dia2)
+
+    Calculates the bottleneck distance between the two persistence diagrams.
+
+.. function:: wasserstein_distance(dia1, dia2, p)
+
+    Calculates the `p`-th Wasserstein distance between the two persistence diagrams.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/python/rips.rst	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,114 @@
+:class:`Rips` class
+======================
+
+.. class:: Rips
+
+    .. method:: __init__(distances)
+    
+        Initializes :class:`Rips` with the given `distances` whose main purpose
+        is to return the distance of two points given their indices. See
+        Distances_ below.
+
+    .. method:: generate(k, max, functor[, seq])
+     
+        Calls `functor` with every simplex in the `k`-skeleton of the Rips
+        complex :math:`VR` (`max`). If `seq` is provided, then the complex is
+        restricted to the vertex indices in the sequence.
+
+    .. method:: vertex_cofaces(v, k, max, functor[, seq])
+     
+        Calls `functor` with every coface of the vertex `v` in the `k`-skeleton
+        of the Rips complex :math:`VR` (`max`). If `seq` is provided, then the
+        complex is restricted to the vertex indices in the sequence.
+
+    .. method:: edge_cofaces(u, v, k, max, functor[, seq])
+     
+        Calls `functor` with every coface of the edge (`u`, `v`) in the
+        `k`-skeleton of the Rips complex :math:`VR` (`max`). If `seq` is
+        provided, then the complex is restricted to the vertex indices in the
+        sequence.
+
+    .. method:: cmp(s1, s2)
+
+        Compares simplices `s1` and `s2` with respect to their ordering in the
+        Rips complex.  Note that like Python's built in `cmp` this is a three
+        possible outsome comparison (-1,0,1) for (:math:`\leq, =, \geq`,
+        respectively).
+
+    .. method:: eval(s)
+
+        Returns the size of simplex `s`, i.e. the length of its longest edge.
+
+
+.. _distances:
+
+Distances
+---------
+
+An instance of `distances` passed to the constructor of :class:`Rips` should
+know its length and the distances between the points. The length should be
+retrievable via ``len(distance)`` and it determines how many points the complex
+is built on. The distances between the points are inferred by the class
+:class:`Rips` by calling `distances` with a pair of vertices as arguments.
+
+For example, the following class represents 10 points on an integer lattice::
+
+    class Distances:
+        def __len__(self): 
+            return 10
+
+        def __call__(self, x, y):
+            return math.fabs(y-x)
+
+The bindings expose a C++ class as a Python class :class:`PairwiseDistances` to deal with
+explicit points in a Euclidean space. In pure Python it could be defined as
+follows (in fact it used to be a pure Python class, and one may still find it in 
+:sfile:`bindings/python/dionysus/distances.py`; its performance is much slower
+than its pure C++ analog)::
+
+    class PairwiseDistances:
+        def __init__(self, points, norm = l2):
+            self.points = points
+            self.norm = norm
+
+        def __len__(self):
+            return len(self.points)
+
+        def __call__(self, p1, p2):
+            return self.norm([x - y for (x,y) in zip(self.points[p1], self.points[p2])])
+
+Another distances class is available that speeds up the computation of the Rips
+complex at the expense of the memory usage: :class:`ExplicitDistances`. It is
+initialized with an instance of any class that behaves like a distances class,
+and it stores all of its distances explicitly to not have to recompute them in
+the future::
+
+    distances = PairwiseDistances(points)
+    distances = ExplicitDistances(distances)
+
+With :class:`PairwiseDistances` being a C++ class, and
+:class:`ExplicitDistances` being pure Python, the speed-up seems minor.
+
+
+Example
+-------
+
+The following example reads in points from a file, and fills the list
+`simplices` with the simplices of the 2-skeleton of the Rips complex built on
+those vertices with distance cutoff parameter 50. Subsequently it computes the
+persistence of the resulting filtration (defined by ``rips.cmp``)::
+
+    points = [for p in points_file('...')]
+    distances = PairwiseDistances(points)
+    rips = Rips(distances)
+    simplices = Filtration()
+    rips.generate(2, 50, simplices.append)
+    
+    simplices.sort(rips.cmp)
+    p = StaticPersistence(simplices)
+    p.pair_simplices()
+
+Essentially the same example is implemented in
+:sfile:`examples/rips/rips-pairwise.py`, although it reads the `k` and `max`
+parameters for the Rips complex on the command line, and uses a trick to speed
+up the computation.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/python/simplex.rst	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,84 @@
+:class:`Simplex` class
+======================
+
+.. class:: Simplex
+
+    .. method:: __init__(seq[, data])
+    
+        Initializes :class:`Simplex` from the given sequence `seq` and
+        optionally real value `data`, e.g.::
+    
+            s = Simplex([1,2,3], 7.8)
+
+    .. method:: add(v)
+        
+        Adds vertex `v` to the simplex, increasing its dimension by 1.
+
+        .. seealso:: :meth:`~Simplex.join`
+
+    .. attribute:: boundary
+
+        Iterator over the boundary :math:`\partial \sigma` of the simplex,
+        e.g.::
+            
+            for sb in s.boundary: print sb
+
+    .. method:: contains(v)
+
+        :returns: `True` iff the simplex contains vertex `v`.
+
+    .. method:: dimension()
+
+        :returns: the dimension of the simplex (one less than its number of
+                  vertices).
+
+    .. method:: join(other)
+        
+        Joins the current simplex with the `other` simplex. The method copies over 
+        the vertices from the `other` simplex.
+
+    .. attribute:: data
+        
+        Real value stored in the simplex.
+
+    .. attribute:: vertices
+
+        (Sorted) vertices of the simplex accessible as a sequence, e.g.::
+        
+            for v in s.vertices: print v,
+
+    .. method:: __hash__()
+    .. method:: __eq__(other)
+
+        Simplices are hashable, and equality comparable, and therefore can be
+        stored in a dictionary.  Simplices are equal if their
+        :attr:`~Simplex.vertices` are the same.
+
+
+Utility functions for manipulating simplices
+--------------------------------------------
+
+The first function :func:`vertex_cmp` is a Python interface to a C++ function.
+The rest are pure Python functions defined in
+:sfile:`bindings/python/dionysus/__init__.py`.
+
+.. function:: vertex_cmp(s1, s2)
+    
+    Compares the two simplices with respect to the lexicographic order of their vertices.
+
+.. function:: vertex_dim_cmp(s1, s2)
+    
+    Compares the two simplices with respect to their dimension, and lexicographically 
+    within the same dimension.
+
+.. function:: data_cmp(s1, s2)
+    
+    Compares the two simplices with respect to the data (real values) they
+    store.
+
+.. function:: data_dim_cmp(s1, s2)
+    
+    Compares the two simplices with respect to their dimension and within the same 
+    dimension with respect to their data.
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/python/static-persistence.rst	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,113 @@
+:class:`StaticPersistence` class
+================================
+
+.. class:: StaticPersistence
+
+    .. method:: __init__(filtration)
+
+        Initializes :class:`StaticPersistence` with the given
+        :class:`Filtration`. This operation effectively computes the boundary
+        matrix of the complex captured by the filtration with rows and columns
+        sorted with respect to the filtration ordering.
+
+    .. method:: pair_simplices(store_negative = False)
+
+        Pairs simplices using the [ELZ02]_ algorithm. `store_negative` indicates
+        whether to store the negative simplices in the cycles.
+
+    .. method:: __call__(i)
+
+        Given an SPNode in the internal representation, the method returns its
+        integer offset from the beginning of the filtration. This is useful to
+        lookup the actual name of the simplex in the complex.
+
+    .. method:: make_simplex_map(filtration)
+
+        Creates an auxilliary :class:`PersistenceSimplexMap` used to lookup the actual
+        simplices from the persistence indices. For example, the following
+        snippet prints out all the unpaired simplices::
+
+            smap = persistence.make_simplex_map(filtration)
+            for i in persistence:
+                if i.unpaired(): print smap[i]
+
+    .. method:: __iter__()
+
+        Iterator over the nodes (representing individual simplices). See
+        :class:`SPNode`.
+
+    .. method:: __len__()
+
+        Returns the number of nodes (i.e. the number of simplices).
+
+
+.. class:: SPNode
+
+    The class represents nodes stored in :class:`StaticPersistence`. These nodes
+    are aware of their :meth:`sign` and :attr:`pair` (and :meth:`cycle` if
+    negative after :meth:`StaticPersistence.pair_simplices` has run).
+
+    .. method:: sign()
+
+        Returns the sign of the simplex: `True` for positive, `False` for
+        negative.
+
+    .. method:: pair()
+
+        Simplex's pair. The pair is set to self if the siplex is unpaired.
+
+    .. attribute:: cycle
+
+        If the simplex is negative, its cycle (that it kills) is non-empty, and
+        can be accessed using this method. The cycle itself is an iterable
+        container of :class:`SPNode`. For example, one can print the basis for
+        the (bounding) cycles::
+
+            smap = persistence.make_simplex_map(filtration)
+            for i in persistence:
+                for ii in i.cycle: print smap[ii]
+
+    .. method:: unpaired()
+
+        Indicates whether the simplex is unpaired.
+
+.. class:: SPersistenceSimplexMap
+
+    .. method:: __getitem__(i)
+
+        Given a persistence index, i.e. an :class:`SPNode`, returns the
+        :class:`Simplex` it represents.
+
+
+:class:`DynamicPersistenceChains` class
+=======================================
+
+.. class:: DynamicPersistenceChains
+
+    This class works exactly like :class:`StaticPersistence`, providing all the
+    same methods. The only difference is that when iterating over it, the
+    elements are of type :class:`DPCNode`, described below. 
+
+.. class:: DPCNode
+
+    This class works just like :class:`SPNode`, except it has an additional
+    attribute :attr:`chain`. 
+
+    .. attribute:: chain
+    
+        It allows one to retrieve the "chain" associated with the simplex. 
+        (In terms of the :math:`R = DV` decomposition, it gives access to the
+        columns of the matrix :math:`V`.) In case of the positive simplex, this
+        is a cycle created by the addition of this simplex.  This access is
+        particularly useful for the unpaired positive simplices, allowing one to
+        recover the cycles they create. In case of the negative simplex, this chain's
+        boundary is exactly what's stored in the :attr:`~SPNode.cycle` attribute.
+    
+        For example, to print out all the essential cycles of the complex, one
+        can run the following loop::
+
+            smap = persistence.make_simplex_map(filtration)
+            for i in persistence:
+                if i.unpaired()
+                    for ii in i.chain: print smap[ii]
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/python/zigzag-persistence.rst	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,115 @@
+:class:`ZigzagPersistence` class
+================================
+
+The class deals with the setting :math:`K_1 \rightarrow K_2 \leftarrow K_3 \rightarrow \dots`.
+The :ref:`triangle-zigzag-example` illustrates the use of :class:`ZigzagPersistence`.
+
+.. class:: ZigzagPersistence
+
+    .. method:: add(boundary, birth)
+        
+        Adds a simplex with the given `boundary` to the complex, i.e. 
+        :math:`K_{i+1} = K_i \cup \sigma` and `boundary` = :math:`\partial \sigma`.
+        If a new class is born as a result of the addition, `birth` is stored with 
+        it for future reference.
+
+        :returns: a pair (`i`, `d`). 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
+                  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:`~ZigzagPersistence.add` or
+                  :meth:`~ZigzagPersistence.remove` when the class that just
+                  died was born.
+
+    .. method:: remove(index, birth)
+      
+        Removes the simplex identified by the given `index` from the complex. If
+        a new class is born as a result of the removal, `birth` is stored with
+        it for future reference.
+        
+        :returns: `None` if a birth has occurred, otherwise it contains the value 
+                  passed as `birth` to :meth:`~ZigzagPersistence.add` or
+                  :meth:`~ZigzagPersistence.remove` when the class that just
+                  died was born.
+
+    .. method:: is_alive(z)
+
+        Determines whether a given cycle is alive. The input should be an
+        instance of :class:`ZNode`.
+
+    .. method:: __iter__()
+
+        Iterator over elements of type :class:`ZNode`, i.e. the cycles stored in the structure.
+
+.. class:: ZNode
+
+    .. attribute:: birth
+
+        The birth value associated with the cycle. It is passed to
+        :class:`ZigzagPersistence` in method
+        :meth:`~ZigzagPersistence.add`.
+
+    .. method:: __iter__()
+
+        Iterator over the individual nodes (simplices) of the cycle (same
+        indices that are passed to and returned by
+        :meth:`~ZigzagPersistence.add`.
+
+
+Auxilliary functions
+--------------------
+
+A pair of auxilliary functions is provided to help add and remove entire
+collections of simplices. Both are pure Python functions defined in
+:sfile:`bindings/python/dionysus/zigzag.py`.
+
+    .. function:: add_simplices(zigzag, simplices, complex, birth, report_local = False)
+
+        Adds each simplex in `simplices` to the `zigzag`. `complex` is a
+        dictionary mapping simplices to their indices (in `zigzag`'s internal
+        representation). All the newly born classes are given the value of
+        `birth`.
+
+        :returns: list of deaths that occur as a result of `simplices`' removal. 
+                  Each death is a pair of the dimension of the class and the
+                  `birth` value passed when the class was born.  By default the
+                  deaths equal to `birth` are not reported unless `report_local`
+                  is set to `True`.
+
+    .. function:: remove_simplices(zigzag, simplices, complex, birth, report_local = False)
+
+        Same parameters and return as in :func:`add_simplices` except that
+        `simplices` are removed from the `zigzag` and the `complex`.
+
+
+
+:class:`ImageZigzagPersistence` class
+=====================================
+
+The class deals with the setting 
+
+.. math::
+    \begin{array}{ccccccc}
+        K_1         & \rightarrow   & K_2       &   \leftarrow      & K_3       & \rightarrow   & \dots \\
+        \uparrow    &               & \uparrow  &                   & \uparrow  & \\
+        L_1         & \rightarrow   & L_2       &   \leftarrow      & L_3       & \rightarrow   & \dots
+    \end{array}
+
+where the vertical maps are inclusions, i.e. :math:`L_i \subseteq K_i`.
+
+.. class:: ImageZigzagPersistence
+
+    .. method:: add(boundary, subcomplex, birth)
+ 
+        Interface is the same as in :meth:`ZigzagPersistence.add`. The
+        additional parameter `subcomplex` controls whether the simplex is added
+        to :math:`L` or not. We always have :math:`K_{i+1} = K_i \cup \sigma`.
+        If `subcomplex` is true, then :math:`L_{i+1} = L_i \cup \sigma`,
+        otherwise :math:`L_{i+1} = L_i`.
+
+    .. method:: remove(index, birth)
+      
+        Interface is exactly the same as in :meth:`ZigzagPersistence.remove`.        
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/substitutions.aux	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,2 @@
+.. |cpp-only|   replace:: :sup:`(C++ only)`
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/tutorial.rst	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,203 @@
+.. _tutorial:
+
+Brief Tutorial
+==============
+
+It suffices to import only the necessary commands from module :mod:`dionysus`,
+but for the purposes of the tutorial, we import everything::
+
+    from dionysus import *
+
+Read in a points file (for :func:`points_file` the points should appear one per
+line with coordinates separated with spaces; of course, one can read in the
+points however one wants)::
+
+    points = [p for p in points_file('points_filename')]
+    print "Number of points:", len(points)
+
+
+Complexes
+---------
+
+If the points are in :math:`\mathbb{R}^2` or :math:`\mathbb{R}^3`, one can
+construct an alphashape filtration::
+
+    simplices = Filtration()
+    fill_alpha2D_complex(points, simplices)     # for 2D, or
+    fill_alpha3D_complex(points, simplices)     # for 3D
+
+
+Functions :ref:`fill_alpha*_complex <alphashapes>` fill the ``simplices``
+with all the :class:`simplices <Simplex>` of the Delaunay triangulation. 
+Each one has its attribute ``data`` set to a pair: the
+smallest value of the squared distance function on the dual Voronoi cell and
+whether the simplex is critical or not (i.e. whether its dual cell does or
+does not contain a critical point of the distance function).
+See :ref:`alphashapes` for more details, and :ref:`alpha-shape-example` for a
+full example.
+
+As a result, if one wanted only those simplices whose alpha shape value did not
+exceed 10, one could obtain them as follows::
+
+    simplices10 = [s for s in simplices if s.data[0] <= 10]
+
+If the point set lies in higher dimensions, one may construct a Rips complex on
+it. This complex requires only pairwise distances, which makes it very
+versatile. One must first construct an instance of a class providing such
+distances (e.g. :class:`PairwiseDistances` for explicit points, see
+:ref:`distances` for more details), and then pass it to the :class:`Rips`
+complex class::
+
+    distances = PairwiseDistances(points)
+    rips = Rips(distances)
+
+Usually, because of space restrictions, generation of a Rips complex has to be
+restricted to a :math:`k`-skeleton of the complex and some maximal parameter
+:math:`max`. In the following example :math:`k = 3` and :math:`max = 50`::
+
+    simplices = Filtration()
+    rips.generate(3, 50, simplices.append)
+
+:meth:`Rips.generate` takes a skeleton and a maximum distance cutoffs, and a
+function which is called with each of the simplices in the complex (in this
+case, Python list `simplices`' ``append`` method).
+    
+
+Persistence
+-----------
+
+There are two ways of computing persistence in Dionysus. The first *offline*
+way, required by :class:`StaticPersistence` (and its derivatives), is to set up
+the entire filtration at once, compute its persistence in one operation, and
+then examine the pairings. The second way is to feed simplices one by one in an
+*online* manner and manually keep track of the pairs that are created.
+:class:`ZigzagPersistence` and :class:`CohomologyPersistence` accept their
+input this way,
+
+
+Offline
+^^^^^^^
+
+For the first approach, i.e. to use :class:`StaticPersistence`, one must put the
+sort the filtration with respect to some ordering
+(for example, :func:`data_dim_cmp` for alpha shapes or :meth:`Rips.cmp` for the
+Rips complex)::
+
+    simplices.sort(data_dim_cmp)     # for the alpha shapes
+    simplices.sort(rips.cmp)         # for the rips complex
+
+Creating an instance of :class:`StaticPersistence` initialized with the
+filtration really initializes a boundary matrix. The subsequent call to
+:meth:`~StaticPersistence.pair_simplices` reduces the matrix to compute the
+persistence of the filtration::
+
+    p = StaticPersistence(simplices)
+    p.pair_simplices()
+
+Once the simplices are paired, one may examine the pairings by iterating over
+the instance of :class:`StaticPersistence`. We can use an auxilliary map ``smap`` 
+to remap the persistence indices into the actual simplices::
+
+    smap = p.make_simplex_map(simplices)
+    for i in p:
+        if i.sign():
+            birth = smap[i]
+            if i.unpaired():
+                print birth.dimension(), birth.data, "inf"
+                continue
+            
+            death = smap[i.pair()]
+            print birth.dimension(), birth.data, death.data
+
+The iterator ``i`` over the instance ``p`` of :class:`StaticPersistence` is of type
+:class:`SPNode`, and represents individual simplices taken in the filtration
+order. It knows about its own :meth:`~SPNode.sign` and :meth:`~SPNode.pair` as well as
+whether it is :math:`~SPNode.unpaired`. :meth:`StaticPersistence.make_simplex_map` creates 
+a map that we use to get the actual simplices: ``smap[i]`` and ``smap[i.pair()]``.
+The previous code snippet prints out the persistence diagrams of the given
+filtration.
+
+
+Online
+^^^^^^
+
+Class :class:`ZigzagPersistence` accepts additions and removals of the simplices
+one by one, and returns an internal representation of the simplices.
+(:class:`CohomologyPersistence` works in the same way, but accepts only
+additions of the simplices.) 
+When one
+adds a simplex via :meth:`ZigzagPersistence.add`, one must provide its boundary
+in this internal representation together with a *birth value* which
+:class:`ZigzagPersistence` will store in case a class is born as a result of the
+addition. :meth:`~ZigzagPersistence.add` returns a pair ``(i,d)``. ``i`` is the
+internal representation of the newly added simplex, which one must record for
+future use in the boundaries of its cofaces (below it is recorded in the
+dictionary ``complex``). ``d`` is `None` in case of the birth, otherwise, it is the
+previously recorded birth value of the class that dies as a result of the
+addition. The following code adds all the ``simplices`` to a zigzag::
+
+    simplices.sort(data_dim_cmp)
+    complex = {}
+    zz = ZigzagPersistence()
+    for s in simplices:
+        i,d = zz.add([complex[sb] for sb in s.boundary], (s.dimension(), s.data))
+        complex[s] = i
+        if d is not None:                   # we have a death
+            dimension, birth = d            # we previously stored the (dimension, data) pair
+            print dimension, birth, s.data       
+
+Similarly, one can remove simplices by calling :meth:`ZigzagPersistence.remove`
+with the internal index previously returned by :meth:`~ZigzagPersistence.add`::
+
+    for s in reversed(simplices):
+        d = zz.remove(complex[s], (s.dimension() - 1, s.data))
+        del complex[s]
+        if d is not None:
+            dimension, birth = d
+            print dimension, birth, s.data
+
+Naturally, :meth:`~ZigzagPersistence.remove` returns only `d`. 
+
+If one wants to add or remove an entire set of simplices "at once" (i.e.  with
+all births being assigned the same value), there are two helper functions:
+:func:`add_simplices` and :func:`remove_simplices`.
+
+See the :ref:`bindings reference <python-bindings>` for more details, and
+:ref:`triangle-zigzag-example` for an example of :class:`ZigzagPersistence`.
+See :ref:`rips-pairwise-cohomology` for an example of
+:class:`CohomologyPersistence`.
+
+
+.. _speed-up-suggestions:
+
+Speed-up suggestions
+--------------------
+
+Currently, when the choice comes between efficiency and flexibility, the Python
+bindings err on the side of flexibility. There is hope that in the future the
+choice won't really be necessary. Meanwhile, one can use a few techniques that
+speed up computation at the expense of memory. Note, however, that since the
+recent switch of :class:`PairwiseDistances` to C++ rather than pure Python, it
+is not clear whether these deliver a substantial speed-up:
+
+* To avoid (possibly expensive) computation of distances during Rips complex
+  generation, store :class:`ExplicitDistances` (see :ref:`distances`)::
+
+        distances = PairwiseDistances(points)
+        distances = ExplicitDistances(distances)
+
+* To avoid the computation of simplex sizes in the Rips complex during the
+  initialization of a :class:`Filtration`, store them explicitly in
+  :attr:`Simplex.data` attribute (this is not done by default to save memory);
+  then use :func:`data_dim_cmp` when sorting the
+  :class:`Filtration`::
+
+        rips = Rips(distances)
+        simplices = Filtration()
+        rips.generate(..., simplices.append)
+        for s in simplices: s.data = rips.eval(s)
+        simplices.sort(data_dim_cmp)
+
+
+
+.. include::    substitutions.aux
--- a/examples/CMakeLists.txt	Fri Aug 24 16:58:25 2007 -0400
+++ b/examples/CMakeLists.txt	Tue Jun 27 09:37:05 2017 -0700
@@ -1,5 +1,15 @@
-add_subdirectory			(alphashapes)
-add_subdirectory			(ar-vineyard)
-add_subdirectory			(cech-complex)
-add_subdirectory			(grid)
-add_subdirectory			(triangle)
+add_executable                  (bottleneck-distance bottleneck-distance.cpp)
+target_link_libraries           (bottleneck-distance ${libraries} ${Boost_PROGRAM_OPTIONS_LIBRARY})
+
+add_subdirectory            (alphashapes)
+#add_subdirectory           (ar-vineyard)
+add_subdirectory            (cech-complex)
+add_subdirectory            (consistency)
+add_subdirectory            (cohomology)
+add_subdirectory            (fitness)
+add_subdirectory            (pl-functions)
+add_subdirectory            (triangle)
+add_subdirectory            (poincare)
+add_subdirectory            (rips)
+add_subdirectory            (filtration)
+add_subdirectory            (homology-zigzags)
--- a/examples/alphashapes/CMakeLists.txt	Fri Aug 24 16:58:25 2007 -0400
+++ b/examples/alphashapes/CMakeLists.txt	Tue Jun 27 09:37:05 2017 -0700
@@ -1,8 +1,27 @@
-set							(targets						
-							 alphashapes3d
-							 alpharadius)
-							 
-foreach 					(t ${targets})
-	add_executable			(${t} ${t}.cpp ${external_sources})
-	target_link_libraries	(${t} ${libraries} ${cgal_libraries})
-endforeach 					(t ${targets})
+set                             (libraries                      ${libraries} 
+                                                                ${Boost_SERIALIZATION_LIBRARY}
+                                                                ${Boost_PROGRAM_OPTIONS_LIBRARY})
+
+# Build compare-diagrams
+add_executable                  (compare-diagrams               compare-diagrams.cpp)
+target_link_libraries           (compare-diagrams               ${libraries})
+
+# Add targets that depend on CGAL
+if                              (CGAL_FOUND)
+    include                     (${CGAL_USE_FILE})
+
+    set                         (targets                        alphashapes3d
+                                                                alphashapes2d
+                                                                alphashapes3d-cohomology
+                                                                #alpharadius
+                                )
+    add_definitions             (${CGAL_CXX_FLAGS_INIT})
+    include_directories         (${CGAL_INCLUDE_DIRS})
+
+    foreach                     (t ${targets})
+        add_executable          (${t} ${t}.cpp)
+        target_link_libraries   (${t} ${libraries} ${CGAL_LIBRARY} ${CGAL_3RD_PARTY_LIBRARIES})
+    endforeach                  (t ${targets})
+else                            (CGAL_FOUND)
+    message(STATUS "CGAL not found, therefore alphashapes will not be built.")
+endif                           (CGAL_FOUND)
--- a/examples/alphashapes/alpharadius.cpp	Fri Aug 24 16:58:25 2007 -0400
+++ b/examples/alphashapes/alpharadius.cpp	Tue Jun 27 09:37:05 2017 -0700
@@ -1,5 +1,4 @@
-#include <utilities/sys.h>
-#include <utilities/debug.h>
+#include <utilities/log.h>
 
 #include "alphashapes3d.h"
 #include <topology/filtration.h>
@@ -48,11 +47,13 @@
 
 int main(int argc, char** argv) 
 {
-#ifdef CWDEBUG
-	Debug(dc::filtration.on());
-	//Debug(dc::cycle.on());
+#ifdef LOGGING
+	rlog::RLogInit(argc, argv);
 
-	dionysus::debug::init();
+	stdoutLog.subscribeTo( RLOG_CHANNEL("info") );
+	stdoutLog.subscribeTo( RLOG_CHANNEL("error") );
+	stdoutLog.subscribeTo( RLOG_CHANNEL("topology/filtration") );
+	//stdoutLog.subscribeTo( RLOG_CHANNEL("topology/cycle") );
 #endif
 
 	std::istream& in = std::cin;
@@ -66,7 +67,7 @@
 		Point p(x,y,z);
 		Dt.insert(p);
 	}
-	std::cout << "Delaunay triangulation computed" << std::endl;
+	rInfo("Delaunay triangulation computed");
  
 	AlphaSimplex3DVector alpha_ordering;
 	fill_alpha_order(Dt, alpha_ordering);
@@ -83,17 +84,17 @@
 			continue;
 		
 		double current_alpha = CGAL::to_double(cur->value());
-		std::cout << "Current alpha: " << current_alpha << std::endl;
+		rInfo("Current alpha: %f", current_alpha);
 		std::sort(radius_ordering.begin(), radius_ordering.end(), ro);
-		std::cout << "Radius ordering size: " << radius_ordering.size() << std::endl;
+		rInfo("Radius ordering size: %i", radius_ordering.size());
 
 		RadiusFiltration rf;
 		for (SimplexVector::const_iterator cur = radius_ordering.begin(); cur != radius_ordering.end(); ++cur)
 			rf.append(*cur);
 		rf.fill_simplex_index_map();
-		std::cout << "Simplex index map filled" << std::endl;
+		rInfo("Simplex index map filled");
 		rf.pair_simplices(rf.begin(), rf.end());
-		std::cout << "Pairing computed" << std::endl;
+		rInfo("Pairing computed");
 	
 		for (RadiusFiltration::const_Index cur = rf.begin(); cur != rf.end(); ++cur)
 		{
@@ -101,7 +102,7 @@
 	
 			RealValue d1 = cur->distance;
 			//if (cur == cur->pair())
-			//	std::cout << "Unpaired " << cur->dimension() << ' ' << CGAL::to_double(d1) << std::endl;
+			//	rInfo("Unpaired %d %f", cur->dimension(), CGAL::to_double(d1));
 			
 			RealValue d2 = cur->pair()->distance;
 			if (d1 == d2)	continue;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/alphashapes/alphashapes.py	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,42 @@
+# Computes the persistence diagram of the alpha shapes in both 2D and 3D 
+# (decided dynamically based on the input file)
+
+from    dionysus        import Filtration, StaticPersistence, data_dim_cmp, vertex_cmp, \
+                               fill_alpha3D_complex, fill_alpha2D_complex, points_file
+from    sys             import argv, exit
+from    math            import sqrt
+
+
+if len(argv) < 2:
+    print "Usage: %s POINTS" % argv[0]
+    exit()
+
+points = [p for p in points_file(argv[1])]
+f = Filtration()
+if   len(points[0]) == 2:           # 2D
+    fill_alpha2D_complex(points, f)
+elif len(points[1]) == 3:           # 3D
+    fill_alpha3D_complex(points, f)
+
+print "Total number of simplices:", len(f)
+
+f.sort(data_dim_cmp)
+print "Filtration initialized"
+
+p = StaticPersistence(f)
+print "StaticPersistence initialized" 
+
+p.pair_simplices()
+print "Simplices paired"
+
+print "Outputting persistence diagram"
+smap = p.make_simplex_map(f)
+for i in p:
+    if i.sign():
+        b = smap[i]
+        if i.unpaired():
+            print b.dimension(), sqrt(b.data[0]), "inf"
+            continue
+
+        d = smap[i.pair()]
+        print b.dimension(), sqrt(b.data[0]), sqrt(d.data[0])
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/alphashapes/alphashapes2d.cpp	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,69 @@
+#include <utilities/log.h>
+
+#include "alphashapes2d.h"
+#include <topology/filtration.h>
+#include <topology/static-persistence.h>
+#include <topology/persistence-diagram.h>
+#include <iostream>
+
+#include <fstream>
+
+
+typedef Filtration<AlphaSimplex2D>              AlphaFiltration;
+typedef StaticPersistence<>                     Persistence;
+typedef PersistenceDiagram<>                    PDgm;
+
+
+int main(int argc, char** argv) 
+{
+#ifdef LOGGING
+    rlog::RLogInit(argc, argv);
+
+    stdoutLog.subscribeTo( RLOG_CHANNEL("error") );
+    stdoutLog.subscribeTo( RLOG_CHANNEL("info") );
+    //stdoutLog.subscribeTo( RLOG_CHANNEL("topology/filtration") );
+    //stdoutLog.subscribeTo( RLOG_CHANNEL("topology/cycle") );
+#endif
+
+    SetFrequency(GetCounter("filtration/pair"), 10000);
+    SetTrigger(GetCounter("filtration/pair"), GetCounter(""));
+
+    // Read in the point set and compute its Delaunay triangulation
+    std::istream& in = std::cin;
+    double x,y;
+    Delaunay2D Dt;
+    while(in)
+    {
+        in >> x >> y;
+        if (!in) break;
+        Point p(x,y);
+        Dt.insert(p);
+    }
+    rInfo("Delaunay triangulation computed");
+   
+    AlphaFiltration af;
+    fill_complex(Dt, af);
+    rInfo("Simplices: %i", af.size());
+
+    // Create the alpha-shape filtration
+    af.sort(AlphaSimplex2D::AlphaOrder());
+    rInfo("Filtration initialized");
+
+    Persistence p(af);
+    rInfo("Persistence initializaed");
+
+    p.pair_simplices();
+    rInfo("Simplices paired");
+
+    Persistence::SimplexMap<AlphaFiltration>    m       = p.make_simplex_map(af);
+    std::map<Dimension, PDgm>                   dgms;
+    init_diagrams(dgms, p.begin(), p.end(), 
+                  evaluate_through_map(m, AlphaSimplex2D::AlphaValueEvaluator()),
+                  evaluate_through_map(m, AlphaSimplex2D::DimensionExtractor()));
+
+#if 1
+    std::cout << 0 << std::endl << dgms[0] << std::endl;
+    std::cout << 1 << std::endl << dgms[1] << std::endl;
+#endif
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/alphashapes/alphashapes2d.h	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,84 @@
+/**
+ * Author: Dmitriy Morozov
+ * Department of Computer Science, Duke University, 2007
+ */
+
+#ifndef __ALPHASHAPES2D_H__
+#define __ALPHASHAPES2D_H__
+
+#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
+#include <CGAL/Delaunay_triangulation_2.h>
+
+#include <topology/simplex.h>
+#include <utilities/types.h>
+
+#include <vector>
+#include <set>
+#include <iostream>
+
+struct K: CGAL::Exact_predicates_exact_constructions_kernel {};
+
+typedef CGAL::Delaunay_triangulation_2<K>           Delaunay2D;
+typedef Delaunay2D::Point                           Point;
+typedef Delaunay2D::Vertex_handle                   Vertex_handle;
+typedef Delaunay2D::Face_handle                     Face_handle;
+typedef K::FT                                       RealValue;
+
+typedef Delaunay2D::Finite_vertices_iterator        Vertex_iterator;
+typedef Delaunay2D::Finite_edges_iterator           Edge_iterator;
+typedef Delaunay2D::Finite_faces_iterator           Face_iterator;
+
+
+class AlphaSimplex2D: public Simplex<Vertex_handle>
+{
+    public:
+        typedef     Simplex<Vertex_handle>                              Parent;
+        typedef     std::set<AlphaSimplex2D, Parent::VertexComparison>  SimplexSet;
+        typedef     Parent::VertexContainer                             VertexSet;
+
+    public:
+                                    AlphaSimplex2D()                    {}
+                                    AlphaSimplex2D(const Parent& p): 
+                                            Parent(p)                   {}
+                                    AlphaSimplex2D(const AlphaSimplex2D& s): 
+                                            Parent(s)                   { attached_ = s.attached_; alpha_ = s.alpha_; }
+                                    AlphaSimplex2D(const Delaunay2D::Vertex& v);
+        
+                                    AlphaSimplex2D(const Delaunay2D::Edge& e);
+                                    AlphaSimplex2D(const Delaunay2D::Edge& e, const SimplexSet& simplices, const Delaunay2D& Dt);
+        
+                                    AlphaSimplex2D(const Delaunay2D::Face& c);
+        
+        RealType                    value() const                       { return CGAL::to_double(alpha_); }
+        RealValue                   alpha() const                       { return alpha_; }
+        bool                        attached() const                    { return attached_; }
+
+        // Ordering
+        struct AlphaOrder
+        { bool operator()(const AlphaSimplex2D& first, const AlphaSimplex2D& second) const; };
+        
+        struct AlphaValueEvaluator
+        { 
+            typedef                 AlphaSimplex2D                                  first_argument_type;
+            typedef                 RealType                                        result_type;
+
+            RealType                operator()(const AlphaSimplex2D& s) const       { return s.value(); }
+        };
+
+        std::ostream&               operator<<(std::ostream& out) const;
+        
+    private:
+        RealValue                   alpha_;
+        bool                        attached_;
+};
+
+typedef             std::vector<AlphaSimplex2D>                             AlphaSimplex2DVector;
+void                fill_simplex_set(const Delaunay2D& Dt, AlphaSimplex2D::SimplexSet& simplices);
+template<class Filtration>
+void                fill_complex(const Delaunay2D& Dt,     Filtration& filtration);
+
+std::ostream&       operator<<(std::ostream& out, const AlphaSimplex2D& s)  { return s.operator<<(out); }
+
+#include "alphashapes2d.hpp"
+
+#endif // __ALPHASHAPES2D_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/alphashapes/alphashapes2d.hpp	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,123 @@
+#include <utilities/log.h>
+#include <boost/foreach.hpp>
+
+AlphaSimplex2D::
+AlphaSimplex2D(const Delaunay2D::Vertex& v): alpha_(0), attached_(false)
+{
+    for (int i = 0; i < 3; ++i)
+        if (v.face()->vertex(i) != Vertex_handle() && v.face()->vertex(i)->point() == v.point())
+            Parent::add(v.face()->vertex(i));
+}
+
+AlphaSimplex2D::
+AlphaSimplex2D(const Delaunay2D::Edge& e): attached_(false)
+{
+    Face_handle f = e.first;
+    for (int i = 0; i < 3; ++i)
+        if (i != e.second)
+            Parent::add(f->vertex(i));
+}
+
+AlphaSimplex2D::
+AlphaSimplex2D(const Delaunay2D::Edge& e, const SimplexSet& simplices, const Delaunay2D& Dt): attached_(false)
+{
+    Face_handle f = e.first;
+    for (int i = 0; i < 3; ++i)
+        if (i != e.second)
+            Parent::add(f->vertex(i));
+
+    VertexSet::const_iterator v = static_cast<const Parent*>(this)->vertices().begin();
+    const Point& p1 = (*v++)->point();
+    const Point& p2 = (*v)->point();
+
+    Face_handle o = f->neighbor(e.second);
+    if (o == Face_handle())
+    {
+        alpha_ = CGAL::squared_radius(p1, p2);
+        return;
+    }
+    int oi = o->index(f);
+
+    attached_ = false;
+    if (!Dt.is_infinite(f->vertex(e.second)) &&
+        CGAL::side_of_bounded_circle(p1, p2,
+                                     f->vertex(e.second)->point()) == CGAL::ON_BOUNDED_SIDE)
+        attached_ = true;
+    else if (!Dt.is_infinite(o->vertex(oi)) &&
+             CGAL::side_of_bounded_circle(p1, p2,
+                                          o->vertex(oi)->point()) == CGAL::ON_BOUNDED_SIDE)
+        attached_ = true;
+    else
+        alpha_ = CGAL::squared_radius(p1, p2);
+
+    if (attached_)
+    {
+        if (Dt.is_infinite(f))
+            alpha_ = simplices.find(AlphaSimplex2D(*o))->alpha();
+        else if (Dt.is_infinite(o))
+            alpha_ = simplices.find(AlphaSimplex2D(*f))->alpha();
+        else
+            alpha_ = std::min(simplices.find(AlphaSimplex2D(*f))->alpha(),
+                              simplices.find(AlphaSimplex2D(*o))->alpha());
+    }
+}
+
+AlphaSimplex2D::
+AlphaSimplex2D(const Delaunay2D::Face& f): attached_(false)
+{
+    for (int i = 0; i < 3; ++i)
+        Parent::add(f.vertex(i));
+    VertexSet::const_iterator v = static_cast<const Parent*>(this)->vertices().begin();
+    Point p1 = (*v++)->point();
+    Point p2 = (*v++)->point();
+    Point p3 = (*v)->point();
+    alpha_ = CGAL::squared_radius(p1, p2, p3);
+}
+
+
+bool
+AlphaSimplex2D::AlphaOrder::
+operator()(const AlphaSimplex2D& first, const AlphaSimplex2D& second) const
+{
+    if (first.alpha() == second.alpha())
+        return (first.dimension() < second.dimension());
+    else
+        return (first.alpha() < second.alpha());
+}
+
+std::ostream&
+AlphaSimplex2D::
+operator<<(std::ostream& out) const
+{
+    for (VertexSet::const_iterator cur = Parent::vertices().begin();
+                                   cur != Parent::vertices().end(); ++cur)
+        out << **cur << ", ";
+    out << "value = " << value();
+
+    return out;
+}
+
+void fill_simplex_set(const Delaunay2D& Dt, AlphaSimplex2D::SimplexSet& simplices)
+{
+    for(Face_iterator cur = Dt.finite_faces_begin(); cur != Dt.finite_faces_end(); ++cur)
+        simplices.insert(AlphaSimplex2D(*cur));
+    rInfo("Faces inserted");
+    for(Edge_iterator cur = Dt.finite_edges_begin(); cur != Dt.finite_edges_end(); ++cur)
+        simplices.insert(AlphaSimplex2D(*cur, simplices, Dt));
+    rInfo("Edges inserted");
+    for(Vertex_iterator cur = Dt.finite_vertices_begin(); cur != Dt.finite_vertices_end(); ++cur)
+        simplices.insert(AlphaSimplex2D(*cur));
+    rInfo("Vertices inserted");
+}
+
+template<class Filtration>
+void fill_complex(const Delaunay2D& Dt, Filtration& filtration)
+{
+    // Compute all simplices with their alpha values and attachment information
+    // TODO: this can be optimized; the new Filtration can act as a SimplexSet
+    AlphaSimplex2D::SimplexSet simplices;
+    fill_simplex_set(Dt, simplices);
+    BOOST_FOREACH(const AlphaSimplex2D& s, simplices)
+        filtration.push_back(s);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/alphashapes/alphashapes3d-cohomology.cpp	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,132 @@
+#include "alphashapes3d.h"
+#include "../cohomology/wrappers.h"
+
+#include <topology/cohomology-persistence.h>
+
+#include <utilities/log.h>
+#include <utilities/timer.h>
+
+#include <iostream>
+#include <fstream>
+
+#include <boost/program_options.hpp>
+#include <boost/progress.hpp>
+#include <boost/foreach.hpp>
+
+
+typedef     boost::tuple<Dimension, RealType>                       BirthInfo;
+typedef     CohomologyPersistence<BirthInfo>                        Persistence;
+
+typedef     Persistence::SimplexIndex                               Index;
+typedef     Persistence::Death                                      Death;
+typedef     Persistence::CocyclePtr                                 CocyclePtr;
+
+namespace po = boost::program_options;
+
+int main(int argc, char** argv) 
+{
+#ifdef LOGGING
+    rlog::RLogInit(argc, argv);
+
+    stdoutLog.subscribeTo( RLOG_CHANNEL("info") );
+    stdoutLog.subscribeTo( RLOG_CHANNEL("error") );
+    //stdoutLog.subscribeTo( RLOG_CHANNEL("topology/persistence") );
+    //stdoutLog.subscribeTo( RLOG_CHANNEL("topology/chain") );
+#endif
+
+    std::string     infilename, outfilename;
+
+    po::options_description hidden("Hidden options");
+    hidden.add_options()
+        ("input-file",   po::value<std::string>(&infilename),     "Point set whose alpha shape filtration and persistence we want to compute")
+        ("output-file",  po::value<std::string>(&outfilename),    "Where to write the collection of persistence diagrams");
+
+    po::positional_options_description pos;
+    pos.add("input-file", 1);
+    pos.add("output-file", 2);
+    
+    po::options_description all; all.add(hidden);
+
+    po::variables_map vm;
+    po::store(po::command_line_parser(argc, argv).
+                  options(all).positional(pos).run(), vm);
+    po::notify(vm);
+
+    if (!vm.count("input-file") || !vm.count("output-file"))
+    { 
+        std::cout << "Usage: " << argv[0] << " input-file output-file" << std::endl;
+        // std::cout << hidden << std::endl; 
+        return 1; 
+    }
+
+    std::ofstream   diagram_out(outfilename.c_str());
+
+    Timer total_timer; total_timer.start();
+
+    // Read in the point set and compute its Delaunay triangulation
+    std::ifstream in(infilename.c_str());
+    double x,y,z;
+    Delaunay3D Dt;
+    while(in)
+    {
+        in >> x >> y >> z;
+        Point p(x,y,z);
+        Dt.insert(p);
+    }
+    rInfo("Delaunay triangulation computed");
+ 
+    // Set up the alpha shape filtration
+    typedef     std::vector<AlphaSimplex3D>     AlphaSimplex3DVector;
+    AlphaSimplex3DVector complex;
+    fill_complex(Dt, complex);
+    rInfo("Simplices: %d", complex.size());
+    std::sort(complex.begin(), complex.end(), AlphaSimplex3D::AlphaOrder());
+ 
+    Timer persistence_timer; persistence_timer.start();
+    std::map<AlphaSimplex3D, Index, AlphaSimplex3D::VertexComparison>       complex_map;
+    Persistence             p;
+    boost::progress_display show_progress(complex.size());
+
+    #ifdef COUNTERS
+    Counter::CounterType    max_element_count = 0;
+    #endif
+    
+    for(AlphaSimplex3DVector::const_iterator cur = complex.begin(); cur != complex.end(); ++cur)
+    {
+        const AlphaSimplex3D& s = *cur;
+        std::vector<Index>      boundary;
+        for (AlphaSimplex3D::BoundaryIterator bcur  = s.boundary_begin(); bcur != s.boundary_end(); ++bcur)
+            boundary.push_back(complex_map[*bcur]);
+        
+        Index idx; Death d; CocyclePtr ccl;
+        bool store = s.dimension() < 3;
+        boost::tie(idx, d, ccl)     = p.add(boundary.begin(), boundary.end(), boost::make_tuple(s.dimension(), s.value()), store);
+        
+        // c[*cur] = idx;
+        if (store)
+            complex_map[s] = idx;
+
+        if (d && (s.value() - d->get<1>()) > 0)
+        {
+            AssertMsg(d->get<0>() == s.dimension() - 1, "Dimensions must match");
+            diagram_out << (s.dimension() - 1) << " " << d->get<1>() << " " << s.value() << std::endl;
+        }
+        ++show_progress;
+        
+        #ifdef COUNTERS
+        max_element_count = std::max(max_element_count, cCohomologyElementCount->count);
+        #endif
+    }
+    // output infinte persistence pairs 
+    for (Persistence::CocycleIndex cur = p.begin(); cur != p.end(); ++cur)
+        diagram_out << cur->birth.get<0>() << " " << cur->birth.get<1>() << " inf" << std::endl;
+    persistence_timer.stop();
+    
+    total_timer.stop();
+    persistence_timer.check("Persistence timer");
+    total_timer.check("Total timer");
+
+    #ifdef COUNTERS
+    std::cout << "Max element count: " << max_element_count << std::endl;
+    #endif
+}
--- a/examples/alphashapes/alphashapes3d.cpp	Fri Aug 24 16:58:25 2007 -0400
+++ b/examples/alphashapes/alphashapes3d.cpp	Tue Jun 27 09:37:05 2017 -0700
@@ -1,38 +1,106 @@
-#include <utilities/sys.h>
-#include <utilities/debug.h>
+#include <utilities/log.h>
+#include <utilities/timer.h>
 
 #include "alphashapes3d.h"
 #include <topology/filtration.h>
+#include <topology/static-persistence.h>
+#include <topology/persistence-diagram.h>
 #include <iostream>
+
 #include <fstream>
+#include <boost/archive/binary_oarchive.hpp>
+#include <boost/serialization/map.hpp>
+
+#include <boost/program_options.hpp>
 
 
-typedef Filtration<AlphaSimplex3D>				AlphaFiltration;
+typedef Filtration<AlphaSimplex3D>              AlphaFiltration;
+typedef StaticPersistence<>                     Persistence;
+typedef PersistenceDiagram<>                    PDgm;
+
+namespace po = boost::program_options;
 
 int main(int argc, char** argv) 
 {
-	// Read in the point set and compute its Delaunay triangulation
-	std::istream& in = std::cin;
-	double x,y,z;
-	Delaunay Dt;
-	while(in)
-	{
-		in >> x >> y >> z;
-		Point p(x,y,z);
-		Dt.insert(p);
-	}
-	std::cout << "Delaunay triangulation computed" << std::endl;
+#ifdef LOGGING
+    rlog::RLogInit(argc, argv);
+
+    stdoutLog.subscribeTo( RLOG_CHANNEL("info") );
+    stdoutLog.subscribeTo( RLOG_CHANNEL("error") );
+    //stdoutLog.subscribeTo( RLOG_CHANNEL("topology/persistence") );
+    //stdoutLog.subscribeTo( RLOG_CHANNEL("topology/chain") );
+#endif
+
+    // SetFrequency(GetCounter("persistence/pair"), 10000);
+    // SetTrigger(GetCounter("persistence/pair"), GetCounter(""));
+
+    std::string     infilename, outfilename;
+
+    po::options_description hidden("Hidden options");
+    hidden.add_options()
+        ("input-file",   po::value<std::string>(&infilename),     "Point set whose alpha shape filtration and persistence we want to compute")
+        ("output-file",  po::value<std::string>(&outfilename),    "Where to write the collection of persistence diagrams");
+
+    po::positional_options_description pos;
+    pos.add("input-file", 1);
+    pos.add("output-file", 2);
+    
+    po::options_description all; all.add(hidden);
+
+    po::variables_map vm;
+    po::store(po::command_line_parser(argc, argv).
+                  options(all).positional(pos).run(), vm);
+    po::notify(vm);
+
+    if (!vm.count("input-file") || !vm.count("output-file"))
+    { 
+        std::cout << "Usage: " << argv[0] << " input-file output-file" << std::endl;
+        std::cout << hidden << std::endl; 
+        return 1; 
+    }
+
+
+    // Read in the point set and compute its Delaunay triangulation
+    std::ifstream in(infilename.c_str());
+    double x,y,z;
+    Delaunay3D Dt;
+    while(in)
+    {
+        in >> x >> y >> z;
+        Point p(x,y,z);
+        Dt.insert(p);
+    }
+    rInfo("Delaunay triangulation computed");
    
-	AlphaSimplex3DVector alpha_ordering;
-	fill_alpha_order(Dt, alpha_ordering);
-	std::cout << "Simplices: " << alpha_ordering.size() << std::endl;
+    AlphaFiltration  af;
+    fill_complex(Dt, af);
+    rInfo("Simplices: %d", af.size());
+
+    // Create the alpha-shape filtration
+    af.sort(AlphaSimplex3D::AlphaOrder());
+    rInfo("Filtration initialized");
+    
+    Persistence p(af);
+    rInfo("Persistence initializaed");
 
-	// Create the alpha-shape filtration
-	AlphaFiltration af;
-	for (AlphaSimplex3DVector::const_iterator cur = alpha_ordering.begin(); cur != alpha_ordering.end(); ++cur)
-		af.append(*cur);
-	af.fill_simplex_index_map();
-	af.pair_simplices(af.begin(), af.end());
-	std::cout << "Simplices paired" << std::endl;
+    Timer persistence_timer; persistence_timer.start();
+    p.pair_simplices();
+    persistence_timer.stop();
+    rInfo("Simplices paired");
+    persistence_timer.check("Persistence timer");
+
+    Persistence::SimplexMap<AlphaFiltration>    m       = p.make_simplex_map(af);
+    std::map<Dimension, PDgm> dgms;
+    init_diagrams(dgms, p.begin(), p.end(), 
+                  evaluate_through_map(m, AlphaSimplex3D::AlphaValueEvaluator()), 
+                  evaluate_through_map(m, AlphaSimplex3D::DimensionExtractor()));
+#if 0
+    std::cout << 0 << std::endl << dgms[0] << std::endl;
+    std::cout << 1 << std::endl << dgms[1] << std::endl;
+    std::cout << 2 << std::endl << dgms[2] << std::endl;
+#endif
+
+    std::ofstream ofs(outfilename.c_str());
+    boost::archive::binary_oarchive oa(ofs);
+    oa << dgms;
 }
-
--- a/examples/alphashapes/alphashapes3d.h	Fri Aug 24 16:58:25 2007 -0400
+++ b/examples/alphashapes/alphashapes3d.h	Tue Jun 27 09:37:05 2017 -0700
@@ -18,30 +18,25 @@
 
 struct K: CGAL::Exact_predicates_exact_constructions_kernel {};
 
-typedef CGAL::Delaunay_triangulation_3<K>    		Delaunay;
-typedef Delaunay::Point                				Point;
-typedef Delaunay::Vertex            				Vertex;
-typedef Delaunay::Vertex_handle            			Vertex_handle;
-typedef Delaunay::Edge								Edge;
-typedef Delaunay::Facet								Facet;
-typedef Delaunay::Cell								Cell;
-typedef Delaunay::Cell_handle						Cell_handle;
-typedef K::FT										RealValue;
+typedef CGAL::Delaunay_triangulation_3<K>           Delaunay3D;
+typedef Delaunay3D::Point                           Point;
+typedef Delaunay3D::Vertex_handle                   Vertex_handle;
+typedef Delaunay3D::Cell_handle                     Cell_handle;
+typedef K::FT                                       RealValue;
 
-typedef Delaunay::Finite_vertices_iterator    		Vertex_iterator;
-typedef Delaunay::Finite_edges_iterator        		Edge_iterator;
-typedef Delaunay::Finite_facets_iterator        	Facet_iterator;
-typedef Delaunay::Finite_cells_iterator        		Cell_iterator;
-typedef Delaunay::Facet_circulator					Facet_circulator;
+typedef Delaunay3D::Finite_vertices_iterator        Vertex_iterator;
+typedef Delaunay3D::Finite_edges_iterator           Edge_iterator;
+typedef Delaunay3D::Finite_facets_iterator          Facet_iterator;
+typedef Delaunay3D::Finite_cells_iterator           Cell_iterator;
+typedef Delaunay3D::Facet_circulator                Facet_circulator;
 
 
-class AlphaSimplex3D: public SimplexWithVertices<Vertex_handle>
+class AlphaSimplex3D: public Simplex<Vertex_handle>
 {
 	public:
-		typedef 	std::set<AlphaSimplex3D>							SimplexSet;
-		typedef		SimplexWithVertices<Vertex_handle>					Parent;
+		typedef		Simplex<Vertex_handle>					            Parent;
+		typedef 	std::set<AlphaSimplex3D, Parent::VertexComparison>  SimplexSet;
 		typedef		Parent::VertexContainer								VertexSet;
-		typedef		std::list<AlphaSimplex3D>							Cycle;
 
     public:
 									AlphaSimplex3D()					{}
@@ -49,25 +44,32 @@
 											Parent(p) 					{}
 									AlphaSimplex3D(const AlphaSimplex3D& s): 
 											Parent(s) 					{ attached_ = s.attached_; alpha_ = s.alpha_; }
-	    							AlphaSimplex3D(const ::Vertex& v);
+	    							AlphaSimplex3D(const Delaunay3D::Vertex& v);
 		
-								    AlphaSimplex3D(const Edge& e);
-								    AlphaSimplex3D(const Edge& e, const SimplexSet& simplices, Facet_circulator facet_bg);
+								    AlphaSimplex3D(const Delaunay3D::Edge& e);
+								    AlphaSimplex3D(const Delaunay3D::Edge& e, const SimplexSet& simplices, const Delaunay3D& Dt, Facet_circulator facet_bg);
 		
-								    AlphaSimplex3D(const Facet& f);
-								    AlphaSimplex3D(const Facet& f, const SimplexSet& simplices);
+								    AlphaSimplex3D(const Delaunay3D::Facet& f);
+								    AlphaSimplex3D(const Delaunay3D::Facet& f, const SimplexSet& simplices, const Delaunay3D& Dt);
 	    
-									AlphaSimplex3D(const Cell& c);
+									AlphaSimplex3D(const Delaunay3D::Cell& c);
 	    
 		RealType					value() const						{ return CGAL::to_double(alpha_); }
 		RealValue					alpha() const						{ return alpha_; }
 		bool						attached() const					{ return attached_; }
-		Cycle						boundary() const;
 
 		// Ordering
 		struct AlphaOrder
 		{ bool operator()(const AlphaSimplex3D& first, const AlphaSimplex3D& second) const; };
-		
+	
+        struct AlphaValueEvaluator
+        { 
+            typedef                 AlphaSimplex3D                                  first_argument_type;
+            typedef                 RealType                                        result_type;
+
+            RealType                operator()(const AlphaSimplex3D& s) const       { return s.value(); }
+        };
+
 		std::ostream& 				operator<<(std::ostream& out) const;
 		
 	private:
@@ -75,9 +77,9 @@
 		bool 						attached_;
 };
 
-typedef 			std::vector<AlphaSimplex3D>								AlphaSimplex3DVector;
-void 				fill_alpha_order(const Delaunay& Dt, 
-									 AlphaSimplex3DVector& alpha_order);
+void 				fill_simplex_set(const Delaunay3D& Dt, AlphaSimplex3D::SimplexSet& simplices);
+template<class Filtration>
+void 				fill_complex(const Delaunay3D& Dt,     Filtration& filtration);
 
 std::ostream& 		operator<<(std::ostream& out, const AlphaSimplex3D& s)	{ return s.operator<<(out); }
 
--- a/examples/alphashapes/alphashapes3d.hpp	Fri Aug 24 16:58:25 2007 -0400
+++ b/examples/alphashapes/alphashapes3d.hpp	Tue Jun 27 09:37:05 2017 -0700
@@ -1,182 +1,171 @@
-AlphaSimplex3D::	    
-AlphaSimplex3D(const ::Vertex& v): alpha_(0), attached_(false)
+#include <utilities/log.h>
+#include <boost/foreach.hpp>
+
+AlphaSimplex3D::
+AlphaSimplex3D(const Delaunay3D::Vertex& v): alpha_(0), attached_(false)
 {
-	for (int i = 0; i < 4; ++i)
-		if (v.cell()->vertex(i)->point() == v.point())
-			Parent::add(v.cell()->vertex(i));
+    for (int i = 0; i < 4; ++i)
+        if (v.cell()->vertex(i)->point() == v.point())
+            Parent::add(v.cell()->vertex(i));
 }
 
-AlphaSimplex3D::	    
-AlphaSimplex3D(const Edge& e)
+AlphaSimplex3D::
+AlphaSimplex3D(const Delaunay3D::Edge& e)
 {
     Cell_handle c = e.first;
-	Parent::add(c->vertex(e.second));
-	Parent::add(c->vertex(e.third));
+    Parent::add(c->vertex(e.second));
+    Parent::add(c->vertex(e.third));
 }
 
-AlphaSimplex3D::	    
-AlphaSimplex3D(const Edge& e, const SimplexSet& simplices, Facet_circulator facet_bg)
+AlphaSimplex3D::
+AlphaSimplex3D(const Delaunay3D::Edge& e, const SimplexSet& simplices, const Delaunay3D& Dt, Facet_circulator facet_bg)
 {
     Cell_handle c = e.first;
-	Parent::add(c->vertex(e.second));
-	Parent::add(c->vertex(e.third));
+    Parent::add(c->vertex(e.second));
+    Parent::add(c->vertex(e.third));
 
-	Facet_circulator cur = facet_bg;
-	SimplexSet::const_iterator cur_iter = simplices.find(AlphaSimplex3D(*cur));
-	while (cur_iter == simplices.end())
-	{
-		++cur; 
-		cur_iter = simplices.find(AlphaSimplex3D(*cur));
-	}
-	RealValue min = cur_iter->alpha();
-	
-	VertexSet::const_iterator v = Parent::vertices().begin();
-	const Point& p1 = (*v++)->point();
-	const Point& p2 = (*v)->point();
-	attached_ = false;
+    Facet_circulator cur = facet_bg;
+    while (Dt.is_infinite(*cur))    ++cur;
+    SimplexSet::const_iterator cur_iter = simplices.find(AlphaSimplex3D(*cur));
+    RealValue min = cur_iter->alpha();
+
+    const VertexSet& vertices = static_cast<const Parent*>(this)->vertices();
+    VertexSet::const_iterator v = vertices.begin();
+    const Point& p1 = (*v++)->point();
+    const Point& p2 = (*v)->point();
+    attached_ = false;
 
-	if (facet_bg != 0) do
-	{
-		VertexSet::const_iterator v = Parent::vertices().begin();
-		int i0 = (*cur).first->index(*v++);
-		int i1 = (*cur).first->index(*v);
-		int i = 6 - i0 - i1 - (*cur).second;
-		Point p3 = (*cur).first->vertex(i)->point();
+    if (facet_bg != 0) do
+    {
+        VertexSet::const_iterator v = vertices.begin();
+        int i0 = (*cur).first->index(*v++);
+        int i1 = (*cur).first->index(*v);
+        int i = 6 - i0 - i1 - (*cur).second;
+        if (Dt.is_infinite(cur->first->vertex(i))) { ++cur; continue; }
+        Point p3 = (*cur).first->vertex(i)->point();
 
-		cur_iter = simplices.find(AlphaSimplex3D(*cur));
-		if (cur_iter == simplices.end())			// cur is infinite
-		{
-			++cur; continue;
-		}
-		
-		if (CGAL::side_of_bounded_sphere(p1, p2, p3) == CGAL::ON_BOUNDED_SIDE)
-			attached_ = true;
-		RealValue val = cur_iter->alpha();
-		if (val < min)
-			min = val;
-		++cur;
-	} while (cur != facet_bg);
+        cur_iter = simplices.find(AlphaSimplex3D(*cur));
+        if (CGAL::side_of_bounded_sphere(p1, p2, p3) == CGAL::ON_BOUNDED_SIDE)
+            attached_ = true;
+        RealValue val = cur_iter->alpha();
+        if (val < min)
+            min = val;
+        ++cur;
+    } while (cur != facet_bg);
 
-	if (attached_)
-		alpha_ = min;
-	else
-		alpha_ = CGAL::squared_radius(p1, p2);
+    if (attached_)
+        alpha_ = min;
+    else
+        alpha_ = CGAL::squared_radius(p1, p2);
 }
 
-AlphaSimplex3D::	    
-AlphaSimplex3D(const Facet& f)
+AlphaSimplex3D::
+AlphaSimplex3D(const Delaunay3D::Facet& f)
 {
     Cell_handle c = f.first;
-	for (int i = 0; i < 4; ++i)
-		if (i != f.second)
-			Parent::add(c->vertex(i));
+    for (int i = 0; i < 4; ++i)
+        if (i != f.second)
+            Parent::add(c->vertex(i));
 }
 
-AlphaSimplex3D::	    
-AlphaSimplex3D(const Facet& f, const SimplexSet& simplices)
+AlphaSimplex3D::
+AlphaSimplex3D(const Delaunay3D::Facet& f, const SimplexSet& simplices, const Delaunay3D& Dt)
 {
     Cell_handle c = f.first;
-	for (int i = 0; i < 4; ++i)
-		if (i != f.second)
-			Parent::add(c->vertex(i));
+    for (int i = 0; i < 4; ++i)
+        if (i != f.second)
+            Parent::add(c->vertex(i));
 
-	Cell_handle o = c->neighbor(f.second);
-	int oi = o->index(c);
+    Cell_handle o = c->neighbor(f.second);
+    int oi = o->index(c);
+
+    VertexSet::const_iterator v = static_cast<const Parent*>(this)->vertices().begin();
+    const Point& p1 = (*v++)->point();
+    const Point& p2 = (*v++)->point();
+    const Point& p3 = (*v)->point();
 
-	VertexSet::const_iterator v = Parent::vertices().begin();
-	const Point& p1 = (*v++)->point();
-	const Point& p2 = (*v++)->point();
-	const Point& p3 = (*v)->point();
-	
-	attached_ = false;
-	if (CGAL::side_of_bounded_sphere(p1, p2, p3,
-									 c->vertex(f.second)->point()) == CGAL::ON_BOUNDED_SIDE)
-		attached_ = true;
-	else if (CGAL::side_of_bounded_sphere(p1, p2, p3,
-										  o->vertex(oi)->point()) == CGAL::ON_BOUNDED_SIDE)
-		attached_ = true;
-	else
-		alpha_ = squared_radius(p1, p2, p3);
-	
-	if (attached_)
-	{
-		SimplexSet::const_iterator c_iter = simplices.find(AlphaSimplex3D(*c));
-		SimplexSet::const_iterator o_iter = simplices.find(AlphaSimplex3D(*o));
-		if (c_iter == simplices.end())			// c is infinite
-			alpha_ = o_iter->alpha();
-		else if (o_iter == simplices.end())		// o is infinite
-			alpha_ = c_iter->alpha();
-		else
-			alpha_ = std::min(c_iter->alpha(), o_iter->alpha());
-	}
+    attached_ = false;
+    if (!Dt.is_infinite(c->vertex(f.second)) &&
+        CGAL::side_of_bounded_sphere(p1, p2, p3,
+                                     c->vertex(f.second)->point()) == CGAL::ON_BOUNDED_SIDE)
+        attached_ = true;
+    else if (!Dt.is_infinite(o->vertex(oi)) &&
+             CGAL::side_of_bounded_sphere(p1, p2, p3,
+                                          o->vertex(oi)->point()) == CGAL::ON_BOUNDED_SIDE)
+        attached_ = true;
+    else
+        alpha_ = CGAL::squared_radius(p1, p2, p3);
+
+    if (attached_)
+    {
+        if (Dt.is_infinite(c))
+            alpha_ = simplices.find(AlphaSimplex3D(*o))->alpha();
+        else if (Dt.is_infinite(o))
+            alpha_ = simplices.find(AlphaSimplex3D(*c))->alpha();
+        else
+            alpha_ = std::min(simplices.find(AlphaSimplex3D(*c))->alpha(),
+                              simplices.find(AlphaSimplex3D(*o))->alpha());
+    }
 }
 
-AlphaSimplex3D::	    
-AlphaSimplex3D(const Cell& c): attached_(false)
+AlphaSimplex3D::
+AlphaSimplex3D(const Delaunay3D::Cell& c): attached_(false)
 {
-	for (int i = 0; i < 4; ++i)
-		Parent::add(c.vertex(i));
-	VertexSet::const_iterator v = Parent::vertices().begin();
-	Point p1 = (*v++)->point();
-	Point p2 = (*v++)->point();
-	Point p3 = (*v++)->point();
-	Point p4 = (*v)->point();
-	alpha_ = CGAL::squared_radius(p1, p2, p3, p4);
-}
-
-AlphaSimplex3D::Cycle
-AlphaSimplex3D::boundary() const
-{
-	Cycle bdry;
-	Parent::Cycle pbdry = Parent::boundary();
-	for (Parent::Cycle::const_iterator cur = pbdry.begin(); cur != pbdry.end(); ++cur)
-		bdry.push_back(*cur);
-	return bdry;
+    for (int i = 0; i < 4; ++i)
+        Parent::add(c.vertex(i));
+    VertexSet::const_iterator v = static_cast<const Parent*>(this)->vertices().begin();
+    Point p1 = (*v++)->point();
+    Point p2 = (*v++)->point();
+    Point p3 = (*v++)->point();
+    Point p4 = (*v)->point();
+    alpha_ = CGAL::squared_radius(p1, p2, p3, p4);
 }
 
 
-bool 
+bool
 AlphaSimplex3D::AlphaOrder::
 operator()(const AlphaSimplex3D& first, const AlphaSimplex3D& second) const
 {
-	if (first.alpha() == second.alpha())
-		return (first.dimension() < second.dimension());
-	else
-		return (first.alpha() < second.alpha()); 
+    if (first.alpha() == second.alpha())
+        return (first.dimension() < second.dimension());
+    else
+        return (first.alpha() < second.alpha());
 }
 
-std::ostream& 
+std::ostream&
 AlphaSimplex3D::
 operator<<(std::ostream& out) const
 {
-	for (VertexSet::const_iterator cur = Parent::vertices().begin(); cur != Parent::vertices().end(); ++cur)
-		out << **cur << ", ";
-	out << "value = " << value();
+    for (VertexSet::const_iterator cur = Parent::vertices().begin(); cur != Parent::vertices().end(); ++cur)
+        out << **cur << ", ";
+    out << "value = " << value();
 
-	return out;
+    return out;
 }
 
-
-void fill_alpha_order(const Delaunay& Dt, AlphaSimplex3DVector& alpha_order)
+void fill_simplex_set(const Delaunay3D& Dt, AlphaSimplex3D::SimplexSet& simplices)
 {
-	// Compute all simplices with their alpha values and attachment information
-	AlphaSimplex3D::SimplexSet simplices;
-	for(Cell_iterator cur = Dt.finite_cells_begin(); cur != Dt.finite_cells_end(); ++cur)
-		simplices.insert(AlphaSimplex3D(*cur));
-	std::cout << "Cells inserted" << std::endl;
-	for(Facet_iterator cur = Dt.finite_facets_begin(); cur != Dt.finite_facets_end(); ++cur)
-		simplices.insert(AlphaSimplex3D(*cur, simplices));
-	std::cout << "Facets inserted" << std::endl;
-	for(Edge_iterator cur = Dt.finite_edges_begin(); cur != Dt.finite_edges_end(); ++cur)
-		simplices.insert(AlphaSimplex3D(*cur, simplices, Dt.incident_facets(*cur)));
-	std::cout << "Edges inserted" << std::endl;
-	for(Vertex_iterator cur = Dt.finite_vertices_begin(); cur != Dt.finite_vertices_end(); ++cur)
-		simplices.insert(AlphaSimplex3D(*cur));
-	std::cout << "Vertices inserted" << std::endl;
-    
-	// Sort simplices by their alpha values
-	alpha_order.resize(simplices.size());
-	std::copy(simplices.begin(), simplices.end(), alpha_order.begin());
-	std::sort(alpha_order.begin(), alpha_order.end(), AlphaSimplex3D::AlphaOrder());
+    // Compute all simplices with their alpha values and attachment information
+    for(Cell_iterator cur = Dt.finite_cells_begin(); cur != Dt.finite_cells_end(); ++cur)
+        simplices.insert(AlphaSimplex3D(*cur));
+    rInfo("Cells inserted");
+    for(Facet_iterator cur = Dt.finite_facets_begin(); cur != Dt.finite_facets_end(); ++cur)
+        simplices.insert(AlphaSimplex3D(*cur, simplices, Dt));
+    rInfo("Facets inserted");
+    for(Edge_iterator cur = Dt.finite_edges_begin(); cur != Dt.finite_edges_end(); ++cur)
+        simplices.insert(AlphaSimplex3D(*cur, simplices, Dt, Dt.incident_facets(*cur)));
+    rInfo("Edges inserted");
+    for(Vertex_iterator cur = Dt.finite_vertices_begin(); cur != Dt.finite_vertices_end(); ++cur)
+        simplices.insert(AlphaSimplex3D(*cur));
+    rInfo("Vertices inserted");
 }
 
+template<class Filtration>
+void fill_complex(const Delaunay3D& Dt, Filtration& filtration)
+{
+    AlphaSimplex3D::SimplexSet simplices;
+    fill_simplex_set(Dt, simplices);
+    BOOST_FOREACH(const AlphaSimplex3D& s, simplices)
+        filtration.push_back(s);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/alphashapes/compare-diagrams.cpp	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,56 @@
+#include <utilities/types.h>
+#include <topology/persistence-diagram.h>
+
+#include <string>
+#include <iostream>
+#include <fstream>
+#include <boost/archive/binary_iarchive.hpp>
+#include <boost/serialization/map.hpp>
+
+#include <boost/program_options.hpp>
+
+
+typedef PersistenceDiagram<>                    PDgm;
+
+namespace po = boost::program_options;
+
+
+int main(int argc, char* argv[])
+{
+    std::string     filename1, filename2;
+
+    po::options_description hidden("Hidden options");
+    hidden.add_options()
+        ("input-file1",  po::value<std::string>(&filename1), "The first collection of persistence diagrams")
+        ("input-file2",  po::value<std::string>(&filename2), "The second collection of persistence diagrams");
+
+    po::positional_options_description p;
+    p.add("input-file1", 1);
+    p.add("input-file2", 2);
+    
+    po::options_description all; all.add(hidden);
+
+    po::variables_map vm;
+    po::store(po::command_line_parser(argc, argv).
+                  options(all).positional(p).run(), vm);
+    po::notify(vm);
+
+    if (!vm.count("input-file1") || !vm.count("input-file2"))
+    { 
+        std::cout << "Usage: " << argv[0] << " input-file1 input-file2" << std::endl;
+        std::cout << hidden << std::endl; 
+        return 1; 
+    }
+
+    std::ifstream ifs1(filename1.c_str()), ifs2(filename2.c_str());
+    boost::archive::binary_iarchive ia1(ifs1), ia2(ifs2);
+
+    std::map<Dimension, PDgm>       dgms1, dgms2;
+
+    ia1 >> dgms1;
+    ia2 >> dgms2;
+
+    std::cout << "Distance between dimension 0: " << bottleneck_distance(dgms1[0], dgms2[0]) << std::endl;
+    std::cout << "Distance between dimension 1: " << bottleneck_distance(dgms1[1], dgms2[1]) << std::endl;
+    std::cout << "Distance between dimension 2: " << bottleneck_distance(dgms1[2], dgms2[2]) << std::endl;
+}
--- a/examples/ar-vineyard/CMakeLists.txt	Fri Aug 24 16:58:25 2007 -0400
+++ b/examples/ar-vineyard/CMakeLists.txt	Tue Jun 27 09:37:05 2017 -0700
@@ -1,7 +1,10 @@
 set							(targets						
 							 ar-vineyard)
-							 
+	
+add_definitions				(${cgal_cxxflags})
 foreach 					(t ${targets})
 	add_executable			(${t} ${t}.cpp ${external_sources})
-	target_link_libraries	(${t} ${libraries} ${cgal_libraries} ${synaps_libraries})
+	target_link_libraries	(${t}   ${libraries} ${cgal_library} ${CGAL_3RD_PARTY_LIBRARIES} 
+                                    ${Boost_SIGNALS_LIBRARY} 
+                                    ${Boost_PROGRAM_OPTIONS_LIBRARY})
 endforeach 					(t)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/ar-vineyard/ar-function-kernel.h	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,80 @@
+#ifndef __AR_FUNCTION_KERNEL_H__
+#define __AR_FUNCTION_KERNEL_H__
+
+
+#include <stack>
+#include <iostream>
+#include "ar-simplex3d.h"
+
+
+
+/**
+ * Represents function suitable for the FunctionKernel. Albeit very restrictive 
+ * (it only supports subtraction), although that should suffice for KineticSort.
+ */
+class ARFunction
+{
+    public:
+        /// Represents the three forms of the involved functions. See Appendix B of LHI paper.
+        enum                        FunctionForm                                        { none, rho, lambda, phi };
+
+    public:
+                                    ARFunction(FunctionForm f, ARSimplex3D* s): 
+                                        form_(f), form2_(none),
+                                        simplex_(s), simplex2_(0)                       {}
+                                    ARFunction(const ARFunction& other):
+                                        form_(other.form_), form2_(other.form2_),
+                                        simplex_(other.simplex_), 
+                                        simplex2_(other.simplex2_)                      {}
+
+        ARFunction&                 operator-=(const ARFunction& other)                 { form2_ = other.form_; simplex2_ = other.simplex_; return *this; }
+        ARFunction                  operator-(const ARFunction& other)                  { return (ARFunction(*this) -= other); }
+
+        FunctionForm                form() const                                        { return form_; }
+        FunctionForm                form2() const                                       { return form2_; }
+        ARSimplex3D*                simplex() const                                     { return simplex_; }
+        ARSimplex3D*                simplex2() const                                    { return simplex2_; }
+
+        std::ostream&               operator<<(std::ostream& out) const                 { return (out << "(" << form_ << ", " << simplex_ << "), (" 
+                                                                                                             << form2_ << ", " << simplex2_ << ")"); }
+
+    private:
+        FunctionForm                form_, form2_;      // the function is form_ - form2_
+        ARSimplex3D                 *simplex_, *simplex2_;
+};
+
+std::ostream&
+operator<<(std::ostream& out, const ARFunction& f)
+{ return f.operator<<(out); }
+
+/**
+ * Function kernel specialized at solving the kinds of functions involved in 
+ * ARVineyard construction. We cannot use a polynomial kernel (which includes 
+ * rational functions) that we already have because not all involved functions
+ * are rational.
+ */
+class ARFunctionKernel
+{
+    public:
+        typedef                     double                                              FieldType;
+        typedef                     FieldType                                           RootType;
+        typedef                     std::stack<RootType>                                RootStack;
+        typedef                     ARSimplex3D::RealValue                              SimplexFieldType;
+
+        typedef                     ARFunction                                          Function;
+        typedef                     Function::FunctionForm                              FunctionForm;
+    
+    public:
+        static void                 solve(const Function& f, RootStack& stack);
+        static RootType             root(RootType r)                                    { return r; }
+        static RootType             root(SimplexFieldType r)                            { return CGAL::to_double(r); }
+        static int                  sign_at(const Function& f, RootType r);
+        static RootType             between(RootType r1, RootType r2)                   { return (r1 + r2)/2; }
+        static int                  sign_at_negative_infinity(const Function& f);
+
+        static FieldType            value_at(const Function& f, RootType v);
+};
+
+#include "ar-function-kernel.hpp"
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/ar-vineyard/ar-function-kernel.hpp	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,144 @@
+#include <utilities/log.h>
+#include <cmath>
+
+#if LOGGING
+static rlog::RLogChannel* rlARFunctionKernel =                      DEF_CHANNEL("ar/function-kernel", rlog::Log_Debug);
+static rlog::RLogChannel* rlARFunctionKernelValue =                 DEF_CHANNEL("ar/function-kernel/value", rlog::Log_Debug);
+#endif
+
+
+/* For now only rho and phi are implemented */
+void
+ARFunctionKernel::
+solve(const Function& f, RootStack& stack)
+{
+    AssertMsg(stack.empty(), "Stack must be empty before solving");
+    AssertMsg((f.form() != Function::none) && (f.form2() != Function::none), "Solving possible only for differences");
+
+    FunctionForm f1 = f.form(), f2 = f.form2();
+    const ARSimplex3D   *s1 = f.simplex(), 
+                        *s2 = f.simplex2();
+    if (f1 < f2)    { std::swap(f1,f2); std::swap(s1,s2); }         // for simplicity enforce function order 
+                                                                    // to handle fewer cases explicitly
+    AssertMsg(f1 != Function::lambda && f2 != Function::lambda, "Lambda not implemented yet");
+
+    rLog(rlARFunctionKernel,    "Solve: function1 = (%i, %p), function2 = (%i, %p)",
+                                f1, s1, f2, s2);
+    
+    //if (f1 == Function::phi && f2 == Function::phi)         return;
+    //if (f1 == Function::rho && f2 == Function::rho)         return;
+
+    if (f1 == Function::phi && f2 == Function::rho)
+    {
+        SimplexFieldType r = s2->alpha() - s1->phi_const();
+        rLog(rlARFunctionKernel, "  phi = rho => r^2 = %s (%lf)", tostring(r).c_str(), root(r));
+        stack.push(root(r));
+    }
+
+    if (f1 == Function::phi && f2 == Function::lambda)
+    {
+        rLog(rlARFunctionKernel, "  phi = lambda");
+        SimplexFieldType r2 = (s2->rho() + s2->v() - s2->s() - s1->phi_const());
+        r2 *= r2;
+        r2 /= 4*s2->v();
+        r2 += s2->s();
+        if (r2 >= s2->s() + s2->v())
+            stack.push(root(r2));
+
+        SimplexFieldType r1 = s2->rho() - s1->phi_const();
+        if (r1 <= s2->s() + s2->v())
+            stack.push(root(r1));
+    }
+    
+    // FIXME: this is far from complete!
+    if (f1 == Function::lambda && f2 == Function::lambda)
+    {
+        rLog(rlARFunctionKernel, "  lambda = lambda");
+        if ((s1->s() + s1->v() < s2->s() + s2->v()))                // let f1 be the function with larger break point
+        {   std::swap(f1,f2); std::swap(s1,s2); }
+
+        if (s1->rho() > s2->rho())
+        {
+            RootType r = root(s2->s() + s2->v() + s1->rho() - s2->rho()) + 2*sqrt(root(s2->v()*(s1->rho() - s2->rho())));
+            if (r < root(s1->s() + s1->v()) && r > root(s2->s() + s2->v()))
+                stack.push(r);
+        }
+    }
+
+    if (f1 == Function::lambda && f2 == Function::rho)
+    {
+        rLog(rlARFunctionKernel, "  lambda = rho");
+        // perhaps no solutions instead of an assertion is the right way to deal with this
+        AssertMsg(s2->alpha() > s1->rho(), "Rho_0^2 must be greater than Rho^2");
+
+        RootType r = sqrt(root(s2->v()*(s2->alpha() - s1->rho())));         // damn square roots
+        r *= 2;
+        r += root(s1->s() + s1->v() + s2->alpha() - s1->rho());
+    }
+    rLog(rlARFunctionKernel, "  Stack size: %i", stack.size());
+    if (stack.size() > 0) rLog(rlARFunctionKernel, "  Top: %lf", stack.top());
+}
+
+int
+ARFunctionKernel::
+sign_at(const Function& f, RootType r)
+{
+    FieldType v = value_at(f,r);
+    if (v > 0)  return true;
+    else        return false;
+}
+
+int
+ARFunctionKernel::
+sign_at_negative_infinity(const Function& f)
+{
+    FunctionForm f1 = f.form(), f2 = f.form2();
+    const ARSimplex3D   *s1 = f.simplex(), 
+                        *s2 = f.simplex2();
+    int multiplier = 1;
+    if (f1 < f2) { std::swap(f1, f2); std::swap(s1, s2); multiplier = -1; }
+    
+    AssertMsg(f1 != Function::lambda && f2 != Function::lambda, "Lambda not implemented yet");
+
+    if (f1 == Function::phi && f2 == Function::phi)
+    {
+        if (s1->phi_const() == s2->phi_const()) return  0;
+        if (s1->phi_const() > s2->phi_const())  return  1;        // multiplier must be 1
+        else                                    return -1;
+    }
+    
+    if (f1 == Function::phi && f2 == Function::rho)
+        return -multiplier;
+
+    if (f1 == Function::rho && f2 == Function::rho)
+    {
+        if (s1->alpha() == s2->alpha())         return  0;
+        if (s1->alpha() > s2->alpha())          return  1;        // multiplier must be 1
+        else                                    return -1;
+    }
+
+    AssertMsg(false, "The case analysis should be exhaustive in sign at -infinity");
+    return false;
+}
+        
+ARFunctionKernel::FieldType            
+ARFunctionKernel::
+value_at(const Function& f, RootType v)
+{
+    FunctionForm f1 = f.form(), f2 = f.form2();
+    ARSimplex3D     *s1 = f.simplex(), 
+                    *s2 = f.simplex2();
+
+    AssertMsg(f2 == Function::none && s2 == 0, "Value_at knows only about functions themselves, not their differences");
+    AssertMsg(f1 != Function::lambda, "Lambda not implemented yet");
+    rLog(rlARFunctionKernelValue,    "Value_at: function = (%i, %p)", f1, s1);
+
+    if (f1 == Function::phi)
+        return v + root(s1->phi_const());
+
+    if (f1 == Function::rho)
+        return root(s1->alpha());
+    
+    AssertMsg(false, "The case analysis should be exhaustive in value_at");
+    return 0;
+}
--- a/examples/ar-vineyard/ar-simplex3d.h	Fri Aug 24 16:58:25 2007 -0400
+++ b/examples/ar-vineyard/ar-simplex3d.h	Tue Jun 27 09:37:05 2017 -0700
@@ -28,7 +28,6 @@
 typedef Delaunay::Facet								Facet;
 typedef Delaunay::Cell								Cell;
 typedef Delaunay::Cell_handle						Cell_handle;
-typedef K::FT										RealValue;
 
 typedef Delaunay::Finite_vertices_iterator    		Vertex_iterator;
 typedef Delaunay::Finite_edges_iterator        		Edge_iterator;
@@ -40,6 +39,7 @@
 class ARSimplex3D: public SimplexWithVertices<Vertex_handle>
 {
 	public:
+        typedef     K::FT										        RealValue;
 		typedef 	std::map<ARSimplex3D, RealValue>					SimplexPhiMap;
 		typedef		SimplexWithVertices<Vertex_handle>					Parent;
 		typedef		Parent::VertexContainer								VertexSet;
@@ -56,10 +56,11 @@
 		
 								    ARSimplex3D(const Edge& e);
 								    ARSimplex3D(const Edge& e, const Point& z, SimplexPhiMap& simplices, 
-												Facet_circulator facet_bg);
+                                                const Delaunay& Dt, Facet_circulator facet_bg);
 		
 								    ARSimplex3D(const Facet& f);
-								    ARSimplex3D(const Facet& f, const Point& z, const SimplexPhiMap& simplices);
+								    ARSimplex3D(const Facet& f, const Point& z, const SimplexPhiMap& simplices,
+                                                const Delaunay& Dt);
 	    
 									ARSimplex3D(const Cell& c, const Point& z);
 	    
@@ -89,6 +90,8 @@
 		RealValue					phi_const_;	// see LHI paper, Appendices A and B
 		bool 						attached_;
 
+        // in paper's notation: s_ = v^2; v_ = d^2
+
 };
 
 typedef 			std::vector<ARSimplex3D>								ARSimplex3DVector;
--- a/examples/ar-vineyard/ar-simplex3d.hpp	Fri Aug 24 16:58:25 2007 -0400
+++ b/examples/ar-vineyard/ar-simplex3d.hpp	Tue Jun 27 09:37:05 2017 -0700
@@ -1,3 +1,9 @@
+#include <utilities/log.h>
+
+#if LOGGING
+static rlog::RLogChannel* rlARSimplex3D =                       DEF_CHANNEL("ar/simplex3d", rlog::Log_Debug);
+#endif
+
 ARSimplex3D::	    
 ARSimplex3D(const ARSimplex3D& s): Parent(s)
 { 
@@ -35,19 +41,15 @@
 }
 
 ARSimplex3D::	    
-ARSimplex3D(const Edge& e, const Point& z, SimplexPhiMap& simplices, Facet_circulator facet_bg)
+ARSimplex3D(const Edge& e, const Point& z, SimplexPhiMap& simplices, const Delaunay& Dt, Facet_circulator facet_bg)
 {
     Cell_handle c = e.first;
 	Parent::add(c->vertex(e.second));
 	Parent::add(c->vertex(e.third));
 
 	Facet_circulator cur = facet_bg;
+	while (Dt.is_infinite(*cur))    ++cur; 
 	SimplexPhiMap::const_iterator cur_iter = simplices.find(ARSimplex3D(*cur));
-	while (cur_iter == simplices.end())
-	{
-		++cur; 
-		cur_iter = simplices.find(ARSimplex3D(*cur));
-	}
 	RealValue min = cur_iter->first.alpha();
 	RealValue phi_const_min = cur_iter->first.phi_const();
 	
@@ -63,10 +65,8 @@
 		int i0 = (*cur).first->index(*v1);
 		int i1 = (*cur).first->index(*v2);
 		int i = 6 - i0 - i1 - (*cur).second;
-		Point p3 = (*cur).first->vertex(i)->point();
 
-		cur_iter = simplices.find(ARSimplex3D(*cur));
-		if (cur_iter == simplices.end())			// cur is infinite
+		if (Dt.is_infinite(cur->first->vertex(i)))
 		{
 			++cur; continue;
 			// FIXME: what do we do with infinite cofaces (i.e., what
@@ -74,9 +74,11 @@
 			// infinite?
 		}
 		
+		Point p3 = (*cur).first->vertex(i)->point();
 		if (CGAL::side_of_bounded_sphere(p1, p2, p3) == CGAL::ON_BOUNDED_SIDE)
 			attached_ = true;
 		
+	    SimplexPhiMap::const_iterator cur_iter = simplices.find(ARSimplex3D(*cur));
 		RealValue 								val 				= cur_iter->first.alpha();
 		if (val < min) 							min 				= val;
 		RealValue 								phi_const_val 		= cur_iter->first.phi_const();
@@ -99,7 +101,7 @@
 
 	
 	s_ = CGAL::squared_distance(z, K::Segment_3(p1,p2).supporting_line());
-	Point origin;
+	Point origin(0,0,0);
 	Point cc = origin + ((p1 - origin) + (p2 - origin))/2;		// CGAL is funny
 	v_ = CGAL::squared_distance(z, cc) - s_;
 }
@@ -114,7 +116,7 @@
 }
 
 ARSimplex3D::	    
-ARSimplex3D(const Facet& f, const Point& z, const SimplexPhiMap& simplices)
+ARSimplex3D(const Facet& f, const Point& z, const SimplexPhiMap& simplices, const Delaunay& Dt)
 {
     Cell_handle c = f.first;
 	for (int i = 0; i < 4; ++i)
@@ -133,29 +135,33 @@
 	rho_ = squared_radius(p1, p2, p3);
 	
 	attached_ = false;
-	if (CGAL::side_of_bounded_sphere(p1, p2, p3,
+	if (!Dt.is_infinite(c->vertex(f.second)) &&
+        CGAL::side_of_bounded_sphere(p1, p2, p3,
 									 c->vertex(f.second)->point()) == CGAL::ON_BOUNDED_SIDE)
 		attached_ = true;
-	else if (CGAL::side_of_bounded_sphere(p1, p2, p3,
+	else if (!Dt.is_infinite(o->vertex(oi)) &&
+             CGAL::side_of_bounded_sphere(p1, p2, p3,
 										  o->vertex(oi)->point()) == CGAL::ON_BOUNDED_SIDE)
 		attached_ = true;
 	else
 		alpha_ = rho_;
 	
-	SimplexPhiMap::const_iterator c_iter = simplices.find(ARSimplex3D(*c,z));
-	SimplexPhiMap::const_iterator o_iter = simplices.find(ARSimplex3D(*o,z));
-	if (c_iter == simplices.end())			// c is infinite
+	if (Dt.is_infinite(c))
 	{
+	    SimplexPhiMap::const_iterator o_iter = simplices.find(ARSimplex3D(*o,z));
 		if (attached_) alpha_ = o_iter->first.alpha();
 		phi_const_ = o_iter->first.phi_const();					// FIXME: it's probably the other way around
 	}
-	else if (o_iter == simplices.end())		// o is infinite
+	else if (Dt.is_infinite(o))
 	{
+	    SimplexPhiMap::const_iterator c_iter = simplices.find(ARSimplex3D(*c,z));
 		if (attached_) alpha_ = c_iter->first.alpha();
 		phi_const_ = c_iter->first.phi_const();					// FIXME: it's probably the other way around
 	}
 	else
 	{
+	    SimplexPhiMap::const_iterator o_iter = simplices.find(ARSimplex3D(*o,z));
+	    SimplexPhiMap::const_iterator c_iter = simplices.find(ARSimplex3D(*c,z));
 		if (attached_) alpha_ = std::min(c_iter->first.alpha(), o_iter->first.alpha());
 		phi_const_ = std::min(c_iter->first.phi_const(), o_iter->first.phi_const());
 	}
@@ -208,8 +214,9 @@
 ARSimplex3D::
 operator<<(std::ostream& out) const
 {
+    out << this << ": ";
 	for (VertexSet::const_iterator cur = Parent::vertices().begin(); cur != Parent::vertices().end(); ++cur)
-		out << **cur << ", ";
+		out << &(**cur) << ", ";
 	out << "value = " << value();
 
 	return out;
@@ -226,19 +233,19 @@
 	ARSimplex3D::SimplexPhiMap simplices;
 	for(Cell_iterator cur = Dt.finite_cells_begin(); cur != Dt.finite_cells_end(); ++cur)
 		update_simplex_phi_map(ARSimplex3D(*cur, z), simplices);
-	std::cout << "Cells inserted" << std::endl;
+	rLog(rlARSimplex3D, "Cells inserted");
 	for(Vertex_iterator cur = Dt.finite_vertices_begin(); cur != Dt.finite_vertices_end(); ++cur)
 		simplices[ARSimplex3D(*cur, z)] = 0;			// only one tetrahedron can have non-negative phi_const value 
 														// (namely the one containing z); all other simplices will have a 
 														// negative phi_const value, so 0 is safe
-	std::cout << "Vertices inserted" << std::endl;
+	rLog(rlARSimplex3D, "Vertices inserted");
 
 	for(Facet_iterator cur = Dt.finite_facets_begin(); cur != Dt.finite_facets_end(); ++cur)
-		update_simplex_phi_map(ARSimplex3D(*cur, z, simplices), simplices);
-	std::cout << "Facets inserted" << std::endl;
+		update_simplex_phi_map(ARSimplex3D(*cur, z, simplices, Dt), simplices);
+	rLog(rlARSimplex3D, "Facets inserted");
 	for(Edge_iterator cur = Dt.finite_edges_begin(); cur != Dt.finite_edges_end(); ++cur)
-		update_simplex_phi_map(ARSimplex3D(*cur, z, simplices, Dt.incident_facets(*cur)), simplices);
-	std::cout << "Edges inserted" << std::endl;
+		update_simplex_phi_map(ARSimplex3D(*cur, z, simplices, Dt, Dt.incident_facets(*cur)), simplices);
+	rLog(rlARSimplex3D, "Edges inserted");
     
 	// Sort simplices by their alpha values
 	alpha_order.resize(simplices.size()); ARSimplex3DVector::iterator out = alpha_order.begin();
--- a/examples/ar-vineyard/ar-vineyard.cpp	Fri Aug 24 16:58:25 2007 -0400
+++ b/examples/ar-vineyard/ar-vineyard.cpp	Tue Jun 27 09:37:05 2017 -0700
@@ -1,40 +1,80 @@
-#include <utilities/sys.h>
-#include <utilities/debug.h>
+#include <utilities/log.h>
 
 #include "ar-vineyard.h"
 
 #include <iostream>
 #include <fstream>
+#include <string>
+#include <vector>
+
+#include <boost/program_options.hpp>
+namespace po = boost::program_options;
 
 
 int main(int argc, char** argv) 
 {
-#ifdef CWDEBUG
-	Debug(dc::filtration.off());
-	Debug(dc::cycle.off());
-	Debug(dc::vineyard.off());
-	Debug(dc::transpositions.off());
-	Debug(dc::lsfiltration.off());
+#ifdef LOGGING
+	rlog::RLogInit(argc, argv);
+	stderrLog.subscribeTo( RLOG_CHANNEL("error") );
+#endif
+
+	std::string infilename;
+	double zx,zy,zz,r;
+	std::string outfilename;
+
+    po::options_description hidden("Hidden options");
+    hidden.add_options()
+        ("input-file",  po::value<std::string>(&infilename), "Points file")
+        ("x",  po::value<double>(&zx), "x")
+        ("y",  po::value<double>(&zy), "y")
+        ("z",  po::value<double>(&zz), "z")
+        ("r",  po::value<double>(&r), "r")
+        ("output-file",  po::value<std::string>(&outfilename), "Vineyard edges output");
 
-	dionysus::debug::init();
+    std::vector<std::string> log_channels;
+    po::options_description visible("Allowed options");
+    visible.add_options()
+        ("help,h",      "produce help message");
+#if LOGGING
+    visible.add_options()
+        ("log,l",       po::value< std::vector<std::string> >(&log_channels),
+                        "log channels to turn on");
+#endif
+    
+    po::positional_options_description p;
+    p.add("input-file", 1).add("x", 1).add("y", 1).add("z", 1).add("r", 1).add("output-file", 1);
+    
+    po::options_description all; all.add(visible).add(hidden);
+
+    po::variables_map vm;
+    po::store(po::command_line_parser(argc, argv).
+                  options(all).positional(p).run(), vm);
+    po::notify(vm);
+
+#if LOGGING
+    for (std::vector<std::string>::const_iterator cur = log_channels.begin(); cur != log_channels.end(); ++cur)
+        stdoutLog.subscribeTo( RLOG_CHANNEL(cur->c_str()) );
+    /* Interesting channels
+     * "ar/vineyard", "ar/function-kernel/value", "geometry/simulator",
+     * "topology/filtration", "topology/cycle", "topology/vineyard",
+     * "topology/filtration/transpositions", "topology/lowerstar"
+     */
 #endif
 
 	// Read command-line arguments
-	if (argc < 6)
+	if (vm.count("help") || !vm.count("input-file") || !vm.count("output-file") 
+                         || !vm.count("x") || !vm.count("y") || !vm.count("z") || !vm.count("r"))
 	{
-		std::cout << "Usage: ar-vineyard POINTS X Y Z OUTFILENAME" << std::endl;
+		std::cout << "Usage: ar-vineyard [OPTIONS] POINTS X Y Z R OUTFILENAME" << std::endl;
 		std::cout << "  POINTS       - filename containing points" << std::endl;
 		std::cout << "  X,Y,Z        - center-point z at which to compute the vineyard" << std::endl;
+		std::cout << "  R            - maximum radius" << std::endl;
 		std::cout << "  OUTFILENAME  - filename for the resulting vineyard" << std::endl;
+        std::cout << visible << std::endl;
 		std::cout << std::endl;
 		std::cout << "Computes an (alpha,r)-vineyard of the given pointset around the given point." << std::endl;
-		exit(0);
+		return 1;
 	}
-	std::string infilename = argv[1];
-	double zx,zy,zz; std::istringstream(argv[2]) >> zx;
-	std::istringstream(argv[3]) >> zy; std::istringstream(argv[4]) >> zz;
-	std::string outfilename = argv[5];
-	
 	
 	// Read in the point set and compute its Delaunay triangulation
 	std::ifstream in(infilename.c_str());
@@ -52,7 +92,7 @@
 	arv.compute_pairing();
 
 	// Compute vineyard
-	arv.compute_vineyard(true);
+	arv.compute_vineyard(r);
 	std::cout << "Vineyard computed" << std::endl;
 	arv.vineyard()->save_edges(outfilename);
 }
--- a/examples/ar-vineyard/ar-vineyard.h	Fri Aug 24 16:58:25 2007 -0400
+++ b/examples/ar-vineyard/ar-vineyard.h	Tue Jun 27 09:37:05 2017 -0700
@@ -6,84 +6,108 @@
 #ifndef __AR_VINEYARD_H__
 #define __AR_VINEYARD_H__
 
-#include "utilities/sys.h"
-#include "utilities/debug.h"
+#include <boost/signals.hpp>
+#include <boost/bind.hpp>
+#include <list>
+#include <vector>
 
 #include "topology/conesimplex.h"
 #include "topology/filtration.h"
 #include "geometry/kinetic-sort.h"
+#include "geometry/simulator.h"
 
-#include <list>
 #include "ar-simplex3d.h"
+#include "ar-function-kernel.h"
 
 
-class ARConeSimplex: public ConeSimplex<ARSimplex3D>
+template <class Simulator_>
+class ARConeSimplex3D: public ConeSimplex<ARSimplex3D>
 {
 	public:
 		typedef						ConeSimplex<ARSimplex3D>									Parent;
 		typedef						ARSimplex3D													ARSimplex3D;
-		typedef						Filtration<ARConeSimplex>									Filtration;
 		
-		/// \name Polynomial Kernel types
+		/// \name Simulator types
 		/// @{
-		typedef						double														FieldType;
-		typedef						UPolynomial<FieldType>										PolyKernel;
-		typedef						PolyKernel::Polynomial										Polynomial;
-		typedef						Simulator<PolyKernel>										Simulator;
+        typedef                     Simulator_                                                  Simulator;
+        typedef                     typename Simulator::FunctionKernel                          FunctionKernel;
+        typedef                     typename FunctionKernel::Function                           Function;
+        /// @}
 		
-		typedef						KineticSort<ARFiltration, SimplexTrajectoryExtractor, Simulator>
-																								SimplexSort;
-		typedef						SimplexSort::iterator										SimplexSortIterator;
-		typedef						SimplexSortIterator											Key;
+		/// \name ThresholdSort types
+		/// @{
+		typedef 					std::list<Function>										    ThresholdList;
+        typedef                     typename ThresholdList::iterator                            ThresholdListIterator;
+
+		struct 						ThresholdTrajectoryExtractor
+		{	Function                operator()(ThresholdListIterator i) const		            { return *i; } };
+
+		typedef						KineticSort<ThresholdListIterator, 
+                                                ThresholdTrajectoryExtractor, Simulator>		ThresholdSort;
 		/// @}
 
-		/// \name Kinetic Sort types
-		/// @{
-		typedef 					std::list<Polynomial>										ThresholdList;
-
-		struct 						ThresholdTrajectoryExtractor
-		{	Polynomial				operator()(ThresholdList::iterator i) const				{ return *i; } }
-		struct 						SimplexTrajectoryExtractor
-		{	Polynomial				operator()(ARFiltration::iterator i) const					{ i->thresholds().front(); }
+        typedef                     boost::signal<void (Simulator*)>                            NewMaxSignal;
+    
+    public:
+									ARConeSimplex3D(const ARSimplex3D& s, bool coned = false);
+									ARConeSimplex3D(const Parent& p): Parent(p)                 {}      // crucial for boundary() to work correctly
+									ARConeSimplex3D(const ARConeSimplex3D& other):              // need explicit copy-constructor because of the signal
+                                        Parent(other, other.coned()), 
+                                        thresholds_(other.thresholds_)                          {}
 
-		typedef						KineticSort<ThresholdList, ThresholdTrajectoryExtractor, Simulator>	
-																								ThresholdSort;
-		/// @}
+		const ThresholdList&        thresholds() const											{ return thresholds_; }
 
-									ARConeSimplex(const ARSimplex3D& s, bool coned = false): 
-										Parent(s, coned), 
-										thresholds_sort_(&thresholds_)							{}
+        NewMaxSignal&               new_max_signal()                                            { return new_max_signal_; }
+        const Function&             max_threshold() const                                       { return thresholds_.back(); }
+		void						schedule_thresholds(Simulator* simulator);
 
-		Key							kinetic_key() const											{ return key_; }
-		void						set_kinetic_key(Key k)										{ key_ = k; }
-		const ThresholdList&		thresholds() const											{ return thresholds_; }
-
-		void						schedule_thresholds(Simulator* simulator);
+        // need explicit operator= because of the signal
+        ARConeSimplex3D&            operator=(const ARConeSimplex3D& other)                     { Parent::operator=(other); thresholds_ = other.thresholds_; return *this; }
 
 								
 	private:
-		Key							key_;
 		ThresholdList				thresholds_;
 		ThresholdSort				thresholds_sort_;
+        NewMaxSignal                new_max_signal_;
 
-		void						swap_thresholds(ThresholdList* tl, typename ThresholdList::iterator i);
+		void						swap_thresholds(ThresholdListIterator i, Simulator* simulator);
 };
 
-
+/**
+ * Encapsulated filtration, and provides compute_vineyard() functionality.
+ */
 class ARVineyard
 {
 	public:
 		typedef						ARVineyard													Self;
+	
+        /// \name FunctionKernel and Simulator types
+        /// @{
+        typedef                     ARFunctionKernel                                            FunctionKernel;
+        typedef                     FunctionKernel::Function                                    Function;
+        typedef                     Simulator<FunctionKernel>                                   SimulatorAR;
+        /// @}
+
+        /// \name Filtration types
+        /// @{    
+        typedef                     ARConeSimplex3D<SimulatorAR>                                ConeSimplex3D;
+		typedef						Filtration<ConeSimplex3D>									FiltrationAR;
+		typedef						FiltrationAR::Simplex										Simplex;
+		typedef						FiltrationAR::Index											Index;
+		typedef						FiltrationAR::Vineyard										Vineyard;
+		typedef						Vineyard::Evaluator											Evaluator;
+        /// @}
 		
-		typedef						ARConeSimplex::Filtration									ARFiltration;	
-		typedef						ARFiltration::Simplex										Simplex;
-		typedef						ARFiltration::Index											Index;
-		typedef						ARFiltration::Vineyard										Vineyard;
-		typedef						Vineyard::Evaluator											Evaluator;
+        /// \name SimplexSort types
+        /// @{
+        struct 						SimplexTrajectoryExtractor
+		{	Function				operator()(Index i) const									{ return i->max_threshold(); } };
+
+		typedef						KineticSort<Index, SimplexTrajectoryExtractor, SimulatorAR> SimplexSort;
+		typedef						SimplexSort::iterator										SimplexSortIterator;
 		
-		typedef						ARConeSimplex::Simulator									Simulator;	
-		typedef						ARConeSimplex::SimplexSort									SimplexSort;	
-
+        class                       ThresholdChangeSlot;              // used to notify of change in max threshold
+		/// @}
 
 		typedef						std::list<Point>											PointList;
 
@@ -95,21 +119,20 @@
 									~ARVineyard();
 
 		void						compute_pairing();
-		void						compute_vineyard(bool explicit_events = false);
+		void						compute_vineyard(double max_radius);
 		
-		const ARFiltration*			filtration() const											{ return filtration_; }
+		const FiltrationAR*			filtration() const											{ return filtration_; }
 		const Vineyard*				vineyard() const											{ return vineyard_; }
 
 	public:
-		// For Kinetic Sort
-		static void 				swap(ARFiltration* filtration, Index i);
+		void 						swap(Index i, SimulatorAR* simulator);						///< For kinetic sort
 	
 	private:
 		void 						add_simplices();
 		void						change_evaluator(Evaluator* eval);
 
 	private:
-		ARFiltration*				filtration_;
+		FiltrationAR*				filtration_;
 		Vineyard*					vineyard_;
 		Evaluator*					evaluator_;
 
@@ -133,35 +156,58 @@
 
 //BOOST_CLASS_EXPORT(ARVineyard)
 
+#ifdef COUNTERS
+static Counter*  cARVineyardTrajectoryKnee =		 GetCounter("ar/vineyard/trajectoryknee");
+#endif
+
+class ARVineyard::ThresholdChangeSlot
+{   
+    public:
+                                ThresholdChangeSlot(SimplexSortIterator iter, SimplexSort* sort, 
+                                                    Vineyard* vineyard, SimulatorAR* sort_simulator):
+                                    iter_(iter), sort_(sort), vineyard_(vineyard), sort_simulator_(sort_simulator)      { iter_->element->new_max_signal().connect(*this); }
+        void                    operator()(SimulatorAR* simulator)                                
+        { 
+            Count(cARVineyardTrajectoryKnee); 
+            sort_->update_trajectory(iter_, sort_simulator_); 
+            if (iter_->element->sign()) 
+                vineyard_->record_knee(iter_->element);
+            else
+                vineyard_->record_knee(iter_->element->pair());
+        }
+    
+    private:
+        SimplexSortIterator     iter_;
+        SimplexSort*            sort_;              // could make both of these static
+        Vineyard*               vineyard_;          // currently inefficient since there is
+                                                    // only one SimplexSort and one Vineyard, 
+                                                    // but each is stored in every slot
+        SimulatorAR*              sort_simulator_;
+};
 
 class ARVineyard::StaticEvaluator: public Evaluator
 {
 	public:
-									StaticEvaluator(RealType t): time_(t)						{}
+									StaticEvaluator()                   						{}
 
-		virtual RealType			time() const												{ return time_; }
+		virtual RealType			time() const												{ return 0; }
 		virtual RealType			value(const Simplex& s) const								{ return s.value(); }
-
-	private:
-		RealType					time_;
 };
 
 class ARVineyard::KineticEvaluator: public Evaluator
 {
 	public:
-									KineticEvaluator(Simulator::Handle sp, 
-													 ActivePointsTable::Handle apt, 
-													 RealType time_offset): 
-										sp_(sp), apt_(apt)										{}
+									KineticEvaluator(SimulatorAR* simplex_sort_simulator,
+                                                     SimulatorAR* trajectory_sort_simulator): 
+                                        simplex_sort_simulator_(simplex_sort_simulator),
+                                        trajectory_sort_simulator_(trajectory_sort_simulator)   {}
 
-		virtual RealType			time() const												{ return CGAL::to_double(get_time()); }
-		virtual RealType			value(const Simplex& s)	const								{ return CGAL::to_double(apt_->at(s.kinetic_key()).x()(get_time())); }
+		virtual RealType			time() const												{ return std::max(simplex_sort_simulator_->current_time(), trajectory_sort_simulator_->current_time()); }
+		virtual RealType			value(const Simplex& s)	const								{ return FunctionKernel::value_at(s.max_threshold(), time()); }
 
 	private:
-		Simulator::Time				get_time() const											{ return sp_->current_time(); }
-		
-		Simulator::Handle			sp_;
-		ActivePointsTable::Handle 	apt_;
+		SimulatorAR*                simplex_sort_simulator_;
+        SimulatorAR*                trajectory_sort_simulator_;
 };
 
 
--- a/examples/ar-vineyard/ar-vineyard.hpp	Fri Aug 24 16:58:25 2007 -0400
+++ b/examples/ar-vineyard/ar-vineyard.hpp	Tue Jun 27 09:37:05 2017 -0700
@@ -1,44 +1,68 @@
+#include <utilities/log.h>
+
 /* Implementation */
+
+#ifdef LOGGING
+static rlog::RLogChannel* rlARVineyard =                        DEF_CHANNEL("ar/vineyard", rlog::Log_Debug);
+static rlog::RLogChannel* rlARVineyardComputing =               DEF_CHANNEL("ar/vineyard/computing", rlog::Log_Debug);
+static rlog::RLogChannel* rlARVineyardSwap =                    DEF_CHANNEL("ar/vineyard/swap", rlog::Log_Debug);
+static rlog::RLogChannel* rlARVineyardThresholdSwap =           DEF_CHANNEL("ar/vineyard/threshold/swap", rlog::Log_Debug);
+#endif
+
+
+template <class Simulator_>
+ARConeSimplex3D<Simulator_>::
+ARConeSimplex3D(const ARSimplex3D& s, bool coned): Parent(s, coned)
+{}
 	
+template <class Simulator_>
 void
-ARConeSimplex::
-swap_thresholds(ThresholdList* tl, typename ThresholdList::iterator i)
+ARConeSimplex3D<Simulator_>::
+swap_thresholds(ThresholdListIterator i, Simulator* simulator)
 {
-	AssertMsg(tl == &thresholds_, "Swap in the wrong list");		// might as well take advantage of the redundancy
-
+    rLog(rlARVineyardThresholdSwap, "Transposing %s and %s", tostring(*i).c_str(),
+                                                             tostring(*boost::next(i)).c_str());
 	typename ThresholdList::iterator n = boost::next(i);
-	tl->splice(i, *tl, n);
-	if (n == tl->begin())
-
+	thresholds_.splice(i, thresholds_, n);
+	if (boost::next(i) == thresholds_.end())
+        new_max_signal_(simulator);
 }
 
+template <class Simulator_>
 void
-ARConeSimplex::
+ARConeSimplex3D<Simulator_>::
 schedule_thresholds(Simulator* simulator)
 {
-	thresholds_sort_.insert(thresholds_sort_.end(), thresholds_.begin(), thresholds_.end(), simulator);
+    if (!coned()) thresholds_.push_back(Function(Function::rho, this));
+    else        
+    { 
+        thresholds_.push_back(Function(Function::phi, this)); 
+        thresholds_.push_back(Function(Function::rho, this)); 
+	    thresholds_sort_.initialize(thresholds_.begin(), thresholds_.end(), 
+		    						boost::bind(&ARConeSimplex3D::swap_thresholds, this, _1, _2), simulator);
+    }
 }
 
 
 ARVineyard::
-ARVineyard(const PointList& points, const Point& z): simplex_sort_(0), z_(z)
+ARVineyard(const PointList& points, const Point& z): z_(z)
 {
 	for (PointList::const_iterator cur = points.begin(); cur != points.end(); ++cur)
 		dt_.insert(*cur);
-	std::cout << "Delaunay triangulation computed" << std::endl;
+	rLog(rlARVineyard, "Delaunay triangulation computed");
 
 	ARSimplex3DVector alpha_ordering;
 	fill_alpha_order(dt_, z_, alpha_ordering);
-	std::cout << "Delaunay simplices: " << alpha_ordering.size() << std::endl;
+	rLog(rlARVineyard, "Delaunay simplices: %i", alpha_ordering.size());
 		
-	evaluator_ = new StaticEvaluator(0);
+	evaluator_ = new StaticEvaluator;
 	vineyard_ = new Vineyard(evaluator_);
 
-	filtration_ = new ARFiltration(vineyard_);
+	filtration_ = new FiltrationAR(vineyard_);
 	for (ARSimplex3DVector::const_iterator cur = alpha_ordering.begin(); cur != alpha_ordering.end(); ++cur)
 	{
-		filtration_->append(ARConeSimplex(*cur));						// Delaunay simplex
-		filtration_->append(ARConeSimplex(*cur, true));	// Coned off delaunay simplex
+		filtration_->append(ConeSimplex3D(*cur));         // Delaunay simplex
+		filtration_->append(ConeSimplex3D(*cur, true));   // Coned off delaunay simplex
 	}
 }
 
@@ -57,111 +81,64 @@
 	filtration_->fill_simplex_index_map();
 	filtration_->pair_simplices(filtration_->begin(), filtration_->end());
 	vineyard_->start_vines(filtration_->begin(), filtration_->end());
-	std::cout << "Simplices paired" << std::endl;
+	rLog(rlARVineyard, "Simplices paired");
 }
 
 void					
 ARVineyard::
-compute_vineyard(bool explicit_events)
+compute_vineyard(double max_radius)
 {
 	AssertMsg(filtration_->is_paired(), "Simplices must be paired for a vineyard to be computed");
 	
-	Simulator simulator;
-	SimplexSort	simplex_sort(filtration_, swap);
-
-
-
-
-
-
-
-	simplex_sort.initialize(&simulator);
-
-
-
-	typedef Traits::Kinetic_kernel::Point_1 								Point_1;
-	typedef Simulator::Time													Time;
+	SimulatorAR simplex_sort_simulator, trajectory_sort_simulator;
+	SimplexSort	simplex_sort;
 	
-	Traits tr(0,1);
-	Simulator::Handle sp = tr.simulator_handle();
-	ActivePointsTable::Handle apt = tr.active_points_1_table_handle();
-	Sort sort(tr, SortVisitor(this));
-	
-	// Setup the kinetic sort and membership changes
-	std::cout << "Setting up the kinetic sort and membership events" << std::endl;
-	CF cf; 
-	kinetic_map_.clear();
+	// Schedule thresholds
 	for (Index cur = filtration_->begin(); cur != filtration_->end(); ++cur)
-	{
-		F x = cf(F::NT(CGAL::to_double(cur->alpha())));
-		Point_1 p(x);
-		cur->set_kinetic_key(apt->insert(p));
-		kinetic_map_[cur->kinetic_key()] = cur;
-			
-		if (!cur->coned()) continue;						// non-coned simplices stay put, so we are done
+        cur->schedule_thresholds(&trajectory_sort_simulator);
 
-		Time lambda_alpha = CGAL::to_double((cur->alpha() - cur->rho()));	// when lambda becomes greater than alpha
-		lambda_alpha += 2*CGAL::sqrt(CGAL::to_double(cur->s()*lambda_alpha));
-		lambda_alpha += CGAL::to_double(cur->s() + cur->v());
-
-		Time phi_alpha = CGAL::to_double(cur->alpha() - cur->phi_const());
+	// Once thresholds are scheduled, we can initialize the simplex_sort
+	simplex_sort.initialize(filtration_->begin(), filtration_->end(), 
+							boost::bind(&ARVineyard::swap, this, _1, _2), &simplex_sort_simulator);
+    rLog(rlARVineyardComputing, "SimplexSort initialized");
 
-		Time phi_lambda = CGAL::to_double(cur->rho() + cur->s() - cur->v() - cur->phi_const());
-		phi_lambda *= phi_lambda;
-		phi_lambda /= CGAL::to_double(4*cur->s());
-		phi_lambda += CGAL::to_double(cur->v());
-
-		Time sv = CGAL::to_double(cur->s() + cur->v());
-		
-		if (true || phi_lambda < sv || phi_lambda < phi_alpha)		// FIXME: remove true
-		{
-			sp->new_event(Time(phi_alpha), 
-						  MembershipFunctionChangeEvent(cur->kinetic_key(),
-														cf(F::NT(CGAL::to_double(cur->phi_const())), 1),
-														apt));		// \phi^2 = r^2 + \phi_c^2
-			std::cout << "Scheduled" << std::endl;
-		} else
-			std::cout << "Not scheduled" << std::endl;
-		
-
-		//sp->new_event(Time(...), MembershipFunctionChangeEvent(cur->kinetic_key()));
-		
-		std::cout << *cur << std::endl;
-		std::cout << "lambda_alpha: " 		<< lambda_alpha << std::endl;
-		std::cout << "phi_alpha: " 			<< phi_alpha << std::endl;
-		std::cout << "phi_lambda: " 		<< phi_lambda << std::endl;
-		std::cout << "s^2 + v^2: " 			<< sv << std::endl;
-		std::cout << std::endl;
-	}
+    // Connect signals and slots
+    std::vector<ThresholdChangeSlot> slots; 
+    slots.reserve(filtration_->size());
+    for (SimplexSortIterator cur = simplex_sort.begin(); cur != simplex_sort.end(); ++cur)
+        slots.push_back(ThresholdChangeSlot(cur, &simplex_sort, vineyard_, &simplex_sort_simulator));
+    rLog(rlARVineyardComputing, "Signals and slots connected");
+    rLog(rlARVineyardComputing, "SimplexSort size: %i", simplex_sort_simulator.size());
+    rLog(rlARVineyardComputing, "TrajectorySort size: %i", trajectory_sort_simulator.size());
 	
-	// Process all the events (compute the vineyard in the process)
-	// FIXME: the time should not be 1, but something like twice the radius of
-	// the pointset as seen from z
-	change_evaluator(new KineticEvaluator(sp, apt, 0));
-	if (explicit_events)
-	{
-		while (sp->next_event_time() < 1)
-		{
-			std::cout << "Next event time: " << sp->next_event_time() << std::endl;
-			sp->set_current_event_number(sp->current_event_number() + 1);
-			std::cout << "Processed event" << std::endl;
-		}
-	} else
-		sp->set_current_time(1.0);
-	std::cout << "Processed " << sp->current_event_number() << " events" << std::endl;
+    // Simulate
+	change_evaluator(new KineticEvaluator(&simplex_sort_simulator, &trajectory_sort_simulator));
+    while ((simplex_sort_simulator.current_time() < max_radius || trajectory_sort_simulator.current_time() < max_radius) && !(simplex_sort_simulator.reached_infinity() && trajectory_sort_simulator.reached_infinity()))
+    {
+        if (*(simplex_sort_simulator.top()) < *(trajectory_sort_simulator.top()))
+        {
+            rLog(rlARVineyardComputing, "Current time before: %lf (simplex sort)", simplex_sort_simulator.current_time());
+            rLog(rlARVineyardComputing, "Top event: %s (simplex sort)", intostring(*(simplex_sort_simulator.top())).c_str());
+            simplex_sort_simulator.process();
+        } else
+        {
+            rLog(rlARVineyardComputing, "Current time before: %lf (trajectory sort)", trajectory_sort_simulator.current_time());
+            rLog(rlARVineyardComputing, "Top event: %s (trajectory sort)", intostring(*(trajectory_sort_simulator.top())).c_str());
+            trajectory_sort_simulator.process();
+        }
+    }
 	
-	//change_evaluator(new StaticEvaluator(1));
 	vineyard_->record_diagram(filtration_->begin(), filtration_->end());
 }
 		
 void 					
 ARVineyard::
-swap(Key a, Key b)
+swap(Index i, SimulatorAR* simulator)
 {
-	Index ao = kinetic_map_[a], bo = kinetic_map_[b];
-	AssertMsg(filtration_->get_trails_cmp()(ao, bo), "In swap(a,b), a must precede b");
-	filtration_->transpose(ao);
-	AssertMsg(filtration_->get_trails_cmp()(bo, ao), "In swap(a,b), b must precede a after the transposition");
+    rLog(rlARVineyardSwap, "Transposing %p and %p:", &(*i), &(*boost::next(i)));
+    rLog(rlARVineyardSwap, "  %s and", tostring(*i).c_str());
+    rLog(rlARVineyardSwap, "  %s", tostring(*boost::next(i)).c_str());
+	filtration_->transpose(i);
 }
 
 void
@@ -174,30 +151,3 @@
 	evaluator_ = eval;
 	vineyard_->set_evaluator(evaluator_);
 }
-
-void 
-ARVineyardBase::MembershipFunctionChangeEvent::
-process() const
-{
-	apt_->set(key_, function_);
-	std::cout << "Updated for phi's dominance" << std::endl;
-}
-
-
-template<class Vertex_handle>
-void
-ARVineyardBase::SortVisitor::
-before_swap(Vertex_handle a, Vertex_handle b) const
-{ 
-	std::cout << "Swapping elements" << *a << " and " << *b << std::endl;
-	arv_->swap(*a,*b); 
-}
-
-
-std::ostream&
-ARVineyardBase::MembershipFunctionChangeEvent::
-operator<<(std::ostream& out) const
-{
-	return out << "Membership change" << std::endl;
-}
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/bottleneck-distance.cpp	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,68 @@
+#include <utilities/types.h>
+#include <topology/persistence-diagram.h>
+
+#include <string>
+#include <iostream>
+#include <fstream>
+#include <sstream>
+#include <boost/archive/binary_iarchive.hpp>
+#include <boost/serialization/map.hpp>
+
+#include <boost/program_options.hpp>
+
+
+typedef PersistenceDiagram<>                    PDgm;
+
+namespace po = boost::program_options;
+
+
+void read_diagram(PDgm& dgm, const std::string& filename)
+{
+    std::ifstream in(filename.c_str());
+    std::string line;
+    std::getline(in, line);
+    while (in)
+    {
+        std::istringstream sin(line);
+        double x,y;
+        sin >> x >> y;
+        dgm.push_back(PDgm::Point(x,y));
+        std::getline(in, line);
+    }
+}
+
+int main(int argc, char* argv[])
+{
+    std::string     filename1, filename2;
+
+    po::options_description hidden("Hidden options");
+    hidden.add_options()
+        ("input-file1",  po::value<std::string>(&filename1), "The first collection of persistence diagrams")
+        ("input-file2",  po::value<std::string>(&filename2), "The second collection of persistence diagrams");
+
+    po::positional_options_description p;
+    p.add("input-file1", 1);
+    p.add("input-file2", 2);
+
+    po::options_description all; all.add(hidden);
+
+    po::variables_map vm;
+    po::store(po::command_line_parser(argc, argv).
+                  options(all).positional(p).run(), vm);
+    po::notify(vm);
+
+    if (!vm.count("input-file1") || !vm.count("input-file2"))
+    {
+        std::cout << "Usage: " << argv[0] << " input-file1 input-file2" << std::endl;
+        return 1;
+    }
+
+    PDgm dgm1, dgm2;
+    read_diagram(dgm1, filename1);
+    read_diagram(dgm2, filename2);
+    //std::cout << "Size dgm1: " << dgm1.size() << std::endl;
+    //std::cout << "Size dgm2: " << dgm2.size() << std::endl;
+
+    //std::cout << "Distance: " << bottleneck_distance(dgm1, dgm2) << std::endl;
+    std::cout << "L2-Distance: " << wasserstein_distance(dgm1, dgm2, 2) << std::endl;
+}
--- a/examples/cech-complex/CMakeLists.txt	Fri Aug 24 16:58:25 2007 -0400
+++ b/examples/cech-complex/CMakeLists.txt	Tue Jun 27 09:37:05 2017 -0700
@@ -1,7 +1,7 @@
-set							(targets						
-							 cech-complex)
-							 
-foreach 					(t ${targets})
-	add_executable			(${t} ${t}.cpp ${external_sources})
-	target_link_libraries	(${t} ${libraries} ${cgal_libraries})
-endforeach 					(t ${targets})
+set                         (targets                        
+                             cech-complex)
+                             
+foreach                     (t ${targets})
+    add_executable          (${t} ${t}.cpp)
+    target_link_libraries   (${t} ${libraries})
+endforeach                  (t ${targets})
--- a/examples/cech-complex/cech-complex.cpp	Fri Aug 24 16:58:25 2007 -0400
+++ b/examples/cech-complex/cech-complex.cpp	Tue Jun 27 09:37:05 2017 -0700
@@ -1,8 +1,10 @@
-#include <utilities/sys.h>
-#include <utilities/debug.h>
+#include <utilities/log.h>
 
 #include <topology/simplex.h>
 #include <topology/filtration.h>
+#include <topology/static-persistence.h>
+//#include <topology/dynamic-persistence.h>
+#include <topology/persistence-diagram.h>
 #include "Miniball_dynamic_d.h"
 #include <algorithm>
 
@@ -10,120 +12,119 @@
 #include <fstream>
 
 
-typedef 		std::vector<Point>										PointContainer;
-typedef			unsigned int 											PointIndex;
-typedef			SimplexWithValue<PointIndex>							Simplex;
-typedef 		std::vector<Simplex> 									SimplexVector;
-typedef 		Filtration<Simplex>										CechFiltration;
-
-class DimensionValueComparison
-{
-	public:
-		bool	operator()(const Simplex& s1, const Simplex& s2) const
-		{
-			if (s1.dimension() == s2.dimension())
-				return s1.get_value() < s2.get_value();
-			else
-				return s1.dimension() < s2.dimension();
-		}
-};
+typedef         std::vector<Point>                                      PointContainer;
+typedef         unsigned int                                            PointIndex;
+typedef         Simplex<PointIndex, double>                             Smplx;
+typedef         Filtration<Smplx>                                       CechFiltration;
+typedef         StaticPersistence<>                                     Persistence;
+//typedef         DynamicPersistenceTrails<>                              Persistence;
+typedef         PersistenceDiagram<>            PDgm;
 
 int choose(int n, int k)
 {
-	if (k > n/2) k = n-k;
-	int numerator = 1, denominator = 1;
-	for (int i = 0; i < k; ++i)
-	{ numerator *= (n-i); denominator *= (i+1); }
-	return numerator/denominator;
+    if (k > n/2) k = n-k;
+    int numerator = 1, denominator = 1;
+    for (int i = 0; i < k; ++i)
+    { numerator *= (n-i); denominator *= (i+1); }
+    return numerator/denominator;
 }
 
-void add_simplices(SimplexVector& sv, int d, const PointContainer& points)
+void add_simplices(CechFiltration& sv, int d, const PointContainer& points)
 {
-	PointIndex indices[d+1];
-	for (int i = 0; i < d+1; ++i) 
-		indices[i] = d - i;
+    PointIndex indices[d+1];
+    for (int i = 0; i < d+1; ++i) 
+        indices[i] = d - i;
 
-	while(indices[d] < points.size() - d)
-	{
-		// Add simplex
-		Miniball mb(points[indices[0]].dim());
-		Simplex s;
-		for (int i = 0; i < d+1; ++i)
-		{
-			s.add(indices[i]);
-			mb.check_in(points[indices[i]]);
-		}
-		mb.build();
-		s.set_value(mb.squared_radius());
-		sv.push_back(s);
+    while(indices[d] < points.size() - d)
+    {
+        // Add simplex
+        Miniball mb(points[indices[0]].dim());
+        Smplx s;
+        for (int i = 0; i < d+1; ++i)
+        {
+            s.add(indices[i]);
+            mb.check_in(points[indices[i]]);
+        }
+        mb.build();
+        s.data() = mb.squared_radius();
+        sv.push_back(s);
 
-		
-		// Advance indices
-		for (int i = 0; i < d+1; ++i)
-		{
-			++indices[i];
-			if (indices[i] < points.size() - i)
-			{
-				for (int j = i-1; j >= 0; --j)
-					indices[j] = indices[j+1] + 1;
-				break;
-			}
-		}
-	}
+        
+        // Advance indices
+        for (int i = 0; i < d+1; ++i)
+        {
+            ++indices[i];
+            if (indices[i] < points.size() - i)
+            {
+                for (int j = i-1; j >= 0; --j)
+                    indices[j] = indices[j+1] + 1;
+                break;
+            }
+        }
+    }
 }
 
 int main(int argc, char** argv) 
 {
-	// Read in the point set and compute its Delaunay triangulation
-	std::istream& in = std::cin;
-	int ambient_d, homology_d;	
-	in >> ambient_d >> homology_d;
-	
-	std::cout << "Ambient dimension: " << ambient_d << std::endl;
-	std::cout << "Will compute PD up to dimension: " << homology_d << std::endl;
-	
-	// Read points
-	PointContainer points;
-	while(in)
-	{
-		Point p(ambient_d);
-		for (int i = 0; i < ambient_d; ++i)
-			in >> p[i];
-		points.push_back(p);
-	}
-	std::cout << "Points read: " << points.size() << std::endl;
+#ifdef LOGGING
+    rlog::RLogInit(argc, argv);
+
+    stdoutLog.subscribeTo( RLOG_CHANNEL("info") );
+    stdoutLog.subscribeTo( RLOG_CHANNEL("error") );
+#endif
+
+    SetFrequency(GetCounter("persistence/pair"), 10000);
+    SetTrigger(GetCounter("persistence/pair"), GetCounter(""));
+
+    // Read in the point set and compute its Delaunay triangulation
+    std::istream& in = std::cin;
+    int ambient_d, homology_d;
+    in >> ambient_d >> homology_d;
+    
+    rInfo("Ambient dimension: %d", ambient_d);
+    rInfo("Will compute PD up to dimension: %d", homology_d);
+    
+    // Read points
+    PointContainer points;
+    while(in)
+    {
+        Point p(ambient_d);
+        for (int i = 0; i < ambient_d; ++i)
+            in >> p[i];
+        points.push_back(p);
+    }
+    rInfo("Points read: %d", points.size());
    
-	// Compute Cech values
-	CechFiltration cf;
-	{										// resource acquisition is initialization
-		SimplexVector	sv;
-		int num_simplices = 0;
-		for (int i = 0; i <= homology_d + 1; ++i)
-			num_simplices += choose(points.size(), i+1);
-		sv.reserve(num_simplices);
-		std::cout << "Reserved SimplexVector of size: " << num_simplices << std::endl;
+    // Compute simplices with their Cech values
+    int num_simplices = 0;
+    for (int i = 0; i <= homology_d + 1; ++i)
+        num_simplices += choose(points.size(), i+1);
+    rInfo("Reserved SimplexVector of size: %d", num_simplices);
+
+    CechFiltration cf;
+    for (int i = 0; i <= homology_d + 1; ++i)
+        add_simplices(cf, i, points);
+    rInfo("Size of SimplexVector: %d", cf.size());
+
+    // Sort the filtration
+    cf.sort(DataDimensionComparison<Smplx>());
+    rInfo("Filtration initialized");
 
-		for (int i = 0; i <= homology_d + 1; ++i)
-			add_simplices(sv, i, points);
-		std::cout << "Size of SimplexVector: " << sv.size() << std::endl;
-			
-		std::sort(sv.begin(), sv.end(), DimensionValueComparison());
-		
-		for (SimplexVector::const_iterator cur = sv.begin(); cur != sv.end(); ++cur)
-			cf.append(*cur);
-	}
+    // Compute persistence
+    Persistence p(cf);
+    rInfo("Persistence initialized");
+    p.pair_simplices();
+    rInfo("Simplices paired");
 
-	// Compute persistence
-	cf.fill_simplex_index_map();
-	cf.pair_simplices(cf.begin(), cf.end());
-	std::cout << "Simplices paired" << std::endl;
+    Persistence::SimplexMap<CechFiltration>     m = p.make_simplex_map(cf);
+    std::map<Dimension, PDgm> dgms;
+    init_diagrams(dgms, p.begin(), p.end(), 
+                  evaluate_through_map(m, Smplx::DataEvaluator()), 
+                  evaluate_through_map(m,  Smplx::DimensionExtractor()));
 
-	for (CechFiltration::Index i = cf.begin(); i != cf.end(); ++i)
-		if (i->is_paired())
-		{
-			if (i->sign())
-				std::cout << i->dimension() << " " << i->get_value() << " " << i->pair()->get_value() << std::endl;
-		} //else std::cout << i->value() << std::endl;
-
+    for (int i = 0; i <= homology_d; ++i)
+    {
+        std::cout << i << std::endl << dgms[i] << std::endl;
+    }
 }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/cohomology/CMakeLists.txt	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,12 @@
+set                         (targets                        
+                             rips-cohomology
+                             rips-pairwise-cohomology
+                             rips-explicit-cohomology
+                             rips-weighted-cohomology
+                             triangle-cohomology
+                            )
+                             
+foreach                     (t ${targets})
+    add_executable          (${t} ${t}.cpp)
+    target_link_libraries   (${t} ${libraries} ${Boost_PROGRAM_OPTIONS_LIBRARY})
+endforeach                  (t ${targets})
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/cohomology/cocycle.py	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,86 @@
+#!/usr/bin/env python
+
+from    cvxopt          import spmatrix, matrix
+from    cvxopt.blas     import copy
+from    lsqr            import lsqr
+from    sys             import argv, exit
+import  os.path
+
+def smooth(boundary_list, cocycle_list):
+    dimension = max((max(d[1], d[2]) for d in boundary_list))
+    dimension += 1
+
+    # NB: D is a coboundary matrix; 1 and 2 below are transposed
+    D = spmatrix([d[0] for d in boundary_list],
+                 [d[2] for d in boundary_list],
+                 [d[1] for d in boundary_list], (dimension, dimension))
+
+           
+    z = spmatrix([zz[0] for zz in cocycle_list],
+                 [zz[1] for zz in cocycle_list],
+                 [0     for zz in cocycle_list], (dimension, 1))
+
+    v1 = D * z
+    # print "D^2 is zero:", not bool(D*D)
+    # print "D*z is zero:", not bool(v1)
+    z = matrix(z)
+
+    def Dfun(x,y,trans = 'N'):
+        if trans == 'N':
+            copy(D * x, y)
+        elif trans == 'T':
+            copy(D.T * x, y)
+        else:
+            assert False, "Unexpected trans parameter"
+
+    tol = 1e-10
+    show = False
+    maxit = None
+    solution = lsqr(Dfun, matrix(z), show = show, atol = tol, btol = tol, itnlim = maxit)
+    
+    v = z - D*solution[0]
+
+    # print sum(v**2)
+    # assert sum((D*v)**2) < tol and sum((D.T*v)**2) < tol, "Expected a harmonic cocycle"
+    if not (sum((D*v)**2) < tol and sum((D.T*v)**2) < tol):
+        print "Expected a harmonic cocycle:", sum((D*v)**2), sum((D.T*v)**2) 
+
+    return solution[0], v
+
+
+def vertex_values(solution, vertices):
+    values = [None]*len(vertices)
+    for i,v in vertices:
+        values[v] = solution[i]
+    return values
+    
+
+def read_list_file(filename):
+    list = []
+    with open(filename) as fp:
+        for line in fp.xreadlines():
+            if line.startswith('#'): continue
+            list.append(map(int, line.split()))
+    return list
+
+
+if __name__ == '__main__':
+    if len(argv) < 4:
+        print "Usage: %s BOUNDARY COCYCLE VERTEXMAP" % argv[0]
+        exit()
+
+    boundary_filename = argv[1]
+    cocycle_filename = argv[2]
+    vertexmap_filename = argv[3]
+
+    boundary_list = read_list_file(boundary_filename)
+    cocycle_list = read_list_file(cocycle_filename)
+    vertexmap_list = read_list_file(vertexmap_filename)
+
+    solution, v = smooth(boundary_list, cocycle_list)
+    values = vertex_values(solution, vertexmap_list)
+
+    outfn = os.path.splitext(cocycle_filename)[0] + '.val'
+    with open(outfn, 'w') as f:
+        for i,v in enumerate(values):
+            f.write('%d %f\n' % (i,v))
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/cohomology/lsqr.py	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,408 @@
+# LSQR solver from http://pages.cs.wisc.edu/~kline/cvxopt/
+
+from cvxopt import matrix
+from cvxopt.lapack import *
+from cvxopt.blas import *
+from math import sqrt
+
+"""
+a,b are scalars
+
+On exit, returns scalars c,s,r
+"""
+def SymOrtho(a,b):
+    aa=abs(a)
+    ab=abs(b)
+    if b==0.:
+        s=0.
+        r=aa
+        if aa==0.:
+            c=1.
+        else:
+            c=a/aa
+    elif a==0.:
+        c=0.
+        s=b/ab
+        r=ab
+    elif ab>=aa:
+        sb=1
+        if b<0: sb=-1
+        tau=a/b
+        s=sb*(1+tau**2)**-0.5
+        c=s*tau
+        r=b/s
+    elif aa>ab:
+        sa=1
+        if a<0: sa=-1
+        tau=b/a
+        c=sa*(1+tau**2)**-0.5
+        s=c*tau
+        r=a/c
+        
+    return c,s,r
+
+"""
+
+It is usually recommended to use SYMMLQ for symmetric matrices
+
+Requires the syntax
+                   A(x,y)   == y:=[A]*x
+and
+           A(x,y,trans='T') == y:=[A.T]*x
+
+comments with '###' are followed by the intent of the original matlab
+code. This may be useful for debugging.
+
+"""
+
+def lsqr(  A, b, damp=0.0, atol=1e-8, btol=1e-8, conlim=1e8, itnlim=None, show=False, wantvar=False):
+    """
+    
+    [ x, istop, itn, r1norm, r2norm, anorm, acond, arnorm, xnorm, var ]...
+     = lsqr( m, n,  'aprod',  iw, rw, b, damp, atol, btol, conlim, itnlim, show );
+    
+     LSQR solves  Ax = b  or  min ||b - Ax||_2  if damp = 0,
+     or   min || (b)  -  (  A   )x ||   otherwise.
+              || (0)     (damp I)  ||2
+     A  is an m by n matrix defined by  y = aprod( mode,m,n,x,iw,rw ),
+     where the parameter 'aprodname' refers to a function 'aprod' that
+     performs the matrix-vector operations.
+     If mode = 1,   aprod  must return  y = Ax   without altering x.
+     If mode = 2,   aprod  must return  y = A'x  without altering x.
+     WARNING:   The file containing the function 'aprod'
+                must not be called aprodname.m !!!!
+
+    -----------------------------------------------------------------------
+     LSQR uses an iterative (conjugate-gradient-like) method.
+     For further information, see 
+     1. C. C. Paige and M. A. Saunders (1982a).
+        LSQR: An algorithm for sparse linear equations and sparse least squares,
+        ACM TOMS 8(1), 43-71.
+     2. C. C. Paige and M. A. Saunders (1982b).
+        Algorithm 583.  LSQR: Sparse linear equations and least squares problems,
+        ACM TOMS 8(2), 195-209.
+     3. M. A. Saunders (1995).  Solution of sparse rectangular systems using
+        LSQR and CRAIG, BIT 35, 588-604.
+    
+     Input parameters:
+     iw, rw      are not used by lsqr, but are passed to aprod.
+     atol, btol  are stopping tolerances.  If both are 1.0e-9 (say),
+                 the final residual norm should be accurate to about 9 digits.
+                 (The final x will usually have fewer correct digits,
+                 depending on cond(A) and the size of damp.)
+     conlim      is also a stopping tolerance.  lsqr terminates if an estimate
+                 of cond(A) exceeds conlim.  For compatible systems Ax = b,
+                 conlim could be as large as 1.0e+12 (say).  For least-squares
+                 problems, conlim should be less than 1.0e+8.
+                 Maximum precision can be obtained by setting
+                 atol = btol = conlim = zero, but the number of iterations
+                 may then be excessive.
+     itnlim      is an explicit limit on iterations (for safety).
+     show = 1    gives an iteration log,
+     show = 0    suppresses output.
+    
+     Output parameters:
+     x           is the final solution.
+     istop       gives the reason for termination.
+     istop       = 1 means x is an approximate solution to Ax = b.
+                 = 2 means x approximately solves the least-squares problem.
+     r1norm      = norm(r), where r = b - Ax.
+     r2norm      = sqrt( norm(r)^2  +  damp^2 * norm(x)^2 )
+                 = r1norm if damp = 0.
+     anorm       = estimate of Frobenius norm of Abar = [  A   ].
+                                                        [damp*I]
+     acond       = estimate of cond(Abar).
+     arnorm      = estimate of norm(A'*r - damp^2*x).
+     xnorm       = norm(x).
+     var         (if present) estimates all diagonals of (A'A)^{-1} (if damp=0)
+                 or more generally (A'A + damp^2*I)^{-1}.
+                 This is well defined if A has full column rank or damp > 0.
+                 (Not sure what var means if rank(A) < n and damp = 0.)
+                 
+    
+            1990: Derived from Fortran 77 version of LSQR.
+     22 May 1992: bbnorm was used incorrectly.  Replaced by anorm.
+     26 Oct 1992: More input and output parameters added.
+     01 Sep 1994: Matrix-vector routine is now a parameter 'aprodname'.
+                  Print log reformatted.
+     14 Jun 1997: show  added to allow printing or not.
+     30 Jun 1997: var   added as an optional output parameter.
+     07 Aug 2002: Output parameter rnorm replaced by r1norm and r2norm.
+                  Michael Saunders, Systems Optimization Laboratory,
+                  Dept of MS&E, Stanford University.
+    -----------------------------------------------------------------------
+    """
+    """
+         Initialize.
+    """
+    n=len(b)
+    m=n
+    if itnlim is None: itnlim=2*n    
+
+    msg=('The exact solution is  x = 0                              ',
+         'Ax - b is small enough, given atol, btol                  ',
+         'The least-squares solution is good enough, given atol     ',
+         'The estimate of cond(Abar) has exceeded conlim            ',
+         'Ax - b is small enough for this machine                   ',
+         'The least-squares solution is good enough for this machine',
+         'Cond(Abar) seems to be too large for this machine         ',
+         'The iteration limit has been reached                      ');
+
+    var = matrix(0.,(n,1));
+
+    if show:
+        print ' '
+        print 'LSQR            Least-squares solution of  Ax = b'
+        str1 = 'The matrix A has %8g rows  and %8g cols' % (m, n)
+        str2 = 'damp = %20.14e    wantvar = %8g' %( damp,wantvar)
+        str3 = 'atol = %8.2e                 conlim = %8.2e'%( atol, conlim)
+        str4 = 'btol = %8.2e                 itnlim = %8g'  %( btol, itnlim)
+        print str1
+        print str2
+        print str3
+        print str4
+
+    itn    = 0;		istop  = 0;		nstop  = 0;
+    ctol   = 0;
+    if conlim > 0: ctol = 1/conlim
+    anorm  = 0;		acond  = 0;
+    dampsq = damp**2;	ddnorm = 0;		res2   = 0;
+    xnorm  = 0;		xxnorm = 0;		z      = 0;
+    cs2    = -1;		sn2    = 0;
+    
+    """
+    Set up the first vectors u and v for the bidiagonalization.
+     These satisfy  beta*u = b,  alfa*v = A'u.
+    """
+    __x    = matrix(0., (n,1)) # a matrix for temporary holding
+    v      = matrix(0., (n,1))
+    u      = +b;	
+    x      = matrix(0., (n,1))
+    alfa   = 0;
+    beta = nrm2( u );
+    w      = matrix(0., (n,1))
+    
+    if beta > 0:
+        ### u = (1/beta) * u;
+        ### v = feval( aprodname, 2, m, n, u, iw, rw );
+        scal(1/beta,u)
+	A(u,v,trans='T'); #v = feval( aprodname, 2, m, n, u, iw, rw );
+        alfa = nrm2( v );
+
+    if alfa > 0:
+        ### v = (1/alfa) * v;
+        scal(1/alfa,v)
+        copy(v,w)
+
+
+    rhobar = alfa;		phibar = beta;		bnorm  = beta;
+    rnorm  = beta;
+    r1norm = rnorm;
+    r2norm = rnorm;
+
+    # reverse the order here from the original matlab code because
+    # there was an error on return when arnorm==0
+    arnorm = alfa * beta;
+    if arnorm == 0:
+        print msg[0];
+        return x, istop, itn, r1norm, r2norm, anorm, acond, arnorm, xnorm, var 
+
+    head1  = '   Itn      x[0]       r1norm     r2norm ';
+    head2  = ' Compatible   LS      Norm A   Cond A';
+    
+    if show:
+        print ' '
+        print head1, head2
+        test1  = 1;		test2  = alfa / beta;
+        str1   = '%6g %12.5e'    %(    itn,   x[0] );
+        str2   = ' %10.3e %10.3e'%( r1norm, r2norm );
+        str3   = '  %8.1e %8.1e' %(  test1,  test2 );
+        print str1, str2, str3
+        
+    """
+    %------------------------------------------------------------------
+    %     Main iteration loop.
+    %------------------------------------------------------------------
+    """
+    while itn < itnlim:
+        itn = itn + 1;
+        """
+        %     Perform the next step of the bidiagonalization to obtain the
+        %     next  beta, u, alfa, v.  These satisfy the relations
+        %                beta*u  =  a*v   -  alfa*u,
+        %                alfa*v  =  A'*u  -  beta*v.
+        """
+        ### u    = feval( aprodname, 1, m, n, v, iw, rw )  -  alfa*u;
+        copy(u, __x)
+        A(v,u)
+        axpy(__x,u,-alfa)
+
+        beta = nrm2( u );
+        if beta > 0:
+            ### u     = (1/beta) * u;
+            scal(1/beta,u)
+            anorm = sqrt(anorm**2 + alfa**2 + beta**2 + damp**2);
+            ### v     = feval( aprodname, 2, m, n, u, iw, rw )  -  beta*v;
+            copy(v,__x)
+            A(u,v,trans='T')
+            axpy(__x,v,-beta)
+
+            alfa  = nrm2( v );
+            if alfa > 0:
+                ### v = (1/alfa) * v;
+                scal(1/alfa, v)
+
+        """
+        %     Use a plane rotation to eliminate the damping parameter.
+        %     This alters the diagonal (rhobar) of the lower-bidiagonal matrix.
+        """
+
+        rhobar1 = sqrt(rhobar**2 + damp**2);
+        cs1     = rhobar / rhobar1;
+        sn1     = damp   / rhobar1;
+        psi     = sn1 * phibar;
+        phibar  = cs1 * phibar;
+        """
+        %     Use a plane rotation to eliminate the subdiagonal element (beta)
+        %     of the lower-bidiagonal matrix, giving an upper-bidiagonal matrix.
+        """
+
+
+        ###cs      =   rhobar1/ rho;
+        ###sn      =   beta   / rho;
+        cs,sn,rho = SymOrtho(rhobar1,beta)
+        
+        theta   =   sn * alfa;
+        rhobar  = - cs * alfa;
+        phi     =   cs * phibar;
+        phibar  =   sn * phibar;
+        tau     =   sn * phi;
+        """
+        %     Update x and w.
+        """
+        t1      =   phi  /rho;
+        t2      = - theta/rho;
+        dk      =   (1/rho)*w;
+
+        ### x       = x      +  t1*w;
+        axpy(w,x,t1)
+        ### w       = v      +  t2*w;
+        scal(t2,w)
+        axpy(v,w)
+        ddnorm  = ddnorm +  nrm2(dk)**2;
+        if wantvar:
+            ### var = var  +  dk.*dk; 
+            axpy(dk**2, var)
+        """
+        %     Use a plane rotation on the right to eliminate the
+        %     super-diagonal element (theta) of the upper-bidiagonal matrix.
+        %     Then use the result to estimate  norm(x).
+        """
+
+        delta   =   sn2 * rho;
+        gambar  = - cs2 * rho;
+        rhs     =   phi  -  delta * z;
+        zbar    =   rhs / gambar;
+        xnorm   =   sqrt(xxnorm + zbar**2);
+        gamma   =   sqrt(gambar**2 +theta**2);
+        cs2     =   gambar / gamma;
+        sn2     =   theta  / gamma;
+        z       =   rhs    / gamma;
+        xxnorm  =   xxnorm  +  z**2;
+        """
+        %     Test for convergence.
+        %     First, estimate the condition of the matrix  Abar,
+        %     and the norms of  rbar  and  Abar'rbar.
+        """
+        acond   =   anorm * sqrt(ddnorm);
+        res1    =   phibar**2;
+        res2    =   res2  +  psi**2;
+        rnorm   =   sqrt( res1 + res2 );
+        arnorm  =   alfa * abs( tau );
+        """
+        %     07 Aug 2002:
+        %     Distinguish between
+        %        r1norm = ||b - Ax|| and
+        %        r2norm = rnorm in current code
+        %               = sqrt(r1norm^2 + damp^2*||x||^2).
+        %        Estimate r1norm from
+        %        r1norm = sqrt(r2norm^2 - damp^2*||x||^2).
+        %     Although there is cancellation, it might be accurate enough.
+        """
+        r1sq    =   rnorm**2  -  dampsq * xxnorm;
+        r1norm  =   sqrt( abs(r1sq) );
+        if r1sq < 0: r1norm = - r1norm; 
+        r2norm  =   rnorm;
+        """
+        %     Now use these norms to estimate certain other quantities,
+        %     some of which will be small near a solution.
+        """
+        test1   =   rnorm / bnorm;
+        test2   =   arnorm/( anorm * rnorm );
+        test3   =       1 / acond;
+        t1      =   test1 / (1    +  anorm * xnorm / bnorm);
+        rtol    =   btol  +  atol *  anorm * xnorm / bnorm;
+        """
+        %     The following tests guard against extremely small values of
+        %     atol, btol  or  ctol.  (The user may have set any or all of
+        %     the parameters  atol, btol, conlim  to 0.)
+        %     The effect is equivalent to the normal tests using
+        %     atol = eps,  btol = eps,  conlim = 1/eps.
+        """
+        if itn >= itnlim  : istop = 7; 
+        if 1 + test3  <= 1: istop = 6; 
+        if 1 + test2  <= 1: istop = 5; 
+        if 1 + t1     <= 1: istop = 4; 
+        """
+        %     Allow for tolerances set by the user.
+        """
+        if  test3 <= ctol:  istop = 3;
+        if  test2 <= atol:  istop = 2;
+        if  test1 <= rtol:  istop = 1;
+        """
+        %     See if it is time to print something.
+        """
+        prnt = False;
+        if n     <= 40       : prnt = True;
+        if itn   <= 10       : prnt = True;
+        if itn   >= itnlim-10: prnt = True;
+        # if itn%10 == 0       : prnt = True;
+        if test3 <=  2*ctol  : prnt = True;
+        if test2 <= 10*atol  : prnt = True;
+        if test1 <= 10*rtol  : prnt = True;
+        if istop !=  0       : prnt = True;
+
+        if prnt:
+            if show:
+                str1 = '%6g %12.5e'%        (itn,   x[0] );
+                str2 = ' %10.3e %10.3e'% (r1norm, r2norm );
+                str3 = '  %8.1e %8.1e'%  ( test1,  test2 );
+                str4 = ' %8.1e %8.1e'%   ( anorm,  acond );
+                print str1, str2, str3, str4
+
+        if istop != 0: break
+
+    """
+    %     End of iteration loop.
+    %     Print the stopping condition.
+    """
+    if show:
+        print ' '
+        print 'LSQR finished'
+        print msg[istop]
+        print ' '
+        str1 = 'istop =%8g   r1norm =%8.1e'%  ( istop, r1norm );
+        str2 = 'anorm =%8.1e   arnorm =%8.1e'%( anorm, arnorm );
+        str3 = 'itn   =%8g   r2norm =%8.1e'%  (   itn, r2norm );
+        str4 = 'acond =%8.1e   xnorm  =%8.1e'%( acond, xnorm  );
+        print str1+ '   ' +str2
+        print str3+ '   ' +str4
+        print ' '
+
+    return x, istop, itn, r1norm, r2norm, anorm, acond, arnorm, xnorm, var 
+            
+    """
+    %-----------------------------------------------------------------------
+    % End of lsqr.m
+    %-----------------------------------------------------------------------
+    """
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/cohomology/output.h	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,66 @@
+#include <iostream>
+#include <sstream>
+#include <fstream>
+
+#include <boost/tuple/tuple.hpp>
+#include <boost/tuple/tuple_comparison.hpp>
+
+#include <cassert>
+
+bool neq(const Smplx& s1, const Smplx& s2)               
+{ 
+    Smplx::VertexComparison cmp;
+    return cmp(s1, s2) || cmp(s2, s1);
+}
+
+template<class Comparison>
+unsigned index(const SimplexVector& v, const Smplx& s, const Comparison& cmp)
+{
+    SimplexVector::const_iterator it = std::lower_bound(v.begin(), v.end(), s, cmp);
+    while (neq(*it, s)) ++it;
+    return it - v.begin();
+}
+
+template<class Comparison>
+void output_boundary_matrix(std::ostream& out, const SimplexVector& v, const Comparison& cmp)
+{
+    unsigned i = 0;
+    for (SimplexVector::const_iterator cur = v.begin(); cur != v.end(); ++cur)
+    {
+        // std::cout << "Simplex: " << *cur << std::endl;
+        bool                sign = true;
+        for (Smplx::BoundaryIterator bcur  = cur->boundary_begin(); bcur != cur->boundary_end(); ++bcur)
+        {
+            // std::cout << "  " << *bcur << std::endl;
+            out << (sign ? 1 : -1) << " ";
+            out << index(v, *bcur, cmp) << " " << i << "\n";
+            sign = !sign;
+        }
+        ++i;
+    }
+}
+
+void output_vertex_indices(std::ostream& out, const SimplexVector& v)
+{
+    unsigned i = 0;
+    for (SimplexVector::const_iterator cur = v.begin(); cur != v.end(); ++cur)
+    {
+        if (cur->dimension() == 0)
+            out << i << " " << cur->vertices()[0] << std::endl;
+        ++i;
+    }
+}
+
+void output_cocycle(std::string cocycle_prefix, unsigned i, const SimplexVector& v, const BirthInfo& birth, const Persistence::ZColumn& zcol, ZpField::Element prime)
+{
+    std::ostringstream istr; istr << '-' << i;
+    std::string filename = cocycle_prefix + istr.str() + ".ccl";
+    std::ofstream out(filename.c_str());
+    out << "# Cocycle born at " << birth.get<1>() << std::endl;
+    for (Persistence::ZColumn::const_iterator zcur = zcol.begin(); zcur != zcol.end(); ++zcur)
+    {
+        //const Smplx& s = **(zcur->si);
+        out << (zcur->coefficient <= prime/2 ? zcur->coefficient : zcur->coefficient - prime) << " ";
+        out << zcur->si->getValue() << "\n";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/cohomology/rips-cohomology.cpp	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,62 @@
+#include <topology/cohomology-persistence.h>
+#include <topology/rips.h>
+
+#include <utilities/containers.h>           // for BackInsertFunctor
+
+#include <map>
+#include <iostream>
+
+#include <boost/tuple/tuple.hpp>
+    
+// Trivial example of size() points on a line with integer coordinates
+struct Distances
+{
+    typedef         int             IndexType;
+    typedef         double          DistanceType;
+
+    DistanceType    operator()(IndexType a, IndexType b) const      { return std::abs(a - b); }
+
+    size_t          size() const                                    { return 2000; }
+    IndexType       begin() const                                   { return 0; }
+    IndexType       end() const                                     { return size(); }
+};
+
+typedef     CohomologyPersistence<Distances::DistanceType>          Persistence;
+typedef     Persistence::SimplexIndex                               Index;
+typedef     Persistence::Death                                      Death;
+typedef     Persistence::CocyclePtr                                 CocyclePtr;
+
+typedef     Rips<Distances>                                         Generator;
+typedef     Generator::Simplex                                      Smplx;
+
+typedef     std::map<Smplx, Index, 
+                     Smplx::VertexComparison>                       Complex;
+typedef     std::vector<Smplx>                                      SimplexVector;
+
+int main()
+{
+    Distances               distances;
+    Generator               rips(distances);
+    Generator::Evaluator    size(distances);
+    SimplexVector           v;
+    Complex                 c;
+    
+    rips.generate(2, 50, make_push_back_functor(v));
+    std::sort(v.begin(), v.end(), Generator::Comparison(distances));
+    std::cout << "Simplex vector generated, size: " << v.size() << std::endl;
+
+    Persistence p;
+    for (SimplexVector::const_iterator cur = v.begin(); cur != v.end(); ++cur)
+    {
+        std::vector<Index>      boundary;
+        for (Smplx::BoundaryIterator bcur  = cur->boundary_begin(); 
+                                     bcur != cur->boundary_end();       ++bcur)
+            boundary.push_back(c[*bcur]);
+        
+        Index idx; Death d; CocyclePtr ccl;
+        boost::tie(idx, d, ccl)     = p.add(boundary.begin(), boundary.end(), size(*cur));
+        c[*cur] = idx;
+        if (d && (size(*cur) - *d) > 0)
+            std::cout << (cur->dimension() - 1) << " " << *d << " " << size(*cur) << std::endl;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/cohomology/rips-explicit-cohomology.cpp	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,198 @@
+#include <topology/cohomology-persistence.h>
+#include <topology/rips.h>
+
+#include <geometry/l2distance.h>
+#include <geometry/distances.h>
+
+#include <utilities/containers.h>           // for BackInsertFunctor
+#include <utilities/property-maps.h>
+#include <utilities/timer.h>
+#include <utilities/log.h>
+#include <utilities/counter.h>
+#include <utilities/memory.h>
+
+#include <string>
+
+#include <boost/tuple/tuple.hpp>
+#include <boost/program_options.hpp>
+#include <boost/progress.hpp>
+
+#include "wrappers.h"
+
+typedef     PairwiseDistances<PointContainer, L2Distance>           PairDistances;
+typedef     PairDistances::DistanceType                             DistanceType;
+typedef     PairDistances::IndexType                                Vertex;
+ 
+typedef     boost::tuple<Dimension, DistanceType>                   BirthInfo;
+typedef     CohomologyPersistence<BirthInfo, Wrapper<unsigned> >    Persistence;
+typedef     Persistence::SimplexIndex                               Index;
+typedef     Persistence::Death                                      Death;
+typedef     Persistence::CocyclePtr                                 CocyclePtr;
+
+typedef     ExplicitDistances< PairDistances >                      Distances;
+typedef     Rips<Distances, Simplex<Vertex, Index> >                Generator;
+typedef     Generator::Simplex                                      Smplx;
+typedef     std::vector<Smplx>                                      SimplexVector;
+typedef     SimplexVector::const_iterator                           SV_const_iterator;
+
+typedef     std::map<Smplx, Index, Smplx::VertexComparison>         Complex;
+
+#include "output.h"         // for output_*()
+
+void        program_options(int argc, char* argv[], std::string& infilename, unsigned& pt_size, Dimension& skeleton, DistanceType& max_distance, ZpField::Element& prime, std::string& boundary_name, std::string& cocycle_prefix, std::string& vertices_name, std::string& diagram_name);
+
+int main(int argc, char* argv[])
+{
+#ifdef LOGGING
+    rlog::RLogInit(argc, argv);
+
+    stderrLog.subscribeTo( RLOG_CHANNEL("error") );
+#endif
+
+    Dimension               skeleton;
+    DistanceType            max_distance;
+    ZpField::Element        prime;
+    unsigned                pt_size;
+    std::string             infilename, boundary_name, cocycle_prefix, vertices_name, diagram_name;
+
+    program_options(argc, argv, infilename, pt_size, skeleton, max_distance, prime, boundary_name, cocycle_prefix, vertices_name, diagram_name);
+    std::ofstream           bdry_out(boundary_name.c_str());
+    std::ofstream           vertices_out(vertices_name.c_str());
+    std::ofstream           diagram_out(diagram_name.c_str());
+    std::cout << "# of points:     " << pt_size << std::endl;
+    std::cout << "Boundary matrix: " << boundary_name << std::endl;
+    std::cout << "Cocycles:        " << cocycle_prefix << "*.ccl" << std::endl;
+    std::cout << "Vertices:        " << vertices_name << std::endl;
+    std::cout << "Diagram:         " << diagram_name << std::endl;
+
+    Timer total_timer; total_timer.start();
+    
+    // Read the pairwise distances
+    std::ifstream   in(infilename.c_str());
+    Distances       distances(pt_size);
+    for (unsigned i = 0; i < pt_size; ++i)
+        for (unsigned j = 0; j < pt_size; ++j)
+            in >> distances(i,j);
+
+    Generator               rips(distances);
+    Generator::Evaluator    size(distances);
+    Generator::Comparison   cmp(distances);
+    SimplexVector           v;
+    
+    Timer rips_timer; rips_timer.start();
+    rips.generate(skeleton, max_distance, make_push_back_functor(v));
+    std::sort(v.begin(), v.end(), Smplx::VertexComparison());
+
+    std::vector<unsigned> index_in_v(v.size());
+    for (unsigned idx = 0; idx < v.size(); ++idx)
+        index_in_v[idx] = idx;
+    std::sort(index_in_v.begin(), index_in_v.end(), IndirectIndexComparison<SimplexVector, Generator::Comparison>(v, cmp));
+
+    BinarySearchMap<Smplx, SimplexVector::iterator, Smplx::VertexComparison> map_of_v(v.begin(), v.end());
+
+    rips_timer.stop();
+    std::cout << "Simplex vector generated, size: " << v.size() << std::endl;
+
+    output_boundary_matrix(bdry_out, v, Smplx::VertexComparison());
+    output_vertex_indices(vertices_out, v);
+
+    Timer persistence_timer; persistence_timer.start();
+    ZpField                 zp(prime);
+    Persistence             p(zp);
+    boost::progress_display show_progress(v.size());
+
+    for (unsigned j = 0; j < index_in_v.size(); ++j)
+    {
+        SimplexVector::const_iterator cur = v.begin() + index_in_v[j];
+        std::vector<Index>      boundary;
+        for (Smplx::BoundaryIterator bcur  = cur->boundary_begin(); bcur != cur->boundary_end(); ++bcur)
+            boundary.push_back(map_of_v[*bcur]->data());
+        
+        Index idx; Death d; CocyclePtr ccl;
+        bool store = cur->dimension() < skeleton;
+        boost::tie(idx, d, ccl)     = p.add(boundary.begin(), boundary.end(), boost::make_tuple(cur->dimension(), size(*cur)), store, index_in_v[j]);
+        
+        // c[*cur] = idx;
+        if (store)
+            map_of_v[*cur]->data() = idx;
+
+        if (d && (size(*cur) - d->get<1>()) > 0)
+        {
+            AssertMsg(d->get<0>() == cur->dimension() - 1, "Dimensions must match");
+            diagram_out << (cur->dimension() - 1) << " " << d->get<1>() << " " << size(*cur) << std::endl;
+        }
+        ++show_progress;
+    }
+    // output infinte persistence pairs 
+    for (Persistence::CocycleIndex cur = p.begin(); cur != p.end(); ++cur)
+        diagram_out << cur->birth.get<0>() << " " << cur->birth.get<1>() << " inf" << std::endl;
+    persistence_timer.stop();
+
+
+    // p.show_cocycles();
+    // Output alive cocycles of dimension 1
+    if (!cocycle_prefix.empty())
+    {
+        unsigned i = 0;
+        for (Persistence::Cocycles::const_iterator cur = p.begin(); cur != p.end(); ++cur)
+        {
+            if (cur->birth.get<0>() != 1) continue;
+            output_cocycle(cocycle_prefix, i, v, cur->birth, cur->zcolumn, prime);
+            // std::cout << "Cocycle of dimension: " << cur->birth.get<0>() << " born at " << cur->birth.get<1>() << std::endl;
+            ++i;
+        }
+    }
+    total_timer.stop();
+    rips_timer.check("Rips timer");
+    persistence_timer.check("Persistence timer");
+    total_timer.check("Total timer");
+}
+
+void        program_options(int argc, char* argv[], std::string& infilename, unsigned& pt_size, Dimension& skeleton, DistanceType& max_distance, ZpField::Element& prime, std::string& boundary_name, std::string& cocycle_prefix, std::string& vertices_name, std::string& diagram_name)
+{
+    namespace po = boost::program_options;
+
+    po::options_description     hidden("Hidden options");
+    hidden.add_options()
+        ("input-file",          po::value<std::string>(&infilename),        "Point set whose Rips zigzag we want to compute")
+        ("num-pts",             po::value<unsigned>(&pt_size),              "Number of points in the input");
+    
+    po::options_description visible("Allowed options", 100);
+    visible.add_options()
+        ("help,h",                                                                                  "produce help message")
+        ("skeleton-dimsnion,s", po::value<Dimension>(&skeleton)->default_value(2),                  "Dimension of the Rips complex we want to compute")
+        ("prime,p",             po::value<ZpField::Element>(&prime)->default_value(11),             "Prime p for the field F_p")
+        ("max-distance,m",      po::value<DistanceType>(&max_distance)->default_value(Infinity),    "Maximum value for the Rips complex construction")
+        ("boundary,b",          po::value<std::string>(&boundary_name),                             "Filename where to output the boundary matrix")
+        ("cocycle,c",           po::value<std::string>(&cocycle_prefix),                            "Prefix of the filename where to output the 1-dimensional cocycles")
+        ("vertices,v",          po::value<std::string>(&vertices_name),                             "Filename where to output the simplex-vertex mapping")
+        ("diagram,d",           po::value<std::string>(&diagram_name),                              "Filename where to output the persistence diagram");
+#if LOGGING
+    std::vector<std::string>    log_channels;
+    visible.add_options()
+        ("log,l",               po::value< std::vector<std::string> >(&log_channels),           "log channels to turn on (info, debug, etc)");
+#endif
+
+    po::positional_options_description pos;
+    pos.add("input-file", 1);
+    pos.add("num-pts", 1);
+    
+    po::options_description all; all.add(visible).add(hidden);
+
+    po::variables_map vm;
+    po::store(po::command_line_parser(argc, argv).
+                  options(all).positional(pos).run(), vm);
+    po::notify(vm);
+
+#if LOGGING
+    for (std::vector<std::string>::const_iterator cur = log_channels.begin(); cur != log_channels.end(); ++cur)
+        stderrLog.subscribeTo( RLOG_CHANNEL(cur->c_str()) );
+#endif
+
+    if (vm.count("help") || !vm.count("input-file")|| !vm.count("num-pts"))
+    { 
+        std::cout << "Usage: " << argv[0] << " [options] input-file num-pts" << std::endl;
+        std::cout << visible << std::endl; 
+        std::abort();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/cohomology/rips-pairwise-cohomology.cpp	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,209 @@
+#include <topology/cohomology-persistence.h>
+#include <topology/rips.h>
+
+#include <geometry/l2distance.h>
+#include <geometry/distances.h>
+
+#include <utilities/containers.h>           // for BackInsertFunctor
+#include <utilities/property-maps.h>
+#include <utilities/timer.h>
+#include <utilities/log.h>
+#include <utilities/counter.h>
+#include <utilities/memory.h>
+
+#include <string>
+
+#include <boost/tuple/tuple.hpp>
+#include <boost/program_options.hpp>
+#include <boost/progress.hpp>
+
+#include "wrappers.h"
+
+typedef     PairwiseDistances<PointContainer, L2Distance>           PairDistances;
+typedef     PairDistances::DistanceType                             DistanceType;
+typedef     PairDistances::IndexType                                Vertex;
+ 
+typedef     boost::tuple<Dimension, DistanceType>                   BirthInfo;
+typedef     CohomologyPersistence<BirthInfo, Wrapper<unsigned> >    Persistence;
+typedef     Persistence::SimplexIndex                               Index;
+typedef     Persistence::Death                                      Death;
+typedef     Persistence::CocyclePtr                                 CocyclePtr;
+
+typedef     Rips<PairDistances, Simplex<Vertex, Index> >            Generator;
+typedef     Generator::Simplex                                      Smplx;
+typedef     std::vector<Smplx>                                      SimplexVector;
+typedef     SimplexVector::const_iterator                           SV_const_iterator;
+
+typedef     std::map<Smplx, Index, Smplx::VertexComparison>         Complex;
+
+#include "output.h"         // for output_*()
+
+void        program_options(int argc, char* argv[], std::string& infilename, Dimension& skeleton, DistanceType& max_distance, ZpField::Element& prime, std::string& boundary_name, std::string& cocycle_prefix, std::string& vertices_name, std::string& diagram_name);
+
+int main(int argc, char* argv[])
+{
+#ifdef LOGGING
+    rlog::RLogInit(argc, argv);
+
+    stderrLog.subscribeTo( RLOG_CHANNEL("error") );
+#endif
+
+    Dimension               skeleton;
+    DistanceType            max_distance;
+    ZpField::Element        prime;
+    std::string             infilename, boundary_name, cocycle_prefix, vertices_name, diagram_name;
+
+    program_options(argc, argv, infilename, skeleton, max_distance, prime, boundary_name, cocycle_prefix, vertices_name, diagram_name);
+    std::ofstream           bdry_out(boundary_name.c_str());
+    std::ofstream           vertices_out(vertices_name.c_str());
+    std::ofstream           diagram_out(diagram_name.c_str());
+    std::cout << "Boundary matrix: " << boundary_name << std::endl;
+    std::cout << "Cocycles:        " << cocycle_prefix << "*.ccl" << std::endl;
+    std::cout << "Vertices:        " << vertices_name << std::endl;
+    std::cout << "Diagram:         " << diagram_name << std::endl;
+
+    Timer total_timer; total_timer.start();
+    PointContainer          points;
+    read_points(infilename, points);
+
+    PairDistances           distances(points);
+    Generator               rips(distances);
+    Generator::Evaluator    size(distances);
+    Generator::Comparison   cmp(distances);
+    SimplexVector           v;
+    
+    Timer rips_timer; rips_timer.start();
+    rips.generate(skeleton, max_distance, make_push_back_functor(v));
+    std::sort(v.begin(), v.end(), Smplx::VertexComparison());
+
+    std::vector<unsigned> index_in_v(v.size());
+    for (unsigned idx = 0; idx < v.size(); ++idx)
+        index_in_v[idx] = idx;
+    std::sort(index_in_v.begin(), index_in_v.end(), IndirectIndexComparison<SimplexVector, Generator::Comparison>(v, cmp));
+
+    BinarySearchMap<Smplx, SimplexVector::iterator, Smplx::VertexComparison> map_of_v(v.begin(), v.end());
+
+    rips_timer.stop();
+    std::cout << "Simplex vector generated, size: " << v.size() << std::endl;
+
+    output_boundary_matrix(bdry_out, v, Smplx::VertexComparison());
+    output_vertex_indices(vertices_out, v);
+
+    Timer persistence_timer; persistence_timer.start();
+    ZpField                 zp(prime);
+    Persistence             p(zp);
+    boost::progress_display show_progress(v.size());
+    
+    #ifdef COUNTERS
+    Counter::CounterType    max_element_count = 0;
+    unsigned                max_memory = 0;
+    long                    max_rss = 0;
+    long                    max_ixrss = 0;
+    long                    max_idrss = 0;
+    long                    max_isrss = 0;
+
+    int                     max_uordblks = 0;
+    int                     max_fordblks = 0;
+    #endif
+
+    for (unsigned j = 0; j < index_in_v.size(); ++j)
+    {
+        SimplexVector::const_iterator cur = v.begin() + index_in_v[j];
+        std::vector<Index>      boundary;
+        for (Smplx::BoundaryIterator bcur  = cur->boundary_begin(); bcur != cur->boundary_end(); ++bcur)
+            boundary.push_back(map_of_v[*bcur]->data());
+        
+        Index idx; Death d; CocyclePtr ccl;
+        bool store = cur->dimension() < skeleton;
+        boost::tie(idx, d, ccl)     = p.add(boundary.begin(), boundary.end(), boost::make_tuple(cur->dimension(), size(*cur)), store, index_in_v[j]);
+        
+        // c[*cur] = idx;
+        if (store)
+            map_of_v[*cur]->data() = idx;
+
+        if (d && (size(*cur) - d->get<1>()) > 0)
+        {
+            AssertMsg(d->get<0>() == cur->dimension() - 1, "Dimensions must match");
+            diagram_out << (cur->dimension() - 1) << " " << d->get<1>() << " " << size(*cur) << std::endl;
+        }
+        ++show_progress;
+        
+        #ifdef COUNTERS
+        max_element_count = std::max(max_element_count, cCohomologyElementCount->count);
+        #endif
+    }
+    // output infinte persistence pairs 
+    for (Persistence::CocycleIndex cur = p.begin(); cur != p.end(); ++cur)
+        diagram_out << cur->birth.get<0>() << " " << cur->birth.get<1>() << " inf" << std::endl;
+    persistence_timer.stop();
+
+
+    // p.show_cocycles();
+    // Output alive cocycles of dimension 1
+    if (!cocycle_prefix.empty())
+    {
+        unsigned i = 0;
+        for (Persistence::Cocycles::const_iterator cur = p.begin(); cur != p.end(); ++cur)
+        {
+            if (cur->birth.get<0>() != 1) continue;
+            output_cocycle(cocycle_prefix, i, v, cur->birth, cur->zcolumn, prime);
+            // std::cout << "Cocycle of dimension: " << cur->birth.get<0>() << " born at " << cur->birth.get<1>() << std::endl;
+            ++i;
+        }
+    }
+    total_timer.stop();
+    rips_timer.check("Rips timer");
+    persistence_timer.check("Persistence timer");
+    total_timer.check("Total timer");
+
+    #ifdef COUNTERS
+    std::cout << "Max element count: " << max_element_count << std::endl;
+    #endif
+}
+
+void        program_options(int argc, char* argv[], std::string& infilename, Dimension& skeleton, DistanceType& max_distance, ZpField::Element& prime, std::string& boundary_name, std::string& cocycle_prefix, std::string& vertices_name, std::string& diagram_name)
+{
+    namespace po = boost::program_options;
+
+    po::options_description     hidden("Hidden options");
+    hidden.add_options()
+        ("input-file",          po::value<std::string>(&infilename),        "Point set whose Rips zigzag we want to compute");
+    
+    po::options_description visible("Allowed options", 100);
+    visible.add_options()
+        ("help,h",                                                                                  "produce help message")
+        ("skeleton-dimsnion,s", po::value<Dimension>(&skeleton)->default_value(2),                  "Dimension of the Rips complex we want to compute")
+        ("prime,p",             po::value<ZpField::Element>(&prime)->default_value(11),             "Prime p for the field F_p")
+        ("max-distance,m",      po::value<DistanceType>(&max_distance)->default_value(Infinity),    "Maximum value for the Rips complex construction")
+        ("boundary,b",          po::value<std::string>(&boundary_name),                             "Filename where to output the boundary matrix")
+        ("cocycle,c",           po::value<std::string>(&cocycle_prefix),                            "Prefix of the filename where to output the 1-dimensional cocycles")
+        ("vertices,v",          po::value<std::string>(&vertices_name),                             "Filename where to output the simplex-vertex mapping")
+        ("diagram,d",           po::value<std::string>(&diagram_name),                              "Filename where to output the persistence diagram");
+#if LOGGING
+    std::vector<std::string>    log_channels;
+    visible.add_options()
+        ("log,l",               po::value< std::vector<std::string> >(&log_channels),           "log channels to turn on (info, debug, etc)");
+#endif
+
+    po::positional_options_description pos;
+    pos.add("input-file", 1);
+    
+    po::options_description all; all.add(visible).add(hidden);
+
+    po::variables_map vm;
+    po::store(po::command_line_parser(argc, argv).
+                  options(all).positional(pos).run(), vm);
+    po::notify(vm);
+
+#if LOGGING
+    for (std::vector<std::string>::const_iterator cur = log_channels.begin(); cur != log_channels.end(); ++cur)
+        stderrLog.subscribeTo( RLOG_CHANNEL(cur->c_str()) );
+#endif
+
+    if (vm.count("help") || !vm.count("input-file"))
+    { 
+        std::cout << "Usage: " << argv[0] << " [options] input-file" << std::endl;
+        std::cout << visible << std::endl; 
+        std::abort();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/cohomology/rips-pairwise-cohomology.py	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,61 @@
+#!/usr/bin/env python
+
+from    dionysus        import Simplex, CohomologyPersistence, points_file, PairwiseDistances, ExplicitDistances, Rips, data_dim_cmp
+from    sys             import argv, exit
+import  time
+
+def main(filename, skeleton, max, prime = 11):
+    points = [p for p in points_file(filename)]
+    print '#', time.asctime(), "Points read"
+    distances = PairwiseDistances(points)
+    distances = ExplicitDistances(distances)           # speeds up generation of the Rips complex at the expense of memory usage
+    rips = Rips(distances)
+    print '#', time.asctime(), "Rips initialized"
+
+    simplices = []
+    rips.generate(skeleton, max, simplices.append)
+    print '#', time.asctime(), "Generated complex: %d simplices" % len(simplices)
+
+    # While this step is unnecessary (Filtration below can be passed rips.cmp), 
+    # it greatly speeds up the running times
+    for s in simplices: s.data = rips.eval(s)
+    print '#', time.asctime(), simplices[0], '...', simplices[-1]
+
+    simplices.sort(data_dim_cmp)
+    print '#', time.asctime(), "Simplices sorted"
+
+    ch = CohomologyPersistence(prime)
+    complex = {}
+
+    for s in simplices:
+        i,d = ch.add([complex[sb] for sb in s.boundary], (s.dimension(), s.data), store = (s.dimension() < skeleton))
+        complex[s] = i
+        if d: 
+            dimension, birth = d
+            print dimension, birth, s.data
+        # else birth
+
+    for ccl in ch:
+        dimension, birth = ccl.birth
+        if dimension >= skeleton: continue
+        print dimension, birth, 'inf'         # dimension, simplex data = birth
+        print "# Cocycle at (dim=%d, birth=%f)" % ccl.birth
+        for e in ccl:
+            print "#  ", e.si.order, normalized(e.coefficient, prime)
+
+def normalized(coefficient, prime):
+    if coefficient > prime/2:
+        return coefficient - prime
+    return coefficient
+
+if __name__ == '__main__':
+    if len(argv) < 4:
+        print "Usage: %s POINTS SKELETON MAX [PRIME=11]" % argv[0]
+        exit()
+
+    filename = argv[1]
+    skeleton = int(argv[2])
+    max = float(argv[3])
+    prime = (len(argv) > 4 and argv[4]) or 11
+
+    main(filename, skeleton, max, prime)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/cohomology/rips-weighted-cohomology.cpp	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,185 @@
+#include <topology/cohomology-persistence.h>
+#include <topology/weighted-rips.h>
+
+#include <geometry/weighted-l2distance.h>
+#include <geometry/distances.h>
+
+#include <utilities/containers.h>           // for BackInsertFunctor
+#include <utilities/property-maps.h>
+#include <utilities/timer.h>
+#include <utilities/log.h>
+
+#include <string>
+
+#include <boost/tuple/tuple.hpp>
+#include <boost/program_options.hpp>
+#include <boost/progress.hpp>
+
+#include "wrappers.h"
+
+typedef     PairwiseDistances<PointContainer, WeightedL2Distance>   PairDistances;
+typedef     PairDistances::DistanceType                             DistanceType;
+typedef     PairDistances::IndexType                                Vertex;
+ 
+typedef     boost::tuple<Dimension, DistanceType>                   BirthInfo;
+typedef     CohomologyPersistence<BirthInfo, Wrapper<unsigned> >    Persistence;
+typedef     Persistence::SimplexIndex                               Index;
+typedef     Persistence::Death                                      Death;
+typedef     Persistence::CocyclePtr                                 CocyclePtr;
+
+typedef     WeightedRips<PairDistances, Simplex<Vertex, Index> >    Generator;
+typedef     Generator::Simplex                                      Smplx;
+typedef     std::vector<Smplx>                                      SimplexVector;
+typedef     SimplexVector::const_iterator                           SV_const_iterator;
+
+#include "output.h"         // for output_*()
+
+void        program_options(int argc, char* argv[], std::string& infilename, Dimension& skeleton, DistanceType& max_distance, ZpField::Element& prime, std::string& boundary_name, std::string& cocycle_prefix, std::string& vertices_name, std::string& diagram_name);
+
+int main(int argc, char* argv[])
+{
+#ifdef LOGGING
+    rlog::RLogInit(argc, argv);
+
+    stderrLog.subscribeTo( RLOG_CHANNEL("error") );
+#endif
+
+    Dimension               skeleton;
+    DistanceType            max_distance;
+    ZpField::Element        prime;
+    std::string             infilename, boundary_name, cocycle_prefix, vertices_name, diagram_name;
+
+    program_options(argc, argv, infilename, skeleton, max_distance, prime, boundary_name, cocycle_prefix, vertices_name, diagram_name);
+    std::ofstream           bdry_out(boundary_name.c_str());
+    std::ofstream           vertices_out(vertices_name.c_str());
+    std::ofstream           diagram_out(diagram_name.c_str());
+    std::cout << "Boundary matrix: " << boundary_name << std::endl;
+    std::cout << "Cocycles:        " << cocycle_prefix << "*.ccl" << std::endl;
+    std::cout << "Vertices:        " << vertices_name << std::endl;
+    std::cout << "Diagram:         " << diagram_name << std::endl;
+
+    Timer total_timer; total_timer.start();
+    PointContainer          points;
+    read_weighted_points(infilename, points);
+
+    PairDistances           distances(points);
+    Generator               rips(distances);
+    Generator::Evaluator    size(distances);
+    Generator::Comparison   cmp(distances);
+    SimplexVector           v;
+
+    Timer rips_timer; rips_timer.start();
+    rips.generate(skeleton, max_distance, make_push_back_functor(v));
+
+    /* Keep simplices sorted lexicographically (so that we can binary search through them) */
+    std::sort(v.begin(), v.end(), Smplx::VertexComparison());
+
+    /* We also need the simplices sorted by value though for the filtration:
+       index_in_v[j] refers to the simplex v[index_in_v[j]]                      */
+    std::vector<unsigned> index_in_v(v.size());
+    for (unsigned idx = 0; idx < v.size(); ++idx)
+        index_in_v[idx] = idx;
+    std::sort(index_in_v.begin(), index_in_v.end(), IndirectIndexComparison<SimplexVector, Generator::Comparison>(v, cmp));
+
+    /* Set up map access to the lexicographically sorted simplices */
+    BinarySearchMap<Smplx, SimplexVector::iterator, Smplx::VertexComparison> map_of_v(v.begin(), v.end());
+
+    rips_timer.stop();
+    std::cout << "Simplex vector generated, size: " << v.size() << std::endl;
+
+    /*output_boundary_matrix(bdry_out, v, Smplx::VertexComparison());
+    output_vertex_indices(vertices_out, v);*/
+
+    Timer persistence_timer; persistence_timer.start();
+    ZpField                 zp(prime);
+    Persistence             p(zp);
+    boost::progress_display show_progress(v.size());
+    for (unsigned j = 0; j < index_in_v.size(); ++j)
+    {
+        SimplexVector::const_iterator cur = v.begin() + index_in_v[j];
+        std::vector<Index>      boundary;
+        for (Smplx::BoundaryIterator bcur  = cur->boundary_begin(); bcur != cur->boundary_end(); ++bcur)
+            boundary.push_back(map_of_v[*bcur]->data());
+        
+        Index idx; Death d; CocyclePtr ccl;
+        bool store = cur->dimension() < skeleton;
+        boost::tie(idx, d, ccl)     = p.add(boundary.begin(), boundary.end(), boost::make_tuple(cur->dimension(), size(*cur)), store, index_in_v[j]);
+        
+        if (store)
+            map_of_v[*cur]->data() = idx;
+
+        if (d && (size(*cur) - d->get<1>()) > 0)
+        {
+            AssertMsg(d->get<0>() == cur->dimension() - 1, "Dimensions must match");
+            diagram_out << (cur->dimension() - 1) << " " << d->get<1>() << " " << size(*cur) << std::endl;
+        }
+        ++show_progress;
+    }
+    // output infinte persistence pairs 
+    for (Persistence::CocycleIndex cur = p.begin(); cur != p.end(); ++cur)
+        diagram_out << cur->birth.get<0>() << " " << cur->birth.get<1>() << " inf" << std::endl;
+    persistence_timer.stop();
+
+
+    // p.show_cocycles();
+    // Output alive cocycles of dimension 1
+    unsigned i = 0;
+    for (Persistence::Cocycles::const_iterator cur = p.begin(); cur != p.end(); ++cur)
+    {
+        if (cur->birth.get<0>() != 1) continue;
+        output_cocycle(cocycle_prefix, i, v, cur->birth, cur->zcolumn, prime);
+        // std::cout << "Cocycle of dimension: " << cur->birth.get<0>() << " born at " << cur->birth.get<1>() << std::endl;
+        ++i;
+    }
+    total_timer.stop();
+    rips_timer.check("Rips timer");
+    persistence_timer.check("Persistence timer");
+    total_timer.check("Total timer");
+}
+
+void        program_options(int argc, char* argv[], std::string& infilename, Dimension& skeleton, DistanceType& max_distance, ZpField::Element& prime, std::string& boundary_name, std::string& cocycle_prefix, std::string& vertices_name, std::string& diagram_name)
+{
+    namespace po = boost::program_options;
+
+    po::options_description     hidden("Hidden options");
+    hidden.add_options()
+        ("input-file",          po::value<std::string>(&infilename),        "Point set whose Rips zigzag we want to compute");
+    
+    po::options_description visible("Allowed options", 100);
+    visible.add_options()
+        ("help,h",                                                                                  "produce help message")
+        ("skeleton-dimsnion,s", po::value<Dimension>(&skeleton)->default_value(2),                  "Dimension of the Rips complex we want to compute")
+        ("prime,p",             po::value<ZpField::Element>(&prime)->default_value(11),             "Prime p for the field F_p")
+        ("max-distance,m",      po::value<DistanceType>(&max_distance)->default_value(Infinity),    "Maximum value for the Rips complex construction")
+        ("boundary,b",          po::value<std::string>(&boundary_name),                             "Filename where to output the boundary matrix")
+        ("cocycle,c",           po::value<std::string>(&cocycle_prefix),                            "Prefix of the filename where to output the 1-dimensional cocycles")
+        ("vertices,v",          po::value<std::string>(&vertices_name),                             "Filename where to output the simplex-vertex mapping")
+        ("diagram,d",           po::value<std::string>(&diagram_name),                              "Filename where to output the persistence diagram");
+#if LOGGING
+    std::vector<std::string>    log_channels;
+    visible.add_options()
+        ("log,l",               po::value< std::vector<std::string> >(&log_channels),           "log channels to turn on (info, debug, etc)");
+#endif
+
+    po::positional_options_description pos;
+    pos.add("input-file", 1);
+    
+    po::options_description all; all.add(visible).add(hidden);
+
+    po::variables_map vm;
+    po::store(po::command_line_parser(argc, argv).
+                  options(all).positional(pos).run(), vm);
+    po::notify(vm);
+
+#if LOGGING
+    for (std::vector<std::string>::const_iterator cur = log_channels.begin(); cur != log_channels.end(); ++cur)
+        stderrLog.subscribeTo( RLOG_CHANNEL(cur->c_str()) );
+#endif
+
+    if (vm.count("help") || !vm.count("input-file"))
+    { 
+        std::cout << "Usage: " << argv[0] << " [options] input-file" << std::endl;
+        std::cout << visible << std::endl; 
+        std::abort();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/cohomology/triangle-cohomology.cpp	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,94 @@
+#include <topology/simplex.h>
+#include <topology/cohomology-persistence.h>
+
+#include <utilities/log.h>
+#include <utilities/indirect.h>
+
+#include <vector>
+#include <map>
+#include <iostream>
+
+#include <boost/tuple/tuple.hpp>
+
+#if 1
+#include <fstream>
+#include <boost/archive/text_oarchive.hpp>
+#include <boost/archive/text_iarchive.hpp>
+#include <boost/serialization/vector.hpp>
+#endif
+
+typedef         CohomologyPersistence<unsigned>     Persistence;
+typedef         Persistence::SimplexIndex           Index;
+typedef         Persistence::Death                  Death;
+typedef         Persistence::CocyclePtr             CocyclePtr;
+
+typedef         unsigned                            Vertex;
+typedef         Simplex<Vertex, double>             Smplx;
+
+typedef         std::map<Smplx, Index, 
+                         Smplx::VertexComparison>   Complex;
+typedef         std::vector<Smplx>                  SimplexVector;
+
+
+void fillTriangleSimplices(SimplexVector& c)
+{
+    typedef std::vector<Vertex> VertexVector;
+    VertexVector vertices(4);
+    vertices[0] = 0; vertices[1] = 1; vertices[2] = 2; 
+    vertices[3] = 0;
+        
+    VertexVector::const_iterator bg = vertices.begin();
+    VertexVector::const_iterator end = vertices.end();
+    c.push_back(Smplx(bg,     bg + 1, 0));                 // 0 = A
+    c.push_back(Smplx(bg + 1, bg + 2, 1));                 // 1 = B
+    c.push_back(Smplx(bg + 2, bg + 3, 2));                 // 2 = C
+    c.push_back(Smplx(bg,     bg + 2, 2.5));               // AB
+    c.push_back(Smplx(bg + 1, bg + 3, 2.9));               // BC
+    c.push_back(Smplx(bg + 2, end,    3.5));               // CA
+    c.push_back(Smplx(bg,     bg + 3, 5));                 // ABC
+}
+
+int main(int argc, char** argv)
+{
+#ifdef LOGGING
+    rlog::RLogInit(argc, argv);
+
+    stderrLog.subscribeTo(RLOG_CHANNEL("info"));
+    stderrLog.subscribeTo(RLOG_CHANNEL("error"));
+    stderrLog.subscribeTo(RLOG_CHANNEL("topology"));
+#endif
+
+    SimplexVector v;
+    fillTriangleSimplices(v);
+    std::sort(v.begin(), v.end(), Smplx::DataComparison());
+    std::cout << "Simplices filled" << std::endl;
+    for (SimplexVector::const_iterator cur = v.begin(); cur != v.end(); ++cur)
+        std::cout << "  " << *cur << std::endl;
+
+    // Compute persistence
+    Complex         c;
+    ZpField         zp(11);
+    Persistence     p(zp);
+    unsigned i = 0;
+    for (SimplexVector::const_iterator cur = v.begin(); cur != v.end(); ++cur)
+    {
+        std::cout << "-------" << std::endl;
+
+        std::vector<Index>      boundary;
+        for (Smplx::BoundaryIterator bcur  = cur->boundary_begin(); 
+                                     bcur != cur->boundary_end();       ++bcur)
+            boundary.push_back(c[*bcur]);
+        
+        Index idx; Death d; CocyclePtr ccl;
+        boost::tie(idx, d, ccl)     = p.add(boundary.begin(), boundary.end(), i++);
+        c[*cur] = idx;
+        if (d)
+            std::cout << (cur->dimension() - 1) << " " << *d << " " << (i-1) << std::endl;
+            // the dimension above is adjusted for what it would look like in homology
+            // (i.e. when a 1 class kills 0, it's really that in cohomology forward 0 kills 1,
+            //  in cohomology backward 1 kills 0, and in homology 1 kills 0)
+
+        p.show_cocycles();
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/cohomology/wrappers.h	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,59 @@
+/**
+ * Wrapper class
+ * 
+ * At points we need to wrap primitive data types in classes, so that we can
+ * pass them as template arguments to classes that like to inherit from their
+ * template arguments--this is done in CohomologyPersistence, for example.
+ */
+
+template<typename Primitive>
+class    Wrapper
+{
+
+    public:
+
+        Wrapper () {}
+        Wrapper (Primitive v)                       { value = v;    }
+
+        void       setValue  (const Primitive &v)   { value = v;    }
+        Primitive &getValue  ()                     { return value; }
+
+        /* provide seemless integration */
+        Wrapper   &operator =(const Primitive &v)   { setValue(v);     return *this; }
+        operator  Primitive()                       { return getValue;               }
+
+    protected:
+
+        Primitive value;
+
+};
+
+/**
+ * IndirectIndexComparison class
+ * 
+ * This class serves as a comparison function for arrays that are being sorted
+ * even though they only contain *indices* to the real data. Therefore, a reference
+ * to the original data as well as the data comparison function needs to be passed
+ * to this class for it to be functional.
+ */
+
+template<class DataContainer, class DataComparison>
+class IndirectIndexComparison
+{
+
+    public:
+
+        IndirectIndexComparison(const DataContainer &dstor, const DataComparison &dcmp) :
+            container(dstor), comparison(dcmp) { }
+
+        bool operator()(const unsigned &idx_1, const unsigned &idx_2) const
+        {
+            return comparison(container[idx_1], container[idx_2]);
+        }
+
+    private:
+
+        const DataContainer  &container;
+        const DataComparison &comparison;
+
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/consistency/CMakeLists.txt	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,7 @@
+set                         (targets                        
+                             rips-consistency-zigzag)
+                             
+foreach                     (t ${targets})
+    add_executable          (${t} ${t}.cpp)
+    target_link_libraries   (${t} ${libraries} ${Boost_PROGRAM_OPTIONS_LIBRARY} ${Boost_SERIALIZATION_LIBRARY})
+endforeach                  (t ${targets})
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/consistency/make-zigzag-subsamples.py	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,47 @@
+#!/usr/bin/env python 
+
+# Creates POINTS and SUBSAMPLES files from a list of points file in a format
+# suitable for rips-consistency-zigzag.
+
+
+from    sys     import argv, exit
+
+
+def create_subsamples(points_fn, subsamples_fn, points_list):
+    points = []
+    count = []
+    for pfn in points_list:
+        count.append(0)
+        with open(pfn) as f:
+            for line in f:
+                if line.startswith('#'): continue
+                points.append(line)
+                count[-1] += 1
+
+    with open(points_fn, 'w') as f:
+        for line in points:
+            f.write(line)
+
+    cur = 0
+    counts = []
+    for c in count:
+        counts.append(' '.join(map(str, xrange(cur, cur+c))) + '\n')
+        cur += c
+        # counts.append(' '.join(map(str, xrange(cur-c, cur+c))) + '\n')
+    
+    with open(subsamples_fn, 'w') as f:
+        f.writelines(counts)
+
+
+if __name__ == '__main__':
+    if len(argv) < 4:
+        print "Usage: %s POINTS SUBSAMPLES POINTS1 [POINTS2 [POINTS3 [...]]]" % argv[0]
+        print
+        print "Creates a file POINTS with the union of POINTS* and SUBSAMPLES which lists"
+        print "the indices of the points one per line"
+        exit()
+
+    points_fn = argv[1]
+    subsamples_fn = argv[2]
+    points_list = argv[3:]
+    create_subsamples(points_fn, subsamples_fn, points_list)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/consistency/rips-consistency-zigzag.cpp	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,343 @@
+#include <topology/rips.h>
+#include <topology/zigzag-persistence.h>
+
+#include <geometry/l2distance.h>    // Point, PointContainer, L2DistanceType, read_points
+#include <geometry/distances.h>
+
+#include <utilities/types.h>
+#include <utilities/containers.h>
+#include <utilities/log.h>
+#include <utilities/memory.h>       // for report_memory()
+#include <utilities/timer.h>
+
+#include <map>
+#include <cmath>
+#include <fstream>
+#include <sstream>
+#include <stack>
+#include <cstdlib>
+
+#include <boost/tuple/tuple.hpp>
+#include <boost/program_options.hpp>
+#include <boost/progress.hpp>
+
+#ifdef COUNTERS
+static Counter*  cComplexSize =                     GetCounter("rips/size");
+static Counter*  cOperations =                      GetCounter("rips/operations");
+#endif // COUNTERS
+
+typedef     PairwiseDistances<PointContainer, L2Distance>           PairDistances;
+typedef     PairDistances::DistanceType                             DistanceType;
+
+typedef     PairDistances::IndexType                                Vertex;
+typedef     std::vector<Vertex>                                     SubsampleVector;
+
+typedef     Simplex<Vertex>                                         Smplx;
+typedef     std::vector<Smplx>                                      SimplexVector;
+typedef     std::set<Smplx, Smplx::VertexDimensionComparison>       SimplexSet;
+
+typedef     std::vector<Vertex>                                     VertexVector;
+typedef     std::vector<DistanceType>                               EpsilonVector;
+typedef     std::vector<std::pair<Vertex, Vertex> >                 EdgeVector;
+
+typedef     Rips<PairDistances, Smplx>                              RipsGenerator;
+typedef     RipsGenerator::Evaluator                                SimplexEvaluator;
+
+struct      BirthInfo;
+typedef     ZigzagPersistence<BirthInfo>                            Zigzag;
+typedef     Zigzag::SimplexIndex                                    Index;
+typedef     Zigzag::Death                                           Death;
+typedef     std::map<Smplx, Index, 
+                            Smplx::VertexDimensionComparison>       Complex;
+typedef     Zigzag::ZColumn                                         Boundary;
+
+// Information we need to know when a class dies
+struct      BirthInfo
+{
+                    BirthInfo(Dimension d = 0, unsigned i = 0, bool u = false):
+                        dimension(d), index(i), un(u)               {}
+    
+    bool            operator<(const BirthInfo& other) const         { if (index == other.index) return (!un && other.un); else return index < other.index; }
+    bool            operator>(const BirthInfo& other) const         { return other.operator<(*this); }
+    bool            operator>=(const BirthInfo& other) const        { return !operator<(other); }
+    bool            operator<=(const BirthInfo& other) const        { return !operator>(other); }
+
+    Dimension       dimension;
+    unsigned        index;
+    bool            un;
+};
+std::ostream&       operator<<(std::ostream& out, const BirthInfo& bi)
+{ out << "(d=" << bi.dimension << ") " << bi.index; if (bi.un) out << " U " << (bi.index + 1); return out; }
+
+// Forward declarations of auxilliary functions
+void        report_death(std::ostream& out, const BirthInfo& birth, const BirthInfo& death, unsigned skeleton_dimension);
+void        make_boundary(const Smplx& s, Complex& c, const Zigzag& zz, Boundary& b);
+void        process_command_line_options(int           argc,
+                                         char*         argv[],
+                                         unsigned&     skeleton_dimension,
+                                         float&        epsilon,
+                                         std::string&  points_filename,
+                                         std::string&  subsample_filename,
+                                         std::string&  outfilename);
+void        add_simplex(const Smplx& s, const BirthInfo& birth, const BirthInfo& death, 
+                        Complex& complex, Zigzag& zz, std::ostream& out, Timer& add, unsigned skeleton_dimension);
+void        remove_simplex(const Smplx& s, const BirthInfo& birth, const BirthInfo& death, 
+                           Complex& complex, Zigzag& zz, std::ostream& out, Timer& remove, unsigned skeleton_dimension);
+
+int main(int argc, char* argv[])
+{
+#ifdef LOGGING
+    rlog::RLogInit(argc, argv);
+
+    stderrLog.subscribeTo( RLOG_CHANNEL("error") );
+#endif
+
+    Timer total, remove, add, coface, generate;
+    total.start();
+ 
+#if 0
+    SetFrequency(cOperations, 25000);
+    SetTrigger(cOperations, cComplexSize);
+#endif
+
+    unsigned        skeleton_dimension;
+    float           epsilon;
+    std::string     points_filename, subsample_filename, outfilename;
+    process_command_line_options(argc, argv, skeleton_dimension, epsilon, 
+                                             points_filename, subsample_filename, outfilename);
+
+    // Read in points
+    PointContainer      points;
+    read_points(points_filename, points);
+    
+    // Read in subsamples
+    std::ifstream subsample_in(subsample_filename.c_str());
+    std::vector<SubsampleVector> subsamples;
+    subsamples.push_back(SubsampleVector());    //  Empty subsample to start from
+    while(subsample_in)
+    {
+        std::string line; std::getline(subsample_in, line);
+        std::istringstream line_in(line);
+        subsamples.push_back(SubsampleVector());
+        unsigned sample;
+        while (line_in >> sample)
+            subsamples.back().push_back(sample);
+    }
+    AssertMsg(subsamples.front().size() == 0, "The first subsample should be empty");
+    AssertMsg(subsamples.back().size() == 0, "The last subsample should be empty");     // it's a convenient artifact of the stream processing above
+    
+    std::cout << "Subsample size:" << std::endl;
+    for (unsigned i = 0; i < subsamples.size(); ++i)
+        std::cout << "  " << subsamples[i].size() << std::endl;
+
+    // Create output file
+    std::ofstream out(outfilename.c_str());
+
+    // Create pairwise distances
+    PairDistances distances(points);
+    
+
+    // Construct zigzag
+    Complex             complex;
+    Zigzag              zz;
+    RipsGenerator       rips(distances);
+    SimplexEvaluator    size(distances);
+    SimplexVector       subcomplex, across;
+    
+    rInfo("Commencing computation");
+    boost::progress_display show_progress(subsamples.size() - 1);
+    for (unsigned i = 0; i < subsamples.size() - 1; ++i)
+    {
+        // Take union of subsamples i and i+1
+        SubsampleVector forward_difference, backward_difference;
+        std::set_difference(subsamples[i+1].begin(), subsamples[i+1].end(),
+                            subsamples[i].begin(),   subsamples[i].end(),
+                            std::back_inserter(forward_difference));
+        std::set_difference(subsamples[i].begin(),   subsamples[i].end(),
+                            subsamples[i+1].begin(), subsamples[i+1].end(),
+                            std::back_inserter(backward_difference));
+        rInfo("Forward difference size:  %d", forward_difference.size());
+        rInfo("Backward difference size: %d", backward_difference.size());
+
+#if LOGGING
+        rDebug("Forward difference:");
+        for (SubsampleVector::const_iterator cur = forward_difference.begin(); cur != forward_difference.end(); ++cur)
+            rDebug("  %d", *cur);
+        
+        rDebug("Backward difference:");
+        for (SubsampleVector::const_iterator cur = backward_difference.begin(); cur != backward_difference.end(); ++cur)
+            rDebug("  %d", *cur);
+#endif
+
+        // Add simplices:       take star of the vertices in subsamples[i+1] - subsamples[i]
+        //                      by first computing the Rips complex on those vertices, and then 
+        //                      taking the star of each individual simplex (perhaps not the most 
+        //                      efficient procedure, but it will do for the first pass)
+        rInfo("Adding");
+        subcomplex.clear(); across.clear();
+        generate.start();
+        rips.generate(skeleton_dimension, epsilon, make_push_back_functor(subcomplex), forward_difference.begin(), forward_difference.end());
+        std::sort(subcomplex.begin(), subcomplex.end(), Smplx::VertexDimensionComparison());
+        generate.stop();
+        rInfo("  Subcomplex size: %d", subcomplex.size());
+        for (SimplexVector::const_iterator cur = subcomplex.begin(); cur != subcomplex.end(); ++cur)
+        {
+            add_simplex(*cur, BirthInfo(cur->dimension(), i, true), BirthInfo(cur->dimension() - 1, i), 
+                        complex, zz, out, add, skeleton_dimension);
+
+            // Record cofaces with all other vertices outside of the subcomplex
+            coface.start();
+            rips.cofaces(*cur, skeleton_dimension, epsilon, make_push_back_functor(across), subsamples[i].begin(), subsamples[i].end());
+            coface.stop();
+        }
+        std::sort(across.begin(), across.end(), Smplx::VertexDimensionComparison());
+        rInfo("  Subcomplex simplices added");
+        rInfo("  Cross simplices size: %d", across.size());
+
+        // Add simplices that cut across VR(K_i) and VR(K_{i+1})
+        for (SimplexVector::const_iterator cur = across.begin(); cur != across.end(); ++cur)
+            add_simplex(*cur, BirthInfo(cur->dimension(), i, true), BirthInfo(cur->dimension() - 1, i), 
+                        complex, zz, out, add, skeleton_dimension);
+        rInfo("  Cross simplices added");
+
+
+        // Remove simplices:    take star of the vertices in subsamples[i] - subsamples[i+1]
+        rInfo("Removing");
+        subcomplex.clear(); across.clear();
+        generate.start();
+        rips.generate(skeleton_dimension, epsilon, make_push_back_functor(subcomplex), backward_difference.begin(), backward_difference.end());
+        std::sort(subcomplex.begin(), subcomplex.end(), Smplx::VertexDimensionComparison());
+        generate.stop();
+        rInfo("  Subcomplex size: %d", subcomplex.size());
+
+        for (SimplexVector::const_iterator cur = subcomplex.begin(); cur != subcomplex.end(); ++cur)
+            rips.cofaces(*cur, skeleton_dimension, epsilon, make_push_back_functor(across), subsamples[i+1].begin(), subsamples[i+1].end());
+        std::sort(across.begin(), across.end(), Smplx::VertexDimensionComparison());
+        rInfo("  Cross simplices size: %d", across.size());
+
+        for (SimplexVector::const_reverse_iterator cur = across.rbegin(); cur != (SimplexVector::const_reverse_iterator)across.rend(); ++cur)
+            remove_simplex(*cur, BirthInfo(cur->dimension() - 1, i+1), BirthInfo(cur->dimension(), i, true),
+                           complex, zz, out, remove, skeleton_dimension);
+        rInfo("  Cross simplices removed");
+
+        for (SimplexVector::const_reverse_iterator cur = subcomplex.rbegin(); cur != (SimplexVector::const_reverse_iterator)subcomplex.rend(); ++cur)
+            remove_simplex(*cur, BirthInfo(cur->dimension() - 1, i+1), BirthInfo(cur->dimension(), i, true),
+                           complex, zz, out, remove, skeleton_dimension);
+        rInfo("  Subcomplex simplices removed");
+        
+        Dimension betti_1 = 0;
+        for (Zigzag::ZIndex cur = zz.begin(); cur != zz.end(); ++cur)
+            if (cur->birth.dimension == 1 && zz.is_alive(cur)) ++betti_1;
+        
+        rInfo("Complex size: %d, Betti_1 = %d", complex.size(), betti_1);
+        
+        ++show_progress;
+    }
+
+    std::cout << std::endl;
+    total.stop();
+    remove.check("Remove timer          ");
+    add.check   ("Add timer             ");
+    coface.check("Coface timer          ");
+    total.check ("Total timer           ");
+}
+
+
+void        make_boundary(const Smplx& s, Complex& c, const Zigzag& zz, Boundary& b)
+{
+    // rDebug("  Boundary of <%s>", tostring(s).c_str());
+    for (Smplx::BoundaryIterator cur = s.boundary_begin(); cur != s.boundary_end(); ++cur)
+    {
+        b.append(c[*cur], zz.cmp);
+        // rDebug("   %d", c[*cur]->order);
+    }
+}
+
+void        report_death(std::ostream& out, const BirthInfo& birth, const BirthInfo& death, unsigned skeleton_dimension)
+{
+    if (birth.dimension < skeleton_dimension && death >= birth)
+        out << birth << " --- " << death << std::endl;
+}
+
+void        add_simplex(const Smplx& s, const BirthInfo& birth, const BirthInfo& death, 
+                        Complex& complex, Zigzag& zz, std::ostream& out, Timer& add, unsigned skeleton_dimension)
+{
+    rDebug("Adding simplex: %s", tostring(s).c_str());
+
+    Index idx; Death d; Boundary b;
+    make_boundary(s, complex, zz, b);
+    add.start();
+    boost::tie(idx, d)  = zz.add(b, birth);
+    if (d) report_death(out, *d, death, skeleton_dimension);
+    add.stop();
+    complex.insert(std::make_pair(s, idx));
+}
+
+void        remove_simplex(const Smplx& s, const BirthInfo& birth, const BirthInfo& death, 
+                           Complex& complex, Zigzag& zz, std::ostream& out, Timer& remove, unsigned skeleton_dimension)
+{
+    rDebug("Removing simplex: %s", tostring(s).c_str());
+
+    Complex::iterator si = complex.find(s);
+    remove.start();
+    Death d = zz.remove(si->second, birth);
+    remove.stop();
+    if (d) report_death(out, *d, death, skeleton_dimension);
+    complex.erase(si);
+}
+
+void        process_command_line_options(int           argc,
+                                         char*         argv[],
+                                         unsigned&     skeleton_dimension,
+                                         float&        epsilon,
+                                         std::string&  points_filename,
+                                         std::string&  subsample_filename,
+                                         std::string&  outfilename)
+{
+    namespace po = boost::program_options;
+
+    po::options_description hidden("Hidden options");
+    hidden.add_options()
+        ("points-file",         po::value<std::string>(&points_filename),   "Point set whose Rips consistency zigzag we want to compute")
+        ("subsample-file",      po::value<std::string>(&subsample_filename),"Subsample list")
+        ("output-file",         po::value<std::string>(&outfilename),       "Location to save persistence pairs");
+    
+    po::options_description visible("Allowed options", 100);
+    visible.add_options()
+        ("help,h",                                                                              "produce help message")
+        ("skeleton-dimsnion,s", po::value<unsigned>(&skeleton_dimension)->default_value(2),     "Dimension of the Rips complex we want to compute")
+        ("epsilon,e",           po::value<float>(&epsilon)->default_value(0),                   "epsilon to use when computing the Rips complex");
+#if LOGGING
+    std::vector<std::string>    log_channels;
+    visible.add_options()
+        ("log,l",               po::value< std::vector<std::string> >(&log_channels),           "log channels to turn on (info, debug, etc)");
+#endif
+
+    po::positional_options_description pos;
+    pos.add("points-file", 1);
+    pos.add("subsample-file", 1);
+    pos.add("output-file", 1);
+    
+    po::options_description all; all.add(visible).add(hidden);
+
+    po::variables_map vm;
+    po::store(po::command_line_parser(argc, argv).
+                  options(all).positional(pos).run(), vm);
+    po::notify(vm);
+
+#if LOGGING
+    for (std::vector<std::string>::const_iterator cur = log_channels.begin(); cur != log_channels.end(); ++cur)
+        stderrLog.subscribeTo( RLOG_CHANNEL(cur->c_str()) );
+    /**
+     * Interesting channels
+     * "info", "debug", "topology/persistence"
+     */
+#endif
+
+    if (vm.count("help") || !vm.count("points-file") || !vm.count("subsample-file") || !vm.count("output-file"))
+    { 
+        std::cout << "Usage: " << argv[0] << " [options] points-file subsample-file output-file" << std::endl;
+        std::cout << visible << std::endl; 
+        std::abort();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/filtration/CMakeLists.txt	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,7 @@
+set                         (targets                        
+                             filtration-homology)
+                             
+foreach                     (t ${targets})
+    add_executable          (${t} ${t}.cpp)
+    target_link_libraries   (${t} ${libraries} ${Boost_PROGRAM_OPTIONS_LIBRARY})
+endforeach                  (t ${targets})
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/filtration/filtration-homology.cpp	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,140 @@
+#include <topology/simplex.h>
+#include <topology/filtration.h>
+#include <topology/dynamic-persistence.h>
+#include <topology/persistence-diagram.h>
+
+#include <utilities/containers.h>           // for BackInsertFunctor
+#include <utilities/timer.h>
+
+#include <vector>
+#include <fstream>
+
+#include <boost/program_options.hpp>
+
+typedef         unsigned                                                Vertex;
+typedef         Simplex<Vertex>                                         Smplx;
+typedef         Filtration<Smplx>                                       Fltr;
+typedef         DynamicPersistenceChains<>                              Persistence;
+typedef         Persistence::Chain                                      Chain;
+typedef         PersistenceDiagram<>                                    PDgm;
+
+void            program_options(int argc, char* argv[], std::string& infilename, Dimension& skeleton, std::string& diagram_name, Dimension& cycle_dimension, std::string& cycle_filename);
+void            read_filtration(const std::string& filename, Fltr& filtration);
+void            output_chain(std::ostream& out, const Chain& chain, const Persistence& persistence);
+
+int main(int argc, char* argv[])
+{
+    Dimension               skeleton, cycle_dimension;
+    std::string             infilename, diagram_name, cycle_filename;
+
+    program_options(argc, argv, infilename, skeleton, diagram_name, cycle_dimension, cycle_filename);
+    std::ofstream           diagram_out(diagram_name.c_str());
+    std::cout << "Diagram:         " << diagram_name << std::endl;
+    std::ofstream           cycle_out(cycle_filename.c_str());
+    std::cout << "Cycles:          " << cycle_filename << std::endl;
+
+    Fltr                    f;
+    read_filtration(infilename, f);
+    std::cout << "# Read filtration of size: " << f.size() << std::endl;
+
+    Timer persistence_timer; persistence_timer.start();
+    Persistence p(f);
+    p.pair_simplices();
+    persistence_timer.stop();
+
+#if 1
+    // Output chains and pairs
+    Persistence::SimplexMap<Fltr>   m = p.make_simplex_map(f);
+    for (Persistence::iterator cur = p.begin(); cur != p.end(); ++cur)
+    {
+        if (!cur->sign())        // only negative simplices have non-empty cycles
+        {
+            Persistence::OrderIndex birth = cur->pair;      // the cycle that cur killed was born when we added birth (another simplex)
+
+            const Smplx& b = m[birth];
+            const Smplx& d = m[cur];
+            
+            if (b.dimension() >= skeleton) continue;
+            diagram_out << b.dimension() << " " << (p.iterator_to(cur->pair) - p.begin()) << " " << (cur - p.begin()) << std::endl;
+        } else if (cur->unpaired())    // positive could be unpaired
+        {
+            const Smplx& b = m[cur];
+            
+            if (b.dimension() >= skeleton) continue;
+            diagram_out << b.dimension() << " " << (cur - p.begin()) << " inf" << std::endl;
+
+            if (b.dimension() != cycle_dimension) continue;
+            output_chain(cycle_out, cur->chain, p);
+        }
+    }
+#endif
+    
+    persistence_timer.check("# Persistence timer");
+}
+
+void        program_options(int argc, char* argv[], std::string& infilename, Dimension& skeleton, std::string& diagram_name, Dimension& cycle_dimension, std::string& cycle_filename)
+{
+    namespace po = boost::program_options;
+
+    po::options_description     hidden("Hidden options");
+    hidden.add_options()
+        ("input-file",          po::value<std::string>(&infilename),        "Point set whose Rips zigzag we want to compute");
+    
+    po::options_description visible("Allowed options", 100);
+    visible.add_options()
+        ("help,h",                                                                                  "produce help message")
+        ("skeleton-dimsnion,s", po::value<Dimension>(&skeleton)->default_value(2),                  "Dimension of the Rips complex we want to compute")
+        ("diagram,d",           po::value<std::string>(&diagram_name),                              "Filename where to output the persistence diagram")
+        ("cycle-dimension,c",   po::value<Dimension>(&cycle_dimension)->default_value(1),           "Dimension of the essential cycles to output")
+        ("cycle-filename,o",    po::value<std::string>(&cycle_filename),                            "Filename where to output the essential cycles");
+#if LOGGING
+    std::vector<std::string>    log_channels;
+    visible.add_options()
+        ("log,l",               po::value< std::vector<std::string> >(&log_channels),           "log channels to turn on (info, debug, etc)");
+#endif
+
+    po::positional_options_description pos;
+    pos.add("input-file", 1);
+    
+    po::options_description all; all.add(visible).add(hidden);
+
+    po::variables_map vm;
+    po::store(po::command_line_parser(argc, argv).
+                  options(all).positional(pos).run(), vm);
+    po::notify(vm);
+
+#if LOGGING
+    for (std::vector<std::string>::const_iterator cur = log_channels.begin(); cur != log_channels.end(); ++cur)
+        stderrLog.subscribeTo( RLOG_CHANNEL(cur->c_str()) );
+#endif
+
+    if (vm.count("help") || !vm.count("input-file"))
+    { 
+        std::cout << "Usage: " << argv[0] << " [options] input-file" << std::endl;
+        std::cout << visible << std::endl; 
+        std::abort();
+    }
+}
+
+void            read_filtration(const std::string& filename, Fltr& filtration)
+{
+    std::ifstream in(filename.c_str());
+    std::string   line;
+    while(std::getline(in, line))
+    {
+        if (line[0] == '#') continue;               // comment line in the file
+        std::stringstream linestream(line);
+        Vertex v;
+        Smplx s;
+        while (linestream >> v)
+            s.add(v);
+        filtration.push_back(s);            
+    }
+}
+
+void    output_chain(std::ostream& out, const Chain& chain, const Persistence& persistence)
+{
+    out << "---\n";
+    for (Chain::const_iterator iter = chain.begin(); iter != chain.end(); ++iter)
+        out << persistence.iterator_to(*iter) - persistence.begin() << '\n';
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/fitness/CMakeLists.txt	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,10 @@
+set                         (targets
+                             avida-distance
+                             avida-rips-distance
+                             #avida-landscape
+                            )
+    
+foreach                     (t ${targets})
+    add_executable          (${t} ${t}.cpp)
+    target_link_libraries   (${t} ${libraries} ${Boost_PROGRAM_OPTIONS_LIBRARY})
+endforeach                  (t ${targets})
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/fitness/avida-distance.cpp	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,93 @@
+#include <iostream>
+#include <vector>
+#include <algorithm>
+#include "avida-population-detail.h"
+
+#include <topology/filtration.h>
+#include <topology/simplex.h>
+#include <topology/static-persistence.h>
+
+
+typedef         Simplex<AvidaOrganismDetail::IDType, double>        Smplx;
+typedef         std::vector<Smplx>                                  Complex;
+typedef         Filtration<Smplx>                                   Fltr;
+typedef         StaticPersistence<>                                 Persistence;
+
+int main(int argc, char** argv)
+{
+#ifdef LOGGING
+    rlog::RLogInit(argc, argv);
+    //stdoutLog.subscribeTo(RLOG_CHANNEL("info"));
+#endif
+
+    if (argc < 2)
+    {
+        std::cout << "USAGE: avida FILENAME" << std::endl;
+        return 0;
+    }
+
+    AvidaPopulationDetail population(argv[1]);
+    const AvidaPopulationDetail::OrganismVector& organisms = population.get_organisms();
+
+    rInfo("Number of organisms: %d", organisms.size());
+    for (int i = 0; i < population.get_organisms().size(); ++i)
+        rInfo("%d (%s) %f %d %d", organisms[i].id(),
+                                  organisms[i].genome().c_str(),
+                                  organisms[i].fitness(),
+                                  organisms[i].length(),
+                                  organisms[i].genome().size());
+
+    // Distance function filtration
+    Complex simplices;
+
+    // Insert edges between all the organisms
+    AvidaOrganismDetail::DistanceType avg_distance = 0;
+    for (AvidaOrganismDetail::CountType i = 0; i < organisms.size(); ++i)
+    {
+        simplices.push_back(0);                     // all vertices have 0 value
+        simplices.back().add(organisms[i].id());
+
+        for (AvidaOrganismDetail::CountType j = i+1; j < organisms.size(); ++j)
+        {
+            avg_distance += organisms[i].genome_distance(organisms[j]);
+            simplices.push_back(Smplx(organisms[i].genome_distance(organisms[j])));
+            simplices.back().add(organisms[i].id());
+            simplices.back().add(organisms[j].id());
+        }
+    }
+    rInfo("Average distance: %f", float(avg_distance)/
+                                  ((organisms.size()*organisms.size() - organisms.size())/2));
+
+    Fltr f(simplices.begin(), simplices.end(), DataDimensionComparison<Smplx>());
+    Persistence p(f);
+    p.pair_simplices();
+
+    std::cout << "Outputting histogram of death values" << std::endl;
+    typedef std::vector<RealType> DeathVector;
+    DeathVector deaths;
+    Smplx::DataEvaluator    eval;
+    Persistence::SimplexMap<Fltr>   m = p.make_simplex_map(f);
+    for (Persistence::iterator i = p.begin(); i != p.end(); ++i)
+    {
+        if (i->unpaired()) continue;
+        if (i->sign())
+        {
+            const Smplx& s = m[i];
+            const Smplx& t = m[i->pair];
+            AssertMsg(s.dimension() == 0, "Expecting only 0-dimensional diagram");
+            AssertMsg(eval(s) == 0,       "Expecting only 0 birth values in 0-D diagram ");
+            deaths.push_back(eval(t));
+        }
+    }
+
+    // Produce histogram
+    std::sort(deaths.begin(), deaths.end());
+    for (DeathVector::iterator cur = deaths.begin(); cur != deaths.end(); )
+    {
+        DeathVector::iterator nw = std::find_if(cur, deaths.end(), 
+                                                std::bind2nd(std::greater<RealType>(), *cur));
+        std::cout << *cur << "\t" << (nw - cur) << std::endl;
+        cur = nw;
+    }
+    std::cout << "Total: " << deaths.size() + 1;        // +1 for the unpaired
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/fitness/avida-landscape.cpp	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,209 @@
+#include <iostream>
+#include <vector>
+#include <algorithm>
+#include <string>
+#include "avida-population-detail.h"
+
+#include <boost/program_options.hpp>
+
+#include <topology/lowerstarfiltration.h>
+
+
+// Lower-star filtration
+typedef         AvidaPopulationDetail::OrganismIndex                OrganismIndex;
+struct          OrganismVertexType;
+typedef         std::vector<OrganismVertexType>                     VertexVector;
+typedef         VertexVector::iterator                              VertexIndex;
+typedef         LowerStarFiltration<VertexIndex>                    LSFiltration;
+typedef         LSFiltration::Simplex                               Simplex;
+
+struct          OrganismVertexType: public LSFiltration::VertexType<OrganismIndex> 
+{
+    typedef     LSFiltration::VertexType<OrganismIndex>             Parent;
+                OrganismVertexType(OrganismIndex i): Parent(i)      {}
+};
+
+struct          OrganismVertexComparison
+{
+    public:
+        bool    operator()(VertexIndex i, VertexIndex j) const      
+        { return i->index()->fitness() > j->index()->fitness(); }       
+        // > because of -fitness, so that maxima turn into minima
+};
+
+typedef         LSFiltration::Vineyard                              LSVineyard;
+class           StaticEvaluator: public LSVineyard::Evaluator
+{
+    public:
+                StaticEvaluator(float max_fitness): 
+                    max_fitness_(max_fitness)                       {}
+
+        virtual RealType        
+                value(const Simplex& s) const       
+        { return s.get_attachment()->index()->fitness()/max_fitness_; }
+
+    private:
+        float   max_fitness_;
+};
+
+std::ostream& operator<<(std::ostream& out, VertexIndex i)
+{ return (out << (i->index())); }
+
+
+// Distance filtration
+typedef         SimplexWithValue<VertexIndex>                       DistanceSimplex;
+typedef         std::vector<DistanceSimplex>                        DistanceSimplexVector;
+typedef         Filtration<DistanceSimplex>                         DistanceSimplexFiltration;
+
+
+namespace po = boost::program_options;
+
+int main(int argc, char** argv)
+{
+#ifdef LOGGING
+    rlog::RLogInit(argc, argv);
+    stderrLog.subscribeTo(RLOG_CHANNEL("error"));
+    //stdoutLog.subscribeTo(RLOG_CHANNEL("info"));
+#endif
+
+    typedef     AvidaOrganismDetail::DistanceType       DistanceType;
+
+    DistanceType connected_distance;
+    bool connect_mst = false;
+    std::string population_input_fn;
+
+    // Parse program options
+    po::options_description hidden("Hidden options");
+    hidden.add_options()
+        ("input-file",  po::value<std::string>(&population_input_fn),
+                        "Avida population file");
+
+    po::options_description visible("Allowed options");
+    visible.add_options()
+        ("help,h",      "produce help message")
+        ("distance,d",  po::value<DistanceType>(&connected_distance)->default_value(0), 
+                        "set connected distance")
+        ("mst,m",       "connect minimum spanning tree");
+    po::positional_options_description p;
+    p.add("input-file", 1);
+    
+    po::options_description all; all.add(visible).add(hidden);
+
+    po::variables_map vm;
+    po::store(po::command_line_parser(argc, argv).
+                  options(all).positional(p).run(), vm);
+    po::notify(vm);
+
+    if (vm.count("mst"))            { connect_mst = true; }
+    if (vm.count("help") || !vm.count("input-file"))
+    { 
+        std::cout << "Usage: " << argv[0] << " [options] POPULATION" << std::endl;
+        std::cout << visible << std::endl; 
+        return 1; 
+    }
+
+    // Read organisms
+    AvidaPopulationDetail population(population_input_fn);
+    const AvidaPopulationDetail::OrganismVector& organisms = population.get_organisms();
+
+    rInfo("Number of organisms: %d", organisms.size());
+    float max_fitness = organisms[0].fitness();
+    for (int i = 0; i < population.get_organisms().size(); ++i)
+    {
+        max_fitness = std::max(max_fitness, organisms[i].fitness());
+        rInfo("%d (%s) %f %d %d", organisms[i].id(),
+                                  organisms[i].genome().c_str(),
+                                  organisms[i].fitness(),
+                                  organisms[i].length(),
+                                  organisms[i].genome().size());
+    }
+
+    // Order vertices 
+    StaticEvaluator     evaluator(max_fitness);
+    LSVineyard          vineyard(&evaluator);
+    VertexVector        vertices;
+    for (OrganismIndex cur = organisms.begin(); cur != organisms.end(); ++cur)  vertices.push_back(cur);
+    LSFiltration        fitness_filtration(vertices.begin(), vertices.end(), OrganismVertexComparison(), &vineyard);
+
+    // Compute MST and insert its edges if asked
+    if (connect_mst)
+    {
+        DistanceSimplexFiltration filtration;
+        {   // Scope so that simplices is deleted once it's not needed
+            // Distance function filtration
+            DistanceSimplexVector simplices;
+        
+            // Insert edges
+            for (VertexIndex i = vertices.begin(); i != vertices.end(); ++i)
+            {
+                simplices.push_back(DistanceSimplex());
+                simplices.back().add(i);
+        
+                for (VertexIndex j = boost::next(i); j != vertices.end(); ++j)
+                {
+                    simplices.push_back(DistanceSimplex(i->index()->genome_distance(*(j->index()))));
+                    simplices.back().add(i);
+                    simplices.back().add(j);
+                }
+            }
+            std::sort(simplices.begin(), simplices.end(), DimensionValueComparison<DistanceSimplex>());
+        
+            for (DistanceSimplexVector::const_iterator  cur = simplices.begin(); 
+                                                        cur != simplices.end(); ++cur)
+                filtration.append(*cur);
+        }
+
+        filtration.fill_simplex_index_map();
+        filtration.pair_simplices(false);            // pair simplices without storing trails
+
+        for (DistanceSimplexFiltration::Index i = filtration.begin(); i != filtration.end(); ++i)
+        {
+            if (i->is_paired() && !i->sign())
+            {
+                Simplex s(*i);
+                if (i->get_value() > connected_distance)    // <= will be connected below
+                    fitness_filtration.append(s);
+            }
+        }
+    }
+
+    // Add simplices
+    for (VertexIndex cur = vertices.begin(); cur != vertices.end(); ++cur)
+        for (VertexIndex link = boost::next(cur); link != vertices.end(); ++link)
+            if (cur->index()->genome_distance(*(link->index())) <= connected_distance)
+            {
+                Simplex s(2, cur); s.add(link);
+                fitness_filtration.append(s);
+            }
+    rInfo("Number of simplices: %d", fitness_filtration.size());
+
+    // Pair simplices
+    fitness_filtration.fill_simplex_index_map();
+    fitness_filtration.pair_simplices(false);            // pair simplices without storing trails
+
+    //std::cout << "Outputting persistence pairs" << std::endl;
+    for (LSFiltration::Index i = fitness_filtration.begin(); i != fitness_filtration.end(); ++i)
+    {
+        if (i->is_paired())
+        {
+            if (i->sign())
+            {
+                AssertMsg(i->dimension() == 0, "Expecting only 0-dimensional diagram");
+                if (i->pair()->get_attachment() == i->vertices()[0]) continue;     // skip non-critical pairs
+                std::cout << i->dimension() << " " 
+                          << evaluator.value(*i) << " " 
+                          << evaluator.value(*(i->pair())) << std::endl;
+            }
+        }
+        else
+        {
+            if (i->dimension() != 0) continue;
+            std::cout << i->dimension() << " "
+                      << evaluator.value(*i) << " "
+                      << 0 << std::endl;
+            // The infinite pair does not make sense since we are interested in 
+            // max of fitness, rather than min of -fitness. However min value for 
+            // fitness is 0, so it's a natural choice of the answer.
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/fitness/avida-population-detail.h	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,81 @@
+/**
+ * Author: Dmitriy Morozov
+ * Department of Computer Science, Duke University, 2007
+ */
+
+#ifndef __AVIDA_POPULATION_DETAIL_H__
+#define __AVIDA_POPULATION_DETAIL_H__
+
+#include <string>
+#include <vector>
+
+/**
+ * Stores organism details stored in a single line of a population detail file in data/ 
+ * directory of Avida's output.
+ */
+class AvidaOrganismDetail
+{
+	public:
+		typedef			int							IDType;
+		/// Distance between two genomes
+		typedef			unsigned int				DistanceType;
+		typedef			unsigned int				CountType;
+
+						AvidaOrganismDetail(std::string line);
+
+		DistanceType 	genome_distance(const AvidaOrganismDetail& other) const;
+		
+		IDType			id() const									{ return id_; }
+		float			fitness() const								{ return fitness_; }
+		CountType		length() const								{ return genome_length_; }
+		std::string		genome() const								{ return genome_; }
+
+	private:
+		IDType			id_, parent_id_;
+		int				parent_distance_;
+		CountType		num_organisms_alive_, num_organisms_ever_;
+		CountType		genome_length_;
+		float 			merit_, gestation_time_;
+		float 			fitness_;
+		int 			update_born_, update_deactivated_, depth_phylogenetic_tree_;
+		std::string 	genome_;
+};
+
+/**
+ * Stores entire population details (all organisms in a given time step), i.e., stores
+ * an entire population detail file in data/ directory of Avida's ouptut.
+ */
+class AvidaPopulationDetail
+{
+	public:
+		typedef			std::vector<AvidaOrganismDetail>				OrganismVector;
+        typedef         OrganismVector::const_iterator                  OrganismIndex;
+
+						AvidaPopulationDetail(std::string filename);
+
+		const OrganismVector& 
+                        get_organisms() const						    { return organisms_; }
+
+        /// \name Rips
+        /// @{
+        typedef         int                                             IndexType;
+        typedef         double                                          DistanceType;
+
+        DistanceType    operator()(IndexType a, IndexType b) const      { return organisms_[a].genome_distance(organisms_[b]); }
+
+        size_t          size() const                                    { return organisms_.size(); }
+        IndexType       begin() const                                   { return 0; }
+        IndexType       end() const                                     { return size(); }
+        /// @}
+
+	private:
+		OrganismVector	organisms_;
+};
+
+std::ostream& operator<<(std::ostream& out, AvidaPopulationDetail::OrganismIndex i)
+{ return (out << (i->id())); }
+
+
+#include "avida-population-detail.hpp"
+
+#endif //__AVIDA_POPULATION_DETAIL_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/fitness/avida-population-detail.hpp	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,57 @@
+#include <fstream>
+#include <sstream>
+#include "utilities/log.h"
+
+/** AvidaOrganismDetail */
+
+AvidaOrganismDetail::
+AvidaOrganismDetail(std::string line)
+{
+	std::stringstream linestream(line);
+	linestream >> id_ >> parent_id_ >> parent_distance_;
+	linestream >> num_organisms_alive_ >> num_organisms_ever_;
+	linestream >> genome_length_;
+	linestream >> merit_ >> gestation_time_;
+	linestream >> fitness_;
+	linestream >> update_born_ >> update_deactivated_ >> depth_phylogenetic_tree_;
+	linestream >> genome_;
+
+	AssertMsg(genome_length_ == genome_.size(), "Genome must be of given length");
+}
+
+AvidaOrganismDetail::DistanceType
+AvidaOrganismDetail::
+genome_distance(const AvidaOrganismDetail& other) const
+{
+	AssertMsg(genome_.size() == other.genome_.size(), "Currently genome sizes must be the same for distance computation");
+	AssertMsg(genome_length_ == genome_.size(), "Genome length value must match the length of the genome string");
+	AssertMsg(other.genome_length_ == other.genome_.size(), "Genome length value must match the length of the genome string");
+
+	CountType count = 0;
+	for (CountType i = 0; i < genome_.size(); ++i)
+		if (genome_[i] != other.genome_[i])
+			++count;
+
+	return count;
+}
+
+
+/** AvidaPopulationDetail */
+AvidaPopulationDetail::
+AvidaPopulationDetail(std::string filename)
+{
+	std::ifstream infile(filename.c_str());
+	while(infile)
+	{
+		std::string line;
+		std::getline(infile, line);
+		
+		// Skip comments and empty lines
+		char c = '#';
+		std::istringstream linestream(line);
+		linestream >> c;
+		if (c == '#') continue;
+
+		organisms_.push_back(AvidaOrganismDetail(line));
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/fitness/avida-rips-distance.cpp	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,89 @@
+#include <iostream>
+#include <vector>
+#include <algorithm>
+#include "avida-population-detail.h"
+
+#include <topology/filtration.h>
+#include <topology/rips.h>
+#include <topology/static-persistence.h>
+
+#include <geometry/distances.h>     // for ExplicitDistances
+
+
+typedef         ExplicitDistances<AvidaPopulationDetail>            ExplicitDist;
+typedef         Rips<ExplicitDist>                                  RipsGen;
+typedef         RipsGen::Simplex                                    Smplx;
+
+typedef         Filtration<Smplx>                                   Fltr;
+typedef         StaticPersistence<>                                 Persistence;
+
+int main(int argc, char** argv)
+{
+#ifdef LOGGING
+    rlog::RLogInit(argc, argv);
+    stdoutLog.subscribeTo(RLOG_CHANNEL("info"));
+    //stdoutLog.subscribeTo(RLOG_CHANNEL("rips/info"));
+#endif
+
+    if (argc < 2)
+    {
+        std::cout << "USAGE: avida FILENAME" << std::endl;
+        return 0;
+    }
+
+    AvidaPopulationDetail population(argv[1]);
+    ExplicitDist distances(population);
+
+    RipsGen rips(distances);
+    RipsGen::Evaluator evaluator(rips.distances());
+    rInfo("Max distance: %f", rips.max_distance());
+
+    const AvidaPopulationDetail::OrganismVector& organisms = population.get_organisms();
+    rInfo("Number of organisms: %d", organisms.size());
+    /* 
+    for (int i = 0; i < population.get_organisms().size(); ++i)
+        rInfo("%d (%s) %f %d %d", organisms[i].id(),
+                                  organisms[i].genome().c_str(),
+                                  organisms[i].fitness(),
+                                  organisms[i].length(),
+                                  organisms[i].genome().size());
+   */
+
+    rInfo("Starting to generate rips complex");
+    Fltr f;
+    rips.generate(1, rips.max_distance()/2, make_push_back_functor(f));
+    
+    rInfo("Generated Rips complex, filling filtration");
+    f.sort(RipsGen::Comparison(rips.distances()));
+
+    Persistence p(f);
+    p.pair_simplices();
+
+    std::cout << "Outputting histogram of death values" << std::endl;
+    typedef std::vector<RealType> DeathVector;
+    DeathVector deaths;
+    Persistence::SimplexMap<Fltr>   m = p.make_simplex_map(f);
+    for (Persistence::iterator i = p.begin(); i != p.end(); ++i)
+    {
+        if (i->unpaired()) continue;
+        if (i->sign())
+        {
+            const Smplx& s = m[i];
+            const Smplx& t = m[i->pair];
+            AssertMsg(s.dimension() == 0, "Expecting only 0-dimensional diagram");
+            AssertMsg(evaluator(s) == 0, "Expecting only 0 birth values in 0-D diagram ");
+            deaths.push_back(evaluator(t));
+        }
+    }
+
+    // Produce histogram
+    std::sort(deaths.begin(), deaths.end());
+    for (DeathVector::iterator cur = deaths.begin(); cur != deaths.end(); )
+    {
+        DeathVector::iterator nw = std::find_if(cur, deaths.end(), 
+                                                std::bind2nd(std::greater<RealType>(), *cur));
+        std::cout << *cur << "\t" << (nw - cur) << std::endl;
+        cur = nw;
+    }
+    std::cout << "Total: " << deaths.size() + 1;        // +1 for the unpaired
+}
--- a/examples/grid/CMakeLists.txt	Fri Aug 24 16:58:25 2007 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,9 +0,0 @@
-set							(targets						
-							 test-grid2D 
-							 pdbdistance-vineyard
-							 combustion-vineyard)
-							 
-foreach 					(t ${targets})
-	add_executable			(${t} ${t}.cpp ${external_sources})
-	target_link_libraries	(${t} ${libraries} ${cgal_libraries})
-endforeach 					(t ${targets})
--- a/examples/grid/combustion-vineyard.cpp	Fri Aug 24 16:58:25 2007 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,82 +0,0 @@
-/*
- * Author: Dmitriy Morozov
- * Department of Computer Science, Duke University, 2005
- */
-
-#include <utilities/sys.h>
-#include <utilities/debug.h>
-
-#include <iostream>
-#include <fstream>
-#include <algorithm>
-
-#include "grid2D.h"
-#include "grid2Dvineyard.h"
-
-const int xsize = 600;
-const int ysize = 600;
-const int var = 0;			// which variable to use out of nc of them in each record in the file
-
-template<typename T>
-void read(std::ifstream& ifs, T& var)
-{
-	ifs.read(reinterpret_cast<char*>(&var), sizeof(T));
-}
-
-int main(int argc, char** argv)
-{
-	if (argc < 3)
-	{
-		std::cout << "Usage: combustion-vineyard FRAME1 FRAME2" << std::endl;
-		exit(0);
-	}
-	
-	int size0, nc0;
-	int size1, nc1;
-
-	std::cout << "Reading: " << argv[1] << std::endl;
-	std::ifstream ifs0(argv[1], std::ios::binary);
-	std::cout << "Reading: " << argv[2] << std::endl;
-	std::ifstream ifs1(argv[2], std::ios::binary);
-
-	if (!ifs0 || !ifs1)
-	{
-		std::cout << "Could not open the frames" << std::endl;
-		exit(0);
-	}
-
-	read(ifs0, size0); read(ifs0, nc0);
-	read(ifs1, size1); read(ifs1, nc1);
-
-	assert(size0 == size1); assert(nc0 == nc1);
-	assert(size0 == xsize*ysize);
-	
-	Grid2D g0(xsize, ysize), g1(xsize, ysize);
-	
-	for (int y = 0; y < ysize; ++y)
-		for (int x = 0; x < xsize; ++x)
-			for (int d = 0; d < nc0; ++d)
-			{
-				float val0, val1;
-				read(ifs0, val0);
-				read(ifs1, val1);
-				if (d == var)
-				{
-					g0(x,y) = val0;
-					g1(x,y) = val1;
-				}
-			}
-	std::cout << "Grids read" << std::endl;
-	
-	// Generate filtration and compute pairing
-	Grid2DVineyard v(&g0);
-	std::cout << "Filtration generated, size: " << v.filtration()->size() << std::endl;
-	v.compute_pairing();
-	std::cout << "Pairing computed" << std::endl;
-	
-	// Compute vineyard
-	v.compute_vineyard(&g1, true);
-	std::cout << "Vineyard computed" << std::endl;
-
-	v.vineyard()->save_edges("combustion");
-}
--- a/examples/grid/grid2D.h	Fri Aug 24 16:58:25 2007 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,83 +0,0 @@
-/*
- * Author: Dmitriy Morozov
- * Department of Computer Science, Duke University, 2005 -- 2006
- */
-
-#ifndef __GRID2D_H__
-#define __GRID2D_H__
-
-#include <memory>
-#include <vector>
-#include <map>
-#include <set>
-#include <limits>
-//#include <cmath>
-
-#include <boost/serialization/access.hpp>
-#include <boost/serialization/base_object.hpp>
-#include <boost/serialization/split_member.hpp>
-#include <boost/serialization/nvp.hpp>
-
-#include "utilities/types.h"
-
-#include <boost/serialization/export.hpp>
-
-/** 
- * Grid2D stores a grid
- */
-class Grid2D
-{
-	public:
-		typedef					RealType								ValueType;
-		typedef					unsigned int							CoordinateIndex;
-		
-		typedef					std::vector<ValueType>					ValueVector;
-
-	public:
-		Grid2D(CoordinateIndex xx = 1, CoordinateIndex yy = 1);
-
-		/// Sets the grid dimensions to (xx,yy)
-		void					change_dimensions(CoordinateIndex xx, CoordinateIndex yy);
-
-		ValueType&				operator()(CoordinateIndex i, CoordinateIndex j)			{ return data[i*x + j]; }
-		const ValueType&		operator()(CoordinateIndex i, CoordinateIndex j) const		{ return data[i*x + j]; }
-		ValueType&				operator()(CoordinateIndex i)								{ return data[i]; }
-		const ValueType&		operator()(CoordinateIndex i) const							{ return data[i]; }
-
-		CoordinateIndex			xsize() const												{ return x; }
-		CoordinateIndex			ysize() const												{ return y; }
-		CoordinateIndex			size() const												{ return x*y; }
-		
-		/* Given a sequential index of an element return its coordinates */
-		CoordinateIndex			xpos(CoordinateIndex i) const								{ return i / x; }
-		CoordinateIndex			ypos(CoordinateIndex i) const								{ return i % x; }
-		CoordinateIndex			seq(CoordinateIndex i, CoordinateIndex j) const;
-
-		std::ostream&			operator<<(std::ostream& out) const;
-
-		static const CoordinateIndex INVALID_INDEX = -1;
-
-	private:
-		CoordinateIndex 		x,y;
-		ValueVector				data;
-
-#if 0
-	private:
-		// Serialization
-		friend class boost::serialization::access;
-
-		template<class Archive>	void save(Archive& ar, version_type ) const;
-		template<class Archive>	void load(Archive& ar, version_type );
-
-		BOOST_SERIALIZATION_SPLIT_MEMBER()
-#endif
-};
-//BOOST_CLASS_EXPORT(Grid2D)
-		
-
-std::ostream& operator<<(std::ostream& out, const Grid2D& grid)								{ return grid.operator<<(out); }
-
-		
-#include "grid2D.hpp"
-
-#endif // __GRID2D_H__
--- a/examples/grid/grid2D.hpp	Fri Aug 24 16:58:25 2007 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,65 +0,0 @@
-#include <iostream>
-#include <limits>
-
-/* Implementations */
-
-Grid2D::
-Grid2D(CoordinateIndex xx, CoordinateIndex yy):
-	x(xx), y(yy), data(x*y)
-{}
-
-void					
-Grid2D::
-change_dimensions(CoordinateIndex xx, CoordinateIndex yy)
-{
-	x = xx; y = yy;
-	data.resize(x*y);
-}
-
-Grid2D::CoordinateIndex
-Grid2D::
-seq(CoordinateIndex i, CoordinateIndex j) const
-{ 
-	// Do not forget to check if less than 0, if Index is made signed --- dangerous
-	if (i >= x || j >= y)
-		return INVALID_INDEX;
-
-	return i*x + j; 
-}
-
-std::ostream&			
-Grid2D::
-operator<<(std::ostream& out) const
-{
-	for (Grid2D::CoordinateIndex i = 0; i < xsize(); ++i)
-	{
-		for (Grid2D::CoordinateIndex j = 0; j < ysize(); ++j)
-			std::cout << operator()(i, j) << ' ';
-		std::cout << std::endl;
-	}
-	return out;	
-}	
-
-#if 0
-using boost::serialization::make_nvp;
-
-template<class Archive>
-void 
-Grid2D::
-save(Archive& ar, version_type ) const
-{
-	ar << BOOST_SERIALIZATION_NVP(x);
-	ar << BOOST_SERIALIZATION_NVP(y);
-	ar << make_nvp("data", data);
-}
-
-template<class Archive>	
-void 
-Grid2D::
-load(Archive& ar, version_type )
-{
-	ar >> make_nvp("x", x);
-	ar >> make_nvp("y", y);
-	ar >> make_nvp("data", data);
-}
-#endif
--- a/examples/grid/grid2Dvineyard.h	Fri Aug 24 16:58:25 2007 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,198 +0,0 @@
-/*
- * Author: Dmitriy Morozov
- * Department of Computer Science, Duke University, 2005 -- 2006
- */
-
-#ifndef __GRID2DVINEYARD_H__
-#define __GRID2DVINEYARD_H__
-
-#include "utilities/sys.h"
-#include "utilities/debug.h"
-
-#include "grid2D.h"
-#include "topology/lowerstarfiltration.h"
-
-#include <CGAL/Kinetic/Inexact_simulation_traits.h>
-#include <CGAL/Kinetic/Sort.h>
-#include <CGAL/Kinetic/Sort_visitor_base.h>
-
-#include <vector>
-
-
-class Grid2DVineyard
-{
-	public:
-		typedef					Grid2DVineyard										Self;
-			
-		class					VertexType;
-		typedef					std::vector<VertexType>								VertexVector;
-		typedef					VertexVector::iterator								VertexIndex;
-		
-		typedef					LowerStarFiltration<VertexIndex>					LSFiltration; 
-		
-		class					StaticEvaluator;
-		class					KineticEvaluator;
-		class 					VertexComparison;
-		
-		typedef					Grid2D::CoordinateIndex								CoordinateIndex;
-		typedef					Grid2D::ValueType									ValueType;
-
-		typedef					LSFiltration::Index									Index;
-		typedef					LSFiltration::Simplex								Simplex;
-		typedef					LSFiltration::VertexOrderIndex						VertexOrderIndex;
-		typedef					LSFiltration::Vineyard								Vineyard;
-		typedef					Vineyard::Evaluator									Evaluator;
-
-		class					SortVisitor;
-		typedef 				CGAL::Kinetic::Inexact_simulation_traits 			Traits;
-		typedef					CGAL::Kinetic::Sort<Traits, SortVisitor>			Sort;
-		typedef 				Traits::Simulator 									Simulator;
-		typedef 				Traits::Active_points_1_table						ActivePointsTable;
-		typedef 				ActivePointsTable::Key								Key;
-		typedef					std::map<Key, VertexOrderIndex>						KeyOrderMap;
-
-		typedef					std::vector<Grid2D*>								GridStackContainer;
-
-	public:
-								Grid2DVineyard(Grid2D* g);
-								~Grid2DVineyard();
-
-		void					compute_pairing();
-		void					compute_vineyard(Grid2D* grid, bool explicit_events = false);
-		
-		Grid2D*					grid() const										{ return grid_stack_.back(); }
-		Grid2D*					grid(int i) const									{ return grid_stack_[i]; }
-		int						num_grids() const									{ return grid_stack_.size(); }
-		const LSFiltration*		filtration() const									{ return filtration_; }
-		const Vineyard*			vineyard() const									{ return vineyard_; }
-
-	public:
-		// For Kinetic Sort
-		void 					swap(Key a, Key b);
-	
-	protected:
-		// Do something cleverer
-		virtual bool			neighbors(VertexIndex v1, VertexIndex v2) const		{ return true; }
-		
-	private:
-		void 					add_simplices();
-		void					change_evaluator(Evaluator* eval);
-
-	private:
-		GridStackContainer		grid_stack_;
-		VertexVector			vertices_;
-		LSFiltration*			filtration_;
-		Vineyard*				vineyard_;
-		Evaluator*				evaluator_;
-
-		KeyOrderMap				kinetic_map_;
-				
-#if 0
-	private:
-		// Serialization
-		friend class boost::serialization::access;
-		
-		Grid2DVineyard() 																	{}
-
-		template<class Archive> 
-		void serialize(Archive& ar, version_type )
-		{ 
-			ar & BOOST_SERIALIZATION_NVP(grid_stack_); 
-			ar & BOOST_SERIALIZATION_NVP(vertices_); 
-			ar & BOOST_SERIALIZATION_NVP(filtration_); 
-		};
-#endif
-};
-
-//BOOST_CLASS_EXPORT(Grid2DVineyard)
-	
-class Grid2DVineyard::VertexType
-{
-	public:
-		VertexType(CoordinateIndex ii = 0): i_(ii)											{}
-		
-		CoordinateIndex			index() const												{ return i_; }
-		void					set_index(CoordinateIndex i)								{ i_ = i; }
-		VertexOrderIndex		get_order() const											{ return order_; }
-		void					set_order(const VertexOrderIndex& o)						{ order_ = o; }
-		
-		Key						kinetic_key() const											{ return key_; }
-		void					set_kinetic_key(Key k)										{ key_ = k; }
-		
-	private:
-		CoordinateIndex			i_;
-		VertexOrderIndex		order_;
-		Key						key_;
-};
-
-std::ostream& operator<<(std::ostream& out, const Grid2DVineyard::VertexIndex& vi)			{ return out << vi->index(); }
-
-class Grid2DVineyard::VertexComparison
-{
-	public:
-		VertexComparison(const Grid2D* g): grid(g)											{}
-		bool operator()(VertexIndex i, VertexIndex j) const									{ return (*grid)(i->index()) < 
-																									 (*grid)(j->index()); }
-
-	private:
-		const Grid2D*			grid;
-
-#if 0
-	private:
-		// Serialization
-		friend class boost::serialization::access;
-
-								VertexComparison()											{}
-
-		template<class Archive>
-		void 					serialize(Archive& ar, version_type )						{ ar & BOOST_SERIALIZATION_NVP(grid); }
-#endif
-};
-
-class Grid2DVineyard::StaticEvaluator: public Evaluator
-{
-	public:
-								StaticEvaluator(Grid2D* grid, RealType time): 
-									time_(time), grid_(grid)								{}
-
-		virtual RealType		time()														{ return time_; }
-		virtual RealType		value(const Simplex& s)										{ return (*grid_)(s.get_attachment()->index()); }
-								
-	private:
-		RealType				time_;
-		Grid2D*					grid_;
-};
-
-class Grid2DVineyard::KineticEvaluator: public Evaluator
-{
-	public:
-								KineticEvaluator(Simulator::Handle sp, ActivePointsTable::Handle apt, RealType time_offset): 
-									sp_(sp), apt_(apt), time_offset_(time_offset)			{}
-
-		virtual RealType		time()														{ return time_offset_ + CGAL::to_double(get_time()); }
-		virtual RealType		value(const Simplex& s)										{ return CGAL::to_double(apt_->at(s.get_attachment()->kinetic_key()).x()(get_time())); }
-
-	private:
-		Simulator::Time			get_time()													{ return sp_->current_time(); }
-		
-		Simulator::Handle			sp_;
-		ActivePointsTable::Handle 	apt_;
-		RealType					time_offset_;
-};
-
-
-class Grid2DVineyard::SortVisitor: public CGAL::Kinetic::Sort_visitor_base
-{
-	public:
-								SortVisitor(Grid2DVineyard* gv): gv_(gv)					{}
-
-		template<class Vertex_handle>
-		void					before_swap(Vertex_handle a, Vertex_handle b) const			{ gv_->swap(*a,*b); }
-
-	private:
-		Grid2DVineyard*			gv_;
-};
-
-#include "grid2Dvineyard.hpp"
-
-#endif // __GRID2DVINEYARD_H__
--- a/examples/grid/grid2Dvineyard.hpp	Fri Aug 24 16:58:25 2007 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,145 +0,0 @@
-/* Implementation */
-	
-Grid2DVineyard::
-Grid2DVineyard(Grid2D* g): vertices_(g->size())
-{
-	grid_stack_.push_back(g); 
-	for (CoordinateIndex i = 0; i < g->size(); ++i)
-		vertices_[i].set_index(i);
-
-	evaluator_ = new StaticEvaluator(grid(), 0);
-	vineyard_ = new Vineyard(evaluator_);
-
-	filtration_ = new LSFiltration(vertices_.begin(), vertices_.end(), VertexComparison(grid()), vineyard_);
-	add_simplices();
-}
-
-Grid2DVineyard::
-~Grid2DVineyard()
-{
-	delete filtration_;
-	delete vineyard_;
-	delete evaluator_;
-}
-
-void
-Grid2DVineyard::
-compute_pairing()
-{
-	filtration_->fill_simplex_index_map();
-	filtration_->pair_simplices(filtration_->begin(), filtration_->end());
-	vineyard_->start_vines(filtration_->begin(), filtration_->end());
-}
-
-void					
-Grid2DVineyard::
-compute_vineyard(Grid2D* g, bool explicit_events)
-{
-	AssertMsg(filtration_->is_paired(), "Simplices must be paired for a vineyard to be computed");
-	
-	typedef Traits::Kinetic_kernel::Point_1 								Point;
-	typedef Traits::Kinetic_kernel::Function_kernel::Construct_function 	CF; 
-	typedef Traits::Kinetic_kernel::Motion_function 						F; 
-	
-	Traits tr(0,1);
-	Simulator::Handle sp = tr.simulator_handle();
-	ActivePointsTable::Handle apt = tr.active_points_1_table_handle();
-	Sort sort(tr, SortVisitor(this));
-	
-	// Setup the (linear) trajectories
-	std::cout << "Setting up trajectories" << std::endl;
-	CF cf; 
-	kinetic_map_.clear();
-	for (VertexIndex cur = vertices_.begin(); cur != vertices_.end(); ++cur)
-	{
-		ValueType val0 = (*grid())(cur->index());
-		ValueType val1 = (*g)(cur->index());
-		F x = cf(F::NT(val0), F::NT(val1 - val0));			// x = val0 + (val1 - val0)*t
-		Point p(x);
-		cur->set_kinetic_key(apt->insert(p));
-		kinetic_map_[cur->kinetic_key()] = cur->get_order();
-		if (cur->index() % 10000 == 0)
-			std::cout << "Added trajectory: " << cur->index() << " " << val0 << " " << val1 << std::endl;
-	}
-	
-	// Process all the events (compute the vineyard in the process)
-	change_evaluator(new KineticEvaluator(sp, apt, num_grids() - 1));
-	if (explicit_events)
-	{
-		while (sp->next_event_time() < 1)
-		{
-			std::cout << "Next event time: " << sp->next_event_time() << std::endl;
-			sp->set_current_event_number(sp->current_event_number() + 1);
-			std::cout << "Processed event" << std::endl;
-		}
-	} else
-		sp->set_current_time(1.0);
-	std::cout << "Processed " << sp->current_event_number() << " events" << std::endl;
-	
-	// Add the grid to the stack
-	grid_stack_.push_back(g); 
-	change_evaluator(new StaticEvaluator(grid(), num_grids() - 1));
-	vineyard_->record_diagram(filtration_->begin(), filtration_->end());
-}
-		
-void 					
-Grid2DVineyard::
-swap(Key a, Key b)
-{
-	VertexOrderIndex ao = kinetic_map_[a], bo = kinetic_map_[b];
-	AssertMsg(filtration_->get_vertex_cmp()(ao, bo), "In swap(a,b), a must precede b");
-	filtration_->transpose_vertices(ao);
-	AssertMsg(filtration_->get_vertex_cmp()(bo, ao), "In swap(a,b), b must precede a after the transposition");
-}
-
-void 
-Grid2DVineyard::
-add_simplices()
-{
-	// Takes advantage of LowerStarFiltration's smart append (which allows faces
-	// to be inserted after cofaces, since everything is rearranged in the
-	// proper lower star order anyway). Also note that vertices were added by
-	// LowerStarFiltration's constructor
-	for (CoordinateIndex x = 0; x < grid()->xsize() - 1; ++x)
-		for (CoordinateIndex y = 0; y < grid()->ysize() - 1; ++y)
-		{
-			VertexIndex v(&vertices_[grid()->seq(x,y)]);
-			VertexIndex vh(&vertices_[grid()->seq(x+1,y)]);
-			VertexIndex vv(&vertices_[grid()->seq(x,y+1)]);
-			VertexIndex vd(&vertices_[grid()->seq(x+1,y+1)]);
-
-			Simplex sh(v);
-			sh.add(vh);	filtration_->append(sh);		// Horizontal edge
-			sh.add(vd);	filtration_->append(sh);		// "Horizontal" triangle
-			
-			Simplex sv(v);
-			sv.add(vv);	filtration_->append(sv);		// Vertical edge
-			sv.add(vd);	filtration_->append(sv);		// "Vertical" triangle
-			
-			Simplex sd(v);
-			sd.add(vd); filtration_->append(sd);		// Diagonal edge
-
-			if (y == grid()->ysize() - 2)
-			{
-				Simplex s(vv); 
-				s.add(vd); filtration_->append(s);		// Top edge
-			}
-			if (x == grid()->xsize() - 2)
-			{
-				Simplex s(vh); 
-				s.add(vd); filtration_->append(s);		// Right edge
-			}
-		}
-}
-
-void
-Grid2DVineyard::
-change_evaluator(Evaluator* eval)
-{
-	AssertMsg(evaluator_ != 0, "change_evaluator() assumes that existing evaluator is not null");
-		
-	delete evaluator_;
-	evaluator_ = eval;
-	vineyard_->set_evaluator(evaluator_);
-}
-
--- a/examples/grid/pdbdistance-vineyard.cpp	Fri Aug 24 16:58:25 2007 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,82 +0,0 @@
-//#include <boost/archive/binary_oarchive.hpp>
-#include "utilities/sys.h"
-#include "utilities/debug.h"
-
-#include "pdbdistance.h"
-#include "grid2Dvineyard.h"
-
-#include <fstream>
-#include <string>
-#include <sstream>
-
-std::string frame_filename(const std::string& prefix, int frame, int subframe)
-{
-	std::ostringstream os;
-	os << prefix << frame << "_" << subframe << ".pdb";
-	return os.str();
-}
-
-int main(int argc, char** argv)
-{
-#ifdef CWDEBUG
-	Debug(dc::filtration.off());
-	Debug(dc::cycle.off());
-	Debug(dc::vineyard.off());
-	Debug(dc::transpositions.off());
-	Debug(dc::lsfiltration.off());
-
-	dionysus::debug::init();
-#endif
-
-	if (argc < 5)
-	{
-		std::cout << "Usage: pdbdistance FILENAME LASTFRAME LASTSUBFRAME OUTFILENAME [CAs_ONLY]" << std::endl;
-		std::cout << "  FILENAME     - prefix of the filenames of the PDB frames" << std::endl;
-		std::cout << "  LASTFRAME    - the last frame number" << std::endl;
-		std::cout << "  LASTSUBFRAME - the last subframe number" << std::endl;
-		std::cout << "  OUTFILENAME  - filename prefix for the resulting vineyards" << std::endl;
-		std::cout << "  CAs_ONLY     - only use alpha carbons [1 = true, 0 = false, default: 1]" << std::endl;
-		std::cout << std::endl;
-		std::cout << "Computes a vineyard of the pairwise distance function for a sequence of PDB frames." << std::endl;
-		std::cout << "Frames are in files FILENAME#1_#2.pdb, where #1 goes from 0 to LASTFRAME, " << std::endl;
-		std::cout << "and #2 goes from 0 to LASTSUBFRAME." << std::endl;
-		exit(0);
-	}
-	std::string infilename = argv[1];
-	int lastframe; std::istringstream(argv[2]) >> lastframe;
-	int lastsubframe; std::istringstream(argv[3]) >> lastsubframe;
-	std::string outfilename = argv[4];
-	bool cas_only = true;
-	if (argc > 5)
-		std::istringstream(argv[5]) >> cas_only;
-
-	// Compute initial filtration
-	int f = 0; int sf = 0;
-	std::ifstream in(frame_filename(infilename, f, sf++).c_str());
-	Grid2DVineyard v(new PDBDistanceGrid(in, cas_only));
-	in.close();
-	std::cout << "Filtration generated, size: " << v.filtration()->size() << std::endl;
-	v.compute_pairing();
-	std::cout << "Pairing computed" << std::endl;
-
-	// Process frames computing the vineyard
-	while (f <= lastframe)
-	{
-		std::string fn = frame_filename(infilename, f, sf++);
-		std::cout << "Processing " << fn << std::endl;
-		in.open(fn.c_str());
-		v.compute_vineyard(new PDBDistanceGrid(in, cas_only));
-		in.close();
-		if (sf == lastsubframe) { sf = 0; ++f; }
-	}
-	std::cout << "Vineyard computed" << std::endl;
-
-	v.vineyard()->save_edges(outfilename);
-
-#if 0
-	std::ofstream ofs(outfilename.c_str(), std::ios::binary);
-	boost::archive::binary_oarchive oa(ofs);
-	oa << make_nvp("Filtration", pgf);
-	ofs.close();
-#endif
-}
--- a/examples/grid/pdbdistance.h	Fri Aug 24 16:58:25 2007 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,87 +0,0 @@
-/*
- * Author: Dmitriy Morozov
- * Department of Computer Science, Duke University, 2005 -- 2006
- *
- * Depends on Daniel Russel's "simple C++ PDB" (aka DSR-PDB).
- */
-
-#ifndef __PDBDISTANCE_H__
-#define __PDBDISTANCE_H__
-
-#include <fstream>
-#include <string>
-#include <dsrpdb/Protein.h>
-#include <dsrpdb/iterator.h>
-#include <cmath>
-
-#include <boost/serialization/access.hpp>
-
-#include "utilities/types.h"
-#include "grid2D.h"
-
-#include <boost/serialization/export.hpp>
-
-
-class PDBDistanceGrid: public Grid2D
-{
-	public:
-		PDBDistanceGrid()
-		{}
-	
-		PDBDistanceGrid(std::istream& in, bool ca_only = true)
-		{
-			load_stream(in, ca_only);
-		}
-
-		void	load_stream(std::istream& in, bool ca_only = true)
-		{
-			dsrpdb::Protein p(in);
-			typedef std::vector<dsrpdb::Point> PointVector;
-			PointVector coordinates;
-			if (ca_only)
-			{
-				PointVector v(ca_coordinates_begin(p), ca_coordinates_end(p));
-				coordinates.swap(v);
-			}
-			else
-			{
-				PointVector v(backbone_coordinates_begin(p), backbone_coordinates_end(p));
-				coordinates.swap(v);
-			}
-
-			std::cout << "Coordinatess created, size: " << coordinates.size() << std::endl;
-
-			Grid2D::change_dimensions(coordinates.size(), coordinates.size());
-			for (Grid2D::CoordinateIndex i = 0; i < coordinates.size(); ++i)
-				for (Grid2D::CoordinateIndex j = 0; j < coordinates.size(); ++j)
-				{
-					if (i < j)
-						Grid2D::operator()(i,j) = distance(coordinates[i], coordinates[j]);
-					else
-						Grid2D::operator()(i,j) = 0;
-				}
-		}
-
-	private:
-		Grid2D::ValueType distance(dsrpdb::Point p1, dsrpdb::Point p2) const
-		{
-			dsrpdb::Vector v = p1 - p2;
-			return std::sqrt(v*v);
-		}
-
-#if 0
-	private:
-		// Serialization
-		friend class boost::serialization::access;
-		
-		template<class Archive>
-		void serialize(Archive& ar, version_type version)
-		{
-			ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Grid2D);
-		}
-#endif
-};
-
-//BOOST_CLASS_EXPORT(PDBDistanceGrid)
-
-#endif // __PDBDISTANCE_H__
--- a/examples/grid/test-grid2D.cpp	Fri Aug 24 16:58:25 2007 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,16 +0,0 @@
-#include "grid2D.h"
-#include <iostream>
-
-int main()
-{
-	Grid2D grid(40,60);
-	int i = 0;
-	for (int x = 0; x < 40; ++x)
-		for (int y = 0; y < 60; ++y)
-		{
-			grid(x,y) = i++;
-		}
-
-	std::cout << grid(20,30) << std::endl;
-	std::cout << grid << std::endl;
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/homology-zigzags/CMakeLists.txt	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,11 @@
+set                         (targets
+                             rips-pairwise
+                             M-ZZ
+                             dM-ZZ
+                             iR-ZZ
+                             oR-ZZ)
+
+foreach                     (t ${targets})
+    add_executable          (${t} ${t}.cpp)
+    target_link_libraries   (${t} ${libraries} ${Boost_PROGRAM_OPTIONS_LIBRARY})
+endforeach                  (t ${targets})
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/homology-zigzags/M-ZZ.cpp	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,432 @@
+/***************************************************************************
+
+    M-ZZ: Morozov zigzag implementation
+    Copyright (C) 2009-2012   Dmitriy Morozov
+
+    Adapted from its original version ("rips-zigzag.cpp" in
+    the Dionysus library) by Steve Oudot (2012).
+
+    Changelog (2012-11-22):
+
+       - the barcode is now output on a log scale and in a format that is 
+         compatible with the Matlab layer of the PLEX 2.5 library,
+
+       - the barcode representation is now by closed intervals instead of
+         half-open intervals.
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+***************************************************************************/
+
+#include <topology/rips.h>
+#include <topology/zigzag-persistence.h>
+#include <utilities/types.h>
+#include <utilities/containers.h>
+
+#include <geometry/l2distance.h>    // Point, PointContainer, L2DistanceType, read_points
+#include <geometry/distances.h>
+
+#include <utilities/log.h>
+#include <utilities/memory.h>       // for report_memory()
+#include <utilities/timer.h>
+
+#include <map>
+#include <cmath>
+#include <fstream>
+#include <stack>
+#include <cstdlib>
+
+#include <boost/tuple/tuple.hpp>
+#include <boost/program_options.hpp>
+#include <boost/progress.hpp>
+
+#ifdef COUNTERS
+static Counter*  cComplexSize =                     GetCounter("rips/size");
+static Counter*  cOperations =                      GetCounter("rips/operations");
+#endif // COUNTERS
+
+typedef     PairwiseDistances<PointContainer, L2Distance>           PairDistances;
+typedef     PairDistances::DistanceType                             DistanceType;
+
+typedef     PairDistances::IndexType                                Vertex;
+typedef     Simplex<Vertex>                                         Smplx;
+typedef     std::vector<Smplx>                                      SimplexVector;
+typedef     std::list<Smplx>                                        SimplexList;
+typedef     std::set<Smplx, Smplx::VertexDimensionComparison>       SimplexSet;
+
+typedef     std::vector<Vertex>                                     VertexVector;
+typedef     std::vector<DistanceType>                               EpsilonVector;
+typedef     std::vector<std::pair<Vertex, Vertex> >                 EdgeVector;
+
+typedef     Rips<PairDistances, Smplx>                              RipsGenerator;
+typedef     RipsGenerator::Evaluator                                SimplexEvaluator;
+
+struct      BirthInfo;
+typedef     ZigzagPersistence<BirthInfo>                            Zigzag;
+typedef     Zigzag::SimplexIndex                                    Index;
+typedef     Zigzag::Death                                           Death;
+typedef     std::map<Smplx, Index, 
+                            Smplx::VertexDimensionComparison>       Complex;
+typedef     Zigzag::ZColumn                                         Boundary;
+
+typedef     std::vector<std::list<std::pair<double, double> > >     IntervalsVector;
+
+// Information we need to know when a class dies
+struct      BirthInfo
+{
+                    BirthInfo(DistanceType dist = DistanceType(), Dimension dim = Dimension()):
+                        distance(dist), dimension(dim)              {}
+    DistanceType    distance;
+    Dimension       dimension;
+};
+
+// Forward declarations of auxilliary functions
+// Note: min_value is used only for log-scale, so set it up to zero by default
+void write_intervals(std::ostream& out, const IntervalsVector& intervals, int skeleton_dimension, bool logscale, double min_value=0);
+void        report_death(IntervalsVector& intervals, Death d, DistanceType epsilon, DistanceType birthEpsilon, Dimension skeleton_dimension);
+void        make_boundary(const Smplx& s, Complex& c, const Zigzag& zz, Boundary& b);
+std::ostream&   operator<<(std::ostream& out, const BirthInfo& bi);
+void        process_command_line_options(int           argc,
+                                         char*         argv[],
+                                         unsigned&     skeleton_dimension,
+                                         float&        multiplier,
+					 bool&         logscale,
+                                         std::string&  infilename,
+                                         std::string&  outfilename);
+
+int main(int argc, char* argv[])
+{
+#ifdef LOGGING
+    rlog::RLogInit(argc, argv);
+
+    stderrLog.subscribeTo( RLOG_CHANNEL("error") );
+#endif
+
+    Timer total, remove, add, ec, vc;
+    total.start();
+ 
+#if 0
+    SetFrequency(cOperations, 25000);
+    SetTrigger(cOperations, cComplexSize);
+#endif
+
+    unsigned        skeleton_dimension;
+    float           multiplier;
+    std::string     infilename, outfilename;
+    bool            logscale = false;
+    process_command_line_options(argc, argv, skeleton_dimension, multiplier, logscale, infilename, outfilename);
+
+    // Read in points
+    PointContainer      points;
+    read_points(infilename, points);
+    
+    std::cout << "Number of points: " << points.size() << std::endl;
+
+    // Create output file
+    std::ofstream out(outfilename.c_str());
+
+    // Create pairwise distances
+    PairDistances distances(points);
+    
+    // Create intervals DS
+    IntervalsVector intervals(skeleton_dimension);
+    // for (int i=0; i<skeleton_dimension; i++)
+    //   intervals[i] = new std::list<std::pair<double, double> > ();
+
+    // Order vertices and epsilons (in maxmin fashion)
+    VertexVector        vertices;
+    EpsilonVector       epsilons;
+    EdgeVector          edges;
+
+    {
+        EpsilonVector   dist(distances.size(), Infinity);
+    
+        vertices.push_back(distances.begin());
+        //epsilons.push_back(Infinity);
+        while (vertices.size() < distances.size())
+        {
+            for (Vertex v = distances.begin(); v != distances.end(); ++v)
+                dist[v] = std::min(dist[v], distances(v, vertices.back()));
+            EpsilonVector::const_iterator max = std::max_element(dist.begin(), dist.end());
+            vertices.push_back(max - dist.begin());
+            epsilons.push_back(*max);
+        }
+        epsilons.push_back(0);
+    }
+
+    rInfo("Point and epsilon ordering:");
+    for (unsigned i = 0; i < vertices.size(); ++i)
+        rInfo("  %4d: %4d - %f", i, vertices[i], epsilons[i]);
+
+    // Generate and sort all the edges
+    for (unsigned i = 0; i != vertices.size(); ++i)
+        for (unsigned j = i+1; j != vertices.size(); ++j)
+        {
+            Vertex u = vertices[i];
+            Vertex v = vertices[j];
+            if (distances(u,v) <= multiplier*epsilons[j-1])
+                edges.push_back(std::make_pair(u,v));
+        }
+    std::sort(edges.begin(), edges.end(), RipsGenerator::ComparePair(distances));
+    std::cout << "Total participating edges: " << edges.size() << std::endl;
+    for (EdgeVector::const_iterator cur = edges.begin(); cur != edges.end(); ++cur)
+        rDebug("  (%d, %d) %f", cur->first, cur->second, distances(cur->first, cur->second));
+
+    // Construct zigzag
+    Complex             complex;
+    Zigzag              zz;
+    RipsGenerator       rips(distances);
+    SimplexEvaluator    size(distances);
+    
+    // Insert vertices (initial complex is just a disjoint union of vertices)
+    for (unsigned i = 0; i != vertices.size(); ++i)
+    {
+        // Add a vertex
+        Smplx sv; sv.add(vertices[i]);
+        rDebug("Adding %s", tostring(sv).c_str());
+        add.start();
+        complex.insert(std::make_pair(sv, 
+                                      zz.add(Boundary(), 
+                                             BirthInfo(0, 0)).first));
+        add.stop();
+        //rDebug("Newly born cycle order: %d", complex[sv]->low->order);
+        CountNum(cComplexSize, 0);
+        Count(cComplexSize);
+        Count(cOperations);
+    }
+
+    rInfo("Commencing computation");
+    boost::progress_display show_progress(vertices.size());
+    unsigned ce     = 0;        // index of the current one past last edge in the complex
+    for (unsigned stage = 0; stage != vertices.size() - 1; ++stage)
+    {
+        unsigned i = vertices.size() - 1 - stage;
+	// std::cout << "Current stage " << stage << " " 
+	// 	  << vertices[i] << " " << epsilons[i-1] << ": "
+	// 	  << multiplier*epsilons[i-1] << std::endl;
+
+        /* Increase epsilon */
+        // Record the cofaces of all the simplices that need to be removed and reinserted
+        SimplexSet cofaces;
+        rDebug("  Cofaces size: %d", cofaces.size());
+
+        // Add anything else that needs to be inserted into the complex
+        while (ce < edges.size())
+        {
+            Vertex u,v;
+            boost::tie(u,v)     = edges[ce];
+            if (distances(u,v) <= multiplier*epsilons[i-1])
+                ++ce;
+            else
+                break;
+            rDebug("  Recording cofaces of edges[%d]=(%d, %d) with size=%f", (ce-1), u, v, distances(u,v));
+            ec.start();
+            rips.edge_cofaces(u, v, 
+                              skeleton_dimension, 
+                              multiplier*epsilons[i-1], 
+                              make_insert_functor(cofaces),
+                              vertices.begin(),
+                              vertices.begin() + i + 1);
+            ec.stop();
+        }
+        rDebug("  Recorded new cofaces to add");
+
+        // Insert all the cofaces
+        rDebug("  Cofaces size: %d", cofaces.size());
+        for (SimplexSet::const_iterator cur = cofaces.begin(); cur != cofaces.end(); ++cur)
+        {
+            Index idx; Death d; Boundary b;
+            rDebug("  Adding %s, its size %f", tostring(*cur).c_str(), size(*cur));
+            make_boundary(*cur, complex, zz, b);
+            add.start();
+            boost::tie(idx, d)  = zz.add(b,
+                                         BirthInfo(epsilons[i-1], cur->dimension()));
+            add.stop();
+            //if (!d) rDebug("Newly born cycle order: %d", complex[*cur]->low->order);
+            CountNum(cComplexSize, cur->dimension());
+            Count(cComplexSize);
+            Count(cOperations);
+            AssertMsg(zz.check_consistency(), "Zigzag representation must be consistent after removing a simplex");
+            complex.insert(std::make_pair(*cur, idx));
+            report_death(intervals, d, epsilons[i-1], epsilons[i], skeleton_dimension);
+        }
+        rInfo("Increased epsilon; complex size: %d", complex.size());
+        report_memory();
+        
+        /* Remove the vertex */
+        cofaces.clear();
+        rDebug("  Cofaces size: %d", cofaces.size());
+        vc.start();
+        rips.vertex_cofaces(vertices[i], 
+                            skeleton_dimension, 
+                            multiplier*epsilons[i-1], 
+                            make_insert_functor(cofaces),
+                            vertices.begin(),
+                            vertices.begin() + i + 1);
+        vc.stop();
+        rDebug("  Computed cofaces of the vertex, their number: %d", cofaces.size());
+        for (SimplexSet::const_reverse_iterator cur = cofaces.rbegin(); cur != (SimplexSet::const_reverse_iterator)cofaces.rend(); ++cur)
+        {
+            rDebug("    Removing: %s", tostring(*cur).c_str());
+            Complex::iterator si = complex.find(*cur);
+            remove.start();
+            Death d = zz.remove(si->second,
+                                BirthInfo(epsilons[i-1], cur->dimension() - 1));
+            remove.stop();
+            complex.erase(si);
+            CountNumBy(cComplexSize, cur->dimension(), -1);
+            CountBy(cComplexSize, -1);
+            Count(cOperations);
+            AssertMsg(zz.check_consistency(), "Zigzag representation must be consistent after removing a simplex");
+            report_death(intervals, d, epsilons[i-1], epsilons[i], skeleton_dimension);
+        }
+        rInfo("Removed vertex; complex size: %d", complex.size());
+        for (Complex::const_iterator cur = complex.begin(); cur != complex.end(); ++cur)
+            rDebug("  %s", tostring(cur->first).c_str());
+        report_memory();
+        
+        ++show_progress;
+    }
+    
+    // Remove the last vertex
+    AssertMsg(complex.size() == 1, "Only one vertex must remain");
+    remove.start();
+    Death d = zz.remove(complex.begin()->second, BirthInfo(epsilons[0], -1));
+    remove.stop();
+    complex.erase(complex.begin());
+    if (!d)  AssertMsg(false,  "The vertex must have died");
+    report_death(intervals, d, epsilons[0], epsilons[0], skeleton_dimension);
+    CountNumBy(cComplexSize, 0, -1);
+    CountBy(cComplexSize, -1);
+    Count(cOperations);
+    rInfo("Removed vertex; complex size: %d", complex.size());
+    ++show_progress;
+
+    total.stop();
+
+    remove.check("Remove timer          ");
+    add.check   ("Add timer             ");
+    ec.check    ("Edge coface timer     ");
+    vc.check    ("Vertex coface timer   ");
+    total.check ("Total timer           ");
+
+    std::cout << "Writing intervals...";
+    // Note (hack): use epsilons[vertices.size()-2]/2 as minimal value for the log-scale intervals to avoid intervals starting at -infinity and thus a scaling effect
+    write_intervals(out, intervals, skeleton_dimension, logscale, epsilons[vertices.size()-2]/2);
+    std::cout << " done." << std::endl;
+}
+
+
+const double LOG2 = std::log(2.0);
+double log2(double x) {
+  return std::log(x) / LOG2;
+}
+
+void write_intervals(std::ostream& out, const IntervalsVector& intervals, int skeleton_dimension, bool logscale, double min_value) {
+  out << "I = { ";
+    for (int d = 0; d<skeleton_dimension; d++) {
+      out << "[ ";
+      for (std::list<std::pair<double,double> >::const_iterator pit = intervals[d].begin(); pit != intervals[d].end(); pit++)
+	if (logscale)
+	  out << "[" << log2(std::max(pit->first, min_value)) << ";" << log2(std::max(pit->second, min_value)) << "] ";
+	else
+	  out << "[" << pit->first << ";" << pit->second << "] ";
+
+      // add dummy interval if intervals list is empty
+      if (intervals[d].empty())
+	out << "[0;0] ";
+      out << "] ,";
+    }
+    out << "} ";
+} 
+            
+void        report_death(IntervalsVector& intervals, Death d, DistanceType epsilon, DistanceType birthEpsilon, Dimension skeleton_dimension)
+{
+  // std::cerr << "   d = " << d;
+  // if (d)
+  //   std::cerr << "   d->dim = " << d->dimension 
+  // 	      << "   d->dist = " << d->distance;
+  // std::cerr << "   epsilon = " << epsilon << std::endl;
+
+  if (d && ((d->distance - epsilon) != 0) && (d->dimension < skeleton_dimension))
+    intervals[d->dimension].push_back(std::pair<double,double>(d->distance, birthEpsilon));
+}
+
+void        make_boundary(const Smplx& s, Complex& c, const Zigzag& zz, Boundary& b)
+{
+    rDebug("  Boundary of <%s>", tostring(s).c_str());
+    for (Smplx::BoundaryIterator cur = s.boundary_begin(); cur != s.boundary_end(); ++cur)
+    {
+        b.append(c[*cur], zz.cmp);
+        rDebug("   %d", c[*cur]->order);
+    }
+}
+
+std::ostream&   operator<<(std::ostream& out, const BirthInfo& bi)
+{ return (out << bi.distance); }
+
+void        process_command_line_options(int           argc, 
+                                         char*         argv[],
+                                         unsigned&     skeleton_dimension,
+                                         float&        multiplier,
+					 bool&         logscale,
+                                         std::string&  infilename,
+                                         std::string&  outfilename)
+{
+    namespace po = boost::program_options;
+
+    po::options_description hidden("Hidden options");
+    hidden.add_options()
+        ("input-file",          po::value<std::string>(&infilename),        "Point set whose Rips zigzag we want to compute")
+        ("output-file",         po::value<std::string>(&outfilename),       "Location to save persistence pairs");
+    
+    po::options_description visible("Allowed options", 100);
+    visible.add_options()
+        ("help,h",                                                                              "produce help message")
+        ("dim,d", po::value<unsigned>(&skeleton_dimension)->default_value(3),     "maximal dimension of the Rips complex")
+        ("rho,r",        po::value<float>(&multiplier)->default_value(3),                "multiplier rho used in the Rips parameter")
+      ( "logscale,l" , po::value( &logscale )->zero_tokens(), "outputs interval bounds on log_2 scale" ) ;
+#if LOGGING
+    std::vector<std::string>    log_channels;
+    visible.add_options()
+        ("log,l",               po::value< std::vector<std::string> >(&log_channels),           "log channels to turn on (info, debug, etc)");
+#endif
+
+    po::positional_options_description pos;
+    pos.add("input-file", 1);
+    pos.add("output-file", 2);
+    
+    po::options_description all; all.add(visible).add(hidden);
+
+    po::variables_map vm;
+    po::store(po::command_line_parser(argc, argv).
+                  options(all).positional(pos).run(), vm);
+    po::notify(vm);
+
+#if LOGGING
+    for (std::vector<std::string>::const_iterator cur = log_channels.begin(); cur != log_channels.end(); ++cur)
+        stderrLog.subscribeTo( RLOG_CHANNEL(cur->c_str()) );
+    /**
+     * Interesting channels
+     * "info", "debug", "topology/persistence"
+     */
+#endif
+
+    if (vm.count("help") || !vm.count("input-file") || !vm.count("output-file"))
+    { 
+        std::cout << "Usage: " << argv[0] << " [options] input-file output-file" << std::endl;
+        std::cout << visible << std::endl; 
+        std::abort();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/homology-zigzags/README	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,43 @@
+********************************************************************************
+*		 Rips-ZZ: Rips Zigzags for Homology Inference                  *
+********************************************************************************
+
+This is an extension to the Rips package of the Dionysus library. It
+adapts the code of the Morozov zigzag (M-ZZ) and image Rips zigzag
+(iR-ZZ) to the context of the following paper:
+
+Title: Zigzag Zoology: Rips Zigzags for Homology Inference
+Authors: Steve Y. Oudot and Donald R. Sheehy
+
+It also provides two variants of the M-ZZ: the discretized Morozov
+zigzag (dM-ZZ) and the oscillating Rips zigzag (oR-ZZ).
+
+
+Source files:
+
+ - M-ZZ.cpp: implementation of the Morozov zigzag
+ - dM-ZZ.cpp: implementation of the discretized Morozov zigzag
+ - oR-ZZ.cpp: implementation of the oscillating Rips zigzag
+ - iR-ZZ.cpp: implementation of the image Rips zigzag
+ - rips-pairwise.cpp: computation of the standard Rips filtration 
+                      and its persistent homology.
+
+Execution:
+
+ - the list of arguments required by a program can be obtained by
+   running that program without arguments.
+
+ - every program takes in a point cloud file, in xyz... format (no
+   need to indicate the ambient dimension at the beginning of the
+   file. A sample point cloud is provided in the file
+   input/spiral_3d_10k.xyz
+
+ - every program also asks for the name of the output file in which
+   the barcode will be written. The output format is such that the
+   file can be executed in Matlab. This creates a cells structures
+   that can be read by the px_homologyplot function from the PLEX 2.5
+   library (a copy of which is provided). This function will plot the
+   barcode dimension per dimension.
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/homology-zigzags/dM-ZZ.cpp	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,451 @@
+/***************************************************************************
+
+    dM-ZZ: discretized Morozov zigzag implementation
+    Copyright (C) 2012   Steve Oudot
+
+    Adapted from the Morozov zigzag implementation provided in the
+    Rips package of the Dionysus library (see the file "M-ZZ.cpp").
+    The Dionysus library is (C) 2006-2012 Dmitriy Morozov.
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+***************************************************************************/
+
+#include <topology/rips.h>
+#include <topology/zigzag-persistence.h>
+#include <utilities/types.h>
+#include <utilities/containers.h>
+
+#include <geometry/l2distance.h>    // Point, PointContainer, L2DistanceType, read_points
+#include <geometry/distances.h>
+
+#include <utilities/log.h>
+#include <utilities/memory.h>       // for report_memory()
+#include <utilities/timer.h>
+
+#include <map>
+#include <cmath>
+#include <fstream>
+#include <stack>
+#include <cstdlib>
+
+#include <boost/tuple/tuple.hpp>
+#include <boost/program_options.hpp>
+#include <boost/progress.hpp>
+
+#ifdef COUNTERS
+static Counter*  cComplexSize =                     GetCounter("rips/size");
+static Counter*  cOperations =                      GetCounter("rips/operations");
+#endif // COUNTERS
+
+typedef     PairwiseDistances<PointContainer, L2Distance>           PairDistances;
+typedef     PairDistances::DistanceType                             DistanceType;
+
+typedef     PairDistances::IndexType                                Vertex;
+typedef     Simplex<Vertex>                                         Smplx;
+typedef     std::vector<Smplx>                                      SimplexVector;
+typedef     std::list<Smplx>                                        SimplexList;
+typedef     std::set<Smplx, Smplx::VertexDimensionComparison>       SimplexSet;
+
+typedef     std::vector<Vertex>                                     VertexVector;
+typedef     std::vector<DistanceType>                               EpsilonVector;
+typedef     std::vector<std::pair<Vertex, Vertex> >                 EdgeVector;
+
+typedef     Rips<PairDistances, Smplx>                              RipsGenerator;
+typedef     RipsGenerator::Evaluator                                SimplexEvaluator;
+
+struct      BirthInfo;
+typedef     ZigzagPersistence<BirthInfo>                            Zigzag;
+typedef     Zigzag::SimplexIndex                                    Index;
+typedef     Zigzag::Death                                           Death;
+typedef     std::map<Smplx, Index, 
+                            Smplx::VertexDimensionComparison>       Complex;
+typedef     Zigzag::ZColumn                                         Boundary;
+
+typedef     std::vector<std::list<std::pair<double, double> > >     IntervalsVector;
+
+// Information we need to know when a class dies
+struct      BirthInfo
+{
+                    BirthInfo(DistanceType dist = DistanceType(), Dimension dim = Dimension()):
+                        distance(dist), dimension(dim)              {}
+    DistanceType    distance;
+    Dimension       dimension;
+};
+
+// Forward declarations of auxilliary functions
+// Note: min_value is used only for log-scale, so set it up to zero by default
+void write_intervals(std::ostream& out, const IntervalsVector& intervals, int skeleton_dimension, bool logscale, double min_value=0);
+// void        report_death(std::ostream& out, Death d, DistanceType epsilon, Dimension skeleton_dimension);
+void        report_death(IntervalsVector& intervals, Death d, DistanceType epsilon, DistanceType birthEpsilon, Dimension skeleton_dimension);
+void        make_boundary(const Smplx& s, Complex& c, const Zigzag& zz, Boundary& b);
+std::ostream&   operator<<(std::ostream& out, const BirthInfo& bi);
+void        process_command_line_options(int           argc,
+                                         char*         argv[],
+                                         unsigned&     skeleton_dimension,
+                                         float&        multiplier,
+					 float&        discretization_factor,
+					 bool&         logscale,
+                                         std::string&  infilename,
+                                         std::string&  outfilename);
+
+int main(int argc, char* argv[])
+{
+#ifdef LOGGING
+    rlog::RLogInit(argc, argv);
+
+    stderrLog.subscribeTo( RLOG_CHANNEL("error") );
+#endif
+
+    Timer total, remove, add, ec, vc;
+    total.start();
+ 
+#if 0
+    SetFrequency(cOperations, 25000);
+    SetTrigger(cOperations, cComplexSize);
+#endif
+
+    unsigned        skeleton_dimension;
+    float           multiplier;
+    float           discretization_factor;
+    std::string     infilename, outfilename;
+    bool            logscale;
+    process_command_line_options(argc, argv, skeleton_dimension, multiplier, discretization_factor, logscale, infilename, outfilename);
+
+    // Read in points
+    PointContainer      points;
+    read_points(infilename, points);
+    
+    std::cout << "Number of points: " << points.size() << std::endl;
+
+    // Create output file
+    std::ofstream out(outfilename.c_str());
+
+    // Create pairwise distances
+    PairDistances distances(points);
+    
+    // Create intervals DS
+    IntervalsVector intervals(skeleton_dimension);
+    // for (int i=0; i<skeleton_dimension; i++)
+    //   intervals[i] = new std::list<std::pair<double, double> > ();
+
+    // Order vertices and epsilons (in maxmin fashion)
+    VertexVector        vertices;
+    EpsilonVector       epsilons;
+    EdgeVector          edges;
+
+    {
+        EpsilonVector   dist(distances.size(), Infinity);
+    
+        vertices.push_back(distances.begin());
+        //epsilons.push_back(Infinity);
+        while (vertices.size() < distances.size())
+        {
+            for (Vertex v = distances.begin(); v != distances.end(); ++v)
+                dist[v] = std::min(dist[v], distances(v, vertices.back()));
+            EpsilonVector::const_iterator max = std::max_element(dist.begin(), dist.end());
+            vertices.push_back(max - dist.begin());
+            epsilons.push_back(*max);
+        }
+        epsilons.push_back(0);
+    }
+
+    // Discretize sequence
+    unsigned anchor[vertices.size()];
+    anchor[0] = 0;
+    unsigned ref = 0;
+    // std::cout << "Anchors: 0 (" << epsilons[0] << ")";
+    for (unsigned i=0; i<vertices.size(); i++)
+      if (epsilons[i] < epsilons[anchor[ref]]*discretization_factor) {
+	anchor[i] = i;
+	ref = i;
+	// std::cout << " " << i << " (" << epsilons[i] << ")";
+      }
+      else
+	anchor[i] = ref;
+    // std::cout << std::endl;
+
+
+    rInfo("Point and epsilon ordering:");
+    for (unsigned i = 0; i < vertices.size(); ++i)
+        rInfo("  %4d: %4d - %f", i, vertices[i], epsilons[i]);
+
+    // Generate and sort all the edges
+    for (unsigned i = 0; i != vertices.size(); ++i)
+        for (unsigned j = i+1; j != vertices.size(); ++j)
+        {
+            Vertex u = vertices[i];
+            Vertex v = vertices[j];
+            if (distances(u,v) <= multiplier*epsilons[anchor[j-1]])
+                edges.push_back(std::make_pair(u,v));
+        }
+    std::sort(edges.begin(), edges.end(), RipsGenerator::ComparePair(distances));
+    std::cout << "Total participating edges: " << edges.size() << std::endl;
+    for (EdgeVector::const_iterator cur = edges.begin(); cur != edges.end(); ++cur)
+        rDebug("  (%d, %d) %f", cur->first, cur->second, distances(cur->first, cur->second));
+
+    // Construct zigzag
+    Complex             complex;
+    Zigzag              zz;
+    RipsGenerator       rips(distances);
+    SimplexEvaluator    size(distances);
+    
+    // Insert vertices (initial complex is just a disjoint union of vertices)
+    for (unsigned i = 0; i != vertices.size(); ++i)
+    {
+        // Add a vertex
+        Smplx sv; sv.add(vertices[i]);
+        rDebug("Adding %s", tostring(sv).c_str());
+        add.start();
+        complex.insert(std::make_pair(sv, 
+                                      zz.add(Boundary(), 
+                                             BirthInfo(0, 0)).first));
+        add.stop();
+        //rDebug("Newly born cycle order: %d", complex[sv]->low->order);
+        CountNum(cComplexSize, 0);
+        Count(cComplexSize);
+        Count(cOperations);
+    }
+
+    rInfo("Commencing computation");
+    boost::progress_display show_progress(vertices.size());
+    unsigned ce     = 0;        // index of the current one past last edge in the complex
+    for (unsigned stage = vertices.size()-1; stage > 0; stage = anchor[stage-1])
+    {
+      // std::cout << "Current stage " << stage << ": " 
+      // 	  << anchor[stage-1] << " " << epsilons[anchor[stage-1]] << " "
+      // 	  << multiplier*epsilons[anchor[stage-1]] << std::endl;
+      
+        /* Increase epsilon */
+        // Record the cofaces of all the simplices that need to be removed and r`einserted
+        SimplexSet cofaces;
+        rDebug("  Cofaces size: %d", cofaces.size());
+
+        // Add anything else that needs to be inserted into the complex
+        while (ce < edges.size())
+        {
+            Vertex u,v;
+            boost::tie(u,v)     = edges[ce];
+            if (distances(u,v) <= multiplier*epsilons[anchor[stage-1]])
+                ++ce;
+            else
+                break;
+            rDebug("  Recording cofaces of edges[%d]=(%d, %d) with size=%f", (ce-1), u, v, distances(u,v));
+            ec.start();
+            rips.edge_cofaces(u, v, 
+                              skeleton_dimension, 
+                              multiplier*epsilons[anchor[stage-1]], 
+                              make_insert_functor(cofaces),
+                              vertices.begin(),
+                              vertices.begin() + stage + 1);
+            ec.stop();
+        }
+        rDebug("  Recorded new cofaces to add");
+
+        // Insert all the cofaces
+        rDebug("  Cofaces size: %d", cofaces.size());
+        for (SimplexSet::const_iterator cur = cofaces.begin(); cur != cofaces.end(); ++cur)
+        {
+            Index idx; Death d; Boundary b;
+            rDebug("  Adding %s, its size %f", tostring(*cur).c_str(), size(*cur));
+            make_boundary(*cur, complex, zz, b);
+            add.start();
+            boost::tie(idx, d)  = zz.add(b,
+                                         BirthInfo(epsilons[anchor[stage-1]], cur->dimension()));
+            add.stop();
+            //if (!d) rDebug("Newly born cycle order: %d", complex[*cur]->low->order);
+            CountNum(cComplexSize, cur->dimension());
+            Count(cComplexSize);
+            Count(cOperations);
+            AssertMsg(zz.check_consistency(), "Zigzag representation must be consistent after removing a simplex");
+            complex.insert(std::make_pair(*cur, idx));
+            report_death(intervals, d, epsilons[anchor[stage-1]], epsilons[stage], skeleton_dimension);
+        }
+        rInfo("Increased epsilon; complex size: %d", complex.size());
+        report_memory();
+        
+        /* Remove the vertices */
+	for (unsigned i = stage; i>anchor[stage-1]; i--) {
+	  // std::cout << "removing vertex " << i << std::endl;
+	  cofaces.clear();
+	  rDebug("  Cofaces size: %d", cofaces.size());
+	  vc.start();
+	  rips.vertex_cofaces(vertices[i], 
+			      skeleton_dimension, 
+			      multiplier*epsilons[anchor[stage-1]], 
+			      make_insert_functor(cofaces),
+			      vertices.begin(),
+			      vertices.begin() + i + 1);
+	  vc.stop();
+	  rDebug("  Computed cofaces of the vertex, their number: %d", cofaces.size());
+	  for (SimplexSet::const_reverse_iterator cur = cofaces.rbegin(); cur != (SimplexSet::const_reverse_iterator)cofaces.rend(); ++cur)
+	    {
+	      rDebug("    Removing: %s", tostring(*cur).c_str());
+	      Complex::iterator si = complex.find(*cur);
+	      remove.start();
+	      Death d = zz.remove(si->second,
+				  BirthInfo(epsilons[anchor[stage-1]], cur->dimension() - 1));
+	      remove.stop();
+	      complex.erase(si);
+	      CountNumBy(cComplexSize, cur->dimension(), -1);
+	      CountBy(cComplexSize, -1);
+	      Count(cOperations);
+	      AssertMsg(zz.check_consistency(), "Zigzag representation must be consistent after removing a simplex");
+	      report_death(intervals, d, epsilons[anchor[stage-1]], epsilons[stage], skeleton_dimension);
+	    }
+	  rInfo("Removed vertex; complex size: %d", complex.size());
+	  for (Complex::const_iterator cur = complex.begin(); cur != complex.end(); ++cur)
+            rDebug("  %s", tostring(cur->first).c_str());
+	  report_memory();
+	  ++show_progress;
+	}
+    }
+    
+    // Remove the last vertex
+    // std::cout << "removing vertex 0" << std::endl;
+    if (complex.size() != 1) {
+      std::cerr << "Error: Only one vertex must remain" << std::endl;
+      abort();
+    }
+    remove.start();
+    Death d = zz.remove(complex.begin()->second, BirthInfo(epsilons[0], -1));
+    remove.stop();
+    complex.erase(complex.begin());
+    if (!d)  AssertMsg(false,  "The vertex must have died");
+    report_death(intervals, d, epsilons[0], epsilons[0], skeleton_dimension);
+    CountNumBy(cComplexSize, 0, -1);
+    CountBy(cComplexSize, -1);
+    Count(cOperations);
+    rInfo("Removed vertex; complex size: %d", complex.size());
+    ++show_progress;
+
+    total.stop();
+
+    remove.check("Remove timer          ");
+    add.check   ("Add timer             ");
+    ec.check    ("Edge coface timer     ");
+    vc.check    ("Vertex coface timer   ");
+    total.check ("Total timer           ");
+
+    std::cout << "Writing intervals...";
+    // Note (hack): use epsilons[vertices.size()-2]/2 as minimal value for the log-scale intervals to avoid intervals starting at -infinity and thus a scaling effect
+    write_intervals(out, intervals, skeleton_dimension, logscale, epsilons[vertices.size()-2]/2);
+    std::cout << " done." << std::endl;
+}
+
+
+const double LOG2 = std::log(2.0);
+double log2(double x) {
+  return std::log(x) / LOG2;
+}
+
+void write_intervals(std::ostream& out, const IntervalsVector& intervals, int skeleton_dimension, bool logscale, double min_value) {
+  out << "I = { ";
+    for (int d = 0; d<skeleton_dimension; d++) {
+      out << "[ ";
+      for (std::list<std::pair<double,double> >::const_iterator pit = intervals[d].begin(); pit != intervals[d].end(); pit++)
+	if (logscale)
+	  out << "[" << log2(std::max(pit->first, min_value)) << ";" << log2(std::max(pit->second, min_value)) << "] ";
+	else
+	  out << "[" << pit->first << ";" << pit->second << "] ";
+
+      // add dummy interval if intervals list is empty
+      if (intervals[d].empty())
+	out << "[0;0] ";
+      out << "] ,";
+    }
+    out << "} ";
+} 
+            
+void        report_death(IntervalsVector& intervals, Death d, DistanceType epsilon, DistanceType birthEpsilon, Dimension skeleton_dimension)
+{
+  // std::cerr << "   d = " << d;
+  // if (d)
+  //   std::cerr << "   d->dim = " << d->dimension 
+  // 	      << "   d->dist = " << d->distance;
+  // std::cerr << "   epsilon = " << epsilon << std::endl;
+
+  if (d && ((d->distance - epsilon) != 0) && (d->dimension < skeleton_dimension))
+    intervals[d->dimension].push_back(std::pair<double,double>(d->distance, birthEpsilon));
+}
+
+void        make_boundary(const Smplx& s, Complex& c, const Zigzag& zz, Boundary& b)
+{
+    rDebug("  Boundary of <%s>", tostring(s).c_str());
+    for (Smplx::BoundaryIterator cur = s.boundary_begin(); cur != s.boundary_end(); ++cur)
+    {
+        b.append(c[*cur], zz.cmp);
+        rDebug("   %d", c[*cur]->order);
+    }
+}
+
+std::ostream&   operator<<(std::ostream& out, const BirthInfo& bi)
+{ return (out << bi.distance); }
+
+void        process_command_line_options(int           argc, 
+                                         char*         argv[],
+                                         unsigned&     skeleton_dimension,
+                                         float&        multiplier,
+                                         float&        discretization_factor,
+					 bool&         logscale,
+                                         std::string&  infilename,
+                                         std::string&  outfilename)
+{
+    namespace po = boost::program_options;
+
+    po::options_description hidden("Hidden options");
+    hidden.add_options()
+        ("input-file",          po::value<std::string>(&infilename),        "Point set whose Rips zigzag we want to compute")
+        ("output-file",         po::value<std::string>(&outfilename),       "Location to save persistence pairs");
+    
+    po::options_description visible("Allowed options", 100);
+    visible.add_options()
+        ("help,h",                                                                              "produce help message")
+        ("dim,d", po::value<unsigned>(&skeleton_dimension)->default_value(3),     "maximal dimension of the Rips complex")
+        ("rho,r",        po::value<float>(&multiplier)->default_value(3),                "multiplier rho used in the Rips parameter")
+      ("zeta,z",        po::value<float>(&discretization_factor)->default_value(1),                "geometric scale gap in the discretization (cst<=1)")
+      ( "logscale,l" , po::value( &logscale )->zero_tokens(), "outputs interval bounds on log_2 scale" ) ;
+#if LOGGING
+    std::vector<std::string>    log_channels;
+    visible.add_options()
+        ("log,l",               po::value< std::vector<std::string> >(&log_channels),           "log channels to turn on (info, debug, etc)");
+#endif
+
+    po::positional_options_description pos;
+    pos.add("input-file", 1);
+    pos.add("output-file", 2);
+    
+    po::options_description all; all.add(visible).add(hidden);
+
+    po::variables_map vm;
+    po::store(po::command_line_parser(argc, argv).
+                  options(all).positional(pos).run(), vm);
+    po::notify(vm);
+
+#if LOGGING
+    for (std::vector<std::string>::const_iterator cur = log_channels.begin(); cur != log_channels.end(); ++cur)
+        stderrLog.subscribeTo( RLOG_CHANNEL(cur->c_str()) );
+    /**
+     * Interesting channels
+     * "info", "debug", "topology/persistence"
+     */
+#endif
+
+    if (vm.count("help") || !vm.count("input-file") || !vm.count("output-file"))
+    { 
+        std::cout << "Usage: " << argv[0] << " [options] input-file output-file" << std::endl;
+        std::cout << visible << std::endl; 
+        std::abort();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/homology-zigzags/iR-ZZ.cpp	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,525 @@
+/***************************************************************************
+
+    iR-ZZ: image Rips zigzag implementation
+    Copyright (C) 2009-2012   Dmitriy Morozov
+
+    Adapted from its original version ("rips-image-zigzag.cpp" in
+    the Dionysus library) by Steve Oudot (2012).
+
+    Changelog (2012-11-22):
+
+       - the barcode is now output on a log scale and in a format that is 
+         compatible with the Matlab layer of the PLEX 2.5 library,
+
+       - the barcode representation is now by closed intervals instead of 
+         half-open intervals.
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+***************************************************************************/
+
+#include <topology/rips.h>
+#include <topology/image-zigzag-persistence.h>
+#include <utilities/types.h>
+#include <utilities/containers.h>
+
+#include <utilities/log.h>
+#include <utilities/memory.h>       // for report_memory()
+#include <utilities/timer.h>
+
+#include <geometry/l2distance.h>    // for L2Distance and read_points()
+#include <geometry/distances.h>
+
+#include <map>
+#include <cmath>
+#include <fstream>
+#include <stack>
+#include <cstdlib>
+
+#include <boost/tuple/tuple.hpp>
+#include <boost/program_options.hpp>
+#include <boost/progress.hpp>
+
+
+#ifdef COUNTERS
+static Counter*  cComplexSize =                     GetCounter("rips/size");
+static Counter*  cOperations =                      GetCounter("rips/operations");
+#endif // COUNTERS
+
+typedef     PairwiseDistances<PointContainer, L2Distance>           PairDistances;
+typedef     PairDistances::DistanceType                             DistanceType;
+
+typedef     PairDistances::IndexType                                Vertex;
+typedef     Simplex<Vertex>                                         Smplx;
+typedef     std::vector<Smplx>                                      SimplexVector;
+typedef     std::list<Smplx>                                        SimplexList;
+typedef     std::set<Smplx, Smplx::VertexDimensionComparison>       SimplexSet;
+
+typedef     std::vector<Vertex>                                     VertexVector;
+typedef     std::vector<DistanceType>                               EpsilonVector;
+typedef     std::vector<std::pair<Vertex, Vertex> >                 EdgeVector;
+
+typedef     Rips<PairDistances, Smplx>                              RipsGenerator;
+typedef     RipsGenerator::Evaluator                                SimplexEvaluator;
+
+struct      BirthInfo;
+typedef     ImageZigzagPersistence<BirthInfo>                       Zigzag;
+typedef     Zigzag::SimplexIndex                                    Index;
+typedef     Zigzag::Death                                           Death;
+typedef     std::map<Smplx, Index, 
+                            Smplx::VertexDimensionComparison>       Complex;
+typedef     Zigzag::ZColumn                                         Boundary;
+
+typedef     std::vector<std::list<std::pair<double, double> > >     IntervalsVector;
+
+// Information we need to know when a class dies
+struct      BirthInfo
+{
+                    BirthInfo(DistanceType dist = DistanceType(), Dimension dim = Dimension()):
+                        distance(dist), dimension(dim)              {}
+    DistanceType    distance;
+    Dimension       dimension;
+};
+
+// Forward declarations of auxilliary functions
+// Note: min_value is used only for log-scale, so set it up to zero by default
+void write_intervals(std::ostream& out, const IntervalsVector& intervals, int skeleton_dimension, bool logscale, double min_value=0);
+void        report_death(IntervalsVector& intervals, Death d, DistanceType epsilon, DistanceType birthEpsilon, Dimension skeleton_dimension);
+// void        report_death(std::ofstream& out, Death d, DistanceType epsilon, Dimension skeleton_dimension);
+void        make_boundary(const Smplx& s, Complex& c, const Zigzag& zz, Boundary& b);
+void        show_image_betti(Zigzag& zz, Dimension skeleton);
+std::ostream&   operator<<(std::ostream& out, const BirthInfo& bi);
+void        process_command_line_options(int           argc,
+                                         char*         argv[],
+                                         unsigned&     skeleton_dimension,
+                                         float&        from_multiplier, 
+                                         float&        to_multiplier,
+					 bool&         logscale,
+                                         std::string&  infilename,
+                                         std::string&  outfilename);
+
+int main(int argc, char* argv[])
+{
+#ifdef LOGGING
+    rlog::RLogInit(argc, argv);
+
+    stderrLog.subscribeTo( RLOG_CHANNEL("error") );
+#endif
+
+    Timer total, remove, add, ec, vc;
+    total.start();
+ 
+#if 0
+    SetFrequency(cOperations, 25000);
+    SetTrigger(cOperations, cComplexSize);
+#endif
+
+    unsigned        skeleton_dimension;
+    float           from_multiplier, to_multiplier;
+    std::string     infilename, outfilename;
+    bool            logscale = false;
+    process_command_line_options(argc, argv, skeleton_dimension, from_multiplier, to_multiplier, logscale, infilename, outfilename);
+
+    // Read in points
+    PointContainer      points;
+    read_points(infilename, points);
+    
+    // Create output file
+    std::ofstream out(outfilename.c_str());
+
+    // Create pairwise distances
+    PairDistances distances(points);
+    
+    // Create intervals DS
+    IntervalsVector intervals(skeleton_dimension);
+    // for (int i=0; i<skeleton_dimension; i++)
+    //   intervals[i] = new std::list<std::pair<double, double> > ();
+
+    // Order vertices and epsilons (in maxmin fashion)
+    VertexVector        vertices;
+    EpsilonVector       epsilons;
+    EdgeVector          edges;
+
+    {
+        EpsilonVector   dist(distances.size(), Infinity);
+    
+        vertices.push_back(distances.begin());
+        //epsilons.push_back(Infinity);
+        while (vertices.size() < distances.size())
+        {
+            for (Vertex v = distances.begin(); v != distances.end(); ++v)
+                dist[v] = std::min(dist[v], distances(v, vertices.back()));
+            EpsilonVector::const_iterator max = std::max_element(dist.begin(), dist.end());
+            vertices.push_back(max - dist.begin());
+            epsilons.push_back(*max);
+        }
+        epsilons.push_back(0);
+    }
+
+    rInfo("Point and epsilon ordering:");
+    for (unsigned i = 0; i < vertices.size(); ++i)
+        rInfo("  %4d: %4d - %f", i, vertices[i], epsilons[i]);
+
+    // Generate and sort all the edges
+    for (unsigned i = 0; i != vertices.size(); ++i)
+        for (unsigned j = i+1; j != vertices.size(); ++j)
+        {
+            Vertex u = vertices[i];
+            Vertex v = vertices[j];
+            if (distances(u,v) <= to_multiplier*epsilons[j-1])
+                edges.push_back(std::make_pair(u,v));
+        }
+    std::sort(edges.begin(), edges.end(), RipsGenerator::ComparePair(distances));
+    rInfo("Total participating edges: %d", edges.size());
+    for (EdgeVector::const_iterator cur = edges.begin(); cur != edges.end(); ++cur)
+        rDebug("  (%d, %d) %f", cur->first, cur->second, distances(cur->first, cur->second));
+
+    // Construct zigzag
+    Complex             complex;
+    Zigzag              zz;
+    RipsGenerator       rips(distances);
+    SimplexEvaluator    size(distances);
+    
+    // Insert vertices
+    for (unsigned i = 0; i != vertices.size(); ++i)
+    {
+        // Add a vertex
+        Smplx sv; sv.add(vertices[i]);
+        rDebug("Adding %s", tostring(sv).c_str());
+        add.start();
+        complex.insert(std::make_pair(sv, 
+                                      zz.add(Boundary(), 
+                                             true,         // vertex is always in the subcomplex
+                                             BirthInfo(0, 0)).first));
+        add.stop();
+        //rDebug("Newly born cycle order: %d", complex[sv]->low->order);
+        CountNum(cComplexSize, 0);
+        Count(cComplexSize);
+        Count(cOperations);
+    }
+
+    rInfo("Commencing computation");
+    boost::progress_display show_progress(vertices.size());
+    unsigned sce    = 0,        // index of the current one past last edge in the subcomplex
+             ce     = 0;        // index of the current one past last edge in the complex
+    for (unsigned stage = 0; stage != vertices.size() - 1; ++stage)
+    {
+        unsigned i = vertices.size() - 1 - stage;
+        rInfo("Current stage %d: %d %f: %f -> %f", stage, 
+                                                   vertices[i], epsilons[i-1],
+                                                   from_multiplier*epsilons[i-1],
+                                                   to_multiplier*epsilons[i-1]);
+
+        /* Increase epsilon */
+        // Record the cofaces of all the simplices that need to be removed and reinserted
+        SimplexSet cofaces;
+        rDebug("  Cofaces size: %d", cofaces.size());
+        while(sce < ce)
+        {
+            Vertex u,v;
+            boost::tie(u,v)     = edges[sce];
+            if (distances(u,v) <= from_multiplier*epsilons[i-1])
+                ++sce;
+            else
+                break;
+
+            // Skip an edge if any one of its vertices has been removed from the complex
+            bool skip_edge = false;
+            for (unsigned j = i+1; j != vertices.size(); ++j)
+                if (u == vertices[j] || v == vertices[j])
+                {
+                    // Debug only: eventually remove
+                    rDebug("  Skipping edge (%d, %d)", u, v);
+                    Smplx s; s.add(u); s.add(v);
+                    AssertMsg(complex.find(s) == complex.end(), "Simplex should not be in the complex.");
+                    skip_edge = true;
+                    break;
+                }
+            if (skip_edge) continue;
+            rDebug("  Generating cofaces for (%d, %d)", u, v);
+        
+            ec.start();
+            rips.edge_cofaces(u, v, 
+                              skeleton_dimension, 
+                              to_multiplier*epsilons[i], 
+                              make_insert_functor(cofaces),
+                              vertices.begin(),
+                              vertices.begin() + i + 1);
+            ec.stop();
+        }
+        rDebug("  Recorded cofaces to remove");
+        rDebug("  Cofaces size: %d", cofaces.size());
+        // Remove all the cofaces
+        for (SimplexSet::const_reverse_iterator cur = cofaces.rbegin(); cur != (SimplexSet::const_reverse_iterator)cofaces.rend(); ++cur)
+        {
+            rDebug("    Removing %s", tostring(*cur).c_str());
+            Complex::iterator si = complex.find(*cur);
+            remove.start();
+            AssertMsg(!si->second->subcomplex, "We should not remove simplices already in the subcomplex when we increase epsilon");
+            Death d = zz.remove(si->second,
+                                BirthInfo(epsilons[i-1], cur->dimension() - 1));
+            remove.stop();
+            complex.erase(si);
+            CountNumBy(cComplexSize, cur->dimension(), -1);
+            CountBy(cComplexSize, -1);
+            Count(cOperations);
+            AssertMsg(zz.check_consistency(), "Zigzag representation must be consistent after removing a simplex");
+            report_death(intervals, d, epsilons[i-1], epsilons[i], skeleton_dimension);
+        }
+        rDebug("  Removed cofaces");
+
+        // Add anything else that needs to be inserted into the complex
+        while (ce < edges.size())
+        {
+            Vertex u,v;
+            boost::tie(u,v)     = edges[ce];
+            if (distances(u,v) <= to_multiplier*epsilons[i-1])
+                ++ce;
+            else
+                break;
+            rDebug("  Recording cofaces of edges[%d]=(%d, %d) with size=%f", (ce-1), u, v, distances(u,v));
+            ec.start();
+            rips.edge_cofaces(u, v, 
+                              skeleton_dimension, 
+                              to_multiplier*epsilons[i-1], 
+                              make_insert_functor(cofaces),
+                              vertices.begin(),
+                              vertices.begin() + i + 1);
+            ec.stop();
+        }
+        rDebug("  Recorded new cofaces to add");
+
+        // Progress sce
+        while (sce < ce)
+        {
+            Vertex u,v;
+            boost::tie(u,v)     = edges[sce];
+            rDebug("    Progressing sce=%d over (%d, %d) %f", sce, u, v, distances(u,v));
+            if (distances(u,v) <= from_multiplier*epsilons[i-1])   
+                ++sce;
+            else
+                break;
+        }
+        rDebug("  Moved subcomplex index forward");
+
+        // Insert all the cofaces
+        rDebug("  Cofaces size: %d", cofaces.size());
+        for (SimplexSet::const_iterator cur = cofaces.begin(); cur != cofaces.end(); ++cur)
+        {
+            Index idx; Death d; Boundary b;
+            rDebug("  Adding %s, its size %f", tostring(*cur).c_str(), size(*cur));
+            make_boundary(*cur, complex, zz, b);
+            add.start();
+            boost::tie(idx, d)  = zz.add(b,
+                                         size(*cur) <= from_multiplier*epsilons[i-1],
+                                         BirthInfo(epsilons[i-1], cur->dimension()));
+            add.stop();
+            //if (!d) rDebug("Newly born cycle order: %d", complex[*cur]->low->order);
+            CountNum(cComplexSize, cur->dimension());
+            Count(cComplexSize);
+            Count(cOperations);
+            AssertMsg(zz.check_consistency(), "Zigzag representation must be consistent after removing a simplex");
+            complex.insert(std::make_pair(*cur, idx));
+            report_death(intervals, d, epsilons[i-1], epsilons[i], skeleton_dimension);
+        }
+        rInfo("Increased epsilon; complex size: %d", complex.size());
+        show_image_betti(zz, skeleton_dimension);
+        report_memory();
+        
+        /* Remove the vertex */
+        cofaces.clear();
+        rDebug("  Cofaces size: %d", cofaces.size());
+        vc.start();
+        rips.vertex_cofaces(vertices[i], 
+                            skeleton_dimension, 
+                            to_multiplier*epsilons[i-1], 
+                            make_insert_functor(cofaces),
+                            vertices.begin(),
+                            vertices.begin() + i + 1);
+        vc.stop();
+        rDebug("  Computed cofaces of the vertex, their number: %d", cofaces.size());
+        for (SimplexSet::const_reverse_iterator cur = cofaces.rbegin(); cur != (SimplexSet::const_reverse_iterator)cofaces.rend(); ++cur)
+        {
+            rDebug("    Removing: %s", tostring(*cur).c_str());
+            Complex::iterator si = complex.find(*cur);
+            remove.start();
+            Death d = zz.remove(si->second,
+                                BirthInfo(epsilons[i-1], cur->dimension() - 1));
+            remove.stop();
+            complex.erase(si);
+            CountNumBy(cComplexSize, cur->dimension(), -1);
+            CountBy(cComplexSize, -1);
+            Count(cOperations);
+            AssertMsg(zz.check_consistency(), "Zigzag representation must be consistent after removing a simplex");
+            report_death(intervals, d, epsilons[i-1], epsilons[i], skeleton_dimension);
+        }
+        rInfo("Removed vertex; complex size: %d", complex.size());
+        for (Complex::const_iterator cur = complex.begin(); cur != complex.end(); ++cur)
+            rDebug("  %s", tostring(cur->first).c_str());
+        show_image_betti(zz, skeleton_dimension);
+        report_memory();
+        
+        ++show_progress;
+    }
+    
+    // Remove the last vertex
+    AssertMsg(complex.size() == 1, "Only one vertex must remain");
+    remove.start();
+    Death d = zz.remove(complex.begin()->second, BirthInfo(epsilons[0], -1));
+    remove.stop();
+    complex.erase(complex.begin());
+    if (!d)  AssertMsg(false,  "The vertex must have died");
+    report_death(intervals, d, epsilons[0], epsilons[0], skeleton_dimension);
+    CountNumBy(cComplexSize, 0, -1);
+    CountBy(cComplexSize, -1);
+    Count(cOperations);
+    rInfo("Removed vertex; complex size: %d", complex.size());
+    ++show_progress;
+
+    total.stop();
+
+    remove.check("Remove timer          ");
+    add.check   ("Add timer             ");
+    ec.check    ("Edge coface timer     ");
+    vc.check    ("Vertex coface timer   ");
+    total.check ("Total timer           ");
+
+    std::cout << "Writing intervals...";
+    // Note (hack): use epsilons[vertices.size()-2]/2 as minimal value for the log-scale intervals to avoid intervals starting at -infinity and thus a scaling effect
+    write_intervals(out, intervals, skeleton_dimension, logscale, epsilons[vertices.size()-2]/2);
+    std::cout << " done." << std::endl;
+}
+
+
+void write_intervals(std::ostream& out, const IntervalsVector& intervals, int skeleton_dimension, bool logscale, double min_value) {
+  out << "I = { ";
+    for (int d = 0; d<skeleton_dimension; d++) {
+      out << "[ ";
+      for (std::list<std::pair<double,double> >::const_iterator pit = intervals[d].begin(); pit != intervals[d].end(); pit++)
+	if (logscale)
+	  out << "[" << log2(std::max(pit->first, min_value)) << ";" << log2(std::max(pit->second, min_value)) << "] ";
+	else
+	  out << "[" << pit->first << ";" << pit->second << "] ";
+
+      // add dummy interval if intervals list is empty
+      if (intervals[d].empty())
+	out << "[0;0] ";
+      out << "] ,";
+    }
+    out << "} ";
+} 
+            
+void        report_death(IntervalsVector& intervals, Death d, DistanceType epsilon, DistanceType birthEpsilon, Dimension skeleton_dimension)
+{
+  // std::cerr << "   d = " << d;
+  // if (d)
+  //   std::cerr << "   d->dim = " << d->dimension 
+  // 	      << "   d->dist = " << d->distance;
+  // std::cerr << "   epsilon = " << epsilon << std::endl;
+
+  if (d && ((d->distance - epsilon) != 0) && (d->dimension < skeleton_dimension))
+    intervals[d->dimension].push_back(std::pair<double,double>(d->distance, birthEpsilon));
+}
+
+void        make_boundary(const Smplx& s, Complex& c, const Zigzag& zz, Boundary& b)
+{
+    rDebug("  Boundary of <%s>", tostring(s).c_str());
+    for (Smplx::BoundaryIterator cur = s.boundary_begin(); cur != s.boundary_end(); ++cur)
+    {
+        b.append(c[*cur], zz.cmp);
+        rDebug("   %d (inL=%d)", c[*cur]->order, b.back()->subcomplex);
+    }
+}
+
+bool        face_leaving_subcomplex(Complex::reverse_iterator si, const SimplexEvaluator& size, DistanceType after, DistanceType before)
+{
+    const Smplx& s = si->first;
+    for (Smplx::VertexContainer::const_iterator v1 = s.vertices().begin(); v1 != s.vertices().end(); ++v1)
+        for (Smplx::VertexContainer::const_iterator v2 = boost::next(v1); v2 != s.vertices().end(); ++v2)
+        {
+            Smplx e; e.add(*v1); e.add(*v2);
+            if (size(e) > after && size(e) <= before)
+                return true;
+        }
+
+    return false;
+}
+
+void        show_image_betti(Zigzag& zz, Dimension skeleton)
+{
+    for (Zigzag::ZIndex cur = zz.image_begin(); cur != zz.image_end(); ++cur)
+        if (cur->low == zz.boundary_end() && cur->birth.dimension < skeleton)
+            rInfo("Class in the image of dimension: %d",  cur->birth.dimension);
+}
+
+
+std::ostream&   operator<<(std::ostream& out, const BirthInfo& bi)
+{ return (out << bi.distance); }
+
+void        process_command_line_options(int           argc, 
+                                         char*         argv[],
+                                         unsigned&     skeleton_dimension,
+                                         float&        from_multiplier, 
+                                         float&        to_multiplier,
+					 bool&         logscale,
+                                         std::string&  infilename,
+                                         std::string&  outfilename)
+{
+    namespace po = boost::program_options;
+
+    po::options_description hidden("Hidden options");
+    hidden.add_options()
+        ("input-file",          po::value<std::string>(&infilename),        "Point set whose Rips zigzag we want to compute")
+        ("output-file",         po::value<std::string>(&outfilename),       "Location to save persistence pairs");
+    
+    po::options_description visible("Allowed options", 100);
+    visible.add_options()
+        ("help,h",                                                                              "produce help message")
+        ("dim,d", po::value<unsigned>(&skeleton_dimension)->default_value(3),     "maximal dimension of the Rips complex")
+        ("eta,e",        po::value<float>(&from_multiplier)->default_value(3),                "multiplier eta used in the Rips parameter")
+        ("rho,r",        po::value<float>(&to_multiplier)->default_value(3),                "multiplier rho used in the Rips parameter")
+      ( "logscale,l" , po::value<bool>(&logscale)->zero_tokens(), "outputs interval bounds on log_2 scale" ) ;
+#if LOGGING
+    std::vector<std::string>    log_channels;
+    visible.add_options()
+        ("log,l",               po::value< std::vector<std::string> >(&log_channels),           "log channels to turn on (info, debug, etc)");
+#endif
+
+    po::positional_options_description pos;
+    pos.add("input-file", 1);
+    pos.add("output-file", 2);
+    
+    po::options_description all; all.add(visible).add(hidden);
+
+    po::variables_map vm;
+    po::store(po::command_line_parser(argc, argv).
+                  options(all).positional(pos).run(), vm);
+    po::notify(vm);
+
+#if LOGGING
+    for (std::vector<std::string>::const_iterator cur = log_channels.begin(); cur != log_channels.end(); ++cur)
+        stderrLog.subscribeTo( RLOG_CHANNEL(cur->c_str()) );
+    /**
+     * Interesting channels
+     * "info", "debug", "topology/persistence"
+     */
+#endif
+
+    if (vm.count("help") || !vm.count("input-file") || !vm.count("output-file"))
+    { 
+        std::cout << "Usage: " << argv[0] << " [options] input-file output-file" << std::endl;
+        std::cout << visible << std::endl; 
+        std::abort();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/homology-zigzags/oR-ZZ.cpp	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,502 @@
+/***************************************************************************
+
+    oR-ZZ: oscillating Rips zigzag implementation
+    Copyright (C) 2012   Steve Oudot
+
+    Adapted from the Morozov zigzag implementation provided in the
+    Rips package of the Dionysus library (see the file "M-ZZ.cpp").
+    The Dionysus library is (C) 2006-2012 Dmitriy Morozov.
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+***************************************************************************/
+
+#include <topology/rips.h>
+#include <topology/zigzag-persistence.h>
+#include <utilities/types.h>
+#include <utilities/containers.h>
+
+#include <geometry/l2distance.h>    // Point, PointContainer, L2DistanceType, read_points
+#include <geometry/distances.h>
+
+#include <utilities/log.h>
+#include <utilities/memory.h>       // for report_memory()
+#include <utilities/timer.h>
+
+#include <map>
+#include <cmath>
+#include <fstream>
+#include <stack>
+#include <cstdlib>
+
+#include <boost/tuple/tuple.hpp>
+#include <boost/program_options.hpp>
+#include <boost/progress.hpp>
+
+#ifdef COUNTERS
+static Counter*  cComplexSize =                     GetCounter("rips/size");
+static Counter*  cOperations =                      GetCounter("rips/operations");
+#endif // COUNTERS
+
+typedef     PairwiseDistances<PointContainer, L2Distance>           PairDistances;
+typedef     PairDistances::DistanceType                             DistanceType;
+
+typedef     PairDistances::IndexType                                Vertex;
+typedef     Simplex<Vertex>                                         Smplx;
+typedef     std::vector<Smplx>                                      SimplexVector;
+typedef     std::list<Smplx>                                        SimplexList;
+typedef     std::set<Smplx, Smplx::VertexDimensionComparison>       SimplexSet;
+
+typedef     std::vector<Vertex>                                     VertexVector;
+typedef     std::vector<DistanceType>                               EpsilonVector;
+typedef     std::vector<std::pair<Vertex, Vertex> >                 EdgeVector;
+
+typedef     Rips<PairDistances, Smplx>                              RipsGenerator;
+typedef     RipsGenerator::Evaluator                                SimplexEvaluator;
+
+struct      BirthInfo;
+typedef     ZigzagPersistence<BirthInfo>                            Zigzag;
+typedef     Zigzag::SimplexIndex                                    Index;
+typedef     Zigzag::Death                                           Death;
+typedef     std::map<Smplx, Index, 
+                            Smplx::VertexDimensionComparison>       Complex;
+typedef     Zigzag::ZColumn                                         Boundary;
+
+typedef     std::vector<std::list<std::pair<double, double> > >     IntervalsVector;
+
+// Information we need to know when a class dies
+struct      BirthInfo
+{
+                    BirthInfo(DistanceType dist = DistanceType(), Dimension dim = Dimension()):
+                        distance(dist), dimension(dim)              {}
+    DistanceType    distance;
+    Dimension       dimension;
+};
+
+// Forward declarations of auxilliary functions
+void write_intervals(std::ostream& out, const IntervalsVector& intervals, int skeleton_dimension, bool logscale, double min_value=0);
+// void        report_death(std::ostream& out, Death d, DistanceType epsilon, Dimension skeleton_dimension);
+void        report_death(IntervalsVector& intervals, Death d, DistanceType epsilon, DistanceType birthEpsilon, Dimension skeleton_dimension);
+void        make_boundary(const Smplx& s, Complex& c, const Zigzag& zz, Boundary& b);
+std::ostream&   operator<<(std::ostream& out, const BirthInfo& bi);
+void        process_command_line_options(int           argc,
+                                         char*         argv[],
+                                         unsigned&     skeleton_dimension,
+                                         float&        eta,
+					 float&        rho,
+					 bool&         logscale,
+                                         std::string&  infilename,
+                                         std::string&  outfilename);
+
+int main(int argc, char* argv[])
+{
+
+#ifdef LOGGING
+    rlog::RLogInit(argc, argv);
+
+    stderrLog.subscribeTo( RLOG_CHANNEL("error") );
+#endif
+
+    Timer total, remove, add, ec, vc;
+    total.start();
+ 
+#if 0
+    SetFrequency(cOperations, 25000);
+    SetTrigger(cOperations, cComplexSize);
+#endif
+
+    unsigned        skeleton_dimension;
+    float           eta;
+    float           rho;
+    bool            logscale = false;
+    std::string     infilename, outfilename;
+    process_command_line_options(argc, argv, skeleton_dimension, eta, rho, logscale, infilename, outfilename);
+
+    // Read in points
+    PointContainer      points;
+    read_points(infilename, points);
+    
+    std::cout << "Number of points: " << points.size() << std::endl;
+
+    // Create output file
+    std::ofstream out(outfilename.c_str());
+
+    // Create pairwise distances
+    PairDistances distances(points);
+    
+    // Create intervals DS
+    IntervalsVector intervals(skeleton_dimension);
+
+    // Order vertices and epsilons (in maxmin fashion)
+    VertexVector        vertices;
+    EpsilonVector       epsilons;
+    EdgeVector          edges;
+
+    {
+        EpsilonVector   dist(distances.size(), Infinity);
+    
+        vertices.push_back(distances.begin());
+        //epsilons.push_back(Infinity);
+        while (vertices.size() < distances.size())
+        {
+            for (Vertex v = distances.begin(); v != distances.end(); ++v)
+                dist[v] = std::min(dist[v], distances(v, vertices.back()));
+            EpsilonVector::const_iterator max = std::max_element(dist.begin(), dist.end());
+            vertices.push_back(max - dist.begin());
+            epsilons.push_back(*max);
+        }
+        epsilons.push_back(0);
+    }
+
+    rInfo("Point and epsilon ordering:");
+    for (unsigned i = 0; i < vertices.size(); ++i)
+        rInfo("  %4d: %4d - %f", i, vertices[i], epsilons[i]);
+
+    // Generate and sort all the edges
+    for (unsigned i = 0; i != vertices.size(); ++i)
+        for (unsigned j = i+1; j != vertices.size(); ++j)
+        {
+            Vertex u = vertices[i];
+            Vertex v = vertices[j];
+            if (distances(u,v) <= rho*epsilons[j-1])
+                edges.push_back(std::make_pair(u,v));
+        }
+    std::sort(edges.begin(), edges.end(), RipsGenerator::ComparePair(distances));
+    std::cout << "Total participating edges: " << edges.size() << std::endl;
+    for (EdgeVector::const_iterator cur = edges.begin(); cur != edges.end(); ++cur)
+        rDebug("  (%d, %d) %f", cur->first, cur->second, distances(cur->first, cur->second));
+
+    // Construct zigzag
+    Complex             complex;
+    Zigzag              zz;
+    RipsGenerator       rips(distances);
+    SimplexEvaluator    size(distances);
+    
+    // Insert vertices (initial complex is just a disjoint union of vertices)
+    for (unsigned i = 0; i != vertices.size(); ++i)
+    {
+        // Add a vertex
+        Smplx sv; sv.add(vertices[i]);
+        rDebug("Adding %s", tostring(sv).c_str());
+        add.start();
+        complex.insert(std::make_pair(sv, 
+                                      zz.add(Boundary(), 
+                                             BirthInfo(0, 0)).first));
+        add.stop();
+        //rDebug("Newly born cycle order: %d", complex[sv]->low->order);
+        CountNum(cComplexSize, 0);
+        Count(cComplexSize);
+        Count(cOperations);
+    }
+
+    rInfo("Commencing computation");
+    // std::cerr << std::setprecision(15);
+    bool erased[vertices.size()];
+    for (unsigned i = 0; i<vertices.size(); i++)
+      erased[i] = false;
+    boost::progress_display show_progress(vertices.size());
+    unsigned ce     = 0;        // index of the current one past last edge in the complex
+    for (unsigned stage = 0; stage != vertices.size() - 1; ++stage)
+    {
+        unsigned i = vertices.size() - 1 - stage;
+
+        /* Increase epsilon */
+        // Record the cofaces of all the simplices that need to be removed and reinserted
+        SimplexSet cofaces, large_cofaces, tmp_cofaces;
+        rDebug("  Cofaces size: %d", cofaces.size());
+	// std::cerr << "Cofaces sizes: " << cofaces.size() << " "
+	// 	 << large_cofaces.size() << " "
+	// 	 << tmp_cofaces.size() << std::endl;
+
+        // Add anything else that needs to be inserted into the complex
+	unsigned cee = ce;
+	bool ce_set = false;
+
+	// if (stage > 0) {
+	//   std::cerr << "Stage " << stage << " :";
+	//   Vertex u,v;
+	//   boost::tie(u,v)     = edges[cee-1];
+	//   std::cerr << distances(u,v) << " <= " << multiplier*epsilons[i];
+	//   boost::tie(u,v)     = edges[cee];
+	//   std::cerr << " < " << distances(u,v) << " <= "
+	// 	    << epsilons[i-1] << std::endl
+	// 	    << "  vertices[i] = " << vertices[i] << std::endl
+	// 	    << "  vertices[i+1] = " << vertices[i+1] << std::endl;
+	// }
+
+	// if (stage > 0)
+	//   std::cerr << "Stage " << stage << " :" << std::endl;
+
+        while (cee < edges.size())
+        {
+            Vertex u,v;
+            boost::tie(u,v)     = edges[cee];
+	    // if (stage > 0 && (u == vertices[i+1] || v == vertices[i+1]))
+	    // 	std::cerr << "ATTENTION: [" << u << "," << v << "]" << std::endl;
+	    // skip already erased edges (may appear since set of participating is larger than in the Morozov zigzag)
+
+            if (distances(u,v) > eta*epsilons[i-1] && !ce_set) {
+	      ce = cee;
+	      ce_set = true;
+	      // std::cerr << "ce = " << distances(u,v) << " > " << eta*epsilons[i-1] << std::endl;
+	    }
+            if (distances(u,v) > rho*epsilons[i-1]) {
+	      // std::cerr << "cee = " << distances(u,v) << " > " << rho*epsilons[i-1] << std::endl;
+	      break;
+	    }
+            rDebug("  Recording cofaces of edges[%d]=(%d, %d) with size=%f", (cee-1), u, v, distances(u,v));
+            ec.start();
+	    tmp_cofaces.clear();
+
+	    // Ignore edges with already removed vertices
+	    if (!erased[u] && !erased[v])
+	      rips.edge_cofaces(u, v, 
+				skeleton_dimension, 
+				rho*epsilons[i-1], 
+				make_insert_functor(tmp_cofaces),
+				vertices.begin(),
+				vertices.begin() + i + 1);
+	    // insert computed cofaces to cofaces sets
+	    cofaces.insert(tmp_cofaces.begin(), tmp_cofaces.end());
+            if (distances(u,v) > eta*epsilons[i-1])
+	      large_cofaces.insert(tmp_cofaces.begin(), tmp_cofaces.end());
+            ec.stop();
+
+	    ++cee;
+	    if (cee == edges.size() && !ce_set)
+	      ce = cee;
+        }
+        rDebug("  Recorded new cofaces to add");
+
+        // Insert all the cofaces
+        rDebug("  Cofaces size: %d", cofaces.size());
+        for (SimplexSet::const_iterator cur = cofaces.begin(); cur != cofaces.end(); ++cur)
+        {
+            Index idx; Death d; Boundary b;
+            rDebug("  Adding %s, its size %f", tostring(*cur).c_str(), size(*cur));
+	    // std::cerr << "  Adding " << *cur << ", its size " << size(*cur) << std::endl;
+            make_boundary(*cur, complex, zz, b);
+            add.start();
+            boost::tie(idx, d)  = zz.add(b,
+                                         BirthInfo(epsilons[i-1], cur->dimension()));
+            add.stop();
+            //if (!d) rDebug("Newly born cycle order: %d", complex[*cur]->low->order);
+            CountNum(cComplexSize, cur->dimension());
+            Count(cComplexSize);
+            Count(cOperations);
+            AssertMsg(zz.check_consistency(), "Zigzag representation must be consistent after removing a simplex");
+            complex.insert(std::make_pair(*cur, idx));
+            report_death(intervals, d, epsilons[i-1], epsilons[i], skeleton_dimension);
+        }
+        rInfo("Increased epsilon to %f; complex size: %d", rho*epsilons[i-1], complex.size());
+	// std::cerr << "Increased epsilon to " << rho*epsilons[i-1] << ", complex size " << complex.size() << std::endl;
+        report_memory();
+        
+
+	/* Remove edges of length between eta*epsilons[i-1] and rho*epsilons[i-1] and their cofaces */
+        for (SimplexSet::const_reverse_iterator cur = large_cofaces.rbegin(); cur != (SimplexSet::const_reverse_iterator)large_cofaces.rend(); ++cur)
+        {
+            rDebug("    Removing: %s", tostring(*cur).c_str());
+	    // std::cerr << "  Removing " << *cur << std::endl;
+            Complex::iterator si = complex.find(*cur);
+            remove.start();
+            Death d = zz.remove(si->second,
+                                BirthInfo(epsilons[i-1], cur->dimension() - 1));
+            remove.stop();
+            complex.erase(si);
+            CountNumBy(cComplexSize, cur->dimension(), -1);
+            CountBy(cComplexSize, -1);
+            Count(cOperations);
+            AssertMsg(zz.check_consistency(), "Zigzag representation must be consistent after removing a simplex");
+            report_death(intervals, d, epsilons[i-1], epsilons[i], skeleton_dimension);
+        }
+        rInfo("Decreased epsilon to %f; complex size: %d", eta*epsilons[i-1], complex.size());
+        for (Complex::const_iterator cur = complex.begin(); cur != complex.end(); ++cur)
+            rDebug("  %s", tostring(cur->first).c_str());
+        report_memory();
+	// std::cerr << "Decreased epsilon to " << eta*epsilons[i-1] << ", complex size " << complex.size() << std::endl;
+
+
+        /* Remove the vertex */
+        cofaces.clear();
+        rDebug("  Cofaces size: %d", cofaces.size());
+        vc.start();
+        rips.vertex_cofaces(vertices[i], 
+                            skeleton_dimension, 
+                            eta*epsilons[i-1], 
+                            make_insert_functor(cofaces),
+                            vertices.begin(),
+                            vertices.begin() + i + 1);
+        vc.stop();
+        rDebug("  Computed cofaces of the vertex, their number: %d", cofaces.size());
+        for (SimplexSet::const_reverse_iterator cur = cofaces.rbegin(); cur != (SimplexSet::const_reverse_iterator)cofaces.rend(); ++cur)
+        {
+            rDebug("    Removing: %s", tostring(*cur).c_str());
+	    // std::cerr << " Removing " << *cur << std::endl;
+            Complex::iterator si = complex.find(*cur);
+            remove.start();
+            Death d = zz.remove(si->second,
+                                BirthInfo(epsilons[i-1], cur->dimension() - 1));
+            remove.stop();
+            complex.erase(si);
+            CountNumBy(cComplexSize, cur->dimension(), -1);
+            CountBy(cComplexSize, -1);
+            Count(cOperations);
+            AssertMsg(zz.check_consistency(), "Zigzag representation must be consistent after removing a simplex");
+            report_death(intervals, d, epsilons[i-1], epsilons[i], skeleton_dimension);
+        }
+        rInfo("Removed vertex; complex size: %d", complex.size());
+        for (Complex::const_iterator cur = complex.begin(); cur != complex.end(); ++cur)
+            rDebug("  %s", tostring(cur->first).c_str());
+	// std::cerr << " Removed vertex " << vertices[i] << ", complex size " << complex.size() << std::endl;
+	
+	// Book-keep set of erased vertices
+	erased[vertices[i]] = true;
+
+        report_memory();
+        
+        ++show_progress;
+    }
+    
+    // Remove the last vertex
+    AssertMsg(complex.size() == 1, "Only one vertex must remain");
+    remove.start();
+    Death d = zz.remove(complex.begin()->second, BirthInfo(epsilons[0], -1));
+    remove.stop();
+    complex.erase(complex.begin());
+    if (!d)  AssertMsg(false,  "The vertex must have died");
+    report_death(intervals, d, epsilons[0], epsilons[0], skeleton_dimension);
+    CountNumBy(cComplexSize, 0, -1);
+    CountBy(cComplexSize, -1);
+    Count(cOperations);
+    rInfo("Removed vertex; complex size: %d", complex.size());
+    ++show_progress;
+
+    total.stop();
+
+    remove.check("Remove timer          ");
+    add.check   ("Add timer             ");
+    ec.check    ("Edge coface timer     ");
+    vc.check    ("Vertex coface timer   ");
+    total.check ("Total timer           ");
+
+    std::cout << "Writing intervals...";
+    // Note (hack): use epsilons[vertices.size()-2]/2 as minimal value for the log-scale intervals to avoid intervals starting at -infinity and thus a scaling effect
+    write_intervals(out, intervals, skeleton_dimension, logscale, epsilons[vertices.size()-2]/2);
+    std::cout << " done." << std::endl;
+}
+
+
+void write_intervals(std::ostream& out, const IntervalsVector& intervals, int skeleton_dimension, bool logscale, double min_value) {
+  out << "I = { ";
+    for (int d = 0; d<skeleton_dimension; d++) {
+      out << "[ ";
+      for (std::list<std::pair<double,double> >::const_iterator pit = intervals[d].begin(); pit != intervals[d].end(); pit++)
+	if (logscale)
+	  out << "[" << log2(std::max(pit->first, min_value)) << ";" << log2(std::max(pit->second, min_value)) << "] ";
+	else
+	  out << "[" << pit->first << ";" << pit->second << "] ";
+
+      // add dummy interval if intervals list is empty
+      if (intervals[d].empty())
+	out << "[0;0] ";
+      out << "] ,";
+    }
+    out << "} ";
+} 
+            
+void        report_death(IntervalsVector& intervals, Death d, DistanceType epsilon, DistanceType birthEpsilon, Dimension skeleton_dimension)
+{
+  // std::cerr << "   d = " << d;
+  // if (d)
+  //   std::cerr << "   d->dim = " << d->dimension 
+  // 	      << "   d->dist = " << d->distance;
+  // std::cerr << "   epsilon = " << epsilon << std::endl;
+
+  if (d && ((d->distance - epsilon) != 0) && (d->dimension < skeleton_dimension))
+    intervals[d->dimension].push_back(std::pair<double,double>(d->distance, birthEpsilon));
+}
+
+void        make_boundary(const Smplx& s, Complex& c, const Zigzag& zz, Boundary& b)
+{
+    rDebug("  Boundary of <%s>", tostring(s).c_str());
+    for (Smplx::BoundaryIterator cur = s.boundary_begin(); cur != s.boundary_end(); ++cur)
+    {
+        b.append(c[*cur], zz.cmp);
+        rDebug("   %d", c[*cur]->order);
+    }
+}
+
+std::ostream&   operator<<(std::ostream& out, const BirthInfo& bi)
+{ return (out << bi.distance); }
+
+
+void        process_command_line_options(int           argc, 
+                                         char*         argv[],
+                                         unsigned&     skeleton_dimension,
+                                         float&        eta,
+                                         float&        rho,
+					 bool&         logscale,
+                                         std::string&  infilename,
+                                         std::string&  outfilename)
+{
+    namespace po = boost::program_options;
+
+    po::options_description hidden("Hidden options");
+    hidden.add_options()
+        ("input-file",          po::value<std::string>(&infilename),        "Point set whose Rips zigzag we want to compute")
+        ("output-file",         po::value<std::string>(&outfilename),       "Location to save persistence pairs");
+    
+    po::options_description visible("Allowed options", 100);
+    visible.add_options()
+        ("help,h",                                                                              "produce help message")
+        ("dim,d", po::value<unsigned>(&skeleton_dimension)->default_value(3),     "maximal dimension of the Rips complex")
+        ("eta,e",        po::value<float>(&eta)->default_value(3),                "multiplier eta used in the Rips parameter")
+        ("rho,r",        po::value<float>(&rho)->default_value(3),                "multiplier rho used in the Rips parameter")
+      ( "logscale,l" , po::value<bool>(&logscale)->zero_tokens(), "outputs interval bounds on log_2 scale" ) ;
+#if LOGGING
+    std::vector<std::string>    log_channels;
+    visible.add_options()
+        ("log,l",               po::value< std::vector<std::string> >(&log_channels),           "log channels to turn on (info, debug, etc)");
+#endif
+
+    po::positional_options_description pos;
+    pos.add("input-file", 1);
+    pos.add("output-file", 2);
+    
+    po::options_description all; all.add(visible).add(hidden);
+
+    po::variables_map vm;
+    po::store(po::command_line_parser(argc, argv).
+                  options(all).positional(pos).run(), vm);
+    po::notify(vm);
+
+#if LOGGING
+    for (std::vector<std::string>::const_iterator cur = log_channels.begin(); cur != log_channels.end(); ++cur)
+        stderrLog.subscribeTo( RLOG_CHANNEL(cur->c_str()) );
+    /**
+     * Interesting channels
+     * "info", "debug", "topology/persistence"
+     */
+#endif
+
+    if (vm.count("help") || !vm.count("input-file") || !vm.count("output-file"))
+    { 
+        std::cout << "Usage: " << argv[0] << " [options] input-file output-file" << std::endl;
+        std::cout << visible << std::endl; 
+        std::abort();
+    }
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/homology-zigzags/rips-pairwise.cpp	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,222 @@
+/***************************************************************************
+
+    rips-pairwise: Rips filtration + persistent homology 
+    Copyright (C) 2009-2012   Dmitriy Morozov
+
+    Adapted from its original version ("rips-pairwise.cpp" in
+    the Dionysus library) by Steve Oudot (2012).
+
+    Changelog (2012-11-22):
+
+       - the barcode is now output on a log scale and in a format that is 
+         compatible with the Matlab layer of the PLEX 2.5 library,
+
+       - the barcode representation is now by closed intervals instead of 
+         half-open intervals.
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+***************************************************************************/
+
+#include <topology/rips.h>
+#include <topology/filtration.h>
+#include <topology/static-persistence.h>
+#include <topology/dynamic-persistence.h>
+#include <topology/persistence-diagram.h>
+
+#include <geometry/l2distance.h>
+#include <geometry/distances.h>
+
+#include <utilities/containers.h>           // for BackInsertFunctor
+#include <utilities/timer.h>
+
+#include <vector>
+
+#include <boost/program_options.hpp>
+
+
+typedef         PairwiseDistances<PointContainer, L2Distance>           PairDistances;
+typedef         PairDistances::DistanceType                             DistanceType;
+typedef         PairDistances::IndexType                                Vertex;
+
+typedef         Rips<PairDistances>                                     Generator;
+typedef         Generator::Simplex                                      Smplx;
+typedef         Filtration<Smplx>                                       Fltr;
+// typedef         StaticPersistence<>                                     Persistence;
+typedef         DynamicPersistenceChains<>                              Persistence;
+typedef         PersistenceDiagram<>                                    PDgm;
+
+typedef         std::vector<std::list<std::pair<double, double> > >     IntervalsVector;
+
+// Forward declarations of auxilliary functions
+void write_intervals(std::ostream& out, const IntervalsVector& intervals, int skeleton_dimension);
+void            program_options(int argc, char* argv[], std::string& infilename, Dimension& skeleton, DistanceType& max_distance, std::string& diagram_name);
+
+int main(int argc, char* argv[])
+{
+    Dimension               skeleton;
+    DistanceType            max_distance;
+    std::string             infilename, diagram_name;
+
+    program_options(argc, argv, infilename, skeleton, max_distance, diagram_name);
+    std::ofstream           diagram_out(diagram_name.c_str());
+    std::cout << "Diagram:         " << diagram_name << std::endl;
+
+    PointContainer          points;
+    read_points(infilename, points);
+
+    PairDistances           distances(points);
+    Generator               rips(distances);
+    Generator::Evaluator    size(distances);
+    Fltr                    f;
+    
+    // Generate 2-skeleton of the Rips complex for epsilon = 50
+    rips.generate(skeleton, max_distance, make_push_back_functor(f));
+    std::cout << "# Generated complex of size: " << f.size() << std::endl;
+
+    // Generate filtration with respect to distance and compute its persistence
+    f.sort(Generator::Comparison(distances));
+
+    Timer persistence_timer; persistence_timer.start();
+    Persistence p(f);
+    p.pair_simplices();
+    persistence_timer.stop();
+
+#if 1
+    // Create intervals DS
+    IntervalsVector intervals(skeleton);
+
+    // Output cycles
+    Persistence::SimplexMap<Fltr>   m = p.make_simplex_map(f);
+    for (Persistence::iterator cur = p.begin(); cur != p.end(); ++cur)
+    {
+        const Persistence::Cycle& cycle = cur->cycle;
+
+        if (!cur->sign())        // only negative simplices have non-empty cycles
+        {
+            Persistence::OrderIndex birth = cur->pair;      // the cycle that cur killed was born when we added birth (another simplex)
+
+            const Smplx& b = m[birth];
+            const Smplx& d = m[cur];
+            
+            // if (b.dimension() != 1) continue;
+            // std::cout << "Pair: (" << size(b) << ", " << size(d) << ")" << std::endl;
+            if (b.dimension() >= skeleton) continue;
+            // diagram_out << b.dimension() << " " << size(b) << " " << size(d) << std::endl;
+	    intervals[b.dimension()].push_back(std::pair<double,double>(size(b), size(d)));
+        } else if (cur->unpaired())    // positive could be unpaired
+        {
+            const Smplx& b = m[cur];
+            // if (b.dimension() != 1) continue;
+            
+            // std::cout << "Unpaired birth: " << size(b) << std::endl;
+            // cycle = cur->chain;      // TODO
+            if (b.dimension() >= skeleton) continue;
+            // diagram_out << b.dimension() << " " << size(b) << " inf" << std::endl;
+	    intervals[b.dimension()].push_back(std::pair<double,double>(size(b), -1));
+        }
+
+        // Iterate over the cycle
+        // for (Persistence::Cycle::const_iterator si =  cycle.begin();
+        //                                                          si != cycle.end();     ++si)
+        // {
+        //     const Smplx& s = m[*si];
+        //     //std::cout << s.dimension() << std::endl;
+        //     const Smplx::VertexContainer& vertices = s.vertices();          // std::vector<Vertex> where Vertex = Distances::IndexType
+        //     AssertMsg(vertices.size() == s.dimension() + 1, "dimension of a simplex is one less than the number of its vertices");
+        //     std::cout << vertices[0] << " " << vertices[1] << std::endl;
+        // }
+    }
+#endif
+    
+    persistence_timer.check("# Persistence timer");
+
+    std::cout << "Writing intervals...";
+    // Note (hack): use epsilons[vertices.size()-2]/2 as minimal value for the log-scale intervals to avoid intervals starting at -infinity and thus a scaling effect
+    write_intervals(diagram_out, intervals, skeleton);
+    std::cout << " done." << std::endl;
+
+}
+
+
+const double LOG2 = std::log(2.0);
+double log2(double x) {
+  return std::log(x) / LOG2;
+}
+
+void write_intervals(std::ostream& out, const IntervalsVector& intervals, int skeleton_dimension) {
+  out << "I = { ";
+    for (int d = 0; d<skeleton_dimension; d++) {
+      out << "[ ";
+      for (std::list<std::pair<double,double> >::const_iterator pit = intervals[d].begin(); pit != intervals[d].end(); pit++) {
+	if (pit->first == 0)
+	  out << "[-Inf;";
+        else
+	  out << "[" << log2(pit->first) << ";";
+	if (pit->second >= 0)
+	  out << log2(pit->second) << "] ";
+	else
+	  out << "Inf] ";
+      }
+      // add dummy interval if intervals list is empty
+      if (intervals[d].empty())
+	out << "[0;0] ";
+      out << "] ,";
+    }
+    out << "} " << std::endl;
+} 
+
+
+void        program_options(int argc, char* argv[], std::string& infilename, Dimension& skeleton, DistanceType& max_distance, std::string& diagram_name)
+{
+    namespace po = boost::program_options;
+
+    po::options_description     hidden("Hidden options");
+    hidden.add_options()
+        ("input-file",          po::value<std::string>(&infilename),        "Point set whose Rips zigzag we want to compute");
+    
+    po::options_description visible("Allowed options", 100);
+    visible.add_options()
+        ("help,h",                                                                                  "produce help message")
+        ("skeleton-dimsnion,s", po::value<Dimension>(&skeleton)->default_value(2),                  "Dimension of the Rips complex we want to compute")
+        ("max-distance,m",      po::value<DistanceType>(&max_distance)->default_value(Infinity),    "Maximum value for the Rips complex construction")
+        ("diagram,d",           po::value<std::string>(&diagram_name),                              "Filename where to output the persistence diagram");
+#if LOGGING
+    std::vector<std::string>    log_channels;
+    visible.add_options()
+        ("log,l",               po::value< std::vector<std::string> >(&log_channels),           "log channels to turn on (info, debug, etc)");
+#endif
+
+    po::positional_options_description pos;
+    pos.add("input-file", 1);
+    
+    po::options_description all; all.add(visible).add(hidden);
+
+    po::variables_map vm;
+    po::store(po::command_line_parser(argc, argv).
+                  options(all).positional(pos).run(), vm);
+    po::notify(vm);
+
+#if LOGGING
+    for (std::vector<std::string>::const_iterator cur = log_channels.begin(); cur != log_channels.end(); ++cur)
+        stderrLog.subscribeTo( RLOG_CHANNEL(cur->c_str()) );
+#endif
+
+    if (vm.count("help") || !vm.count("input-file"))
+    { 
+        std::cout << "Usage: " << argv[0] << " [options] input-file" << std::endl;
+        std::cout << visible << std::endl; 
+        std::abort();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/pl-functions/CMakeLists.txt	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,16 @@
+set							(targets						
+							 test-grid2D 
+							 test-grid2D-vineyard
+							 combustion-vineyard
+                             pl-vineyard)
+
+if                          (use_dsrpdb)
+    set                     (t                          pdbdistance-vineyard)
+    add_executable			(${t} ${t}.cpp)
+    target_link_libraries	(${t} ${libraries} ${dsrpdb_LIBRARY} ${Boost_PROGRAM_OPTIONS_LIBRARY})
+endif                       (use_dsrpdb)
+
+foreach 					(t ${targets})
+    add_executable			(${t} ${t}.cpp)
+    target_link_libraries	(${t} ${libraries} ${Boost_PROGRAM_OPTIONS_LIBRARY})
+endforeach 					(t ${targets})
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/pl-functions/combustion-vineyard.cpp	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,88 @@
+/*
+ * Author: Dmitriy Morozov
+ * Department of Computer Science, Duke University, 2005
+ */
+
+#include <utilities/log.h>
+
+#include <iostream>
+#include <fstream>
+#include <algorithm>
+
+#include "grid2D.h"
+#include <topology/lsvineyard.h>
+
+const int xsize = 600;
+const int ysize = 600;
+const int var = 0;          // which variable to use out of nc of them in each record in the file
+
+template<typename T>
+void read(std::ifstream& ifs, T& var)
+{
+    ifs.read(reinterpret_cast<char*>(&var), sizeof(T));
+}
+
+int main(int argc, char** argv)
+{
+    if (argc < 3)
+    {
+        std::cout << "Usage: combustion-vineyard FRAME1 FRAME2" << std::endl;
+        exit(0);
+    }
+    
+    int size0, nc0;
+    int size1, nc1;
+
+    std::cout << "Reading: " << argv[1] << std::endl;
+    std::ifstream ifs0(argv[1], std::ios::binary);
+    std::cout << "Reading: " << argv[2] << std::endl;
+    std::ifstream ifs1(argv[2], std::ios::binary);
+
+    if (!ifs0 || !ifs1)
+    {
+        std::cout << "Could not open the frames" << std::endl;
+        exit(0);
+    }
+
+    read(ifs0, size0); read(ifs0, nc0);
+    read(ifs1, size1); read(ifs1, nc1);
+
+    assert(size0 == size1); assert(nc0 == nc1);
+    assert(size0 == xsize*ysize);
+    
+    Grid2D g0(xsize, ysize), g1(xsize, ysize);
+    
+    for (int y = 0; y < ysize; ++y)
+        for (int x = 0; x < xsize; ++x)
+            for (int d = 0; d < nc0; ++d)
+            {
+                float val0, val1;
+                read(ifs0, val0);
+                read(ifs1, val1);
+                if (d == var)
+                {
+                    g0(x,y) = val0;
+                    g1(x,y) = val1;
+                }
+            }
+    std::cout << "Grids read" << std::endl;
+    
+    // Generate the complex, initialize the vineyard (which also computes the pairing)
+    typedef                     LSVineyard<Grid2D::CoordinateIndex, Grid2D>             Grid2DVineyard;
+
+    Grid2DVineyard::LSFiltration        simplices;    
+    g0.complex_generator(make_push_back_functor(simplices));
+    Grid2DVineyard::VertexComparison    vcmp(g0);
+    Grid2DVineyard::SimplexComparison   scmp(vcmp);
+    simplices.sort(scmp);
+
+    Grid2DVineyard              v(g0.begin(), g0.end(), simplices, g0);
+    std::cout << "Filtration generated, size: " << v.filtration().size() << std::endl;
+    std::cout << "Pairing computed" << std::endl;
+    
+    // Compute vineyard
+    v.compute_vineyard(g1);
+    std::cout << "Vineyard computed" << std::endl;
+
+    v.vineyard().save_edges("combustion");
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/pl-functions/cube.py	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,40 @@
+def log2(x):
+    i = 0
+    while x:
+        x >>= 1
+        i += 1
+    return i-1        
+
+class Cube:
+    def __init__(self, vertices):
+        self.vertices = vertices
+
+    def dimension(self):
+        return log2(len(self.vertices))
+
+    def boundary(self):
+        for i in xrange(self.dimension()):
+            for side in [0,1]:
+                vertices = []
+                for idx in xrange(len(self.vertices)/2):
+                    # Insert i-th bit equal to side
+                    v = (idx & ~(2**i-1)) << 1
+                    if side: v |= 2**i
+                    v |= (idx & (2**i - 1))
+                    vertices.append(self.vertices[v])
+                yield Cube(vertices)    
+
+    def __hash__(self):
+        return hash(tuple(self.vertices))
+
+    def __eq__(self, other):
+        return self.vertices == other.vertices
+
+    def __repr__(self):
+        return " ".join(map(str, self.vertices))
+
+
+if __name__ == '__main__':
+    c = Cube(['a', 'b', 'c', 'd'])
+    print c
+    for sb in c.boundary(): print sb
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/pl-functions/grid2D.h	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,96 @@
+/*
+ * Author: Dmitriy Morozov
+ * Department of Computer Science, Duke University, 2005 -- 2006
+ */
+
+#ifndef __GRID2D_H__
+#define __GRID2D_H__
+
+#include <memory>
+#include <vector>
+#include <map>
+#include <set>
+#include <limits>
+#include <iostream>
+//#include <cmath>
+
+#include <boost/serialization/access.hpp>
+#include <boost/serialization/base_object.hpp>
+#include <boost/serialization/split_member.hpp>
+#include <boost/serialization/nvp.hpp>
+#include <boost/serialization/export.hpp>
+
+#include <boost/iterator/counting_iterator.hpp>
+
+#include "utilities/types.h"
+#include "topology/simplex.h"
+
+/** 
+ * Grid2D stores a grid
+ */
+class Grid2D
+{
+    public:
+        typedef                 RealType                                        ValueType;
+        typedef                 ValueType                                       result_type;
+        
+        typedef                 unsigned int                                    CoordinateIndex;
+        typedef                 boost::counting_iterator<CoordinateIndex>       iterator;
+
+        typedef                 Simplex<CoordinateIndex>                        Smplx;
+        typedef                 std::vector<ValueType>                          ValueVector;
+
+    public:
+        Grid2D(CoordinateIndex xx = 1, CoordinateIndex yy = 1);
+
+        /// Sets the grid dimensions to (xx,yy)
+        void                    change_dimensions(CoordinateIndex xx, CoordinateIndex yy);
+
+        ValueType&              operator()(CoordinateIndex i, CoordinateIndex j)            { return data[i*x + j]; }
+        const ValueType&        operator()(CoordinateIndex i, CoordinateIndex j) const      { return data[i*x + j]; }
+        ValueType&              operator()(CoordinateIndex i)                               { return data[i]; }
+        const ValueType&        operator()(CoordinateIndex i) const                         { return data[i]; }
+
+        CoordinateIndex         xsize() const                                               { return x; }
+        CoordinateIndex         ysize() const                                               { return y; }
+        CoordinateIndex         size() const                                                { return x*y; }
+
+        iterator                begin() const                                               { return iterator(0); }
+        iterator                end() const                                                 { return iterator(size()); }
+        
+        /* Given a sequential index of an element return its coordinates */
+        CoordinateIndex         xpos(CoordinateIndex i) const                               { return i / x; }
+        CoordinateIndex         ypos(CoordinateIndex i) const                               { return i % x; }
+        CoordinateIndex         seq(CoordinateIndex i, CoordinateIndex j) const;
+
+        template<class Functor>
+        void                    complex_generator(const Functor& f);
+
+        std::ostream&           operator<<(std::ostream& out) const;
+
+        static const CoordinateIndex INVALID_INDEX = -1;
+
+    private:
+        CoordinateIndex         x,y;
+        ValueVector             data;
+
+#if 0
+    private:
+        // Serialization
+        friend class boost::serialization::access;
+
+        template<class Archive> void save(Archive& ar, version_type ) const;
+        template<class Archive> void load(Archive& ar, version_type );
+
+        BOOST_SERIALIZATION_SPLIT_MEMBER()
+#endif
+};
+//BOOST_CLASS_EXPORT(Grid2D)
+    
+
+std::ostream& operator<<(std::ostream& out, const Grid2D& grid)                             { return grid.operator<<(out); }
+
+        
+#include "grid2D.hpp"
+
+#endif // __GRID2D_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/pl-functions/grid2D.hpp	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,121 @@
+#include <iostream>
+#include <limits>
+
+/* Implementations */
+
+Grid2D::
+Grid2D(CoordinateIndex xx, CoordinateIndex yy):
+    x(xx), y(yy), data(x*y)
+{}
+
+void                    
+Grid2D::
+change_dimensions(CoordinateIndex xx, CoordinateIndex yy)
+{
+    x = xx; y = yy;
+    data.resize(x*y);
+}
+
+Grid2D::CoordinateIndex
+Grid2D::
+seq(CoordinateIndex i, CoordinateIndex j) const
+{ 
+    // Do not forget to check if less than 0, if Index is made signed --- dangerous
+    if (i >= x || j >= y)
+        return INVALID_INDEX;
+
+    return i*x + j; 
+}
+
+std::ostream&           
+Grid2D::
+operator<<(std::ostream& out) const
+{
+    for (Grid2D::CoordinateIndex i = 0; i < xsize(); ++i)
+    {
+        for (Grid2D::CoordinateIndex j = 0; j < ysize(); ++j)
+            std::cout << operator()(i, j) << ' ';
+        std::cout << std::endl;
+    }
+    return out; 
+}   
+
+#if 0
+using boost::serialization::make_nvp;
+
+template<class Archive>
+void 
+Grid2D::
+save(Archive& ar, version_type ) const
+{
+    ar << BOOST_SERIALIZATION_NVP(x);
+    ar << BOOST_SERIALIZATION_NVP(y);
+    ar << make_nvp("data", data);
+}
+
+template<class Archive> 
+void 
+Grid2D::
+load(Archive& ar, version_type )
+{
+    ar >> make_nvp("x", x);
+    ar >> make_nvp("y", y);
+    ar >> make_nvp("data", data);
+}
+#endif
+
+template<class Functor>
+void    
+Grid2D::
+complex_generator(const Functor& f)
+{
+    for (CoordinateIndex x = 0; x < xsize() - 1; ++x)
+        for (CoordinateIndex y = 0; y < ysize() - 1; ++y)
+        {
+            CoordinateIndex v(seq(x,y));
+            CoordinateIndex vh(seq(x+1,y));
+            CoordinateIndex vv(seq(x,y+1));
+            CoordinateIndex vd(seq(x+1,y+1));
+
+            Smplx sh; sh.add(v);  
+            f(sh);
+            sh.add(vh); f(sh);              // Horizontal edge
+            sh.add(vd); f(sh);              // "Horizontal" triangle
+            
+            Smplx sv; sv.add(v);
+            sv.add(vv); f(sv);              // Vertical edge
+            sv.add(vd); f(sv);              // "Vertical" triangle
+            
+            Smplx sd; sd.add(v);
+            sd.add(vd); f(sd);              // Diagonal edge
+
+            if (y == ysize() - 2)
+            {
+                Smplx s; s.add(vv);
+                s.add(vd); f(s);            // Top edge
+            }
+            if (x == xsize() - 2)
+            {
+                Smplx s; s.add(vh);
+                s.add(vd); f(s);            // Right edge
+            }
+        }
+    
+    // Last row
+    for (CoordinateIndex x = 0; x < xsize(); ++x)
+    {
+        std::cout << x << " " << ysize() - 1 << " " << seq(x, ysize() - 1) << std::endl;
+        CoordinateIndex v(seq(x, ysize() - 1));
+        Smplx s; s.add(v);
+        f(s);
+    }
+
+    // Last column
+    for (CoordinateIndex y = 0; y < ysize() - 1; ++y)
+    {
+        std::cout << xsize() - 1 << " " << y << " " << seq(xsize() - 1, y) << std::endl;
+        CoordinateIndex v(seq(xsize() - 1, y));
+        Smplx s; s.add(v);
+        f(s);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/pl-functions/lscubes.py	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,61 @@
+#!/usr/bin/env python
+
+from    dionysus        import CohomologyPersistence
+from    cube            import Cube
+from    sys             import argv, exit
+
+
+def max_vertex(s, vertices):
+    return max((vertices[v] for v in s.vertices))
+
+def max_vertex_cmp(s1, s2, vertices):
+    m1 = max_vertex(s1, vertices)
+    m2 = max_vertex(s2, vertices)
+    return cmp(m1, m2) or cmp(s1.dimension(), s2.dimension())
+
+def lsf(values_filename, cubes_filename, prime = 11):
+    # Read vertices
+    vertices = []
+    with open(values_filename) as f:
+        for line in f:
+            if line.startswith('#'): continue
+            vertices.append(float(line.split()[0]))
+
+    # Read cubes
+    fltr = []
+    with open(cubes_filename) as f:
+        for line in f:
+            if line.startswith('#'): continue
+            fltr.append(Cube(map(int, line.split())))
+    fltr.sort(lambda x,y: max_vertex_cmp(x,y,vertices))
+    for i,c in enumerate(fltr): c.data = i
+
+    ch = CohomologyPersistence(prime)
+    complex = {}
+
+    for c in fltr:
+        # print "%s: %s" % (c, " + ".join(map(str, c.boundary())))
+        # print complex
+        i,d,_ = ch.add([complex[cb] for cb in c.boundary()], c.data)
+        complex[c] = i
+        if d:
+            birth = d
+            print c.dimension() - 1, max_vertex(fltr[birth], vertices), max_vertex(c, vertices)
+
+    for ccl in ch:
+        birth = ccl.birth
+        c = fltr[birth]
+        print c.dimension(), max_vertex(c, vertices), 'inf'
+
+if __name__ == '__main__':
+    if len(argv) < 3:
+        print "Usage: %s VERTICES CUBES" % argv[0]
+        print 
+        print "Computes persistence of the lower star filtration of the cubical "
+        print "complex explicitly listed out in CUBES with vertex values given in VERTICES."
+        exit()
+
+    values = argv[1]
+    cubes = argv[2]
+
+    lsf(values, cubes)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/pl-functions/lsfiltration.py	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,61 @@
+#!/usr/bin/env python
+
+from    dionysus        import Simplex, Filtration, StaticPersistence, vertex_cmp
+from    sys             import argv, exit
+
+
+def max_vertex(s, vertices):
+    return max((vertices[v] for v in s.vertices))
+
+def max_vertex_cmp(s1, s2, vertices):
+    m1 = max_vertex(s1, vertices)
+    m2 = max_vertex(s2, vertices)
+    return cmp(m1, m2) or cmp(s1.dimension(), s2.dimension())
+
+def lsf(values_filename, simplices_filename):
+    # Read vertices
+    vertices = []
+    with open(values_filename) as f:
+        for line in f:
+            if line.startswith('#'): continue
+            vertices.append(float(line.split()[0]))
+
+    # Read simplices
+    fltr = Filtration()
+    with open(simplices_filename) as f:
+        for line in f:
+            if line.startswith('#'): continue
+            fltr.append(Simplex(map(int, line.split())))
+    fltr.sort(lambda x,y: max_vertex_cmp(x,y,vertices))
+
+    # Compute persistence
+    p = StaticPersistence(fltr)
+    p.pair_simplices()
+    
+    # Output the persistence diagram
+    smap = p.make_simplex_map(fltr)
+    for i in p:
+        if not i.sign(): continue
+
+        b = smap[i]
+        d = smap[i.pair()]
+
+        if i.unpaired():
+            print b.dimension(), max_vertex(b, vertices), "inf"
+            continue
+
+        print b.dimension(), max_vertex(b, vertices), max_vertex(d, vertices)
+
+
+if __name__ == '__main__':
+    if len(argv) < 3:
+        print "Usage: %s VERTICES SIMPLICES" % argv[0]
+        print 
+        print "Computes persistence of the lower star filtration of the simplicial "
+        print "complex explicitly listed out in SIMPLICES with vertex values given in VERTICES."
+        exit()
+
+    values = argv[1]
+    simplices = argv[2]
+
+    lsf(values, simplices)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/pl-functions/pdbdistance-vineyard.cpp	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,124 @@
+//#include <boost/archive/binary_oarchive.hpp>
+#include "utilities/log.h"
+
+#include "pdbdistance.h"
+#include <topology/lsvineyard.h>
+
+#include <fstream>
+#include <string>
+#include <sstream>
+
+#include <boost/program_options.hpp>
+
+void        program_options(int argc, char* argv[], std::string& input_fn_list,
+                                                    std::string& output_prefix, 
+                                                    bool& all_atoms,
+                                                    bool& save_vines);
+
+int main(int argc, char** argv)
+{
+#ifdef LOGGING
+	rlog::RLogInit(argc, argv);
+#endif
+
+    std::string                 input_fn_list, output_fn;
+    bool                        all_atoms = false, save_vines = false;
+    program_options(argc, argv, input_fn_list, output_fn, all_atoms, save_vines);
+
+	// Compute initial filtration
+    std::vector<std::string> frame_fns;
+    std::ifstream in_fns(input_fn_list.c_str());
+    std::string fn;
+    while(std::getline(in_fns, fn))
+        frame_fns.push_back(fn);
+        
+	std::ifstream in(frame_fns[0].c_str());
+    PDBDistanceGrid ginit(in, !all_atoms);
+	in.close();
+
+    typedef                     LSVineyard<Grid2D::CoordinateIndex, Grid2D>             Grid2DVineyard;
+    
+    Grid2DVineyard::LSFiltration        simplices;    
+    ginit.complex_generator(make_push_back_functor(simplices));
+    Grid2DVineyard::VertexComparison    vcmp(ginit);
+    Grid2DVineyard::SimplexComparison   scmp(vcmp);
+    simplices.sort(scmp);
+    std::cout << "Complex generated, size: " << simplices.size() << std::endl;
+
+    Grid2DVineyard              v(ginit.begin(), ginit.end(), simplices, ginit);
+	std::cout << "Filtration generated, size: " << v.filtration().size() << std::endl;
+	std::cout << "Pairing computed" << std::endl;
+
+	// Process frames computing the vineyard
+	for (size_t i = 1; i < frame_fns.size(); ++i)
+	{
+		std::cout << "Processing " << frame_fns[i] << std::endl;
+		in.open(frame_fns[i].c_str());
+		v.compute_vineyard(PDBDistanceGrid(in, !all_atoms));
+		in.close();
+	}
+	std::cout << "Vineyard computed" << std::endl;
+
+    if (save_vines)
+        v.vineyard().save_vines(output_fn);
+    else
+    	v.vineyard().save_edges(output_fn);
+
+#if 0
+	std::ofstream ofs(output_fn.c_str(), std::ios::binary);
+	boost::archive::binary_oarchive oa(ofs);
+	oa << make_nvp("Filtration", pgf);
+	ofs.close();
+#endif
+}
+
+void        program_options(int argc, char* argv[], std::string& input_fn_list, 
+                                                    std::string& output_prefix, 
+                                                    bool& all_atoms,
+                                                    bool& save_vines)
+{
+    namespace po = boost::program_options;
+
+    po::options_description     hidden("Hidden options");
+    hidden.add_options()
+        ("input-fn-list",       po::value<std::string>(&input_fn_list),         "prefix of the input frames")
+        ("output-prefix",       po::value<std::string>(&output_prefix),         "output prefix");
+    
+    po::options_description visible("Allowed options", 100);
+    visible.add_options()
+        ("all-atoms,a",         po::bool_switch(&all_atoms),                    "process all atoms (not only alpha carbons)")
+        ("save-vines,v",        po::bool_switch(&save_vines),                   "save vines instead of edges")
+        ("help,h",                                                              "produce help message");
+#if LOGGING
+    std::vector<std::string>    log_channels;
+    visible.add_options()
+        ("log,l",               po::value< std::vector<std::string> >(&log_channels),           "log channels to turn on (info, debug, etc)");
+#endif
+
+    po::positional_options_description pos;
+    pos.add("input-fn-list", 1);
+    pos.add("output-prefix", 1);
+    
+    po::options_description all; all.add(visible).add(hidden);
+
+    po::variables_map vm;
+    po::store(po::command_line_parser(argc, argv).
+                  options(all).positional(pos).run(), vm);
+    po::notify(vm);
+
+#if LOGGING
+    for (std::vector<std::string>::const_iterator cur = log_channels.begin(); cur != log_channels.end(); ++cur)
+        stderrLog.subscribeTo( RLOG_CHANNEL(cur->c_str()) );
+#endif
+
+    if (vm.count("help") || !vm.count("input-fn-list") || !vm.count("output-prefix"))
+    { 
+        std::cout << "Usage: " << argv[0] << " [options] input-fn-list output-prefix" << std::endl;
+        std::cout << visible << std::endl; 
+		std::cout << std::endl;
+		std::cout << "Computes a vineyard of the pairwise distance function for a sequence of PDB frames." << std::endl;
+		std::cout << "Frames are listed in input-fn-list file." << std::endl;
+        std::abort();
+    }
+}
+                                                    
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/pl-functions/pdbdistance.h	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,87 @@
+/*
+ * Author: Dmitriy Morozov
+ * Department of Computer Science, Duke University, 2005 -- 2006
+ *
+ * Depends on Daniel Russel's "simple C++ PDB" (aka DSR-PDB).
+ */
+
+#ifndef __PDBDISTANCE_H__
+#define __PDBDISTANCE_H__
+
+#include <fstream>
+#include <string>
+#include <dsrpdb/Protein.h>
+#include <dsrpdb/iterator.h>
+#include <cmath>
+
+#include <boost/serialization/access.hpp>
+
+#include "utilities/types.h"
+#include "grid2D.h"
+
+#include <boost/serialization/export.hpp>
+
+
+class PDBDistanceGrid: public Grid2D
+{
+	public:
+		PDBDistanceGrid()
+		{}
+	
+		PDBDistanceGrid(std::istream& in, bool ca_only = true)
+		{
+			load_stream(in, ca_only);
+		}
+
+		void	load_stream(std::istream& in, bool ca_only = true)
+		{
+			dsrpdb::Protein p(in);
+			typedef std::vector<dsrpdb::Point> PointVector;
+			PointVector coordinates;
+			if (ca_only)
+			{
+				PointVector v(ca_coordinates_begin(p), ca_coordinates_end(p));
+				coordinates.swap(v);
+			}
+			else
+			{
+				PointVector v(backbone_coordinates_begin(p), backbone_coordinates_end(p));
+				coordinates.swap(v);
+			}
+
+			std::cout << "Coordinatess created, size: " << coordinates.size() << std::endl;
+
+			Grid2D::change_dimensions(coordinates.size(), coordinates.size());
+			for (Grid2D::CoordinateIndex i = 0; i < coordinates.size(); ++i)
+				for (Grid2D::CoordinateIndex j = 0; j < coordinates.size(); ++j)
+				{
+					if (i < j)
+						Grid2D::operator()(i,j) = distance(coordinates[i], coordinates[j]);
+					else
+						Grid2D::operator()(i,j) = 0;
+				}
+		}
+
+	private:
+		Grid2D::ValueType distance(dsrpdb::Point p1, dsrpdb::Point p2) const
+		{
+			dsrpdb::Vector v = p1 - p2;
+			return std::sqrt(v*v);
+		}
+
+#if 0
+	private:
+		// Serialization
+		friend class boost::serialization::access;
+		
+		template<class Archive>
+		void serialize(Archive& ar, version_type version)
+		{
+			ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Grid2D);
+		}
+#endif
+};
+
+//BOOST_CLASS_EXPORT(PDBDistanceGrid)
+
+#endif // __PDBDISTANCE_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/pl-functions/pl-vineyard.cpp	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,169 @@
+#include <utilities/log.h>
+
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <vector>
+
+#include <topology/lsvineyard.h>
+
+#include <boost/program_options.hpp>
+#include <boost/iterator/counting_iterator.hpp>
+#include <boost/function.hpp>
+#include <boost/bind.hpp>
+#include <boost/lambda/lambda.hpp>
+namespace bl = boost::lambda;
+
+
+typedef     double                                      VertexValue;
+typedef     unsigned                                    Vertex;
+typedef     std::vector<VertexValue>                    VertexVector;
+struct SubscriptFunctor: public std::unary_function<Vertex, VertexValue>
+{
+                                SubscriptFunctor(const VertexVector& v): vec(&v)    {}
+        float                   operator()(Vertex i) const                          { return (*vec)[i]; }
+        SubscriptFunctor&       operator=(const SubscriptFunctor& other)            { vec = other.vec; return *this; }
+        const VertexVector*     vec;
+};
+typedef     SubscriptFunctor                            VertexEvaluator;
+typedef     std::vector<VertexVector>                   VertexVectorVector;
+typedef     LSVineyard<Vertex, VertexEvaluator>         PLVineyard;
+typedef     PLVineyard::Simplex                         Smplx;              // gotta start using namespaces
+
+void        program_options(int argc, char* argv[], std::string& complex_fn, 
+                                                    std::string& values_fn, 
+                                                    std::string& output_prefix, 
+                                                    bool& skip_infinite_vines, 
+                                                    bool& save_vines,
+                                                    bool& explicit_events);
+void        read_simplices(const std::string& complex_fn, PLVineyard::LSFiltration& simplices);
+void        read_vertices(const std::string& vertex_fn, VertexVectorVector& vertices); 
+
+
+int main(int argc, char** argv)
+{
+#ifdef LOGGING
+    rlog::RLogInit(argc, argv);
+#endif     
+    
+    std::string                 complex_fn, values_fn, output_prefix;
+    bool                        skip_infinite_vines = false, explicit_events = false, save_vines = false;
+    program_options(argc, argv, complex_fn, values_fn, output_prefix, skip_infinite_vines, save_vines, explicit_events);
+
+
+    // Read in the complex
+    PLVineyard::LSFiltration            simplices;
+    read_simplices(complex_fn, simplices);
+    std::cout << "Complex read, size: " << simplices.size() << std::endl;
+
+    // Read in vertex values
+    VertexVectorVector                  vertices;
+    read_vertices(values_fn, vertices);
+
+    // Setup the vineyard
+    VertexEvaluator                     veval(vertices[0]);
+    PLVineyard::VertexComparison        vcmp(veval);
+    PLVineyard::SimplexComparison       scmp(vcmp);
+    simplices.sort(scmp);
+    PLVineyard                      v(boost::counting_iterator<Vertex>(0),
+                                      boost::counting_iterator<Vertex>(vertices[0].size()), 
+                                      simplices, veval);
+    std::cout << "Pairing computed" << std::endl;
+
+    // Compute vineyard
+    for (size_t i = 1; i < vertices.size(); ++i)
+    {
+        veval = VertexEvaluator(vertices[i]);
+        v.compute_vineyard(veval);
+        std::cout << "Processed frame: " << i << std::endl;
+    }
+    std::cout << "Vineyard computed" << std::endl;
+    
+    if (save_vines)
+        v.vineyard().save_vines(output_prefix, skip_infinite_vines);
+    else
+        v.vineyard().save_edges(output_prefix, skip_infinite_vines);
+}
+
+
+void        read_simplices(const std::string& complex_fn, PLVineyard::LSFiltration& simplices)
+{
+    std::ifstream   in(complex_fn.c_str());
+    std::string     line;
+    while (std::getline(in, line))
+    {
+        std::istringstream  strin(line);
+        simplices.push_back(Smplx(std::istream_iterator<Vertex>(strin), std::istream_iterator<Vertex>()));
+    }
+    std::cout << "Simplices read:" << std::endl;
+    std::copy(simplices.begin(), simplices.end(), std::ostream_iterator<Smplx>(std::cout, "\n"));
+}
+
+void        read_vertices(const std::string& vertex_fn, VertexVectorVector& vertices)
+{
+    std::ifstream   in(vertex_fn.c_str());
+    std::string     line;
+    while (std::getline(in, line))
+    {
+        std::istringstream  strin(line);
+        vertices.push_back(VertexVector(std::istream_iterator<VertexValue>(strin), std::istream_iterator<VertexValue>()));
+    }
+    std::cout << "Vertex values read:" << std::endl;
+    for (size_t i = 0; i < vertices.size(); ++i)
+    {
+        std::copy(vertices[i].begin(), vertices[i].end(), std::ostream_iterator<VertexValue>(std::cout, " "));
+        std::cout << std::endl;
+    }
+}
+
+void        program_options(int argc, char* argv[], std::string& complex_fn, 
+                                                    std::string& values_fn, 
+                                                    std::string& output_prefix, 
+                                                    bool& skip_infinite_vines,
+                                                    bool& save_vines,
+                                                    bool& explicit_events)
+{
+    namespace po = boost::program_options;
+
+    po::options_description     hidden("Hidden options");
+    hidden.add_options()
+        ("complex-file",        po::value<std::string>(&complex_fn),            "file listing the simplices of the complex")
+        ("values-file",         po::value<std::string>(&values_fn),             "file listing the values at the vertices")
+        ("output-prefix",       po::value<std::string>(&output_prefix),         "output prefix");
+    
+    po::options_description visible("Allowed options", 100);
+    visible.add_options()
+        ("skip-infinite,s",     po::bool_switch(&skip_infinite_vines),                          "skip infinite vines in the output")
+        ("explicit-events,e",   po::bool_switch(&explicit_events),                              "process kinetic sort events one by one")
+        ("save-vines,v",        po::bool_switch(&save_vines),                                   "save vines instead of edges")
+        ("help,h",                                                                              "produce help message");
+#if LOGGING
+    std::vector<std::string>    log_channels;
+    visible.add_options()
+        ("log,l",               po::value< std::vector<std::string> >(&log_channels),           "log channels to turn on (info, debug, etc)");
+#endif
+
+    po::positional_options_description pos;
+    pos.add("complex-file", 1);
+    pos.add("values-file", 1);
+    pos.add("output-prefix", 1);
+    
+    po::options_description all; all.add(visible).add(hidden);
+
+    po::variables_map vm;
+    po::store(po::command_line_parser(argc, argv).
+                  options(all).positional(pos).run(), vm);
+    po::notify(vm);
+
+#if LOGGING
+    for (std::vector<std::string>::const_iterator cur = log_channels.begin(); cur != log_channels.end(); ++cur)
+        stderrLog.subscribeTo( RLOG_CHANNEL(cur->c_str()) );
+#endif
+
+    if (vm.count("help") || !vm.count("complex-file") || !vm.count("values-file") || !vm.count("output-prefix"))
+    { 
+        std::cout << "Usage: " << argv[0] << " [options] complex-file values-file output-prefix" << std::endl;
+        std::cout << visible << std::endl; 
+        std::abort();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/pl-functions/test-grid2D-vineyard.cpp	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,54 @@
+#include <utilities/log.h>
+
+#include <iostream>
+#include <fstream>
+#include <algorithm>
+
+#include "grid2D.h"
+#include <topology/lsvineyard.h>
+
+int main(int argc, char** argv)
+{
+#ifdef LOGGING
+    rlog::RLogInit(argc, argv);
+    // stdoutLog.subscribeTo(RLOG_CHANNEL("topology"));
+    // stdoutLog.subscribeTo(RLOG_CHANNEL("topology/persistence/transpositions"));
+    // stdoutLog.subscribeTo(RLOG_CHANNEL("topology/vineyard"));
+    stdoutLog.subscribeTo(RLOG_CHANNEL("lsvineyard"));
+#endif     
+
+    Grid2D g0(2, 2), g1(2, 2);
+    g0(0,0) = 1; g0(0,1) = 2; g0(1,0) = 3; g0(1,1) = 0;
+    g1(0,0) = 4; g1(0,1) = 2; g1(1,0) = 3; g1(1,1) = 5;
+    
+    // Generate the complex, initialize the vineyard (which also computes the pairing)
+    typedef                     LSVineyard<Grid2D::CoordinateIndex, Grid2D>             Grid2DVineyard;
+    
+    Grid2DVineyard::LSFiltration        simplices;    
+    g0.complex_generator(make_push_back_functor(simplices));
+    Grid2DVineyard::VertexComparison    vcmp(g0);
+    Grid2DVineyard::SimplexComparison   scmp(vcmp);
+    simplices.sort(scmp);
+    std::cout << "Complex generated, size: " << simplices.size() << std::endl;
+    std::copy(simplices.begin(), simplices.end(), std::ostream_iterator<Grid2D::Smplx>(std::cout, "\n"));
+
+    Grid2DVineyard              v(g0.begin(), g0.end(), simplices, g0);
+    std::cout << "Filtration generated, size: " << v.filtration().size() << std::endl;
+    std::cout << "Pairing computed" << std::endl;
+ 
+    // Simplex order before
+    std::cout << "Simplex order:" << std::endl;
+    for (Grid2DVineyard::LSFiltration::Index cur = v.filtration().begin(); cur != v.filtration().end(); ++cur)
+        std::cout << "  " << v.filtration().simplex(cur) << std::endl;
+
+    // Compute vineyard
+    v.compute_vineyard(g1);
+    std::cout << "Vineyard computed" << std::endl;
+    
+    // Simplex order after
+    std::cout << "Simplex order:" << std::endl;
+    for (Grid2DVineyard::LSFiltration::Index cur = v.filtration().begin(); cur != v.filtration().end(); ++cur)
+        std::cout << "  " << v.filtration().simplex(cur) << std::endl;
+
+    v.vineyard().save_edges("test-vineyard");
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/pl-functions/test-grid2D.cpp	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,16 @@
+#include "grid2D.h"
+#include <iostream>
+
+int main()
+{
+	Grid2D grid(40,60);
+	int i = 0;
+	for (int x = 0; x < 40; ++x)
+		for (int y = 0; y < 60; ++y)
+		{
+			grid(x,y) = i++;
+		}
+
+	std::cout << grid(20,30) << std::endl;
+	std::cout << grid << std::endl;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/poincare/CMakeLists.txt	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,7 @@
+set                         (targets                        
+                             poincare)
+                             
+foreach                     (t ${targets})
+    add_executable          (${t} ${t}.cpp)
+    target_link_libraries   (${t} ${libraries} ${Boost_PROGRAM_OPTIONS_LIBRARY})
+endforeach                  (t ${targets})
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/poincare/poincare-filtration.txt	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,392 @@
+9
+2
+2 9
+4
+4 9
+2 4
+2 4 9
+1
+1 9
+1 4
+1 4 9
+1 2
+1 2 9
+1 2 4
+1 2 4 9
+15
+2 15
+4 15
+2 4 15
+1 15
+1 4 15
+1 2 15
+1 2 4 15
+14
+2 14
+6
+6 14
+2 6
+2 6 14
+1 14
+1 6
+1 6 14
+1 2 14
+1 2 6
+1 2 6 14
+6 15
+2 6 15
+1 6 15
+1 2 6 15
+9 14
+2 9 14
+1 9 14
+1 2 9 14
+12
+3
+3 12
+4 12
+3 4
+3 4 12
+1 12
+1 4 12
+1 3
+1 3 12
+1 3 4
+1 3 4 12
+3 15
+3 4 15
+1 3 15
+1 3 4 15
+10
+3 10
+7
+7 10
+3 7
+3 7 10
+1 10
+1 7
+1 7 10
+1 3 10
+1 3 7
+1 3 7 10
+7 12
+3 7 12
+1 7 12
+1 3 7 12
+10 15
+3 10 15
+1 10 15
+1 3 10 15
+9 12
+4 9 12
+1 9 12
+1 4 9 12
+13
+5
+5 13
+6 13
+5 6
+5 6 13
+1 13
+1 6 13
+1 5
+1 5 13
+1 5 6
+1 5 6 13
+5 14
+5 6 14
+1 5 14
+1 5 6 14
+11
+5 11
+8
+8 11
+5 8
+5 8 11
+1 11
+1 8
+1 8 11
+1 5 11
+1 5 8
+1 5 8 11
+8 13
+5 8 13
+1 8 13
+1 5 8 13
+11 14
+5 11 14
+1 11 14
+1 5 11 14
+13 15
+6 13 15
+1 13 15
+1 6 13 15
+8 10
+7 8
+7 8 10
+1 8 10
+1 7 8
+1 7 8 10
+7 11
+7 8 11
+1 7 11
+1 7 8 11
+11 12
+7 11 12
+1 11 12
+1 7 11 12
+10 13
+8 10 13
+1 10 13
+1 8 10 13
+9 11
+9 11 12
+1 9 11
+1 9 11 12
+9 11 14
+1 9 11 14
+10 13 15
+1 10 13 15
+5 10
+3 5
+3 5 10
+2 10
+2 5
+2 5 10
+2 3
+2 3 10
+2 3 5
+2 3 5 10
+3 11
+3 5 11
+2 11
+2 5 11
+2 3 11
+2 3 5 11
+2 7
+2 7 10
+2 3 7
+2 3 7 10
+3 13
+7 13
+3 7 13
+2 13
+2 7 13
+2 3 13
+2 3 7 13
+11 13
+3 11 13
+2 11 13
+2 3 11 13
+4 13
+9 13
+4 9 13
+2 9 13
+2 4 13
+2 4 9 13
+4 11
+4 11 13
+2 4 11
+2 4 11 13
+11 15
+4 11 15
+2 11 15
+2 4 11 15
+2 8
+2 8 11
+2 5 8
+2 5 8 11
+5 12
+8 12
+5 8 12
+2 12
+2 8 12
+2 5 12
+2 5 8 12
+10 12
+5 10 12
+2 10 12
+2 5 10 12
+6 12
+6 10
+6 10 12
+2 6 12
+2 6 10
+2 6 10 12
+10 14
+6 10 14
+2 10 14
+2 6 10 14
+12 15
+6 12 15
+2 12 15
+2 6 12 15
+7 9
+7 9 13
+2 7 9
+2 7 9 13
+7 14
+7 9 14
+2 7 14
+2 7 9 14
+7 10 14
+2 7 10 14
+8 15
+8 11 15
+2 8 15
+2 8 11 15
+8 12 15
+2 8 12 15
+4 14
+4 5
+4 5 14
+3 14
+3 5 14
+3 4 14
+3 4 5
+3 4 5 14
+5 15
+4 5 15
+3 5 15
+3 4 5 15
+12 14
+4 12 14
+3 12 14
+3 4 12 14
+5 10 15
+3 5 10 15
+3 11 14
+3 5 11 14
+12 13
+7 12 13
+3 12 13
+3 7 12 13
+13 14
+11 13 14
+3 13 14
+3 11 13 14
+12 13 14
+3 12 13 14
+5 7
+6 7
+5 6 7
+4 7
+4 6
+4 6 7
+4 5 7
+4 5 6
+4 5 6 7
+4 6 14
+4 5 6 14
+7 15
+5 7 15
+4 7 15
+4 5 7 15
+6 11
+6 7 11
+4 7 11
+4 6 11
+4 6 7 11
+10 11
+6 10 11
+4 10
+4 10 11
+4 6 10
+4 6 10 11
+4 10 14
+4 6 10 14
+7 11 15
+4 7 11 15
+8 9
+8 9 12
+4 8
+4 8 12
+4 8 9
+4 8 9 12
+8 9 13
+4 8 13
+4 8 9 13
+4 10 13
+4 8 10
+4 8 10 13
+8 14
+8 10 14
+4 8 14
+4 8 10 14
+8 12 14
+4 8 12 14
+10 11 13
+4 10 11 13
+6 7 13
+5 7 13
+5 6 7 13
+5 9
+5 9 13
+5 7 9
+5 7 9 13
+9 15
+7 9 15
+5 9 15
+5 7 9 15
+5 9 12
+5 8 9
+5 8 9 12
+5 8 9 13
+9 10
+9 10 12
+5 9 10
+5 9 10 12
+9 10 15
+5 9 10 15
+6 11 12
+6 7 12
+6 7 11 12
+6 12 13
+6 7 12 13
+10 11 12
+6 10 11 12
+12 13 15
+6 12 13 15
+7 8 14
+7 8 10 14
+7 8 15
+7 8 11 15
+14 15
+8 14 15
+7 14 15
+7 8 14 15
+9 14 15
+7 9 14 15
+12 14 15
+8 12 14 15
+9 10 11
+9 10 11 12
+16
+10 16
+11 16
+10 11 16
+9 16
+9 11 16
+9 10 16
+9 10 11 16
+15 16
+10 15 16
+9 15 16
+9 10 15 16
+14 16
+11 14 16
+9 14 16
+9 11 14 16
+14 15 16
+9 14 15 16
+13 16
+11 13 16
+10 13 16
+10 11 13 16
+13 15 16
+10 13 15 16
+13 14 16
+11 13 14 16
+13 14 15
+12 13 14 15
+13 14 15 16
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/poincare/poincare.cpp	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,86 @@
+#include "topology/simplex.h"
+#include "topology/filtration.h"
+#include "topology/static-persistence.h"
+#include "topology/persistence-diagram.h"
+
+#include <iostream>
+#include <fstream>
+#include <sstream>
+#include <string>
+#include <boost/program_options.hpp>
+
+typedef         Simplex<unsigned, unsigned>     Smplx;
+typedef         Filtration<Smplx>               Fltr;
+typedef         StaticPersistence<>             Persistence;
+typedef         PersistenceDiagram<>            PDgm;
+
+namespace po = boost::program_options;
+
+int main(int argc, char** argv)
+{
+    std::string infilename;
+
+    // Parse program options
+    po::options_description hidden("Hidden options");
+    hidden.add_options()
+        ("input-file",  po::value<std::string>(&infilename),
+                        "Filtration filename");
+
+    po::options_description visible("Allowed options");
+    visible.add_options()
+        ("help,h",      "produce help message");
+    po::positional_options_description p;
+    p.add("input-file", 1);
+    
+    po::options_description all; all.add(visible).add(hidden);
+
+    po::variables_map vm;
+    po::store(po::command_line_parser(argc, argv).
+                  options(all).positional(p).run(), vm);
+    po::notify(vm);
+
+    if (vm.count("help") || !vm.count("input-file"))
+    { 
+        std::cout << "Usage: " << argv[0] << " [options] FILENAME" << std::endl;
+        std::cout << visible << std::endl; 
+        return 1; 
+    }
+
+
+    Fltr f;
+    std::ifstream in(infilename.c_str());
+    unsigned int i = 0;
+    std::string s;
+    std::getline(in, s);
+    while(in)
+    {
+        std::istringstream linestream(s);
+        Smplx simplex(i++);
+        unsigned int vertex;
+        linestream >> vertex;
+        while(linestream)
+        {
+            simplex.add(vertex);
+            linestream >> vertex;
+        }
+        std::cout << simplex << std::endl;
+        f.push_back(simplex);
+        std::getline(in, s);
+    }
+    
+    f.sort(Smplx::DataComparison());
+    Persistence pers(f);
+    pers.pair_simplices();
+
+    Persistence::SimplexMap<Fltr>   m = pers.make_simplex_map(f);
+    std::map<Dimension, PDgm> dgms;
+    init_diagrams(dgms, pers.begin(), pers.end(), 
+                  evaluate_through_map(m, Smplx::DataEvaluator()), 
+                  evaluate_through_map(m, Smplx::DimensionExtractor()));
+
+    std::cout << 0 << std::endl << dgms[0] << std::endl;
+    std::cout << 1 << std::endl << dgms[1] << std::endl;
+    std::cout << 2 << std::endl << dgms[2] << std::endl;
+    std::cout << 3 << std::endl << dgms[3] << std::endl;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/poincare/poincare.dat	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,99 @@
+# 16 vertex triangulation of Poincare sphere
+# made by Bjo"rner and Lutz,
+# in "Simplicial manifolds, bistellar flips and a 16-vertex
+#     triangulation of the Poincar\'e homology 3-sphere",
+#     to appear in Experimental Mathematics.
+# This example has f = (1, 16, 106, 180, 90).
+#
+# Found on Masahiro Hachimori's page at
+# http://infoshako.sk.tsukuba.ac.jp/~hachi/math/library/poincare_eng.html
+1 2 4 9
+1 2 4 15
+1 2 6 14
+1 2 6 15
+1 2 9 14
+1 3 4 12
+1 3 4 15
+1 3 7 10
+1 3 7 12
+1 3 10 15
+1 4 9 12
+1 5 6 13
+1 5 6 14
+1 5 8 11
+1 5 8 13
+1 5 11 14
+1 6 13 15
+1 7 8 10
+1 7 8 11
+1 7 11 12
+1 8 10 13
+1 9 11 12
+1 9 11 14
+1 10 13 15
+2 3 5 10
+2 3 5 11
+2 3 7 10
+2 3 7 13
+2 3 11 13
+2 4 9 13
+2 4 11 13
+2 4 11 15
+2 5 8 11
+2 5 8 12
+2 5 10 12
+2 6 10 12
+2 6 10 14
+2 6 12 15
+2 7 9 13
+2 7 9 14
+2 7 10 14
+2 8 11 15
+2 8 12 15
+3 4 5 14
+3 4 5 15
+3 4 12 14
+3 5 10 15
+3 5 11 14
+3 7 12 13
+3 11 13 14
+3 12 13 14
+4 5 6 7
+4 5 6 14
+4 5 7 15
+4 6 7 11
+4 6 10 11
+4 6 10 14
+4 7 11 15
+4 8 9 12
+4 8 9 13
+4 8 10 13
+4 8 10 14
+4 8 12 14
+4 10 11 13
+5 6 7 13
+5 7 9 13
+5 7 9 15
+5 8 9 12
+5 8 9 13
+5 9 10 12
+5 9 10 15
+6 7 11 12
+6 7 12 13
+6 10 11 12
+6 12 13 15
+7 8 10 14
+7 8 11 15
+7 8 14 15
+7 9 14 15
+8 12 14 15
+9 10 11 12
+9 10 11 16
+9 10 15 16
+9 11 14 16
+9 14 15 16
+10 11 13 16
+10 13 15 16
+11 13 14 16
+12 13 14 15
+13 14 15 16
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/rips/CMakeLists.txt	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,16 @@
+set                         (targets                        
+                             rips
+                             rips-pairwise
+                             rips-weighted
+                             rips-image-zigzag
+                             rips-zigzag)
+                             
+foreach                     (t ${targets})
+    add_executable          (${t} ${t}.cpp)
+    target_link_libraries   (${t} ${libraries} ${Boost_PROGRAM_OPTIONS_LIBRARY} ${Boost_SERIALIZATION_LIBRARY})
+endforeach                  (t ${targets})
+
+add_custom_target           (rips.py ALL 
+                             ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/rips.py ${CMAKE_CURRENT_BINARY_DIR}/rips.py)
+add_custom_target           (rips-pairwise.py ALL 
+                             ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/rips-pairwise.py ${CMAKE_CURRENT_BINARY_DIR}/rips-pairwise.py)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/rips/rips-image-zigzag.cpp	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,452 @@
+#include <topology/rips.h>
+#include <topology/image-zigzag-persistence.h>
+#include <utilities/types.h>
+#include <utilities/containers.h>
+
+#include <utilities/log.h>
+#include <utilities/memory.h>       // for report_memory()
+#include <utilities/timer.h>
+
+#include <geometry/l2distance.h>    // for L2Distance and read_points()
+#include <geometry/distances.h>
+
+#include <map>
+#include <cmath>
+#include <fstream>
+#include <stack>
+#include <cstdlib>
+
+#include <boost/tuple/tuple.hpp>
+#include <boost/program_options.hpp>
+#include <boost/progress.hpp>
+
+
+#ifdef COUNTERS
+static Counter*  cComplexSize =                     GetCounter("rips/size");
+static Counter*  cOperations =                      GetCounter("rips/operations");
+#endif // COUNTERS
+
+typedef     PairwiseDistances<PointContainer, L2Distance>           PairDistances;
+typedef     PairDistances::DistanceType                             DistanceType;
+
+typedef     PairDistances::IndexType                                Vertex;
+typedef     Simplex<Vertex>                                         Smplx;
+typedef     std::vector<Smplx>                                      SimplexVector;
+typedef     std::list<Smplx>                                        SimplexList;
+typedef     std::set<Smplx, Smplx::VertexDimensionComparison>       SimplexSet;
+
+typedef     std::vector<Vertex>                                     VertexVector;
+typedef     std::vector<DistanceType>                               EpsilonVector;
+typedef     std::vector<std::pair<Vertex, Vertex> >                 EdgeVector;
+
+typedef     Rips<PairDistances, Smplx>                              RipsGenerator;
+typedef     RipsGenerator::Evaluator                                SimplexEvaluator;
+
+struct      BirthInfo;
+typedef     ImageZigzagPersistence<BirthInfo>                       Zigzag;
+typedef     Zigzag::SimplexIndex                                    Index;
+typedef     Zigzag::Death                                           Death;
+typedef     std::map<Smplx, Index, 
+                            Smplx::VertexDimensionComparison>       Complex;
+typedef     Zigzag::ZColumn                                         Boundary;
+
+// Information we need to know when a class dies
+struct      BirthInfo
+{
+                    BirthInfo(DistanceType dist = DistanceType(), Dimension dim = Dimension()):
+                        distance(dist), dimension(dim)              {}
+    DistanceType    distance;
+    Dimension       dimension;
+};
+
+// Forward declarations of auxilliary functions
+void        report_death(std::ofstream& out, Death d, DistanceType epsilon, Dimension skeleton_dimension);
+void        make_boundary(const Smplx& s, Complex& c, const Zigzag& zz, Boundary& b);
+void        show_image_betti(Zigzag& zz, Dimension skeleton);
+std::ostream&   operator<<(std::ostream& out, const BirthInfo& bi);
+void        process_command_line_options(int           argc,
+                                         char*         argv[],
+                                         unsigned&     skeleton_dimension,
+                                         float&        from_multiplier, 
+                                         float&        to_multiplier,
+                                         std::string&  infilename,
+                                         std::string&  outfilename);
+
+int main(int argc, char* argv[])
+{
+#ifdef LOGGING
+    rlog::RLogInit(argc, argv);
+
+    stderrLog.subscribeTo( RLOG_CHANNEL("error") );
+#endif
+
+    Timer total, remove, add, ec, vc;
+    total.start();
+ 
+#if 0
+    SetFrequency(cOperations, 25000);
+    SetTrigger(cOperations, cComplexSize);
+#endif
+
+    unsigned        skeleton_dimension;
+    float           from_multiplier, to_multiplier;
+    std::string     infilename, outfilename;
+    process_command_line_options(argc, argv, skeleton_dimension, from_multiplier, to_multiplier, infilename, outfilename);
+
+    // Read in points
+    PointContainer      points;
+    read_points(infilename, points);
+    
+    // Create output file
+    std::ofstream out(outfilename.c_str());
+
+    // Create pairwise distances
+    PairDistances distances(points);
+    
+    // Order vertices and epsilons (in maxmin fashion)
+    VertexVector        vertices;
+    EpsilonVector       epsilons;
+    EdgeVector          edges;
+
+    {
+        EpsilonVector   dist(distances.size(), Infinity);
+    
+        vertices.push_back(distances.begin());
+        //epsilons.push_back(Infinity);
+        while (vertices.size() < distances.size())
+        {
+            for (Vertex v = distances.begin(); v != distances.end(); ++v)
+                dist[v] = std::min(dist[v], distances(v, vertices.back()));
+            EpsilonVector::const_iterator max = std::max_element(dist.begin(), dist.end());
+            vertices.push_back(max - dist.begin());
+            epsilons.push_back(*max);
+        }
+        epsilons.push_back(0);
+    }
+
+    rInfo("Point and epsilon ordering:");
+    for (unsigned i = 0; i < vertices.size(); ++i)
+        rInfo("  %4d: %4d - %f", i, vertices[i], epsilons[i]);
+
+    // Generate and sort all the edges
+    for (unsigned i = 0; i != vertices.size(); ++i)
+        for (unsigned j = i+1; j != vertices.size(); ++j)
+        {
+            Vertex u = vertices[i];
+            Vertex v = vertices[j];
+            if (distances(u,v) <= to_multiplier*epsilons[j-1])
+                edges.push_back(std::make_pair(u,v));
+        }
+    std::sort(edges.begin(), edges.end(), RipsGenerator::ComparePair(distances));
+    rInfo("Total participating edges: %d", edges.size());
+    for (EdgeVector::const_iterator cur = edges.begin(); cur != edges.end(); ++cur)
+        rDebug("  (%d, %d) %f", cur->first, cur->second, distances(cur->first, cur->second));
+
+    // Construct zigzag
+    Complex             complex;
+    Zigzag              zz;
+    RipsGenerator       rips(distances);
+    SimplexEvaluator    size(distances);
+    
+    // Insert vertices
+    for (unsigned i = 0; i != vertices.size(); ++i)
+    {
+        // Add a vertex
+        Smplx sv; sv.add(vertices[i]);
+        rDebug("Adding %s", tostring(sv).c_str());
+        add.start();
+        complex.insert(std::make_pair(sv, 
+                                      zz.add(Boundary(), 
+                                             true,         // vertex is always in the subcomplex
+                                             BirthInfo(0, 0)).first));
+        add.stop();
+        //rDebug("Newly born cycle order: %d", complex[sv]->low->order);
+        CountNum(cComplexSize, 0);
+        Count(cComplexSize);
+        Count(cOperations);
+    }
+
+    rInfo("Commencing computation");
+    boost::progress_display show_progress(vertices.size());
+    unsigned sce    = 0,        // index of the current one past last edge in the subcomplex
+             ce     = 0;        // index of the current one past last edge in the complex
+    for (unsigned stage = 0; stage != vertices.size() - 1; ++stage)
+    {
+        unsigned i = vertices.size() - 1 - stage;
+        rInfo("Current stage %d: %d %f: %f -> %f", stage, 
+                                                   vertices[i], epsilons[i-1],
+                                                   from_multiplier*epsilons[i-1],
+                                                   to_multiplier*epsilons[i-1]);
+
+        /* Increase epsilon */
+        // Record the cofaces of all the simplices that need to be removed and reinserted
+        SimplexSet cofaces;
+        rDebug("  Cofaces size: %d", cofaces.size());
+        while(sce < ce)
+        {
+            Vertex u,v;
+            boost::tie(u,v)     = edges[sce];
+            if (distances(u,v) <= from_multiplier*epsilons[i-1])
+                ++sce;
+            else
+                break;
+
+            // Skip an edge if any one of its vertices has been removed from the complex
+            bool skip_edge = false;
+            for (unsigned j = i+1; j != vertices.size(); ++j)
+                if (u == vertices[j] || v == vertices[j])
+                {
+                    // Debug only: eventually remove
+                    rDebug("  Skipping edge (%d, %d)", u, v);
+                    Smplx s; s.add(u); s.add(v);
+                    AssertMsg(complex.find(s) == complex.end(), "Simplex should not be in the complex.");
+                    skip_edge = true;
+                    break;
+                }
+            if (skip_edge) continue;
+            rDebug("  Generating cofaces for (%d, %d)", u, v);
+        
+            ec.start();
+            rips.edge_cofaces(u, v, 
+                              skeleton_dimension, 
+                              to_multiplier*epsilons[i], 
+                              make_insert_functor(cofaces),
+                              vertices.begin(),
+                              vertices.begin() + i + 1);
+            ec.stop();
+        }
+        rDebug("  Recorded cofaces to remove");
+        rDebug("  Cofaces size: %d", cofaces.size());
+        // Remove all the cofaces
+        for (SimplexSet::const_reverse_iterator cur = cofaces.rbegin(); cur != (SimplexSet::const_reverse_iterator)cofaces.rend(); ++cur)
+        {
+            rDebug("    Removing %s", tostring(*cur).c_str());
+            Complex::iterator si = complex.find(*cur);
+            remove.start();
+            AssertMsg(!si->second->subcomplex, "We should not remove simplices already in the subcomplex when we increase epsilon");
+            Death d = zz.remove(si->second,
+                                BirthInfo(epsilons[i-1], cur->dimension() - 1));
+            remove.stop();
+            complex.erase(si);
+            CountNumBy(cComplexSize, cur->dimension(), -1);
+            CountBy(cComplexSize, -1);
+            Count(cOperations);
+            AssertMsg(zz.check_consistency(), "Zigzag representation must be consistent after removing a simplex");
+            report_death(out, d, epsilons[i-1], skeleton_dimension);
+        }
+        rDebug("  Removed cofaces");
+
+        // Add anything else that needs to be inserted into the complex
+        while (ce < edges.size())
+        {
+            Vertex u,v;
+            boost::tie(u,v)     = edges[ce];
+            if (distances(u,v) <= to_multiplier*epsilons[i-1])
+                ++ce;
+            else
+                break;
+            rDebug("  Recording cofaces of edges[%d]=(%d, %d) with size=%f", (ce-1), u, v, distances(u,v));
+            ec.start();
+            rips.edge_cofaces(u, v, 
+                              skeleton_dimension, 
+                              to_multiplier*epsilons[i-1], 
+                              make_insert_functor(cofaces),
+                              vertices.begin(),
+                              vertices.begin() + i + 1);
+            ec.stop();
+        }
+        rDebug("  Recorded new cofaces to add");
+
+        // Progress sce
+        while (sce < ce)
+        {
+            Vertex u,v;
+            boost::tie(u,v)     = edges[sce];
+            rDebug("    Progressing sce=%d over (%d, %d) %f", sce, u, v, distances(u,v));
+            if (distances(u,v) <= from_multiplier*epsilons[i-1])   
+                ++sce;
+            else
+                break;
+        }
+        rDebug("  Moved subcomplex index forward");
+
+        // Insert all the cofaces
+        rDebug("  Cofaces size: %d", cofaces.size());
+        for (SimplexSet::const_iterator cur = cofaces.begin(); cur != cofaces.end(); ++cur)
+        {
+            Index idx; Death d; Boundary b;
+            rDebug("  Adding %s, its size %f", tostring(*cur).c_str(), size(*cur));
+            make_boundary(*cur, complex, zz, b);
+            add.start();
+            boost::tie(idx, d)  = zz.add(b,
+                                         size(*cur) <= from_multiplier*epsilons[i-1],
+                                         BirthInfo(epsilons[i-1], cur->dimension()));
+            add.stop();
+            //if (!d) rDebug("Newly born cycle order: %d", complex[*cur]->low->order);
+            CountNum(cComplexSize, cur->dimension());
+            Count(cComplexSize);
+            Count(cOperations);
+            AssertMsg(zz.check_consistency(), "Zigzag representation must be consistent after removing a simplex");
+            complex.insert(std::make_pair(*cur, idx));
+            report_death(out, d, epsilons[i-1], skeleton_dimension);
+        }
+        rInfo("Increased epsilon; complex size: %d", complex.size());
+        show_image_betti(zz, skeleton_dimension);
+        report_memory();
+        
+        /* Remove the vertex */
+        cofaces.clear();
+        rDebug("  Cofaces size: %d", cofaces.size());
+        vc.start();
+        rips.vertex_cofaces(vertices[i], 
+                            skeleton_dimension, 
+                            to_multiplier*epsilons[i-1], 
+                            make_insert_functor(cofaces),
+                            vertices.begin(),
+                            vertices.begin() + i + 1);
+        vc.stop();
+        rDebug("  Computed cofaces of the vertex, their number: %d", cofaces.size());
+        for (SimplexSet::const_reverse_iterator cur = cofaces.rbegin(); cur != (SimplexSet::const_reverse_iterator)cofaces.rend(); ++cur)
+        {
+            rDebug("    Removing: %s", tostring(*cur).c_str());
+            Complex::iterator si = complex.find(*cur);
+            remove.start();
+            Death d = zz.remove(si->second,
+                                BirthInfo(epsilons[i-1], cur->dimension() - 1));
+            remove.stop();
+            complex.erase(si);
+            CountNumBy(cComplexSize, cur->dimension(), -1);
+            CountBy(cComplexSize, -1);
+            Count(cOperations);
+            AssertMsg(zz.check_consistency(), "Zigzag representation must be consistent after removing a simplex");
+            report_death(out, d, epsilons[i-1], skeleton_dimension);
+        }
+        rInfo("Removed vertex; complex size: %d", complex.size());
+        for (Complex::const_iterator cur = complex.begin(); cur != complex.end(); ++cur)
+            rDebug("  %s", tostring(cur->first).c_str());
+        show_image_betti(zz, skeleton_dimension);
+        report_memory();
+        
+        ++show_progress;
+    }
+    
+    // Remove the last vertex
+    AssertMsg(complex.size() == 1, "Only one vertex must remain");
+    remove.start();
+    Death d = zz.remove(complex.begin()->second, BirthInfo(epsilons[0], -1));
+    remove.stop();
+    complex.erase(complex.begin());
+    if (!d)  AssertMsg(false,  "The vertex must have died");
+    report_death(out, d, epsilons[0], skeleton_dimension);
+    CountNumBy(cComplexSize, 0, -1);
+    CountBy(cComplexSize, -1);
+    Count(cOperations);
+    rInfo("Removed vertex; complex size: %d", complex.size());
+    ++show_progress;
+
+    total.stop();
+
+    remove.check("Remove timer          ");
+    add.check   ("Add timer             ");
+    ec.check    ("Edge coface timer     ");
+    vc.check    ("Vertex coface timer   ");
+    total.check ("Total timer           ");
+}
+
+
+            
+void        report_death(std::ofstream& out, Death d, DistanceType epsilon, Dimension skeleton_dimension)
+{
+    if (d && ((d->distance - epsilon) != 0) && (d->dimension < skeleton_dimension))
+        out << d->dimension << " " << d->distance << " " << epsilon << std::endl;
+}
+
+void        make_boundary(const Smplx& s, Complex& c, const Zigzag& zz, Boundary& b)
+{
+    rDebug("  Boundary of <%s>", tostring(s).c_str());
+    for (Smplx::BoundaryIterator cur = s.boundary_begin(); cur != s.boundary_end(); ++cur)
+    {
+        b.append(c[*cur], zz.cmp);
+        rDebug("   %d (inL=%d)", c[*cur]->order, b.back()->subcomplex);
+    }
+}
+
+bool        face_leaving_subcomplex(Complex::reverse_iterator si, const SimplexEvaluator& size, DistanceType after, DistanceType before)
+{
+    const Smplx& s = si->first;
+    for (Smplx::VertexContainer::const_iterator v1 = s.vertices().begin(); v1 != s.vertices().end(); ++v1)
+        for (Smplx::VertexContainer::const_iterator v2 = boost::next(v1); v2 != s.vertices().end(); ++v2)
+        {
+            Smplx e; e.add(*v1); e.add(*v2);
+            if (size(e) > after && size(e) <= before)
+                return true;
+        }
+
+    return false;
+}
+
+void        show_image_betti(Zigzag& zz, Dimension skeleton)
+{
+    for (Zigzag::ZIndex cur = zz.image_begin(); cur != zz.image_end(); ++cur)
+        if (cur->low == zz.boundary_end() && cur->birth.dimension < skeleton)
+            rInfo("Class in the image of dimension: %d",  cur->birth.dimension);
+}
+
+
+std::ostream&   operator<<(std::ostream& out, const BirthInfo& bi)
+{ return (out << bi.distance); }
+
+void        process_command_line_options(int           argc, 
+                                         char*         argv[],
+                                         unsigned&     skeleton_dimension,
+                                         float&        from_multiplier, 
+                                         float&        to_multiplier,
+                                         std::string&  infilename,
+                                         std::string&  outfilename)
+{
+    namespace po = boost::program_options;
+
+    po::options_description hidden("Hidden options");
+    hidden.add_options()
+        ("input-file",          po::value<std::string>(&infilename),        "Point set whose Rips zigzag we want to compute")
+        ("output-file",         po::value<std::string>(&outfilename),       "Location to save persistence pairs");
+    
+    po::options_description visible("Allowed options", 100);
+    visible.add_options()
+        ("help,h",                                                                              "produce help message")
+        ("skeleton-dimsnion,s", po::value<unsigned>(&skeleton_dimension)->default_value(2),     "Dimension of the Rips complex we want to compute")
+        ("from,f",              po::value<float>(&from_multiplier)->default_value(4),           "From multiplier for the epsilon (distance to next maxmin point) when computing the Rips complex")
+        ("to,t",                po::value<float>(&to_multiplier)->default_value(16),            "To multiplier for the epsilon (distance to next maxmin point) when computing the Rips complex");
+#if LOGGING
+    std::vector<std::string>    log_channels;
+    visible.add_options()
+        ("log,l",               po::value< std::vector<std::string> >(&log_channels),           "log channels to turn on (info, debug, etc)");
+#endif
+
+    po::positional_options_description pos;
+    pos.add("input-file", 1);
+    pos.add("output-file", 2);
+    
+    po::options_description all; all.add(visible).add(hidden);
+
+    po::variables_map vm;
+    po::store(po::command_line_parser(argc, argv).
+                  options(all).positional(pos).run(), vm);
+    po::notify(vm);
+
+#if LOGGING
+    for (std::vector<std::string>::const_iterator cur = log_channels.begin(); cur != log_channels.end(); ++cur)
+        stderrLog.subscribeTo( RLOG_CHANNEL(cur->c_str()) );
+    /**
+     * Interesting channels
+     * "info", "debug", "topology/persistence"
+     */
+#endif
+
+    if (vm.count("help") || !vm.count("input-file") || !vm.count("output-file"))
+    { 
+        std::cout << "Usage: " << argv[0] << " [options] input-file output-file" << std::endl;
+        std::cout << visible << std::endl; 
+        std::abort();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/rips/rips-pairwise.cpp	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,147 @@
+#include <topology/rips.h>
+#include <topology/filtration.h>
+#include <topology/static-persistence.h>
+#include <topology/dynamic-persistence.h>
+#include <topology/persistence-diagram.h>
+
+#include <geometry/l2distance.h>
+#include <geometry/distances.h>
+
+#include <utilities/containers.h>           // for BackInsertFunctor
+#include <utilities/timer.h>
+
+#include <vector>
+
+#include <boost/program_options.hpp>
+
+
+typedef         PairwiseDistances<PointContainer, L2Distance>           PairDistances;
+typedef         PairDistances::DistanceType                             DistanceType;
+typedef         PairDistances::IndexType                                Vertex;
+
+typedef         Rips<PairDistances>                                     Generator;
+typedef         Generator::Simplex                                      Smplx;
+typedef         Filtration<Smplx>                                       Fltr;
+// typedef         StaticPersistence<>                                     Persistence;
+typedef         DynamicPersistenceChains<>                              Persistence;
+typedef         PersistenceDiagram<>                                    PDgm;
+
+void            program_options(int argc, char* argv[], std::string& infilename, Dimension& skeleton, DistanceType& max_distance, std::string& diagram_name);
+
+int main(int argc, char* argv[])
+{
+    Dimension               skeleton;
+    DistanceType            max_distance;
+    std::string             infilename, diagram_name;
+
+    program_options(argc, argv, infilename, skeleton, max_distance, diagram_name);
+    std::ofstream           diagram_out(diagram_name.c_str());
+    std::cout << "Diagram:         " << diagram_name << std::endl;
+
+    PointContainer          points;
+    read_points(infilename, points);
+
+    PairDistances           distances(points);
+    Generator               rips(distances);
+    Generator::Evaluator    size(distances);
+    Fltr                    f;
+    
+    // Generate 2-skeleton of the Rips complex for epsilon = 50
+    rips.generate(skeleton, max_distance, make_push_back_functor(f));
+    std::cout << "# Generated complex of size: " << f.size() << std::endl;
+
+    // Generate filtration with respect to distance and compute its persistence
+    f.sort(Generator::Comparison(distances));
+
+    Timer persistence_timer; persistence_timer.start();
+    Persistence p(f);
+    p.pair_simplices();
+    persistence_timer.stop();
+
+#if 1
+    // Output cycles
+    Persistence::SimplexMap<Fltr>   m = p.make_simplex_map(f);
+    for (Persistence::iterator cur = p.begin(); cur != p.end(); ++cur)
+    {
+        const Persistence::Cycle& cycle = cur->cycle;
+
+        if (!cur->sign())        // only negative simplices have non-empty cycles
+        {
+            Persistence::OrderIndex birth = cur->pair;      // the cycle that cur killed was born when we added birth (another simplex)
+
+            const Smplx& b = m[birth];
+            const Smplx& d = m[cur];
+            
+            // if (b.dimension() != 1) continue;
+            // std::cout << "Pair: (" << size(b) << ", " << size(d) << ")" << std::endl;
+            if (b.dimension() >= skeleton) continue;
+            diagram_out << b.dimension() << " " << size(b) << " " << size(d) << std::endl;
+        } else if (cur->unpaired())    // positive could be unpaired
+        {
+            const Smplx& b = m[cur];
+            // if (b.dimension() != 1) continue;
+            
+            // std::cout << "Unpaired birth: " << size(b) << std::endl;
+            // cycle = cur->chain;      // TODO
+            if (b.dimension() >= skeleton) continue;
+            diagram_out << b.dimension() << " " << size(b) << " inf" << std::endl;
+        }
+
+        // Iterate over the cycle
+        // for (Persistence::Cycle::const_iterator si =  cycle.begin();
+        //                                                          si != cycle.end();     ++si)
+        // {
+        //     const Smplx& s = m[*si];
+        //     //std::cout << s.dimension() << std::endl;
+        //     const Smplx::VertexContainer& vertices = s.vertices();          // std::vector<Vertex> where Vertex = Distances::IndexType
+        //     AssertMsg(vertices.size() == s.dimension() + 1, "dimension of a simplex is one less than the number of its vertices");
+        //     std::cout << vertices[0] << " " << vertices[1] << std::endl;
+        // }
+    }
+#endif
+    
+    persistence_timer.check("# Persistence timer");
+}
+
+void        program_options(int argc, char* argv[], std::string& infilename, Dimension& skeleton, DistanceType& max_distance, std::string& diagram_name)
+{
+    namespace po = boost::program_options;
+
+    po::options_description     hidden("Hidden options");
+    hidden.add_options()
+        ("input-file",          po::value<std::string>(&infilename),        "Point set whose Rips zigzag we want to compute");
+    
+    po::options_description visible("Allowed options", 100);
+    visible.add_options()
+        ("help,h",                                                                                  "produce help message")
+        ("skeleton-dimsnion,s", po::value<Dimension>(&skeleton)->default_value(2),                  "Dimension of the Rips complex we want to compute")
+        ("max-distance,m",      po::value<DistanceType>(&max_distance)->default_value(Infinity),    "Maximum value for the Rips complex construction")
+        ("diagram,d",           po::value<std::string>(&diagram_name),                              "Filename where to output the persistence diagram");
+#if LOGGING
+    std::vector<std::string>    log_channels;
+    visible.add_options()
+        ("log,l",               po::value< std::vector<std::string> >(&log_channels),           "log channels to turn on (info, debug, etc)");
+#endif
+
+    po::positional_options_description pos;
+    pos.add("input-file", 1);
+    
+    po::options_description all; all.add(visible).add(hidden);
+
+    po::variables_map vm;
+    po::store(po::command_line_parser(argc, argv).
+                  options(all).positional(pos).run(), vm);
+    po::notify(vm);
+
+#if LOGGING
+    for (std::vector<std::string>::const_iterator cur = log_channels.begin(); cur != log_channels.end(); ++cur)
+        stderrLog.subscribeTo( RLOG_CHANNEL(cur->c_str()) );
+#endif
+
+    if (vm.count("help") || !vm.count("input-file"))
+    { 
+        std::cout << "Usage: " << argv[0] << " [options] input-file" << std::endl;
+        std::cout << visible << std::endl; 
+        std::abort();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/rips/rips-pairwise.py	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,58 @@
+#/usr/bin/env python
+
+
+from    dionysus    import Rips, PairwiseDistances, StaticPersistence, Filtration, points_file, \
+                           ExplicitDistances, data_dim_cmp
+from    sys         import argv, exit
+import  time
+
+def main(filename, skeleton, max):
+    points = [p for p in points_file(filename)]
+    distances = PairwiseDistances(points)
+    # distances = ExplicitDistances(distances)           # speeds up generation of the Rips complex at the expense of memory usage
+    rips = Rips(distances)
+    print time.asctime(), "Rips initialized"
+
+    simplices = Filtration()
+    rips.generate(skeleton, max, simplices.append)
+    print time.asctime(), "Generated complex: %d simplices" % len(simplices)
+
+    # While this step is unnecessary (Filtration below can be passed rips.cmp), 
+    # it greatly speeds up the running times
+    for s in simplices: s.data = rips.eval(s)
+    print time.asctime(), simplices[0], '...', simplices[-1]
+
+    simplices.sort(data_dim_cmp)             # could be rips.cmp if s.data for s in simplices is not set
+    print time.asctime(), "Set up filtration"
+
+    p = StaticPersistence(simplices)
+    print time.asctime(), "Initialized StaticPersistence"
+
+    p.pair_simplices()
+    print time.asctime(), "Simplices paired"
+
+    print "Outputting persistence diagram"
+    smap = p.make_simplex_map(simplices)
+    for i in p:
+        if i.sign():
+            b = smap[i]
+
+            if b.dimension() >= skeleton: continue
+
+            if i.unpaired():
+                print b.dimension(), b.data, "inf"
+                continue
+
+            d = smap[i.pair()]
+            print b.dimension(), b.data, d.data
+
+if __name__ == '__main__':
+    if len(argv) < 4:
+        print "Usage: %s POINTS SKELETON MAX" % argv[0]
+        exit()
+
+    filename = argv[1]
+    skeleton = int(argv[2])
+    max = float(argv[3])
+
+    main(filename, skeleton, max)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/rips/rips-weighted.cpp	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,144 @@
+#include <topology/weighted-rips.h>
+#include <topology/filtration.h>
+#include <topology/static-persistence.h>
+#include <topology/dynamic-persistence.h>
+#include <topology/persistence-diagram.h>
+
+//#define RIPS_CLOSURE_CECH_SKELETON
+#ifndef RIPS_CLOSURE_CECH_SKELETON
+#include <geometry/weighted-l2distance.h>
+#else
+#include <geometry/weighted-cechdistance.h>
+#endif
+
+#include <geometry/distances.h>
+
+#include <utilities/containers.h>           // for BackInsertFunctor
+#include <utilities/timer.h>
+
+#include <vector>
+
+#include <boost/program_options.hpp>
+
+
+typedef         PairwiseDistances<PointContainer, WeightedL2Distance>   PairDistances;
+typedef         PairDistances::DistanceType                             DistanceType;
+typedef         PairDistances::IndexType                                Vertex;
+
+typedef         WeightedRips<PairDistances>                             Generator;
+typedef         Generator::Simplex                                      Smplx;
+typedef         Filtration<Smplx>                                       Fltr;
+typedef         StaticPersistence<>                                     Persistence;
+//typedef         DynamicPersistenceChains<>                              Persistence;
+typedef         PersistenceDiagram<>                                    PDgm;
+
+void            program_options(int argc, char* argv[], std::string& infilename, Dimension& skeleton, DistanceType& max_distance);
+
+int main(int argc, char* argv[])
+{
+#ifdef LOGGING
+    rlog::RLogInit(argc, argv);
+
+    stderrLog.subscribeTo( RLOG_CHANNEL("error") );
+#endif
+
+    Dimension               skeleton;
+    DistanceType            max_distance;
+    std::string             infilename;
+
+    program_options(argc, argv, infilename, skeleton, max_distance);
+
+    PointContainer          points;
+    read_weighted_points(infilename, points);
+
+    PairDistances           distances(points);
+    Generator               rips(distances);
+    Generator::Evaluator    size(distances);
+    Generator::Comparison   cmp (distances);
+    Fltr                    complex;
+    
+    // Generate skeleton of the weighted Rips complex for epsilon = 50
+    rips.generate(skeleton, max_distance, make_push_back_functor(complex));
+    std::cout << "# Generated complex of size: " << complex.size() << std::endl;
+
+    // Generate filtration with respect to distance and compute its persistence
+    complex.sort(cmp);
+
+    Timer persistence_timer; persistence_timer.start();
+    Persistence p(complex);
+    p.pair_simplices();
+    persistence_timer.stop();
+
+    // Output cycles
+    Persistence::SimplexMap<Fltr>   m = p.make_simplex_map(complex);
+    for (Persistence::iterator cur = p.begin(); cur != p.end(); ++cur)
+    {
+        const Persistence::Cycle& cycle = cur->cycle;
+
+        if (!cur->sign())        // only negative simplices have non-empty cycles
+        {
+            Persistence::OrderIndex birth = cur->pair;      // the cycle that cur killed was born when we added birth (another simplex)
+
+            const Smplx& b = m[birth];
+            const Smplx& d = m[cur];
+            
+            if (b.dimension() >= skeleton) continue;
+            std::cout << b.dimension() << " " << size(b) << " " << size(d) << std::endl;
+        } else if (cur->unpaired())    // positive could be unpaired
+        {
+            const Smplx& b = m[cur];
+            if (b.dimension() >= skeleton) continue;
+            
+            std::cout << b.dimension() << " " << size(b) << " inf" << std::endl;
+            //cycle = cur->chain;
+        }
+    }
+    
+    persistence_timer.check("# Persistence timer");
+}
+
+void        program_options(int argc, char* argv[], std::string& infilename, Dimension& skeleton, DistanceType& max_distance)
+{
+    namespace po = boost::program_options;
+
+    po::options_description     hidden("Hidden options");
+    hidden.add_options()
+        ("input-file",          po::value<std::string>(&infilename),        "Point set whose weighed Rips zigzag we want to compute");
+    
+    po::options_description visible("Allowed options", 100);
+    visible.add_options()
+        ("help,h",                                                                                  "produce help message")
+        ("skeleton-dimsnion,s", po::value<Dimension>(&skeleton)->default_value(2),                  "Dimension of the weighted Rips complex we want to compute")
+        ("max-distance,m",      po::value<DistanceType>(&max_distance)->default_value(Infinity),    "Maximum value for the weighted Rips complex construction");
+#if LOGGING
+    std::vector<std::string>    log_channels;
+    visible.add_options()
+        ("log,l",               po::value< std::vector<std::string> >(&log_channels),           "log channels to turn on (info, debug, etc)");
+#endif
+
+    po::positional_options_description pos;
+    pos.add("input-file", 1);
+    
+    po::options_description all; all.add(visible).add(hidden);
+
+    po::variables_map vm;
+    po::store(po::command_line_parser(argc, argv).
+                  options(all).positional(pos).run(), vm);
+    po::notify(vm);
+
+#if LOGGING
+    for (std::vector<std::string>::const_iterator cur = log_channels.begin(); cur != log_channels.end(); ++cur)
+        stderrLog.subscribeTo( RLOG_CHANNEL(cur->c_str()) );
+    /**
+     * Interesting channels
+     * "info", "debug", "topology/persistence"
+     */
+#endif
+
+    if (vm.count("help") || !vm.count("input-file"))
+    { 
+        std::cout << "Usage: " << argv[0] << " [options] input-file" << std::endl;
+        std::cout << visible << std::endl; 
+        std::abort();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/rips/rips-zigzag.cpp	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,353 @@
+#include <topology/rips.h>
+#include <topology/zigzag-persistence.h>
+#include <utilities/types.h>
+#include <utilities/containers.h>
+
+#include <geometry/l2distance.h>    // Point, PointContainer, L2DistanceType, read_points
+#include <geometry/distances.h>
+
+#include <utilities/log.h>
+#include <utilities/memory.h>       // for report_memory()
+#include <utilities/timer.h>
+
+#include <map>
+#include <cmath>
+#include <fstream>
+#include <stack>
+#include <cstdlib>
+
+#include <boost/tuple/tuple.hpp>
+#include <boost/program_options.hpp>
+#include <boost/progress.hpp>
+
+#ifdef COUNTERS
+static Counter*  cComplexSize =                     GetCounter("rips/size");
+static Counter*  cOperations =                      GetCounter("rips/operations");
+#endif // COUNTERS
+
+typedef     PairwiseDistances<PointContainer, L2Distance>           PairDistances;
+typedef     PairDistances::DistanceType                             DistanceType;
+
+typedef     PairDistances::IndexType                                Vertex;
+typedef     Simplex<Vertex>                                         Smplx;
+typedef     std::vector<Smplx>                                      SimplexVector;
+typedef     std::list<Smplx>                                        SimplexList;
+typedef     std::set<Smplx, Smplx::VertexDimensionComparison>       SimplexSet;
+
+typedef     std::vector<Vertex>                                     VertexVector;
+typedef     std::vector<DistanceType>                               EpsilonVector;
+typedef     std::vector<std::pair<Vertex, Vertex> >                 EdgeVector;
+
+typedef     Rips<PairDistances, Smplx>                              RipsGenerator;
+typedef     RipsGenerator::Evaluator                                SimplexEvaluator;
+
+struct      BirthInfo;
+typedef     ZigzagPersistence<BirthInfo>                            Zigzag;
+typedef     Zigzag::SimplexIndex                                    Index;
+typedef     Zigzag::Death                                           Death;
+typedef     std::map<Smplx, Index, 
+                            Smplx::VertexDimensionComparison>       Complex;
+typedef     Zigzag::ZColumn                                         Boundary;
+
+// Information we need to know when a class dies
+struct      BirthInfo
+{
+                    BirthInfo(DistanceType dist = DistanceType(), Dimension dim = Dimension()):
+                        distance(dist), dimension(dim)              {}
+    DistanceType    distance;
+    Dimension       dimension;
+};
+
+// Forward declarations of auxilliary functions
+void        report_death(std::ostream& out, Death d, DistanceType epsilon, Dimension skeleton_dimension);
+void        make_boundary(const Smplx& s, Complex& c, const Zigzag& zz, Boundary& b);
+std::ostream&   operator<<(std::ostream& out, const BirthInfo& bi);
+void        process_command_line_options(int           argc,
+                                         char*         argv[],
+                                         unsigned&     skeleton_dimension,
+                                         float&        multiplier,
+                                         std::string&  infilename,
+                                         std::string&  outfilename);
+
+int main(int argc, char* argv[])
+{
+#ifdef LOGGING
+    rlog::RLogInit(argc, argv);
+
+    stderrLog.subscribeTo( RLOG_CHANNEL("error") );
+#endif
+
+    Timer total, remove, add, ec, vc;
+    total.start();
+ 
+#if 0
+    SetFrequency(cOperations, 25000);
+    SetTrigger(cOperations, cComplexSize);
+#endif
+
+    unsigned        skeleton_dimension;
+    float           multiplier;
+    std::string     infilename, outfilename;
+    process_command_line_options(argc, argv, skeleton_dimension, multiplier, infilename, outfilename);
+
+    // Read in points
+    PointContainer      points;
+    read_points(infilename, points);
+    
+    // Create output file
+    std::ofstream out(outfilename.c_str());
+
+    // Create pairwise distances
+    PairDistances distances(points);
+    
+    // Order vertices and epsilons (in maxmin fashion)
+    VertexVector        vertices;
+    EpsilonVector       epsilons;
+    EdgeVector          edges;
+
+    {
+        EpsilonVector   dist(distances.size(), Infinity);
+    
+        vertices.push_back(distances.begin());
+        //epsilons.push_back(Infinity);
+        while (vertices.size() < distances.size())
+        {
+            for (Vertex v = distances.begin(); v != distances.end(); ++v)
+                dist[v] = std::min(dist[v], distances(v, vertices.back()));
+            EpsilonVector::const_iterator max = std::max_element(dist.begin(), dist.end());
+            vertices.push_back(max - dist.begin());
+            epsilons.push_back(*max);
+        }
+        epsilons.push_back(0);
+    }
+
+    rInfo("Point and epsilon ordering:");
+    for (unsigned i = 0; i < vertices.size(); ++i)
+        rInfo("  %4d: %4d - %f", i, vertices[i], epsilons[i]);
+
+    // Generate and sort all the edges
+    for (unsigned i = 0; i != vertices.size(); ++i)
+        for (unsigned j = i+1; j != vertices.size(); ++j)
+        {
+            Vertex u = vertices[i];
+            Vertex v = vertices[j];
+            if (distances(u,v) <= multiplier*epsilons[j-1])
+                edges.push_back(std::make_pair(u,v));
+        }
+    std::sort(edges.begin(), edges.end(), RipsGenerator::ComparePair(distances));
+    rInfo("Total participating edges: %d", edges.size());
+    for (EdgeVector::const_iterator cur = edges.begin(); cur != edges.end(); ++cur)
+        rDebug("  (%d, %d) %f", cur->first, cur->second, distances(cur->first, cur->second));
+
+    // Construct zigzag
+    Complex             complex;
+    Zigzag              zz;
+    RipsGenerator       rips(distances);
+    SimplexEvaluator    size(distances);
+    
+    // Insert vertices
+    for (unsigned i = 0; i != vertices.size(); ++i)
+    {
+        // Add a vertex
+        Smplx sv; sv.add(vertices[i]);
+        rDebug("Adding %s", tostring(sv).c_str());
+        add.start();
+        complex.insert(std::make_pair(sv, 
+                                      zz.add(Boundary(), 
+                                             BirthInfo(0, 0)).first));
+        add.stop();
+        //rDebug("Newly born cycle order: %d", complex[sv]->low->order);
+        CountNum(cComplexSize, 0);
+        Count(cComplexSize);
+        Count(cOperations);
+    }
+
+    rInfo("Commencing computation");
+    boost::progress_display show_progress(vertices.size());
+    unsigned ce     = 0;        // index of the current one past last edge in the complex
+    for (unsigned stage = 0; stage != vertices.size() - 1; ++stage)
+    {
+        unsigned i = vertices.size() - 1 - stage;
+        rInfo("Current stage %d: %d %f: %f", stage, 
+                                             vertices[i], epsilons[i-1],
+                                             multiplier*epsilons[i-1]);
+
+        /* Increase epsilon */
+        // Record the cofaces of all the simplices that need to be removed and reinserted
+        SimplexSet cofaces;
+        rDebug("  Cofaces size: %d", cofaces.size());
+
+        // Add anything else that needs to be inserted into the complex
+        while (ce < edges.size())
+        {
+            Vertex u,v;
+            boost::tie(u,v)     = edges[ce];
+            if (distances(u,v) <= multiplier*epsilons[i-1])
+                ++ce;
+            else
+                break;
+            rDebug("  Recording cofaces of edges[%d]=(%d, %d) with size=%f", (ce-1), u, v, distances(u,v));
+            ec.start();
+            rips.edge_cofaces(u, v, 
+                              skeleton_dimension, 
+                              multiplier*epsilons[i-1], 
+                              make_insert_functor(cofaces),
+                              vertices.begin(),
+                              vertices.begin() + i + 1);
+            ec.stop();
+        }
+        rDebug("  Recorded new cofaces to add");
+
+        // Insert all the cofaces
+        rDebug("  Cofaces size: %d", cofaces.size());
+        for (SimplexSet::const_iterator cur = cofaces.begin(); cur != cofaces.end(); ++cur)
+        {
+            Index idx; Death d; Boundary b;
+            rDebug("  Adding %s, its size %f", tostring(*cur).c_str(), size(*cur));
+            make_boundary(*cur, complex, zz, b);
+            add.start();
+            boost::tie(idx, d)  = zz.add(b,
+                                         BirthInfo(epsilons[i-1], cur->dimension()));
+            add.stop();
+            //if (!d) rDebug("Newly born cycle order: %d", complex[*cur]->low->order);
+            CountNum(cComplexSize, cur->dimension());
+            Count(cComplexSize);
+            Count(cOperations);
+            AssertMsg(zz.check_consistency(), "Zigzag representation must be consistent after removing a simplex");
+            complex.insert(std::make_pair(*cur, idx));
+            report_death(out, d, epsilons[i-1], skeleton_dimension);
+        }
+        rInfo("Increased epsilon; complex size: %d", complex.size());
+        report_memory();
+        
+        /* Remove the vertex */
+        cofaces.clear();
+        rDebug("  Cofaces size: %d", cofaces.size());
+        vc.start();
+        rips.vertex_cofaces(vertices[i], 
+                            skeleton_dimension, 
+                            multiplier*epsilons[i-1], 
+                            make_insert_functor(cofaces),
+                            vertices.begin(),
+                            vertices.begin() + i + 1);
+        vc.stop();
+        rDebug("  Computed cofaces of the vertex, their number: %d", cofaces.size());
+        for (SimplexSet::const_reverse_iterator cur = cofaces.rbegin(); cur != (SimplexSet::const_reverse_iterator)cofaces.rend(); ++cur)
+        {
+            rDebug("    Removing: %s", tostring(*cur).c_str());
+            Complex::iterator si = complex.find(*cur);
+            remove.start();
+            Death d = zz.remove(si->second,
+                                BirthInfo(epsilons[i-1], cur->dimension() - 1));
+            remove.stop();
+            complex.erase(si);
+            CountNumBy(cComplexSize, cur->dimension(), -1);
+            CountBy(cComplexSize, -1);
+            Count(cOperations);
+            AssertMsg(zz.check_consistency(), "Zigzag representation must be consistent after removing a simplex");
+            report_death(out, d, epsilons[i-1], skeleton_dimension);
+        }
+        rInfo("Removed vertex; complex size: %d", complex.size());
+        for (Complex::const_iterator cur = complex.begin(); cur != complex.end(); ++cur)
+            rDebug("  %s", tostring(cur->first).c_str());
+        report_memory();
+        
+        ++show_progress;
+    }
+    
+    // Remove the last vertex
+    AssertMsg(complex.size() == 1, "Only one vertex must remain");
+    remove.start();
+    Death d = zz.remove(complex.begin()->second, BirthInfo(epsilons[0], -1));
+    remove.stop();
+    complex.erase(complex.begin());
+    if (!d)  AssertMsg(false,  "The vertex must have died");
+    report_death(out, d, epsilons[0], skeleton_dimension);
+    CountNumBy(cComplexSize, 0, -1);
+    CountBy(cComplexSize, -1);
+    Count(cOperations);
+    rInfo("Removed vertex; complex size: %d", complex.size());
+    ++show_progress;
+
+    total.stop();
+
+    remove.check("Remove timer          ");
+    add.check   ("Add timer             ");
+    ec.check    ("Edge coface timer     ");
+    vc.check    ("Vertex coface timer   ");
+    total.check ("Total timer           ");
+}
+
+
+            
+void        report_death(std::ostream& out, Death d, DistanceType epsilon, Dimension skeleton_dimension)
+{
+    if (d && ((d->distance - epsilon) != 0) && (d->dimension < skeleton_dimension))
+        out << d->dimension << " " << d->distance << " " << epsilon << std::endl;
+}
+
+void        make_boundary(const Smplx& s, Complex& c, const Zigzag& zz, Boundary& b)
+{
+    rDebug("  Boundary of <%s>", tostring(s).c_str());
+    for (Smplx::BoundaryIterator cur = s.boundary_begin(); cur != s.boundary_end(); ++cur)
+    {
+        b.append(c[*cur], zz.cmp);
+        rDebug("   %d", c[*cur]->order);
+    }
+}
+
+std::ostream&   operator<<(std::ostream& out, const BirthInfo& bi)
+{ return (out << bi.distance); }
+
+void        process_command_line_options(int           argc, 
+                                         char*         argv[],
+                                         unsigned&     skeleton_dimension,
+                                         float&        multiplier,
+                                         std::string&  infilename,
+                                         std::string&  outfilename)
+{
+    namespace po = boost::program_options;
+
+    po::options_description hidden("Hidden options");
+    hidden.add_options()
+        ("input-file",          po::value<std::string>(&infilename),        "Point set whose Rips zigzag we want to compute")
+        ("output-file",         po::value<std::string>(&outfilename),       "Location to save persistence pairs");
+    
+    po::options_description visible("Allowed options", 100);
+    visible.add_options()
+        ("help,h",                                                                              "produce help message")
+        ("skeleton-dimsnion,s", po::value<unsigned>(&skeleton_dimension)->default_value(2),     "Dimension of the Rips complex we want to compute")
+        ("multiplier,m",        po::value<float>(&multiplier)->default_value(6),                "Multiplier for the epsilon (distance to next maxmin point) when computing the Rips complex");
+#if LOGGING
+    std::vector<std::string>    log_channels;
+    visible.add_options()
+        ("log,l",               po::value< std::vector<std::string> >(&log_channels),           "log channels to turn on (info, debug, etc)");
+#endif
+
+    po::positional_options_description pos;
+    pos.add("input-file", 1);
+    pos.add("output-file", 2);
+    
+    po::options_description all; all.add(visible).add(hidden);
+
+    po::variables_map vm;
+    po::store(po::command_line_parser(argc, argv).
+                  options(all).positional(pos).run(), vm);
+    po::notify(vm);
+
+#if LOGGING
+    for (std::vector<std::string>::const_iterator cur = log_channels.begin(); cur != log_channels.end(); ++cur)
+        stderrLog.subscribeTo( RLOG_CHANNEL(cur->c_str()) );
+    /**
+     * Interesting channels
+     * "info", "debug", "topology/persistence"
+     */
+#endif
+
+    if (vm.count("help") || !vm.count("input-file") || !vm.count("output-file"))
+    { 
+        std::cout << "Usage: " << argv[0] << " [options] input-file output-file" << std::endl;
+        std::cout << visible << std::endl; 
+        std::abort();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/rips/rips.cpp	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,110 @@
+#include <topology/rips.h>
+#include <topology/filtration.h>
+#include <topology/static-persistence.h>
+#include <topology/dynamic-persistence.h>
+#include <topology/persistence-diagram.h>
+#include <utilities/containers.h>           // for BackInsertFunctor
+
+#include <fstream>
+#include <boost/archive/binary_oarchive.hpp>
+#include <boost/serialization/map.hpp>
+
+// Trivial example of size() points on a line with integer coordinates
+struct Distances
+{
+    typedef         int             IndexType;
+    typedef         double          DistanceType;
+
+    DistanceType    operator()(IndexType a, IndexType b) const      { return std::abs(a - b); }
+
+    size_t          size() const                                    { return 2000; }
+    IndexType       begin() const                                   { return 0; }
+    IndexType       end() const                                     { return size(); }
+};
+
+//typedef         Rips<ExplicitDistances<Distances> >                   Generator;
+typedef         Rips<Distances>                                         Generator;
+typedef         Generator::Simplex                                      Smplx;
+typedef         Filtration<Smplx>                                       Fltr;
+typedef         StaticPersistence<>                                     Persistence;
+// typedef         DynamicPersistenceChains<>                              Persistence;
+typedef         PersistenceDiagram<>                                    PDgm;
+
+
+int main(int argc, char* argv[])
+{
+#ifdef LOGGING
+	rlog::RLogInit(argc, argv);
+
+	stdoutLog.subscribeTo( RLOG_CHANNEL("error") );
+	stdoutLog.subscribeTo( RLOG_CHANNEL("info") );
+	//stdoutLog.subscribeTo( RLOG_CHANNEL("rips/info") );
+	//stdoutLog.subscribeTo( RLOG_CHANNEL("rips/debug") );
+#endif
+
+    Distances distances;
+    
+    // Storing ExplicitDistances speeds up the computation (at the price of memory)
+    //ExplicitDistances<Distances> explicit_distances(distances);
+
+    Generator               rips(distances);
+    Generator::Evaluator    size(distances);
+    Fltr                    f;
+    
+    // Generate 2-skeleton of the Rips complex for epsilon = 50
+    rips.generate(2, 10, make_push_back_functor(f));
+    rInfo("Generated complex of size: %d",  f.size());
+
+    // Generate filtration with respect to distance and compute its persistence
+    f.sort(Generator::Comparison(distances));
+    Persistence p(f);
+    p.pair_simplices();
+    rInfo("Simplices paired");
+
+    Persistence::SimplexMap<Fltr>   m = p.make_simplex_map(f);
+
+    // Record the persistence intervals in the persistence diagrams
+    std::map<Dimension, PDgm> dgms;
+    init_diagrams(dgms, p.begin(), p.end(), 
+                  evaluate_through_map(m, size), 
+                  evaluate_through_map(m, Smplx::DimensionExtractor()));
+
+    // Serialize the diagrams to a file
+    std::ofstream ofs("rips-diagrams");
+    boost::archive::binary_oarchive oa(ofs);
+    oa << dgms;
+
+    // Output cycles
+    for (Persistence::iterator cur = p.begin(); cur != p.end(); ++cur)
+    {
+        const Persistence::Cycle& cycle = cur->cycle;
+
+        if (!cur->sign())        // only negative simplices have non-empty cycles
+        {
+            Persistence::OrderIndex birth = cur->pair;      // the cycle that cur killed was born when we added birth (another simplex)
+
+            const Smplx& b = m[birth];
+            const Smplx& d = m[cur];
+            
+            if (b.dimension() != 1) continue;
+            std::cout << "Pair: (" << size(b) << ", " << size(d) << ")" << std::endl;
+        } else if (cur->unpaired())    // positive could be unpaired
+        {
+            const Smplx& b = m[cur];
+            if (b.dimension() != 1) continue;
+            
+            std::cout << "Unpaired birth: " << size(b) << std::endl;
+            // cycle = cur->chain;
+        }
+
+        // Iterate over the cycle
+        for (Persistence::Cycle::const_iterator si =  cycle.begin(); si != cycle.end(); ++si)
+        {
+            const Smplx& s = m[*si];
+            //std::cout << s.dimension() << std::endl;
+            const Smplx::VertexContainer& vertices = s.vertices();          // std::vector<Vertex> where Vertex = Distances::IndexType
+            AssertMsg(vertices.size() == s.dimension() + 1, "dimension of a simplex is one less than the number of its vertices");
+            std::cout << vertices[0] << " " << vertices[1] << std::endl;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/rips/rips.py	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,42 @@
+from    math        import fabs
+from    dionysus    import Rips, Filtration, StaticPersistence #, enable_log
+
+# Simple minded pairwise distance functor distance
+class Distances:
+    def __len__(self):
+        return 5
+
+    def __call__(self, x, y):
+        return fabs(y-x)
+
+dist = Distances()
+r = Rips(dist)
+lst = Filtration()
+lst2 = Filtration()
+
+#enable_log('rips')
+
+r.generate(1, 3, lst.append)
+r.generate(1, 3, lst2.append, [0,2,4])
+
+print "Rips complex on all vertices:", lst
+print "Rips complex on vertices [0,2,4]):", lst2
+
+print "Values:", [map(r.eval, lst)]
+print "Sorted:", sorted(lst, r.cmp)
+
+cofaces = []
+r.vertex_cofaces(2, 1, 3, cofaces.append)
+print "Cofaces of vertex 2:", cofaces
+
+cofaces = []
+r.vertex_cofaces(2, 1, 3, cofaces.append, [0,2,4])
+print "Cofaces of vertex 2 on vertices [0,2,4]:", cofaces
+
+f = lst
+f.sort(r.cmp)
+p = StaticPersistence(f)
+p.pair_simplices()
+smap = p.make_simplex_map(f)
+for s in p:
+    print smap[s], s.sign()
--- a/examples/triangle/CMakeLists.txt	Fri Aug 24 16:58:25 2007 -0400
+++ b/examples/triangle/CMakeLists.txt	Tue Jun 27 09:37:05 2017 -0700
@@ -1,7 +1,10 @@
-set							(targets						
-							 triangle)
-							 
-foreach 					(t ${targets})
-	add_executable			(${t} ${t}.cpp ${external_sources})
-	target_link_libraries	(${t} ${libraries})
-endforeach 					(t ${targets})
+set                         (targets
+                             triangle
+                             triangle-zigzag)
+
+set                         (libraries                          ${libraries} ${Boost_SERIALIZATION_LIBRARY})
+                             
+foreach                     (t ${targets})
+    add_executable          (${t} ${t}.cpp)
+    target_link_libraries   (${t} ${libraries})
+endforeach                  (t ${targets})
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/triangle/triangle-chains.py	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,33 @@
+from dionysus import Simplex, Filtration, DynamicPersistenceChains, \
+                     vertex_cmp, data_cmp, data_dim_cmp \
+
+complex = [Simplex((0,),        0),                 # A
+           Simplex((1,),        1),                 # B
+           Simplex((2,),        2),                 # C
+           Simplex((0,1),       2.5),               # AB
+           Simplex((1,2),       2.9),               # BC
+           Simplex((0,2),       3.5)]               # CA
+
+print "Complex:", complex
+print "Vertex: ", sorted(complex, vertex_cmp)
+print "Data:   ", sorted(complex, data_cmp)
+print "DataDim:", sorted(complex, data_dim_cmp)
+
+f = Filtration(complex, data_cmp)
+print "Complex in the filtration order:", ', '.join((str(s) for s in f))
+
+p = DynamicPersistenceChains(f)
+print "Persistence initialized"
+p.pair_simplices()
+print "Simplices paired"
+
+smap = p.make_simplex_map(f)
+for i in p:
+    print i.sign(), i.pair().sign()
+    print "%s (%d) - %s (%d)" % (smap[i], i.sign(), smap[i.pair()], i.pair().sign())
+    print "Cycle (%d):" % len(i.cycle), " + ".join((str(smap[ii]) for ii in i.cycle))
+    
+    if i.unpaired():
+        print "Chain (%d):" % len(i.chain), " + ".join((str(smap[ii]) for ii in i.chain))
+
+print "Number of unpaired simplices:", len([i for i in p if i.unpaired()])
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/triangle/triangle-zigzag.cpp	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,87 @@
+#include <vector>
+#include <cassert>
+#include <iostream>
+
+#include <topology/simplex.h>
+#include <topology/zigzag-persistence.h>
+#include <boost/tuple/tuple.hpp>
+
+typedef     ZigzagPersistence<unsigned>     Zigzag;
+typedef     Zigzag::SimplexIndex            Index;
+typedef     Zigzag::Death                   Death;
+typedef     Zigzag::ZColumn                 Boundary;
+typedef     std::vector<Index>              Complex;
+
+int main(int argc, char** argv)
+{
+#ifdef LOGGING
+    rlog::RLogInit(argc, argv);
+
+    //stdoutLog.subscribeTo(RLOG_CHANNEL("topology/persistence"));
+#endif
+
+
+    Zigzag zz;
+    Complex c;
+    Index i; Death d;
+    unsigned birth = 0;
+
+    // Adding the triangle
+    std::cout << birth << ": adding 0" << std::endl;
+    boost::tie(i, d)        = zz.add(Boundary(), birth++);  // A
+    c.push_back(i);
+    assert(!d);                                             // birth
+
+    std::cout << birth << ": adding 1" << std::endl;
+    boost::tie(i, d)        = zz.add(Boundary(), birth++);  // B
+    c.push_back(i);
+    assert(!d);                                             // birth
+
+    std::cout << birth << ": adding 2" << std::endl;
+    boost::tie(i, d)        = zz.add(Boundary(), birth++); // C
+    c.push_back(i);
+    assert(!d);                                             // birth
+    
+    std::cout << birth << ": adding 3" << std::endl;
+    boost::tie(i, d)        = zz.add(Boundary(c.begin(), 
+                                              boost::next(c.begin(),2)), 
+                                     birth++);              // AB
+    c.push_back(i);
+    assert(d);                                              // death
+    if (d)                  std::cout << "Death of: " << *d << std::endl;
+
+    std::cout << birth << ": adding 4" << std::endl;
+    boost::tie(i, d)        = zz.add(Boundary(boost::next(c.begin()), 
+                                              boost::next(c.begin(),3)), 
+                                     birth++);              // BC
+    c.push_back(i);
+    assert(d);                                              // death
+    if (d)                  std::cout << "Death of: " << *d << std::endl;
+    
+    std::cout << birth << ": adding 5" << std::endl;
+    {
+        Boundary bdry; bdry.append(*c.begin(), zz.cmp); bdry.append(*boost::next(c.begin(), 2), zz.cmp);
+        boost::tie(i, d)    = zz.add(bdry, birth++);        // AC
+    }
+    c.push_back(i);
+    assert(!d);                                             // birth
+    
+    std::cout << birth << ": adding 6" << std::endl;
+    boost::tie(i, d)        = zz.add(Boundary(boost::next(c.begin(), 3), 
+                                              boost::next(c.begin(), 6)), 
+                                     birth++);              // ABC
+    c.push_back(i);
+    assert(d);                                              // death
+    if (d)                  std::cout << "Death of: " << *d << std::endl;
+
+    //zz.show_all();
+
+    // Removing the triangle in reverse order
+    for (Complex::reverse_iterator cur = c.rbegin(); cur != c.rend(); ++cur)
+    {
+        std::cout << birth << ": removing " << (*cur)->order << std::endl;
+        d = zz.remove(*cur, birth++);
+        if (d)              std::cout << "Death of: " << *d << std::endl;
+        //zz.show_all();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/triangle/triangle-zigzag.py	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,35 @@
+from dionysus import Simplex, ZigzagPersistence, \
+                     vertex_cmp, data_cmp \
+#                    ,enable_log
+
+complex = {Simplex((0,),        0):     None,                   # A
+           Simplex((1,),        1):     None,                   # B
+           Simplex((2,),        2):     None,                   # C
+           Simplex((0,1),       2.5):   None,                   # AB
+           Simplex((1,2),       2.9):   None,                   # BC
+           Simplex((0,2),       3.5):   None,                   # CA
+           Simplex((0,1,2),     5):     None}                   # ABC
+
+print "Complex:"
+for s in sorted(complex.keys()): print s
+print
+
+#enable_log("topology/persistence")
+zz = ZigzagPersistence()
+
+# Add all the simplices
+b = 1
+for s in sorted(complex.keys(), data_cmp):
+    print "%d: Adding %s" % (b, s)
+    i,d = zz.add([complex[ss] for ss in s.boundary], b)
+    complex[s] = i
+    if d:   print "Interval (%d, %d)" % (d, b-1)
+    b += 1
+
+# Remove all the simplices
+for s in sorted(complex.keys(), data_cmp, reverse = True):
+    print "%d: Removing %s" % (b, s)
+    d = zz.remove(complex[s], b)
+    del complex[s]
+    if d:   print "Interval (%d, %d)" % (d, b-1)
+    b += 1
--- a/examples/triangle/triangle.cpp	Fri Aug 24 16:58:25 2007 -0400
+++ b/examples/triangle/triangle.cpp	Tue Jun 27 09:37:05 2017 -0700
@@ -1,63 +1,140 @@
-#include "topology/filtration.h"
+#include <utilities/log.h>
+
 #include "topology/simplex.h"
+#include "topology/filtration.h"
+#include "topology/static-persistence.h"
+#include "topology/dynamic-persistence.h"
+#include "topology/persistence-diagram.h"
+#include <utilities/indirect.h>
+
 #include <vector>
+#include <map>
 #include <iostream>
 
-typedef 		SimplexWithValue<int> 			Simplex;
-typedef			Filtration<Simplex>				TriangleFiltration;
+
+#if 1
+#include <fstream>
+#include <boost/archive/text_oarchive.hpp>
+#include <boost/archive/text_iarchive.hpp>
+#include <boost/serialization/vector.hpp>
+#endif
 
-void fillTriangleSimplices(TriangleFiltration& f)
+typedef         unsigned                                            Vertex;
+typedef         Simplex<Vertex, double>                             Smplx;
+typedef         Filtration<Smplx>                                   Fltr;
+// typedef         StaticPersistence<>                                 Persistence;
+typedef         DynamicPersistenceTrails<>                          Persistence;
+typedef         PersistenceDiagram<>                                PDgm;
+typedef         OffsetBeginMap<Persistence, Fltr, 
+                               Persistence::iterator, 
+                               Fltr::Index>                         PersistenceFiltrationMap;
+typedef         OffsetBeginMap<Fltr, Persistence,
+                               Fltr::Index, 
+                               Persistence::iterator>               FiltrationPersistenceMap;
+
+// Transposes elements of the filtration together with the 
+struct FiltrationTranspositionVisitor: public Persistence::TranspositionVisitor
 {
-	typedef std::vector<int> VertexVector;
-	VertexVector vertices(4);
-	vertices[0] = 0; vertices[1] = 1; vertices[2] = 2; 
-	vertices[3] = 0;
-		
-	VertexVector::const_iterator bg = vertices.begin();
-	VertexVector::const_iterator end = vertices.end();
-	f.append(Simplex(bg,     bg + 1, 0));				// 0 = A
-	f.append(Simplex(bg + 1, bg + 2, 1));				// 1 = B
-	f.append(Simplex(bg + 2, bg + 3, 2));				// 2 = C
-	f.append(Simplex(bg,     bg + 2, 2.5));				// AB
-	f.append(Simplex(bg + 1, bg + 3, 2.9));				// BC
-	f.append(Simplex(bg + 2, end, 3.5));				// CA
-	f.append(Simplex(bg,     bg + 3, 5));				// ABC
+    typedef     Persistence::iterator                               iterator;
+
+                FiltrationTranspositionVisitor(const Persistence& p,
+                                               Fltr& f):
+                    p_(p), f_(f)                                    {}                                               
+    void        transpose(iterator i)                               { f_.transpose(f_.begin() + (i - p_.begin())); }
+
+    const Persistence&  p_;
+    Fltr&               f_;
+};
+
+void fillTriangleSimplices(Fltr& c)
+{
+    typedef std::vector<Vertex> VertexVector;
+    VertexVector vertices(4);
+    vertices[0] = 0; vertices[1] = 1; vertices[2] = 2; 
+    vertices[3] = 0;
+        
+    VertexVector::const_iterator bg = vertices.begin();
+    VertexVector::const_iterator end = vertices.end();
+    c.push_back(Smplx(bg,     bg + 1, 0));                 // 0 = A
+    c.push_back(Smplx(bg + 1, bg + 2, 1));                 // 1 = B
+    c.push_back(Smplx(bg + 2, bg + 3, 2));                 // 2 = C
+    c.push_back(Smplx(bg,     bg + 2, 2.5));               // AB
+    c.push_back(Smplx(bg + 1, bg + 3, 2.9));               // BC
+    c.push_back(Smplx(bg + 2, end,    3.5));               // CA
+    c.push_back(Smplx(bg,     bg + 3, 5));                 // ABC
 }
 
-int main()
+int main(int argc, char** argv)
 {
-#ifdef CWDEBUG
-	dionysus::debug::init();
+#ifdef LOGGING
+    rlog::RLogInit(argc, argv);
+
+    stdoutLog.subscribeTo(RLOG_CHANNEL("topology/persistence"));
+    //stdoutLog.subscribeTo(RLOG_CHANNEL("topology/chain"));
+    //stdoutLog.subscribeTo(RLOG_CHANNEL("topology/vineyard"));
+#endif
 
-	Debug(dc::filtration.on());
-	Debug(dc::cycle.off());
-	Debug(dc::vineyard.on());
-	Debug(dc::transpositions.on());
+    Fltr f;
+    fillTriangleSimplices(f);
+    std::cout << "Simplices filled" << std::endl;
+    for (Fltr::Index cur = f.begin(); cur != f.end(); ++cur)
+        std::cout << "  " << *cur << std::endl;
+
+#if 1           // testing serialization of the Filtration (really Simplex)
+  {  
+    std::ofstream ofs("complex");
+    boost::archive::text_oarchive oa(ofs);
+    oa << f;
+    f.clear();
+  }  
+
+  {
+    std::ifstream ifs("complex");
+    boost::archive::text_iarchive ia(ifs);
+    ia >> f;
+  }  
 #endif
 
-	Evaluator<Simplex> e;
-	TriangleFiltration::Vineyard v(&e);
-	TriangleFiltration tf(&v);
-	fillTriangleSimplices(tf);
-	
-	tf.fill_simplex_index_map();
-	tf.pair_simplices();
-	v.start_vines(tf.begin(), tf.end());
-	
-	std::cout << "Filtration size: " << tf.size() << std::endl;
-	std::cout << tf << std::endl;
+    f.sort(Smplx::DataComparison());
+    std::cout << "Filtration initialized" << std::endl;
+    std::cout << f << std::endl;
+
+    Persistence p(f);
+    std::cout << "Persistence initialized" << std::endl;
+
+    p.pair_simplices();
+    std::cout << "Simplices paired" << std::endl;
+
+    Persistence::SimplexMap<Fltr>   m = p.make_simplex_map(f);
+    std::map<Dimension, PDgm> dgms;
+    init_diagrams(dgms, p.begin(), p.end(), 
+                  evaluate_through_map(m, Smplx::DataEvaluator()),
+                  evaluate_through_map(m, Smplx::DimensionExtractor()));
+
+    std::cout << 0 << std::endl << dgms[0] << std::endl;
+    std::cout << 1 << std::endl << dgms[1] << std::endl;
 
-#if 1
-	Simplex BC; BC.add(1); BC.add(2);
-	Simplex AB; AB.add(0); AB.add(1);
-	std::cout << BC << std::endl;
-	std::cout << *tf.get_index(BC) << std::endl;
-	tf.transpose(tf.get_index(BC));
-	std::cout << tf;
-	std::cout << AB << std::endl;
-	std::cout << *tf.get_index(AB) << std::endl;
-	tf.transpose(tf.get_index(AB));
-	std::cout << tf;
-#endif
+    PersistenceFiltrationMap                                    pfmap(p, f);
+    DimensionFunctor<PersistenceFiltrationMap, Fltr>            dim(pfmap, f);
+
+    // Transpositions
+    FiltrationPersistenceMap        fpmap(f, p);
+    FiltrationTranspositionVisitor  visitor(p, f);
+    Smplx A;  A.add(0);
+    std::cout << A << std::endl;
+    std::cout << "Transposing A: " << p.transpose(fpmap[f.find(A)], dim, visitor) << std::endl;     // 1.2 unpaired
+
+    Smplx BC; BC.add(1); BC.add(2);
+    Smplx AB; AB.add(0); AB.add(1);
+    std::cout << BC << std::endl;
+    std::cout << p.transpose(fpmap[f.find(BC)], dim, visitor) << std::endl;         // 3.1
+    // p.transpose(fpmap[f.find(BC)], dim, visitor);
+    std::cout << AB << std::endl;
+    std::cout << p.transpose(fpmap[f.find(AB)], dim, visitor) << std::endl;         // 2.1
+    // p.transpose(fpmap[f.find(AB)], dim, visitor);
+
+    std::cout << p.transpose(p.begin(), dim, visitor) << std::endl;         // transposition case 1.2 special
+    std::cout << p.transpose(boost::next(p.begin()), dim, visitor) << std::endl;
+    std::cout << p.transpose(boost::next(p.begin(),3), dim, visitor) << std::endl;
 }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/triangle/triangle.py	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,31 @@
+from dionysus import Simplex, Filtration, StaticPersistence, \
+                     vertex_cmp, data_cmp, data_dim_cmp \
+
+complex = [Simplex((0,),        0),                 # A
+           Simplex((1,),        1),                 # B
+           Simplex((2,),        2),                 # C
+           Simplex((0,1),       2.5),               # AB
+           Simplex((1,2),       2.9),               # BC
+           Simplex((0,2),       3.5),               # CA
+           Simplex((0,1,2),     5)]                 # ABC
+
+print "Complex:", complex
+print "Vertex: ", sorted(complex, vertex_cmp)
+print "Data:   ", sorted(complex, data_cmp)
+print "DataDim:", sorted(complex, data_dim_cmp)
+
+f = Filtration(complex, data_cmp)
+print "Complex in the filtration order:", ', '.join((str(s) for s in f))
+
+p = StaticPersistence(f)
+print "Persistence initialized"
+p.pair_simplices(True)
+print "Simplices paired"
+
+smap = p.make_simplex_map(f)
+for i in p:
+    print i.sign(), i.pair().sign()
+    print "%s (%d) - %s (%d)" % (smap[i], i.sign(), smap[i.pair()], i.pair().sign())
+    print "Cycle (%d):" % len(i.cycle), " + ".join((str(smap[ii]) for ii in i.cycle))
+
+print "Number of unpaired simplices:", len([i for i in p if i.unpaired()])
--- a/include/dionysus.h	Fri Aug 24 16:58:25 2007 -0400
+++ b/include/dionysus.h	Tue Jun 27 09:37:05 2017 -0700
@@ -1,6 +1,6 @@
 /*
  * Author: Dmitriy Morozov
- * Department of Computer Science, Duke University, 2006
+ * Department of Computer Science, Duke University, 2006--2008
  *
  * For now file exists only to store the main page of the documentation
  */
@@ -9,3 +9,16 @@
  * Detailed description of Dionysus with references to all the classes, 
  * and code samples goes here.
  */
+
+/**
+ * \defgroup topology Topology Classes
+ */
+
+/**
+ * \defgroup geometry Geometry Classes
+ */
+
+/**
+ * \defgroup kinetic Kinetic Data Structures Classes
+ * \ingroup  geometry
+ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/geometry/distances.h	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,71 @@
+#ifndef __DISTANCES_H__
+#define __DISTANCES_H__
+
+#include <vector>
+
+/**
+ * Class: ExplicitDistances 
+ * Stores the pairwise distances of Distances_ instance passed at construction. 
+ * It's a protypical Distances template argument for the Rips complex.
+ */
+template<class Distances_>
+class ExplicitDistances
+{
+    public:
+        typedef             Distances_                                      Distances;
+        typedef             size_t                                          IndexType;
+        typedef             typename Distances::DistanceType                DistanceType;
+
+                            ExplicitDistances(IndexType size):
+                                size_(size), 
+                                distances_(size*(size + 1)/2 + size)        {}
+                            ExplicitDistances(const Distances& distances);
+
+        DistanceType        operator()(IndexType a, IndexType b) const;
+        DistanceType&       operator()(IndexType a, IndexType b);
+
+        size_t              size() const                                    { return size_; }
+        IndexType           begin() const                                   { return 0; }
+        IndexType           end() const                                     { return size(); }
+
+    private:
+        std::vector<DistanceType>                   distances_;
+        size_t                                      size_;
+};
+
+
+/**
+ * Class: PairwiseDistances
+ * Given a Container_ of points and a Distance_, it computes distances between elements 
+ * in the container (given as instances of Index_ defaulted to unsigned) using the Distance_ functor.
+ *
+ * Container_ is assumed to be an std::vector. That simplifies a number of things.
+ */
+template<class Container_, class Distance_, typename Index_ = unsigned>
+class PairwiseDistances
+{
+    public:
+        typedef             Container_                                      Container;
+        typedef             Distance_                                       Distance;
+        typedef             Index_                                          IndexType;
+        typedef             typename Distance::result_type                  DistanceType;
+
+
+                            PairwiseDistances(const Container& container, 
+                                              const Distance& distance = Distance()):
+                                container_(container), distance_(distance)  {}
+
+        DistanceType        operator()(IndexType a, IndexType b) const      { return distance_(container_[a], container_[b]); }
+
+        size_t              size() const                                    { return container_.size(); }
+        IndexType           begin() const                                   { return 0; }
+        IndexType           end() const                                     { return size(); }
+
+    private:
+        const Container&    container_;
+        Distance            distance_;
+};
+
+#include "distances.hpp"
+
+#endif // __DISTANCES_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/geometry/distances.hpp	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,30 @@
+template<class Distances_>
+ExplicitDistances<Distances_>::
+ExplicitDistances(const Distances& distances): 
+    size_(distances.size()), distances_((distances.size() * (distances.size() + 1))/2)
+{
+    IndexType i = 0;
+    for (typename Distances::IndexType a = distances.begin(); a != distances.end(); ++a)
+        for (typename Distances::IndexType b = a; b != distances.end(); ++b)
+        {
+            distances_[i++] = distances(a,b);
+        }
+}
+
+template<class Distances_>
+typename ExplicitDistances<Distances_>::DistanceType
+ExplicitDistances<Distances_>::
+operator()(IndexType a, IndexType  b) const
+{
+    if (a > b) std::swap(a,b);
+    return distances_[a*size_ - ((a*(a-1))/2) + (b-a)];
+}
+
+template<class Distances_>
+typename ExplicitDistances<Distances_>::DistanceType&
+ExplicitDistances<Distances_>::
+operator()(IndexType a, IndexType  b)
+{
+    if (a > b) std::swap(a,b);
+    return distances_[a*size_ - ((a*(a-1))/2) + (b-a)];
+}
--- a/include/geometry/euclidean.h	Fri Aug 24 16:58:25 2007 -0400
+++ b/include/geometry/euclidean.h	Tue Jun 27 09:37:05 2017 -0700
@@ -14,15 +14,19 @@
 #include "number-traits.h"
 
 
+/**
+ * Geometric Kernel. Defines operations on geometric primitives.
+ * \ingroup geometry
+ */
 template<class NumberType_ = double>
 class Kernel
 {
 	public:
 		typedef 					unsigned int								DimensionType;
 		typedef						NumberType_									NumberType;
-		typedef						LinearAlgebra<NumberType>					LinearAlgebra;
-		typedef						typename LinearAlgebra::MatrixType			MatrixType;
-		typedef						typename LinearAlgebra::VectorType			VectorType;
+		typedef						LinearAlgebra<NumberType>					LinearAlgebraK;
+		typedef						typename LinearAlgebraK::MatrixType			MatrixType;
+		typedef						typename LinearAlgebraK::VectorType			VectorType;
 
 		class						Point;
 		class						Sphere;
@@ -56,7 +60,10 @@
 };
 
 
-/* Point */
+/** 
+ * Point class.
+ * \ingroup geometry 
+ */
 template<class NumberType_>
 class Kernel<NumberType_>::Point: public VectorType
 {
@@ -77,7 +84,10 @@
 };
 
 
-/* Sphere */
+/** 
+ * Sphere class.
+ * \ingroup geometry
+ */
 template<class NumberType_>
 class Kernel<NumberType_>::Sphere
 {
--- a/include/geometry/kinetic-sort.h	Fri Aug 24 16:58:25 2007 -0400
+++ b/include/geometry/kinetic-sort.h	Tue Jun 27 09:37:05 2017 -0700
@@ -7,38 +7,40 @@
 #include <iostream>
 
 /**
- * Maintains elements of the given data structure in the sorted order assuming the elements follow 
+ * Maintains elements of the given data structure in the sorted order assuming the elements follow
  * trajectories given by TrajectoryExtractor_.
  *
  *  \arg ElementIterator_     iterator over the underlying data structure that's kept in sorted order
- *  \arg TrajectoryExtractor_ applied to the iterator into SortDS_ should return a rational 
- *                            function describing the 
- *  \arg Simulator_           the Simulator type, e.g. Simulator. Note that KineticSort does not store 
+ *  \arg TrajectoryExtractor_ applied to the iterator into SortDS_ should return a function
+ *                            (of type Simulator_::FunctionKernel::Function) describing the trajectory of the element
+ *  \arg Simulator_           the Simulator type, e.g. Simulator. Note that KineticSort does not store
  *                            a pointer to the Simulator (so a pointer is passed in each relevant operation)
  *  \arg Swap_                is called with an ElementIterator_ when a swap needs to be performed
+ *
+ *  \ingroup kinetic
  */
-template<class ElementIterator_, class TrajectoryExtractor_, 
+template<class ElementIterator_, class TrajectoryExtractor_,
 		 class Simulator_, class Swap_ = boost::function<void(ElementIterator_ pos, Simulator_* simulator)> >
 class KineticSort
 {
 	public:
 		typedef						Simulator_									Simulator;
-		typedef						typename Simulator::PolynomialKernel		PolynomialKernel;
+		typedef						typename Simulator::FunctionKernel		    FunctionKernel;
 		typedef						ElementIterator_							ElementIterator;
 		typedef						Swap_										Swap;
 		typedef						TrajectoryExtractor_						TrajectoryExtractor;
-		
+
 		typedef						typename Simulator::Key						SimulatorKey;
 
-									
+
 	private:
 		/* Implementation */
 		struct Node
 		{
 			ElementIterator			element;
-			SimulatorKey			swap_event_key;		
+			SimulatorKey			swap_event_key;
 
-									Node(ElementIterator e, SimulatorKey k): 
+									Node(ElementIterator e, SimulatorKey k):
 										element(e), swap_event_key(k)			{}
 		};
 
@@ -51,7 +53,7 @@
 		/// \name Core Functionality
 		/// @{
 									KineticSort();
-									KineticSort(ElementIterator b, ElementIterator e, Swap swap, Simulator* simulator);
+									KineticSort(ElementIterator b, ElementIterator e, Swap swap, Simulator* simulator, const TrajectoryExtractor& te = TrajectoryExtractor());
 		void						initialize(ElementIterator b, ElementIterator e, Swap swap, Simulator* simulator);
 
 		void						insert(iterator pos, ElementIterator f, ElementIterator l, Simulator* simulator);
@@ -66,6 +68,8 @@
 		iterator					begin() 									{ return list_.begin(); }
 		iterator					end() 										{ return list_.end(); }
 
+        const TrajectoryExtractor&  trajectory_extractor() const                { return te_; }
+
 	private:
 		class SwapEvent;
 		void						schedule_swaps(iterator b, iterator e, Simulator* s);
@@ -73,7 +77,8 @@
 
 	private:
 		NodeList					list_;
-		Swap						swap_;	
+		Swap						swap_;
+        TrajectoryExtractor         te_;
 };
 
 #include "kinetic-sort.hpp"
--- a/include/geometry/kinetic-sort.hpp	Fri Aug 24 16:58:25 2007 -0400
+++ b/include/geometry/kinetic-sort.hpp	Tue Jun 27 09:37:05 2017 -0700
@@ -1,3 +1,19 @@
+#include "utilities/log.h"
+#include "utilities/counter.h"
+
+#ifdef LOGGING
+static rlog::RLogChannel* rlKineticSort =           DEF_CHANNEL("geometry/kinetic-sort", rlog::Log_Debug);
+static rlog::RLogChannel* rlKineticSortAudit =      DEF_CHANNEL("geometry/kinetic-sort/audit", rlog::Log_Debug);
+static rlog::RLogChannel* rlKineticSortSchedule =   DEF_CHANNEL("geometry/kinetic-sort/schedule", rlog::Log_Debug);
+static rlog::RLogChannel* rlKineticSortProcess =    DEF_CHANNEL("geometry/kinetic-sort/process", rlog::Log_Debug);
+#endif // LOGGING
+
+#ifdef COUNTERS
+static Counter*  cKineticSort =                     GetCounter("kinetic-sort");
+static Counter*  cKineticSortSwap =                 GetCounter("kinetic-sort/swap");
+#endif // COUNTERS
+
+
 template<class ElementIterator_, class TrajectoryExtractor_, class Simulator_, class Swap_>
 KineticSort<ElementIterator_, TrajectoryExtractor_, Simulator_, Swap_>::
 KineticSort()
@@ -5,7 +21,8 @@
 
 template<class ElementIterator_, class TrajectoryExtractor_, class Simulator_, class Swap_>
 KineticSort<ElementIterator_, TrajectoryExtractor_, Simulator_, Swap_>::
-KineticSort(ElementIterator b, ElementIterator e, Swap swap, Simulator* simulator)
+KineticSort(ElementIterator b, ElementIterator e, Swap swap, Simulator* simulator, const TrajectoryExtractor& te):
+    te_(te)
 {
 	initialize(b, e, swap, simulator);
 }
@@ -81,6 +98,7 @@
 {
 	// TODO: AssertMsg(boost::next(pos) != list_.end(), "Cannot swap the last element");
 
+    Count(cKineticSortSwap);
 	swap_(pos->element, simulator);
 
 	// Remove events
@@ -106,35 +124,36 @@
 KineticSort<ElementIterator_, TrajectoryExtractor_, Simulator_, Swap_>::
 audit(Simulator* simulator) const
 {
-	typedef 		typename Simulator::RationalFunction		RationalFunction;
+	typedef 		typename Simulator::Function		        Function;
 	typedef 		typename Simulator::Time					Time;
 	
 	Time t = simulator->audit_time();
-	std::cout << "Auditing at " << t << std::endl;
+	rLog(rlKineticSortAudit, "Auditing at %s", tostring(t).c_str());
 
-	TrajectoryExtractor	te;
-	
 	typename NodeList::const_iterator next = list_.begin();
 	typename NodeList::const_iterator cur = next++;
-	RationalFunction cur_trajectory = te(cur->element);
+	Function cur_trajectory = te_(cur->element);
 	while (next != list_.end())
 	{
-		(*(cur->swap_event_key))->print(std::cout << "  ") << std::endl;
+		rLog(rlKineticSortAudit, "  %s", intostring(**(cur->swap_event_key)).c_str());
 
-		RationalFunction next_trajectory = te(next->element);
-		std::cout << "  Auditing:   " << cur_trajectory << ", " << next_trajectory << std::endl;
-		std::cout << "  Difference: " << next_trajectory - cur_trajectory << std::endl;
-		std::cout << "  Sign at:    " << t << ", " << PolynomialKernel::sign_at(next_trajectory - cur_trajectory, t) << std::endl;
-		if (PolynomialKernel::sign_at(next_trajectory - cur_trajectory, t) == -1)
+		Function next_trajectory = te_(next->element);
+		rLog(rlKineticSortAudit, "  Auditing:   %s, %s", tostring(cur_trajectory).c_str(),
+                                                         tostring(next_trajectory).c_str());
+		rLog(rlKineticSortAudit, "  Difference: %s", tostring(next_trajectory - cur_trajectory).c_str());
+		rLog(rlKineticSortAudit, "  Sign at:    %s, %s", tostring(t).c_str(),
+                                                         tostring(FunctionKernel::sign_at(next_trajectory - cur_trajectory, t)).c_str());
+		if (FunctionKernel::sign_at(next_trajectory - cur_trajectory, t) == -1)
 		{
-			std::cout << "Audit failed at " << *cur->element << ", " << *next->element << std::endl;
+			// rError("Audit failed at %s, %s", tostring(*cur->element).c_str(), 
+            //                                  tostring(*next->element).c_str());
 			return false;
 		}
 
 		cur_trajectory = next_trajectory;
 		cur = next++;
 	}
-	if (cur != list_.end()) (*(cur->swap_event_key))->print(std::cout << "  ") << std::endl;
+	if (cur != list_.end()) rLog(rlKineticSortAudit, "  %s", intostring(**(cur->swap_event_key)).c_str());
 	return true;
 }
 
@@ -144,17 +163,15 @@
 KineticSort<ElementIterator_, TrajectoryExtractor_, Simulator_, Swap_>::
 schedule_swaps(iterator b, iterator e, Simulator* simulator)
 {
-	typedef 		typename Simulator::RationalFunction		RationalFunction;
-	
-	TrajectoryExtractor	te;
+	typedef 		typename Simulator::Function		        Function;
 	
 	iterator next = b; 
 	iterator cur = next++;
-	RationalFunction cur_trajectory = te(cur->element);
+	Function cur_trajectory = te_(cur->element);
 	while (next != e)
 	{
-		RationalFunction next_trajectory = te(next->element);
-		std::cout << "Next trajectory: " << next_trajectory << std::endl;
+		Function next_trajectory = te_(next->element);
+		rLog(rlKineticSortSchedule, "Next trajectory: %s", tostring(next_trajectory).c_str());
 		// TODO: add assertion that (next_trajectory - cur_trajectory)(s->curren_time()) > 0
 		cur->swap_event_key = simulator->add(next_trajectory - cur_trajectory, SwapEvent(this, cur));
 		cur = next++;
@@ -168,7 +185,7 @@
 KineticSort<ElementIterator_, TrajectoryExtractor_, Simulator_, Swap_>::
 schedule_swaps(iterator i, Simulator* simulator)
 {
-	typedef 		typename Simulator::RationalFunction		RationalFunction;
+	typedef 		typename Simulator::Function		        Function;
 	
 	if (i == list_.end()) return;
 	if (boost::next(i) == list_.end())
@@ -177,17 +194,14 @@
 		return;
 	}
 
-	TrajectoryExtractor	te;
-	
 	iterator next = boost::next(i); 
-	RationalFunction i_trajectory = te(i->element);
-	RationalFunction next_trajectory = te(next->element);
+	Function i_trajectory = te_(i->element);
+	Function next_trajectory = te_(next->element);
 	
 	//std::cout << "Updating swaps for: " << i_trajectory << ", " << next_trajectory << std::endl;
 	//std::cout << "Difference:         " << next_trajectory - i_trajectory << std::endl;
 
 	i->swap_event_key = simulator->add(next_trajectory - i_trajectory, SwapEvent(this, i));
-	//i->swap_event_key = simulator->add(next_trajectory, SwapEvent(this, i));
 }
 
 /* SwapEvent */
@@ -205,7 +219,7 @@
 		virtual bool				process(Simulator* s) const;
 		void						set_position(iterator i)					{ pos_ = i; }
 		iterator					position() const							{ return pos_; }
-		std::ostream&				print(std::ostream& out) const;
+		std::ostream&				operator<<(std::ostream& out) const;
 
 	private:
 		KineticSort*				sort_;
@@ -217,7 +231,7 @@
 KineticSort<ElementIterator_, TrajectoryExtractor_, Simulator_, Swap_>::SwapEvent::
 process(Simulator* s) const
 { 
-	std::cout << "Swapping. Current time: " << s->current_time() << std::endl;
+	rLog(rlKineticSortProcess, "Swapping. Current time: %s", tostring(s->current_time()).c_str());
 	sort_->swap(pos_, s); 
 	return true; 
 }
@@ -225,9 +239,8 @@
 template<class ElementIterator_, class TrajectoryExtractor_, class Simulator_, class Swap_>
 std::ostream&				
 KineticSort<ElementIterator_, TrajectoryExtractor_, Simulator_, Swap_>::SwapEvent::
-print(std::ostream& out) const
+operator<<(std::ostream& out) const
 {
-	Parent::print(out) << ", SwapEvent at " << TrajectoryExtractor_()(position()->element);
+	Parent::operator<<(out) << "SwapEvent at " << sort_->trajectory_extractor()(position()->element);
 	return out;
 }
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/geometry/l2distance.h	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,47 @@
+#ifndef __L2_DISTANCE_H__
+#define __L2_DISTANCE_H__
+
+#include <utilities/types.h>
+#include <utilities/log.h>
+
+#include <vector>
+#include <fstream>
+#include <functional>
+#include <cmath>
+#include <string>
+#include <sstream>
+
+
+typedef     std::vector<double>                                     Point;
+typedef     std::vector<Point>                                      PointContainer;
+
+struct L2Distance:
+    public std::binary_function<const Point&, const Point&, double>
+{
+    result_type     operator()(const Point& p1, const Point& p2) const
+    {
+        AssertMsg(p1.size() == p2.size(), "Points must be in the same dimension (in L2Distance): dim1=%d, dim2=%d", p1.size(), p2.size());
+        result_type sum = 0;
+        for (size_t i = 0; i < p1.size(); ++i)
+            sum += (p1[i] - p2[i])*(p1[i] - p2[i]);
+
+        return sqrt(sum);
+    }
+};
+
+void    read_points(const std::string& infilename, PointContainer& points)
+{
+    std::ifstream in(infilename.c_str());
+    std::string   line;
+    while(std::getline(in, line))
+    {
+        if (line[0] == '#') continue;               // comment line in the file
+        std::stringstream linestream(line);
+        double x;
+        points.push_back(Point());
+        while (linestream >> x)
+            points.back().push_back(x);
+    }
+}
+
+#endif // __L2_DISTANCE_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/geometry/linear-kernel.h	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,46 @@
+#ifndef __LINEAR_KERNEL_H__
+#define __LINEAR_KERNEL_H__
+
+#include <stack>
+#include <iostream>
+#include <boost/operators.hpp>
+
+template<class T>
+class LinearKernel
+{
+	public:
+        struct                      Function;
+
+		typedef						T					                                RootType;
+		typedef						std::stack<RootType>								RootStack;
+
+		static void					solve(const Function& f, RootStack& stack)          { if (f.a1 != 0) stack.push(-f.a0/f.a1); }
+		static RootType				root(const T& r)									{ return r; }
+		static int					sign_at(const Function& f, const RootType& r)       { RootType y = f(r); if (y < 0) return -1; if (y > 0) return 1; return 0; }
+		static RootType				between(const RootType& r1, const RootType& r2)		{ return (r1 + r2)/2; }
+		static int					sign_at_negative_infinity(const Function& f)        { if (f.a1 < 0) return 1; if (f.a1 > 0) return -1; if (f.a0 > 0) return 1; if (f.a0 < 0) return -1; return 0; }
+};
+
+template<class T>
+struct LinearKernel<T>::Function: boost::additive<Function>
+{
+        typedef                     T                                                   RootType;
+
+                                    Function(RootType aa0, RootType aa1 = 0):
+                                        a0(aa0), a1(aa1)                                {}
+
+        RootType                    operator()(RootType r) const                        { return a1 * r + a0; }
+        Function&                   operator+=(const Function& other)                   { a1 += other.a1; a0 += other.a0; return *this; }
+        Function&                   operator-=(const Function& other)                   { a1 -= other.a1; a0 -= other.a0; return *this; }
+        std::ostream&               operator<<(std::ostream& out) const                 { out << a1 << "*x + " << a0; return out; }
+
+        RootType                    a0, a1;
+};
+
+// TODO: need to make this generic
+std::ostream&                       operator<<(std::ostream& out, const LinearKernel<double>::Function& f)
+{
+    return f.operator<<(out);
+}
+
+#endif
--- a/include/geometry/polynomial.h	Fri Aug 24 16:58:25 2007 -0400
+++ b/include/geometry/polynomial.h	Tue Jun 27 09:37:05 2017 -0700
@@ -21,17 +21,18 @@
 {
 	public:
 		typedef						typename SynapsTraits<T>::Polynomial				Polynomial;
-		typedef						RationalFunction<Polynomial>						RationalFunction;
+		typedef						RationalFunction<Polynomial>						RationalFunctionP;
+        typedef                     RationalFunctionP                                   Function;
 
 		typedef						typename SynapsTraits<T>::Solver					Solver;
 		typedef						typename SynapsTraits<T>::RootType					RootType;
 		typedef						std::stack<RootType>								RootStack;
 
-		static void					solve(const RationalFunction& rf, RootStack& stack);
+		static void					solve(const RationalFunctionP& rf, RootStack& stack);
 		static RootType				root(const T& r)									{ return SynapsTraits<T>::root(r); }
-		static int					sign_at(const RationalFunction& rf, const RootType& r);
+		static int					sign_at(const RationalFunctionP& rf, const RootType& r);
 		static RootType				between(const RootType& r1, const RootType& r2)		{ return SynapsTraits<T>::between(r1,r2); }
-		static bool					sign_at_negative_infinity(const RationalFunction& rf);
+		static int					sign_at_negative_infinity(const RationalFunctionP& rf);
 };
 
 template<class T>
--- a/include/geometry/polynomial.hpp	Fri Aug 24 16:58:25 2007 -0400
+++ b/include/geometry/polynomial.hpp	Tue Jun 27 09:37:05 2017 -0700
@@ -1,10 +1,14 @@
+#include <utilities/log.h>
+
 template<class T>
 void
 UPolynomial<T>::
-solve(const RationalFunction& rf, RootStack& stack)
+solve(const RationalFunctionP& rf, RootStack& stack)
 {
 	typedef SYNAPS::Seq<RootType>		RootSeq;
 
+    AssertMsg(stack.empty(), "Stack must be empty before solve");
+
 	RootSeq seq_num = SYNAPS::solve(SynapsTraits<T>::convert(rf.numerator()), Solver());
 	RootSeq seq_den = SYNAPS::solve(SynapsTraits<T>::convert(rf.denominator()), Solver());
 
@@ -28,22 +32,23 @@
 template<class T>
 int
 UPolynomial<T>::
-sign_at(const RationalFunction& rf, const RootType& r)
+sign_at(const RationalFunctionP& rf, const RootType& r)
 {
 	return SynapsTraits<T>::sign_at(rf.numerator(), r) * SynapsTraits<T>::sign_at(rf.denominator(), r);
 }
 
 template<class T>
-bool
+int
 UPolynomial<T>::
-sign_at_negative_infinity(const RationalFunction& rf)
+sign_at_negative_infinity(const RationalFunctionP& rf)
 {
 	const Polynomial& num = rf.numerator();
 	const Polynomial& den = rf.denominator();
-	unsigned int ndegree = num.get_degree();
-	unsigned int ddegree = den.get_degree();
-	return (((ndegree + 1) % 2 == 0) ^ (num[ndegree] > 0)) ^
-		   (((ddegree + 1) % 2 == 0) ^ (den[ddegree] > 0));
+	int ndegree = num.get_degree();
+	int ddegree = den.get_degree();
+    if (ndegree == -1) return 0;          // ndegree == -1 => num == 0, and 0 is 0 at -infinity
+	return !((((ndegree + 1) % 2 == 0) ^ (num[ndegree] > 0)) ^
+		     (((ddegree + 1) % 2 == 0) ^ (den[ddegree] > 0))) ? 1:-1;
 }
 
 SynapsTraits<QQ>::RootType
--- a/include/geometry/simulator.h	Fri Aug 24 16:58:25 2007 -0400
+++ b/include/geometry/simulator.h	Tue Jun 27 09:37:05 2017 -0700
@@ -1,121 +1,136 @@
 #ifndef __SIMULATOR_H__
 #define __SIMULATOR_H__
 
-#include "utilities/eventqueue.h"
-#include "polynomial.h"
+#include <utilities/eventqueue.h>
+#include <utilities/indirect.h>
 
-template<class Comparison>  						class IndirectComparison;
+#include <limits>
 
 /**
- * Simulator class. Keeps a queue of events. Infinity is reached if the Event 
- * at the front of the queue has an empty root stack. Keeps track of current time, 
- * Event addition, and processes events one by one. Degeneracies are handled by 
- * assuming that the RationalFunction responsible for the event must be positive
- * before the Event occurs.
+ * Simulator class. Keeps a queue of events. Infinity is reached if the Event
+ * at the front of the queue has an empty root stack. Keeps track of current time,
+ * Event addition, and processes events one by one. Degeneracies are handled by
+ * assuming that the FunctionKernel::Function responsible for the event must be
+ * positive before the Event occurs.
+ *
+ * \ingroup kinetic
  */
-template<class PolyKernel_, template<class Event> class EventComparison_ = std::less>
+template<class FuncKernel_, template<class Event> class EventComparison_ = std::less>
 class Simulator
 {
-	public:
-		typedef						PolyKernel_									PolynomialKernel;
-		typedef						typename PolynomialKernel::Polynomial		Polynomial;
-		typedef						typename PolynomialKernel::RationalFunction	RationalFunction;
-		typedef						typename PolynomialKernel::RootStack		RootStack;
-		typedef						typename PolynomialKernel::RootType			RootType;
-		typedef						RootType									Time;
+    public:
+        typedef                     FuncKernel_                                 FunctionKernel;
+        typedef                     typename FunctionKernel::Function           Function;
+        typedef                     typename FunctionKernel::RootStack          RootStack;
+        typedef                     typename FunctionKernel::RootType           RootType;
+        typedef                     RootType                                    Time;
 
-		class Event;
-		typedef						EventComparison_<Event>						EventComparison;
-		typedef						EventQueue<Event*, IndirectComparison<EventComparison> >			
-																				EventQueue;
-		typedef						typename EventQueue::iterator				Key;
-		typedef						typename EventQueue::const_iterator			const_Key;
+        class Event;
+        typedef                     EventComparison_<Event>                     EventComparison;
+
+        class IndirectEventComparison;
+        typedef                     EventQueue<Event*, IndirectEventComparison> EventQueueS;
+        typedef                     typename EventQueueS::iterator              Key;
+        typedef                     typename EventQueueS::const_iterator        const_Key;
 
 
-									Simulator(Time start = PolynomialKernel::root(0)):
-										current_(start), 
-										reached_infinity_(false)				{}
+                                    Simulator(Time start = FunctionKernel::root(0)):
+                                        current_(start)                         {}
+                                    ~Simulator()                                { for (Key cur = queue_.top(); cur != queue_.end(); ++cur) delete *cur; }
 
 
-		template<class Event_> 
-		Key							add(const Event_& e);
-		template<class Event_> 
-		Key							add(const RationalFunction& f, const Event_& e);
-		void						process();
-		void						update(Key k, const RationalFunction& f);
-		
-		void						remove(Key k)								{ queue_.remove(k); }
-		Key							null_key() 									{ return queue_.end(); }
+        template<class Event_>
+        Key                         add(const Event_& e);
+        template<class Event_>
+        Key                         add(const Function& f, const Event_& e);
+        void                        process();
+        //void                        update(Key k, const Function& f);
+
+        void                        remove(Key k)                               { Event* e = *k; queue_.remove(k); delete e; }
+        Key                         null_key()                                  { return queue_.end(); }
 
-		Time						current_time() const						{ return current_; }
-		Time						audit_time() const;
-		bool						reached_infinity() const					{ return reached_infinity_; }
-
-		std::ostream&				print(std::ostream& out) const;
+        Time                        current_time() const                        { return current_; }
+        Time                        audit_time() const;
+        bool                        reached_infinity() const                    { return queue_.empty() || (*queue_.top())->root_stack().empty(); }
+        Time                        next_event_time() const                     { return queue_.empty() ? std::numeric_limits<Time>::infinity():(*queue_.top())->root_stack().top(); }
 
-	private:
-		void						update(Key i);
+        Event*                      top() const                                 { return *(queue_.top()); }
+        unsigned                    size() const                                { return queue_.size(); }
+        unsigned                    event_count() const                         { return count_; }
 
-	private:
-		Time						current_;
-		EventQueue					queue_;
-		bool						reached_infinity_;
+        std::ostream&               operator<<(std::ostream& out) const;
+
+    private:
+        Time                        current_;
+        EventQueueS                 queue_;
+        unsigned                    count_;
 };
 
 
 /**
- * Base class for events. Stores a root stack, subclasses need to define process(). 
- * Event with an empty root stack compares greater than any other Event, 
+ * Base class for events. Stores a root stack, subclasses need to define process().
+ * Event with an empty root stack compares greater than any other Event,
  * pushing those events to the end of the queue.
  */
-template<class PolyKernel_, template<class Event> class EventComparison_>
-class Simulator<PolyKernel_, EventComparison_>::Event
+template<class FuncKernel_, template<class Event> class EventComparison_>
+class Simulator<FuncKernel_, EventComparison_>::Event
 {
-	public:
-		typedef						PolyKernel_									PolynomialKernel;
-		typedef						typename PolynomialKernel::RootStack		RootStack;
+    public:
+        typedef                     FuncKernel_                                 FunctionKernel;
+        typedef                     typename FunctionKernel::RootStack          RootStack;
 
-		/// Returns true if the event needs to remain in the Simulator 
-		/// (top of the root_stack() will be used for new time)
-		virtual	bool				process(Simulator* s) const					=0;
-		
-		RootStack&					root_stack()								{ return root_stack_; }
-		const RootStack&			root_stack() const							{ return root_stack_; }
+        virtual                     ~Event()                                    {}
+
+        /// process() is called when the event is at the top of the queue
+        /// in the simulator.
+        /// Returns true if the event needs to remain in the Simulator
+        /// (top of the root_stack() will be used for new time).
+        virtual bool                process(Simulator* s) const                 =0;
+        RootStack&                  root_stack()                                { return root_stack_; }
+        const RootStack&            root_stack() const                          { return root_stack_; }
 
-		bool						operator<(const Event& e) const				
-		{ 
-			if (root_stack().empty())
-				return false;
-			else if (e.root_stack().empty())
-				return true;
-			else
-				return root_stack().top() < e.root_stack().top();
-		}
+        bool                        operator<(const Event& e) const
+        {
+            if (root_stack().empty())
+                return false;
+            else if (e.root_stack().empty())
+                return true;
+            else
+                return root_stack().top() < e.root_stack().top();
+        }
 
-		virtual std::ostream&		print(std::ostream& out) const				{ return out << "Event with " << root_stack_.size() << " roots"; }
+        virtual std::ostream&       operator<<(std::ostream& out) const
+        {
+            out << "Event with " << root_stack_.size() << " roots";
+            if (!root_stack_.empty()) out << "; top root: " << root_stack_.top();
+            out << ", ";
+            return out;
+        }
 
-	private:
-		RootStack					root_stack_;
+    private:
+        RootStack                   root_stack_;
 };
 
 /**
- * Compares elements pointed at by its arguments using the provided Comparison_ 
+ * Compares elements pointed at by its arguments using the provided Comparison_
  * (which must not take any arguments during construction).
  */
-template<class Comparison_>
-class IndirectComparison: public std::binary_function<const typename Comparison_::first_argument_type*, 
-													  const typename Comparison_::second_argument_type*, 
-													  bool>
+template<class FuncKernel_, template<class Event> class EventComparison_>
+class Simulator<FuncKernel_, EventComparison_>::IndirectEventComparison:
+    public std::binary_function<const typename EventComparison::first_argument_type*,
+                                const typename EventComparison::second_argument_type*,
+                                bool>
 {
-	public:
-		typedef						Comparison_											Comparison;
-		typedef						const typename Comparison::first_argument_type*		first_argument_type;
-		typedef						const typename Comparison::second_argument_type*	second_argument_type;
+    public:
+        typedef                     EventComparison                                     Comparison;
+        typedef                     const typename Comparison::first_argument_type*     first_argument_type;
+        typedef                     const typename Comparison::second_argument_type*    second_argument_type;
 
-		bool						operator()(first_argument_type e1, second_argument_type e2) const
-		{ return Comparison()(*e1, *e2); }
+        bool                        operator()(first_argument_type e1, second_argument_type e2) const
+        { return Comparison()(*e1, *e2); }
 };
 
+
 #include "simulator.hpp"
 
 #endif // __SIMULATOR_H__
--- a/include/geometry/simulator.hpp	Fri Aug 24 16:58:25 2007 -0400
+++ b/include/geometry/simulator.hpp	Tue Jun 27 09:37:05 2017 -0700
@@ -1,87 +1,137 @@
-template<class PolyKernel_, template<class Event> class EventComparison_>
+#include "utilities/log.h"
+#include "utilities/counter.h"
+
+#ifdef LOGGING
+static rlog::RLogChannel* rlSimulator =             DEF_CHANNEL("geometry/simulator", rlog::Log_Debug);
+
+#endif // LOGGING
+
+#ifdef COUNTERS
+static Counter*  cSimulatorProcess =                GetCounter("simulator/process");
+#endif // COUNTERS
+
+
+template<class FuncKernel_, template<class Event> class EventComparison_>
 template<class Event_>
-typename Simulator<PolyKernel_, EventComparison_>::Key
-Simulator<PolyKernel_, EventComparison_>::
+typename Simulator<FuncKernel_, EventComparison_>::Key
+Simulator<FuncKernel_, EventComparison_>::
 add(const Event_& e)
 {
-	Event* ee = new Event_(e);
-	return queue_.push(ee);
+    Event* ee = new Event_(e);
+    return queue_.push(ee);
 }
 
-template<class PolyKernel_, template<class Event> class EventComparison_>
+template<class FuncKernel_, template<class Event> class EventComparison_>
 template<class Event_>
-typename Simulator<PolyKernel_, EventComparison_>::Key
-Simulator<PolyKernel_, EventComparison_>::
-add(const RationalFunction& f, const Event_& e)
+typename Simulator<FuncKernel_, EventComparison_>::Key
+Simulator<FuncKernel_, EventComparison_>::
+add(const Function& f, const Event_& e)
 {
-	Event* ee = new Event_(e);
-	//std::cout << "Solving: " << f << std::endl;
-	PolynomialKernel::solve(f, ee->root_stack());
-	bool sign = PolynomialKernel::sign_at_negative_infinity(f);
-	while (!ee->root_stack().empty() && ee->root_stack().top() < current_time())
-	{
-		ee->root_stack().pop();
-		sign = !sign;
-	}
-	if (sign) ee->root_stack().pop();			// TODO: double-check the logic
-	//std::cout << "Pushing: " << ee->root_stack().top() << std::endl;
-	return queue_.push(ee);
-}
-		
-template<class PolyKernel_, template<class Event> class EventComparison_>
-void
-Simulator<PolyKernel_, EventComparison_>::
-update(Key k, const RationalFunction& f)
-{
-	Event* ee = *k;
-	ee->root_stack() = RootStack();								// no clear() in std::stack
-	PolynomialKernel::solve(f, ee->root_stack());
-	while (!ee->root_stack().empty() && ee->root_stack().top() < current_time())
-		ee->root_stack().pop();
-	update(k);
+    Event* ee = new Event_(e);
+    rLog(rlSimulator, "Solving: %s", tostring(f).c_str());
+    int sign = FunctionKernel::sign_at_negative_infinity(f);        // going to be sign after current time
+    rLog(rlSimulator, "Sign at -infinity: %i", sign);
+    if (sign != 0)
+    {
+        FunctionKernel::solve(f, ee->root_stack());
+        rLog(rlSimulator, "Got solution with root stack size: %i", ee->root_stack().size());
+    }
+
+    while (!ee->root_stack().empty() && ee->root_stack().top() < current_time())
+    {
+        // rLog(rlSimulator, "Popping expired root: %f", ee->root_stack().top());
+        ee->root_stack().pop();
+        sign *= -1;
+    }
+
+    if (sign == -1)
+    {
+        rLog(rlSimulator, "Popping the root because of negative sign (degeneracy)");
+        // rLog(rlSimulator, "Popping the root because of negative sign (degeneracy): %f", ee->root_stack().top());
+        // rLog(rlSimulator, "  Current time: %f", current_time());
+        // AssertMsg(ee->root_stack().top() == current_time(),
+                 // "If sign is negative, we must be in the degenerate case");
+        ee->root_stack().pop();
+    }
+
+    if (ee->root_stack().empty())
+        rLog(rlSimulator, "Pushing event with empty root stack");
+    else
+    {
+        rLog(rlSimulator, "Root stack size: %i", ee->root_stack().size());
+        rLog(rlSimulator, "Pushing: %s", tostring(ee->root_stack().top()).c_str());
+    }
+    Key k = queue_.push(ee);
+    return k;
 }
 
-template<class PolyKernel_, template<class Event> class EventComparison_>
+//template<class FuncKernel_, template<class Event> class EventComparison_>
+//void
+//Simulator<FuncKernel_, EventComparison_>::
+//update(Key k, const Function& f)
+//{
+//    Event* ee = *k;
+//    Event* e = new Event;
+//    e->root_stack() = RootStack();                              // no clear() in std::stack
+//    FunctionKernel::solve(f, e->root_stack());
+//    while (!e->root_stack().empty() && e->root_stack().top() < current_time())
+//        e->root_stack().pop();
+//    queue_.replace(k, e);
+//    delete ee;
+//}
+
+template<class FuncKernel_, template<class Event> class EventComparison_>
 void
-Simulator<PolyKernel_, EventComparison_>::
+Simulator<FuncKernel_, EventComparison_>::
 process()
 {
-	std::cout << "Queue size: " << queue_.size() << std::endl;
-	Key top = queue_.top();
-	Event* e = *top;
-	
-	if (e->root_stack().empty()) 		{ reached_infinity_ = true; return; }
-	else 								{ current_ = e->root_stack().top(); e->root_stack().pop();  }
-	
-	if (e->process(this))				update(top);
-	else								{ queue_.pop(); delete e; }
+    Count(cSimulatorProcess);
+    if (reached_infinity()) return;
+    rLog(rlSimulator, "Queue size: %i", queue_.size());
+    Key top = queue_.top();
+    Event* e = *top;
+    rLog(rlSimulator, "Processing event: %s", intostring(*e).c_str());
+
+    current_ = e->root_stack().top(); e->root_stack().pop();
+    queue_.demoted(top);
+
+    // Get the top element out of the queue, put it back depending on what process() says
+    if (!(e->process(this)))            { queue_.remove(top);  delete e; }
+
+    ++count_;
 }
 
-template<class PolyKernel_, template<class Event> class EventComparison_>
-void
-Simulator<PolyKernel_, EventComparison_>::
-update(Key i)
-{
-	queue_.update(i);
-}
-		
-template<class PolyKernel_, template<class Event> class EventComparison_>
-typename Simulator<PolyKernel_, EventComparison_>::Time
-Simulator<PolyKernel_, EventComparison_>::
+template<class FuncKernel_, template<class Event> class EventComparison_>
+typename Simulator<FuncKernel_, EventComparison_>::Time
+Simulator<FuncKernel_, EventComparison_>::
 audit_time() const
 {
-	const_Key top = queue_.top();
-	Event* e = *top;
+    const_Key top = queue_.top();
+    Event* e = *top;
+
+    if (e->root_stack().empty()) return current_ + 1;
+    else return FunctionKernel::between(e->root_stack().top(), current_);
+}
 
-	if (e->root_stack().empty()) return current_ + 1;
-	else return PolynomialKernel::between(e->root_stack().top(), current_);
+template<class FuncKernel_, template<class Event> class EventComparison_>
+std::ostream&
+Simulator<FuncKernel_, EventComparison_>::
+operator<<(std::ostream& out) const
+{
+    out << "Simulator: " << std::endl;
+    return queue_.print(out, "  ");
 }
-		
-template<class PolyKernel_, template<class Event> class EventComparison_>
+
+template<class FuncKernel_, template<class Event> class EventComparison_>
 std::ostream&
-Simulator<PolyKernel_, EventComparison_>::
-print(std::ostream& out) const
+operator<<(std::ostream& out, const Simulator<FuncKernel_, EventComparison_>& s)
 {
-	out << "Simulator: " << std::endl;
-	return queue_.print(out, "  ");
+    return s.operator<<(out);
 }
+
+template<class FuncKernel_, template<class Event> class EventComparison_>
+std::ostream&
+operator<<(std::ostream& out, const typename Simulator<FuncKernel_, EventComparison_>::Event& e)
+{
+    return e.operator<<(out);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/geometry/weighted-cechdistance.h	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,55 @@
+#ifndef __L2_DISTANCE_H__
+#define __L2_DISTANCE_H__
+
+#include <utilities/types.h>
+
+#include <vector>
+#include <fstream>
+#include <functional>
+#include <cmath>
+#include <string>
+#include <sstream>
+
+
+typedef     std::vector<double>                                     Point;
+typedef     std::vector<Point>                                      PointContainer;
+
+struct WeightedL2Distance:
+    public std::binary_function<const Point&, const Point&, double>
+{
+    result_type     operator()(const Point& p1, const Point& p2) const
+    {
+        AssertMsg(p1.size() == p2.size(), "Points must be in the same dimension (in L2Distance): dim1=%d, dim2=%d", p1.size()-1, p2.size()-1);
+
+        /* the distance of a point to itself is the radius at which the "power distance" ball around it appears:
+           d(p,p) := sqrt(-w_p) */
+        if (p1 == p2)
+            return sqrt(-p1[p1.size()-1]); 
+
+        /* otherwise, the distance is the radius at which the power balls around p, q intersect:
+           d(p,q) := sqrt( ( (w_p-w_q)^2 / 4||p-q||^2 ) - (w_p+w_q) / 2 + ||p-q||^2 / 4 ) */
+        result_type sq_l2dist = 0;
+        result_type wp = p1[p1.size()-1];
+        result_type wq = p2[p2.size()-1];
+        for (size_t i = 0; i < p1.size()-1; ++i)
+            sq_l2dist += (p1[i] - p2[i])*(p1[i] - p2[i]);
+        return sqrt( (wp-wq)*(wp-wq) / (4 * sq_l2dist) - (wp+wq) / 2 + sq_l2dist / 4 );
+    }
+};
+
+void    read_weighted_points(const std::string& infilename, PointContainer& points)
+{
+    std::ifstream in(infilename.c_str());
+    std::string   line;
+    while(std::getline(in, line))
+    {
+        if (line[0] == '#') continue;               // comment line in the file
+        std::stringstream linestream(line);
+        double x;
+        points.push_back(Point());
+        while (linestream >> x)
+            points.back().push_back(x);
+    }
+}
+
+#endif // __L2_DISTANCE_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/geometry/weighted-l2distance.h	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,54 @@
+#ifndef __L2_DISTANCE_H__
+#define __L2_DISTANCE_H__
+
+#include <utilities/types.h>
+#include <utilities/log.h>
+
+#include <vector>
+#include <fstream>
+#include <functional>
+#include <cmath>
+#include <string>
+#include <sstream>
+
+
+typedef     std::vector<double>                                     Point;
+typedef     std::vector<Point>                                      PointContainer;
+
+struct WeightedL2Distance:
+    public std::binary_function<const Point&, const Point&, double>
+{
+    result_type     operator()(const Point& p1, const Point& p2) const
+    {
+        AssertMsg(p1.size() == p2.size(), "Points must be in the same dimension (in L2Distance): dim1=%d, dim2=%d", p1.size()-1, p2.size()-1);
+
+        /* the distance of a point to itself is the radius at which the "power distance" ball around it appears:
+           d(p,p) := sqrt(-w_p) */
+        if (p1 == p2)
+            return sqrt(-p1[p1.size()-1]);
+
+        /* otherwise, the distance is the radius at which the power balls around p, q intersect:
+           d(p,q) := sqrt( ||p-q||^2 - w_p - w_q ) */
+        result_type sq_l2dist = 0;
+        for (size_t i = 0; i < p1.size()-1; ++i)
+            sq_l2dist += (p1[i] - p2[i])*(p1[i] - p2[i]);
+        return sqrt(sq_l2dist - p1[p1.size()-1] - p2[p2.size()-1]);
+    }
+};
+
+void    read_weighted_points(const std::string& infilename, PointContainer& points)
+{
+    std::ifstream in(infilename.c_str());
+    std::string   line;
+    while(std::getline(in, line))
+    {
+        if (line[0] == '#') continue;               // comment line in the file
+        std::stringstream linestream(line);
+        double x;
+        points.push_back(Point());
+        while (linestream >> x)
+            points.back().push_back(x);
+    }
+}
+
+#endif // __L2_DISTANCE_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/topology/chain.h	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,129 @@
+/**
+ * Author: Dmitriy Morozov
+ * Department of Computer Science, Duke University, 2005-2008
+ */
+
+#ifndef __CHAIN_H__
+#define __CHAIN_H__
+
+//#include "utilities/types.h"
+#include <boost/serialization/access.hpp>
+#include <boost/serialization/serialization.hpp>
+#include <boost/iterator/iterator_traits.hpp>
+#include <boost/optional.hpp>
+#include <iterator>
+#include <string>
+
+#include <utilities/containers.h>
+
+/**
+ * Class: ChainWrapper
+ * Class storing a chain of simplices. Stores items in the order defined by ConsistencyCmp. 
+ * The actual order of the elements is defined by OrderCmp. Instances of those 
+ * classes are not stored in Chain for efficiency, and are passed as arguments to those methods 
+ * that require them.
+ *
+ * \ingroup topology
+ *
+ * TODO: add field (defaulting to Z_2)
+ */
+template <class Container_>
+class ChainWrapper: public Container_, 
+                    public SizeStorage<Container_>
+{
+    public:
+        /// \name Template Parameters
+        /// @{
+        typedef         Container_                                                                  Container;
+        typedef         SizeStorage<Container>                                                      Size;
+        typedef         typename boost::iterator_value<typename Container::iterator>::type          Item;
+        /// @}
+        
+        typedef         ChainWrapper                                                                Self;
+        typedef         Container                                                                   ChainRepresentation; 
+
+        /// \name Accessor typedefs
+        /// @{
+        typedef         typename ChainRepresentation::iterator                                      iterator; 
+        typedef         typename ChainRepresentation::const_iterator                                const_iterator; 
+        typedef         typename ChainRepresentation::const_reference                               const_reference; 
+        typedef         typename ChainRepresentation::reference                                     reference; 
+        typedef         typename ChainRepresentation::pointer                                       pointer; 
+        typedef         typename ChainRepresentation::const_pointer                                 const_pointer; 
+        typedef         Item                                                                        value_type;
+        /// @}
+        
+    public:     
+                                                ChainWrapper();
+                                                ChainWrapper(const ChainWrapper& c);
+        template<class Iterator>                ChainWrapper(Iterator bg, Iterator end);
+        
+        /// \name Whole Chain operations
+        /// @{
+        /** Add c to *this assuming both Chains are sorted in increasing order according to cmp. */
+        template<class ConsistencyComparison>                        
+        Self&                                   add(const Self& c, const ConsistencyComparison& cmp);
+        
+        void                                    swap(ChainWrapper& c);                          ///< Swaps the contents of c and *this (like STL's swap destroys c)
+        void                                    clear();
+        
+        template<class ConsistencyComparison>
+        void                                    sort(const ConsistencyComparison& cmp);         ///< Sort elements to enforce consistency
+
+        size_t                                  size() const                                        { return Size::size(*this); }
+
+        using                                   ChainRepresentation::empty;
+        /// @}
+        
+        /// \name Modifiers
+        /// @{
+        void                                    remove(iterator i)                              { ChainRepresentation::erase(i); Size::operator--(); }
+        void                                    remove(const_reference x)                       { remove(std::find(begin(), end(), x)); }
+        bool                                    remove_if_contains(const_reference x);
+
+        template<class ConsistencyComparison>
+        void                                    append(const_reference x, const ConsistencyComparison& cmp);
+        /// @}
+        
+        /// \name Accessors
+        /// @{
+        using                                   ChainRepresentation::begin;
+        using                                   ChainRepresentation::end;
+        using                                   ChainRepresentation::front;
+        using                                   ChainRepresentation::back;
+        
+        template<class OrderComparison>
+        const_reference                         top(const OrderComparison& cmp) const;          ///< First element in cmp order
+
+        boost::optional<const_iterator>         contains(const_reference x) const;              ///< tests whether chain contains x
+        boost::optional<iterator>               contains(const_reference x);                    ///< tests whether chain contains x
+        /// @}
+    
+        /// \name Debugging
+        /// @{
+        template<class OrderComparison>
+        const_reference                         get_first(const OrderComparison& cmp) const;    ///< First element in cmp order
+
+        template<class OutputMap>
+        std::string                             tostring(const OutputMap& outmap = OutputMap()) const;
+        /// @}
+        
+        /// Technically, it's an internal operation, and should be followed by a sort()
+        using                                   ChainRepresentation::push_back;
+
+    private:
+        using                                   ChainRepresentation::insert;
+        using                                   ChainRepresentation::erase;
+        
+    private:
+        // Serialization
+        typedef                                 Container                                           Parent;
+        friend class                            boost::serialization::access;
+        template<class Archive> 
+        void                                    serialize(Archive& ar, boost::serialization::version_type );
+};
+
+#include "chain.hpp"
+
+#endif // __CHAIN_H__
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/topology/chain.hpp	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,182 @@
+#include <algorithm>
+#include <vector>
+#include "utilities/containers.h"
+
+#include <boost/serialization/split_member.hpp>
+#include <boost/serialization/nvp.hpp>
+#include <boost/serialization/binary_object.hpp>
+#include <boost/utility.hpp>
+
+#include "utilities/log.h"
+#include "utilities/counter.h"
+
+using boost::serialization::make_nvp;
+using boost::serialization::make_binary_object;
+
+#ifdef LOGGING
+static rlog::RLogChannel* rlChain =                 DEF_CHANNEL( "topology/chain", rlog::Log_Debug);
+#endif // LOGGING
+
+#ifdef COUNTERS
+static Counter*  cChainAddBasic =                   GetCounter("chain/add/basic");
+static Counter*  cChainAddComparison =              GetCounter("chain/add/comparison");
+#endif // COUNTERS
+
+template<class C>
+ChainWrapper<C>::
+ChainWrapper()
+{}
+
+template<class C>
+ChainWrapper<C>::
+ChainWrapper(const ChainWrapper& c): 
+    ChainRepresentation(c), Size(c)
+{}
+
+template<class C>
+template<class Iterator>
+ChainWrapper<C>::
+ChainWrapper(Iterator bg, Iterator end): 
+    ChainRepresentation(bg, end), Size(ChainRepresentation::size())
+{}
+
+template<class C>
+template<class ConsistencyCmp>
+void
+ChainWrapper<C>::
+append(const_reference x, const ConsistencyCmp& cmp)                        
+{ 
+    Size::operator++();
+
+    // First try the special cases that x goes at the end
+    if (empty() || cmp(back(), x))
+        push_back(x); 
+    // Then try the special case that x goes at the front
+    else if (cmp(x, front()))
+        ContainerTraits<C,ConsistencyCmp>::push_front(*this, x);
+    else
+        insert(std::upper_bound(begin(), end(), x, cmp), x);
+}
+        
+template<class C>
+template<class OrderComparison>
+typename ChainWrapper<C>::const_reference               
+ChainWrapper<C>::
+top(const OrderComparison& cmp) const
+{ 
+    AssertMsg(!empty(), "Chain must not be empty for low()");
+    return *std::min_element(begin(), end(), cmp);
+}
+
+template<class C>
+void 
+ChainWrapper<C>::
+swap(ChainWrapper& c)
+{
+    ChainRepresentation::swap(c);
+    Size::swap(c);
+}
+
+template<class C>
+void 
+ChainWrapper<C>::
+clear()
+{
+    ChainRepresentation::clear();
+    Size::clear();
+}
+
+template<class C>
+template<class ConsistencyComparison>
+void 
+ChainWrapper<C>::
+sort(const ConsistencyComparison& cmp)
+{ 
+    ContainerTraits<C,ConsistencyComparison>::sort(*this, cmp);
+}
+
+template<class C>
+boost::optional<typename ChainWrapper<C>::const_iterator>
+ChainWrapper<C>::
+contains(const_reference x) const
+{
+    const_iterator res = std::find(begin(), end(), x);
+    return boost::make_optional(res != end(), res);
+}
+
+template<class C>
+boost::optional<typename ChainWrapper<C>::iterator>
+ChainWrapper<C>::
+contains(const_reference x)
+{
+    iterator res = std::find(begin(), end(), x);
+    return boost::make_optional(res != end(), res);
+}
+
+template<class C>
+bool
+ChainWrapper<C>::
+remove_if_contains(const_reference x)
+{
+    boost::optional<iterator> i = contains(x);
+    if (i)
+    {
+        remove(*i);
+        return true;
+    } else
+        return false;
+}
+
+template<class C>
+template<class OutputMap>
+std::string
+ChainWrapper<C>::
+tostring(const OutputMap& outmap) const
+{
+    std::string str;
+    for (const_iterator cur = begin(); cur != end(); ++cur)
+    {
+        if (cur != begin()) str += ", ";
+        str += outmap(*cur);
+    }
+    return str;
+}
+
+template<class C>
+template<class ConsistencyCmp>
+typename ChainWrapper<C>::Self& 
+ChainWrapper<C>::
+add(const Self& c, const ConsistencyCmp& cmp)
+{
+    // TODO: tmp-based addition is necessary and useful for Containers that are vectors, 
+    //       however, I believe it creates costly overhead for Containers that are lists.
+    //       Need to put some thought into this.
+    ChainRepresentation     tmp;
+
+    CountingBackInserter<ChainRepresentation> bi(tmp);
+    std::set_symmetric_difference(begin(), end(), c.begin(), c.end(), bi, cmp);
+
+    CountBy(cChainAddBasic, size() + c.size() - (size() + c.size() - tmp.size())/2);
+    
+    static_cast<ChainRepresentation*>(this)->swap(tmp);
+    static_cast<Size*>(this)->swap(bi);   
+
+    return *this;
+}
+
+template<class C>
+template<class OrderComparison>
+typename ChainWrapper<C>::const_reference 
+ChainWrapper<C>::
+get_first(const OrderComparison& cmp) const
+{ return top(cmp); }
+
+        
+template<class C>
+template<class Archive> 
+void                        
+ChainWrapper<C>::
+serialize(Archive& ar, boost::serialization::version_type )
+{
+    ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Parent);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/topology/cohomology-persistence.h	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,138 @@
+#ifndef __COHOMOLOGY_PERSISTENCE_H__
+#define __COHOMOLOGY_PERSISTENCE_H__
+
+#if DEBUG_CONTAINERS
+    #include <debug/list>
+    #include <debug/vector>
+    namespace s = std::__debug;
+    #warning "Using debug/list and debug/vector in CohomologyPersistence"
+#else
+    #include <list>
+    #include <vector>
+    namespace s = std;
+#endif
+
+#include <vector>
+#include <list>
+#include <utility>
+
+#include <topology/field-arithmetic.h>
+#include "utilities/types.h"
+
+#include <boost/optional.hpp>
+#include <boost/intrusive/list.hpp>
+namespace bi = boost::intrusive;
+
+#include <boost/tuple/tuple.hpp>
+#include <boost/shared_ptr.hpp>
+
+
+template<class BirthInfo_, class SimplexData_ = Empty<>, class Field_ = ZpField>
+class CohomologyPersistence
+{
+    public:
+        typedef             BirthInfo_                                                  BirthInfo;
+        typedef             SimplexData_                                                SimplexData;
+        typedef             Field_                                                      Field;
+
+        typedef             typename Field::Element                                     FieldElement;
+
+
+                            CohomologyPersistence(const Field& field = Field()):
+                                field_(field), image_begin_(cocycles_.end())            {}
+
+
+        // An entry in a cocycle column
+        struct  SNode;      // members: si, coefficient, ci
+        typedef             s::vector<SNode>                                            ZColumn;
+        typedef             bi::list<SNode, bi::constant_time_size<false> >             ZRow;
+        class   CompareSNode;
+
+        struct  SHead;      // members: row, order
+        typedef             s::list<SHead>                                              Simplices;
+        typedef             typename Simplices::iterator                                SimplexIndex;
+
+        struct  Cocycle;    // members: zcolumn, birth, order
+        typedef             s::list<Cocycle>                                            Cocycles;
+        typedef             typename Cocycles::iterator                                 CocycleIndex;
+        typedef             std::pair<CocycleIndex, FieldElement>                       CocycleCoefficientPair;
+
+        typedef             boost::optional<BirthInfo>                                  Death;
+        typedef             boost::shared_ptr<ZColumn>                                  CocyclePtr;
+        typedef             boost::tuple<SimplexIndex, Death, CocyclePtr>               IndexDeathCocycle;
+
+        // return either a SimplexIndex or a Death
+        // BI = BoundaryIterator; it should dereference to a SimplexIndex
+        template<class BI>
+        IndexDeathCocycle   add(BI begin, BI end, BirthInfo b, bool store = true, const SimplexData& sd = SimplexData(), bool image = true);
+        
+        // if sign needs to be specified explicitly, provide (parallel) coefficient_iter
+        template<class BI, class CI>
+        IndexDeathCocycle   add(CI coefficient_iter, BI begin, BI end, BirthInfo b, bool store = true, const SimplexData& sd = SimplexData(), bool image = true);
+
+        void                show_cocycles() const;
+        CocycleIndex        begin()                                                     { return image_begin_; }
+        CocycleIndex        end()                                                       { return cocycles_.end(); }
+
+    private:
+        void                add_cocycle(CocycleCoefficientPair& z1, CocycleCoefficientPair& z2);
+
+    private:
+        Simplices           simplices_;
+        Cocycles            cocycles_;
+        CocycleIndex        image_begin_;
+        Field               field_;
+};
+        
+// Simplex representation
+template<class BirthInfo_, class SimplexData_, class Field_>
+struct CohomologyPersistence<BirthInfo_, SimplexData_, Field_>::SHead: public SimplexData
+{
+                    SHead(const SHead& other):
+                        SimplexData(other), order(other.order)                  {}  // don't copy row since we can't
+                    SHead(const SimplexData& sd, unsigned o): 
+                        SimplexData(sd), order(o)                               {}
+
+    // intrusive list corresponding to row of s in Z^*, not ordered in any particular order
+    ZRow            row;
+    unsigned        order;
+};
+
+// An entry in a cocycle column; it's also an element in an intrusive list, hence the list_base_hook<>
+typedef             bi::list_base_hook<bi::link_mode<bi::auto_unlink> >         auto_unlink_hook;
+template<class BirthInfo_, class SimplexData_, class Field_>
+struct CohomologyPersistence<BirthInfo_, SimplexData_, Field_>::SNode: public auto_unlink_hook
+{
+                    SNode(const SNode& other):
+                        si(other.si), coefficient(other.coefficient), 
+                        ci(other.ci)                                            {}
+
+                    SNode(SimplexIndex sidx, FieldElement coef, CocycleIndex cidx): 
+                        si(sidx), coefficient(coef), ci(cidx)                   {}
+
+    SimplexIndex    si;
+    FieldElement    coefficient;
+
+    CocycleIndex    ci;                         // TODO: is there no way to get rid of this overhead?
+
+    void            unlink()                    { auto_unlink_hook::unlink(); }
+};
+
+template<class BirthInfo_, class SimplexData_, class Field_>
+struct CohomologyPersistence<BirthInfo_, SimplexData_, Field_>::Cocycle
+{
+                    Cocycle(const BirthInfo& b, unsigned o):
+                        birth(b), order(o)                                      {}
+
+    ZColumn         zcolumn;
+    BirthInfo       birth;
+    signed          order;
+
+    bool            operator<(const Cocycle& other) const                       { return order > other.order; }
+    bool            operator==(const Cocycle& other) const                      { return order == other.order; }
+};
+
+
+#include "cohomology-persistence.hpp"
+
+#endif // __COHOMOLOGY_PERSISTENCE_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/topology/cohomology-persistence.hpp	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,292 @@
+#include <boost/utility.hpp>
+#include <queue>
+#include <vector>
+#include <limits>
+
+#include <utilities/log.h>
+#include <utilities/indirect.h>
+#include <utilities/counter.h>
+
+#include <boost/iterator/transform_iterator.hpp>
+#include <boost/iterator/counting_iterator.hpp>
+#include <boost/foreach.hpp>
+
+#include <boost/lambda/lambda.hpp>
+#include <boost/lambda/bind.hpp>
+namespace bl = boost::lambda;
+
+#include <boost/make_shared.hpp>
+
+#ifdef LOGGING
+static rlog::RLogChannel* rlCohomology =                DEF_CHANNEL("topology/cohomology",        rlog::Log_Debug);
+#endif
+
+#ifdef COUNTERS
+static Counter*  cCohomologyAddBasic =                  GetCounter("cohomology/add/basic");
+static Counter*  cCohomologyAddComparison =             GetCounter("cohomology/add/comparison");
+static Counter*  cCohomologyElementCount =              GetCounter("cohomology/elements");
+static Counter*  cCohomologyCocycleCount =              GetCounter("cohomology/cocycles");
+static Counter*  cCohomologyCandidatesCount =           GetCounter("cohomology/candidates");
+#endif // COUNTERS
+
+template<class BirthInfo, class SimplexData, class Field>
+class CohomologyPersistence<BirthInfo, SimplexData, Field>::CompareSNode
+{
+    public:
+        bool        operator()(const SNode& s1, const SNode& s2) const                  { return s1.si->order < s2.si->order; }
+};
+    
+
+struct Alternator
+{
+    typedef         int         result_type;
+    int             operator()(int x) const                                             { return (x % 2)*2 - 1; }
+};
+    
+
+template<class BirthInfo, class SimplexData, class Field>
+template<class BI>
+typename CohomologyPersistence<BirthInfo, SimplexData, Field>::IndexDeathCocycle
+CohomologyPersistence<BirthInfo, SimplexData, Field>::
+add(BI begin, BI end, BirthInfo birth, bool store, const SimplexData& sd, bool image)
+{
+    // Set coefficient to be an iterator over (-1)^i
+    
+    return add(boost::make_transform_iterator(boost::make_counting_iterator(1), Alternator()),
+               begin, end, 
+               birth, store, sd, image);
+}
+
+
+template<class BirthInfo, class SimplexData, class Field>
+template<class BI, class CI>
+typename CohomologyPersistence<BirthInfo, SimplexData, Field>::IndexDeathCocycle
+CohomologyPersistence<BirthInfo, SimplexData, Field>::
+add(CI coefficient_iter, BI begin, BI end, BirthInfo birth, bool store, const SimplexData& sd, bool image)
+{
+    // Create simplex representation
+    simplices_.push_back(SHead(sd, simplices_.empty() ? 0 : (simplices_.back().order + 1)));
+    SimplexIndex    si = boost::prior(simplices_.end());
+
+    // Find out if there are cocycles that evaluate to non-zero on the new simplex
+    typedef         std::list<CocycleCoefficientPair>           Candidates;
+    Candidates      candidates, candidates_bulk;
+    rLog(rlCohomology, "Boundary");
+
+    for (BI cur = begin; cur != end; ++cur)
+    {
+        FieldElement coefficient = field_.init(*coefficient_iter++);
+        SimplexIndex cursi = *cur;
+
+        rLog(rlCohomology, "  %d %d", cursi->order, coefficient);
+        BOOST_FOREACH(const SNode& zcur, std::make_pair(cursi->row.begin(), cursi->row.end()))
+            candidates_bulk.push_back(std::make_pair(zcur.ci, field_.mul(coefficient, zcur.coefficient)));
+    }
+
+    candidates_bulk.sort(make_first_comparison(make_indirect_comparison(std::less<Cocycle>())));
+    CountBy(cCohomologyCandidatesCount, candidates_bulk.size());
+    
+#if LOGGING    
+    rLog(rlCohomology,  "  Candidates bulk");
+    for (typename Candidates::iterator cur  = candidates_bulk.begin(); 
+                                       cur != candidates_bulk.end(); ++cur)
+        rLog(rlCohomology, "    %d %d", cur->first->order, cur->second);
+#endif
+
+    // Remove duplicates
+    {
+        typename Candidates::const_iterator cur = candidates_bulk.begin();
+        while (cur != candidates_bulk.end())
+        {
+            typename Candidates::const_iterator next = cur;
+            FieldElement sum = field_.zero();
+            while (next != candidates_bulk.end() && next->first == cur->first) 
+            { 
+                sum = field_.add(sum, next->second);
+                ++next; 
+            }
+    
+            rLog(rlCohomology, "  Bulk candidate %d sum %d", cur->first->order, sum);
+            if (!field_.is_zero(sum))
+                candidates.push_back(CocycleCoefficientPair(cur->first, sum));
+    
+            cur = next;
+        }
+    }
+
+    // Birth
+    if (candidates.empty())
+    {
+        // rLog(rlCohomology, "  Birth occurred");
+        if (!store)
+        {
+            simplices_.pop_back();
+            boost::shared_ptr<ZColumn> p = boost::make_shared<ZColumn>();
+            return boost::make_tuple(simplices_.end(), Death(), p);
+        }
+        
+        signed order = 0;
+        if (image)
+            if (image_begin_ == cocycles_.end())
+                order = std::numeric_limits<signed>::min();
+            else
+                order = image_begin_->order + 1;
+        else
+            if (!cocycles_.empty() && cocycles_.front().order >= 0)     // we have something outside the image
+                order = cocycles_.front().order + 1;
+
+        CocycleIndex nw;
+        if (image)
+        {
+            image_begin_ = cocycles_.insert(image_begin_, Cocycle(birth, order));
+            nw = image_begin_;
+        } else
+        {
+            cocycles_.push_front(Cocycle(birth, order));
+            nw = cocycles_.begin();
+        }
+        
+        rLog(rlCohomology,  "Birth: %d", nw->order);
+
+        // set up the cocycle
+        ZColumn& cocycle = nw->zcolumn;
+        cocycle.push_back(SNode(si, field_.id(), nw));
+        si->row.push_back(cocycle.front());
+        rLog(rlCohomology,  "  Cocyle: %d", si->order);
+        
+        Count(cCohomologyElementCount);
+        Count(cCohomologyCocycleCount);
+
+        boost::shared_ptr<ZColumn> p = boost::make_shared<ZColumn>();
+        return boost::make_tuple(si, Death(), p);
+    }
+
+    // Death
+    rLog(rlCohomology,  "Death");
+
+#if LOGGING
+    // Debug only, output candidates
+    rLog(rlCohomology,  "  Candidates");
+    for (typename Candidates::iterator cur  = candidates.begin(); cur != candidates.end(); ++cur)
+        rLog(rlCohomology, "    %d %d", cur->first->order, cur->second);
+#endif
+
+    CocycleCoefficientPair& z   = candidates.front();
+    Death d                     = z.first->birth;
+    rLog(rlCohomology, "  Order: %d", z.first->order);
+    if (z.first->order >= 0)    // if death outside image
+        d = Death();            // no death occurs outside the image
+    else
+        if (z.first == image_begin_)
+            ++image_begin_;
+
+    // add z to everything else in candidates
+    for (typename Candidates::iterator cur  = boost::next(candidates.begin()); 
+                                       cur != candidates.end(); ++cur)
+    {
+        CountBy(cCohomologyElementCount, -cur->first->zcolumn.size());
+        add_cocycle(*cur, z);
+        CountBy(cCohomologyElementCount, cur->first->zcolumn.size());
+    }
+
+    for (typename ZColumn::iterator cur = z.first->zcolumn.begin(); cur != z.first->zcolumn.end(); ++cur)
+        cur->unlink();
+    
+    CountBy(cCohomologyElementCount, -z.first->zcolumn.size());
+    CountBy(cCohomologyCocycleCount, -1);
+    boost::shared_ptr<ZColumn> p = boost::make_shared<ZColumn>();
+    p->swap(z.first->zcolumn);
+    cocycles_.erase(z.first);
+
+    return boost::make_tuple(si, d, p);
+}
+        
+template<class BirthInfo, class SimplexData, class Field>
+void
+CohomologyPersistence<BirthInfo, SimplexData, Field>::
+show_cocycles() const
+{
+    std::cout << "Cocycles: " << cocycles_.size() << std::endl;
+    for (typename Cocycles::const_iterator cur = cocycles_.begin(); cur != cocycles_.end(); ++cur)
+    {
+        // std::cout << cur->order << " (" << cur->birth << "): ";
+        for (typename ZColumn::const_iterator zcur = cur->zcolumn.begin(); zcur != cur->zcolumn.end(); ++zcur)
+            std::cout << zcur->coefficient << " * " << zcur->si->order << ", ";
+        std::cout << std::endl;
+    }
+}
+
+template<class BirthInfo, class SimplexData, class Field>
+void
+CohomologyPersistence<BirthInfo, SimplexData, Field>::
+add_cocycle(CocycleCoefficientPair& to, CocycleCoefficientPair& from)
+{
+    rLog(rlCohomology,  "Adding cocycle %d to %d", from.first->order, to.first->order);
+
+    FieldElement    multiplier = field_.neg(field_.div(to.second, from.second));
+    CocycleIndex    ci = to.first;
+    CompareSNode    cmp;
+
+    // Insert at the end optimization
+    if (cmp(to.first->zcolumn.back(), from.first->zcolumn.front()) && 
+        to.first->zcolumn.capacity() >= (to.first->zcolumn.size() + from.first->zcolumn.size()))
+    {
+        BOOST_FOREACH(const SNode& fs, from.first->zcolumn)
+        {
+            to.first->zcolumn.push_back(SNode(fs.si, field_.mul(multiplier, fs.coefficient), ci));
+            fs.si->row.push_back(to.first->zcolumn.back());
+            Count(cCohomologyAddBasic);
+        }
+
+        return;
+    }
+
+    ZColumn         nw;
+    typename ZColumn::iterator tcur = to.first->zcolumn.begin();
+    typename ZColumn::iterator fcur = from.first->zcolumn.begin();
+    while (tcur != to.first->zcolumn.end() && fcur != from.first->zcolumn.end())
+    {
+        rLog(rlCohomology, "  %d %d", tcur->si->order, fcur->si->order);
+        Count(cCohomologyAddComparison);
+        Count(cCohomologyAddBasic);
+        if (cmp(*tcur, *fcur))
+        {
+            nw.push_back(*tcur);
+            ++tcur;
+        }
+        else if (cmp(*fcur, *tcur))
+        {
+            nw.push_back(SNode(fcur->si, field_.mul(multiplier, fcur->coefficient), ci));
+            ++fcur;
+        }
+        else        // equality
+        {
+            FieldElement res = field_.mul(multiplier, tcur->coefficient);
+            res = field_.add(fcur->coefficient, res);
+            if (!field_.is_zero(res))
+                nw.push_back(SNode(fcur->si, res, ci));
+            ++tcur; ++fcur;
+        }
+    }
+    for (; tcur != to.first->zcolumn.end(); ++tcur)
+    {
+        rLog(rlCohomology, "  %d", tcur->si->order);
+        Count(cCohomologyAddBasic);
+        nw.push_back(SNode(*tcur));
+    }
+    for (; fcur != from.first->zcolumn.end(); ++fcur)
+    {
+        rLog(rlCohomology, "  %d", fcur->si->order);
+        Count(cCohomologyAddBasic);
+        nw.push_back(SNode(fcur->si, field_.mul(multiplier, fcur->coefficient), ci));
+    }
+
+
+    for (typename ZColumn::iterator cur = to.first->zcolumn.begin(); cur != to.first->zcolumn.end(); ++cur)
+        cur->unlink();
+
+    to.first->zcolumn.swap(nw);
+
+    for (typename ZColumn::iterator cur = to.first->zcolumn.begin(); cur != to.first->zcolumn.end(); ++cur)
+        cur->si->row.push_back(*cur);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/topology/complex-traits.h	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,77 @@
+#ifndef __COMPLEX_TRAITS_H__
+#define __COMPLEX_TRAITS_H__
+
+#include <vector>
+#include <map>
+#include "utilities/property-maps.h"
+
+// Class: ComplexTraits
+// Class that extracts various properties of a complex.
+//
+// Parameter:
+//   Complex -      the type whose traits we are extracting
+template<class Complex_>
+struct ComplexTraits
+{
+    /* 
+     * Typedefs: Associated types
+     * Types extractable by the traits class.
+     *
+     * Complex -            the type of the complex
+     * Simplex -            the type of the simplex stored in the complex
+     * Index -              the type used to refer to the elements of the complex
+     * IndexComparison -    the type used to compare indices
+     */
+    typedef         Complex_                                                Complex;
+    typedef         typename Complex::Simplex                               Simplex;
+    typedef         typename Complex::Index                                 Index;
+    typedef         std::less<Index>                                        IndexComparison;
+
+    /* Typedefs: Maps
+     * Maps to go from Indicies to Simplices and back.
+     *
+     * SimplexIndexMap -    the map from Simplex to the Index (could be implemented via a binary search, or a map)
+     */
+    typedef         AssociativeMap<std::map<Simplex, Index, 
+                                   typename Simplex::VertexComparison> >    SimplexIndexMap;
+
+    // Function: simplex_index_map() 
+    // Initializes an SimplexIndexMap given a Complex.
+    static SimplexIndexMap
+                    simplex_index_map(const Complex& complex)               { return SimplexIndexMap(complex.begin(),
+                                                                                                     complex.end()); } 
+
+    static Index    begin(const Complex& complex)                           { return complex.begin(); }
+    static Index    end(const Complex& complex)                             { return complex.end(); }
+
+    static const Simplex&
+                    simplex(Index i)                                        { return *i; }
+};
+
+
+// Specializations
+template<class Simplex_>
+struct ComplexTraits<std::vector<Simplex_> >
+{
+    typedef         std::vector<Simplex_>                                   Complex;
+    typedef         Simplex_                                                Simplex;
+    typedef         typename Complex::const_iterator                        Index;
+    typedef         std::less<Index>                                        IndexComparison;
+
+    typedef         BinarySearchMap<Simplex, Index,
+                                    typename Simplex::VertexComparison>     SimplexIndexMap;
+
+    static SimplexIndexMap
+                    simplex_index_map(const Complex& complex)               { return SimplexIndexMap(complex.begin(),
+                                                                                                     complex.end()); }
+    static SimplexIndexMap
+                    simplex_index_map(Index bg, Index end)                  { return SimplexIndexMap(bg, end); }
+
+    static Index    begin(const Complex& complex)                           { return complex.begin(); }
+    static Index    end(const Complex& complex)                             { return complex.end(); }
+
+    static const Simplex&
+                    simplex(Index i)                                        { return *i; }
+};
+
+#endif // __COMPLEX_TRAITS_H__
--- a/include/topology/conesimplex.h	Fri Aug 24 16:58:25 2007 -0400
+++ b/include/topology/conesimplex.h	Tue Jun 27 09:37:05 2017 -0700
@@ -9,30 +9,54 @@
 #include <list>
 #include <iostream>
 
-template<class S>
-class ConeSimplex: public S
+#include "utilities/types.h"
+#include "simplex.h"
+
+
+template<class V, class T = Empty>
+class ConeSimplex: public Simplex<V,T>
 {
-	public:
-		typedef		S													Parent;
-		typedef		ConeSimplex<S>										Self;
-		typedef		std::list<Self>										Cycle;
+    public:
+        typedef     Simplex<V,T>                                        Parent;
+        typedef     ConeSimplex<V,T>                                    Self;
 
     public:
-								ConeSimplex(const Parent& parent, 
-											bool coned = false):
-									Parent(parent), coned_(coned)		{}
-	    
-		Cycle					boundary() const;
-		bool					coned() const							{ return coned_; }
+                                ConeSimplex(const Self& s): 
+                                    Parent(s), coned_(s.coned_)         {}
+                                ConeSimplex(const Parent& parent, 
+                                            bool coned = false):
+                                    Parent(parent), coned_(coned)       {}
+        
+        Cycle                   boundary() const;
+        bool                    coned() const                           { return coned_; }
+        Dimension               dimension() const                       { return coned_ ? (Parent::dimension() + 1) : Parent::dimension(); }
+        
+        bool                    operator==(const Self& other) const     { return !(coned_ ^ other.coned_) && Parent::operator==(other); }
 
-		std::ostream& 			operator<<(std::ostream& out) const;
-		
-	private:
-		bool					coned_;
+        std::ostream&           operator<<(std::ostream& out) const;
+
+        struct ConedVertexComparison;
+        
+    private:
+        bool                    coned_;
 };
 
-template<class S>
-std::ostream& 		operator<<(std::ostream& out, const ConeSimplex<S>& s)	{ return s.operator<<(out); }
+template<class V, class T>
+struct ConeSimplex<V,T>::ConedVertexComparison: public typename Simplex<V,T>::VertexComparison
+{
+        typedef     typename Simplex<V,T>::VertexComparison         Parent; 
+    
+        bool                    operator()(const Self& a, const Self& b) const       
+        { 
+            if (a.coned() ^ b.coned())
+                return b.coned();                   // coned simplices shall come after non-coned ones
+            else
+                return Parent::operator()(a,b);     // within coned/non-coned order by vertices
+        }
+};
+
+template<class V, class T>
+std::ostream&       operator<<(std::ostream& out, const ConeSimplex<V,T>& s)  { return s.operator<<(out); }
 
 #include "conesimplex.hpp"
 
--- a/include/topology/cycle.h	Fri Aug 24 16:58:25 2007 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,115 +0,0 @@
-/**
- * Author: Dmitriy Morozov
- * Department of Computer Science, Duke University, 2005-2006
- */
-
-#ifndef __CYCLE_H__
-#define __CYCLE_H__
-
-#include "utilities/sys.h"
-#include "utilities/debug.h"
-
-#include "utilities/types.h"
-#include "utilities/circular_list.h"
-#include <list>
-#include <boost/serialization/access.hpp>
-
-/**
- * Class storing a cycle of simplices. Stores items in the order defined by ConsistencyCmp. 
- * The actual order of the elements is defined by OrderCmp. Instances of those 
- * classes are not stored in Cycle for efficiency, and are passed as arguments to those methods 
- * that require them.
- */
-template <class Itm, class OrderCmp, class ConsistencyCmp = OrderCmp>
-class Cycle: public List<Itm>
-{
-	public:
-		/// \name Template Parameters
-		/// @{
-		typedef			Itm												Item;
-		typedef			OrderCmp										OrderComparison;
-		typedef			ConsistencyCmp									ConsistencyComparison;
-		/// @}
-		
-		typedef 		Cycle<Item, OrderComparison, ConsistencyCmp>	Self;
-		typedef			List<Item> 										CycleRepresentation; 
-
-		/// \name Accessor typedefs
-		/// @{
-		typedef			typename CycleRepresentation::iterator			iterator; 
-		typedef			typename CycleRepresentation::const_iterator	const_iterator; 
-		typedef			typename CycleRepresentation::const_reference	const_reference; 
-		typedef			typename CycleRepresentation::reference			reference; 
-		typedef			typename CycleRepresentation::pointer			pointer; 
-		typedef			typename CycleRepresentation::const_pointer		const_pointer; 
-		/// @}
-		
-	public:		
-						Cycle();
-						Cycle(const Cycle& c);
-		
-		/// \name Whole Cycle operations
-		/// @{
-		/** Add c to *this assuming both Cycles are sorted in increasing order according to cmp. */
-		Self&			add(const Self& c, const ConsistencyComparison& cmp);
-		void			swap(Cycle& c); 								///< Swaps the contents of c and *this (like STL's swap destroys c)
-		//void 			insertion_sort(const Comparison& cmp); 			///< Sort list[i] using insertion sort
-		void			sort(const ConsistencyComparison& cmp);			///< Sort elements to enforce consistency
-		using 			CycleRepresentation::empty;
-		using 			CycleRepresentation::clear;
-		using			CycleRepresentation::size;
-		/// @}
-		
-		/// \name Modifiers
-		/// @{
-		using 			CycleRepresentation::erase;
-		void			append(const_reference x, const ConsistencyComparison& cmp);
-		/// @}
-		
-		/// \name Accessors
-		/// @{
-		using 			CycleRepresentation::begin;
-		using 			CycleRepresentation::end;
-		const_reference	top(const OrderComparison& cmp) const;			///< First element in cmp order
-		iterator		get_second(const OrderComparison& cmp) const;	///< Second element in cmp order
-		/// @}
-
-		/// \name Block access optimizations
-		// Between operations used in optimization of transpositions for regular vertices. Maybe we don't need these? TODO
-		/// @{
-		/** Return first after i, but before or equal j; return i if no such element found */
-		const_reference	first_between(const_reference i, const_reference j, const OrderComparison& cmp);
-		/// Add lists and remove all elements after i and before or equal to j
-		const_reference	add_and_first_between(const Self& c, const ConsistencyComparison& consistency_cmp,
-											  const_reference i, const_reference j, const OrderComparison& order_cmp);
-		/// Erase everything after i, but before or equal to j
-		void 			erase_between(const_reference i, const_reference j, const OrderComparison& cmp);
-		/// @}
-	
-		/// \name Debugging
-		/// @{
-		const_reference get_first(const OrderComparison& cmp) const;	///< First element in cmp order
-		std::ostream&	operator<<(std::ostream& out) const;
-		/// @}
-		
-	private:
-		typedef			std::list<Item>									TemporaryCycleRepresenation;
-		
-		using 			CycleRepresentation::push_back;
-		using 			CycleRepresentation::insert;
-
-	private:
-		size_t sz;
-		
-	private:
-		// Serialization
-		typedef			List<Item>										Parent;
-		friend class 	boost::serialization::access;
-		template<class Archive> 
-		void			serialize(Archive& ar, version_type );
-};
-
-#include "cycle.hpp"
-
-#endif // __CYCLE_H__
-
--- a/include/topology/cycle.hpp	Fri Aug 24 16:58:25 2007 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,280 +0,0 @@
-#include <algorithm>
-#include <vector>
-
-#include <boost/serialization/split_member.hpp>
-#include <boost/serialization/nvp.hpp>
-#include <boost/serialization/binary_object.hpp>
-#include <boost/utility.hpp>
-
-using boost::serialization::make_nvp;
-using boost::serialization::make_binary_object;
-
-template<class I, class OrderCmp, class ConsistencyCmp>
-Cycle<I,OrderCmp,ConsistencyCmp>::
-Cycle(): sz(0)
-{}
-
-template<class I, class OrderCmp, class ConsistencyCmp>
-Cycle<I,OrderCmp,ConsistencyCmp>::
-Cycle(const Cycle& c): CycleRepresentation(c), sz(c.sz)					
-{}
-
-template<class I, class OrderCmp, class ConsistencyCmp>
-void
-Cycle<I,OrderCmp,ConsistencyCmp>::
-append(const_reference x, const ConsistencyCmp& cmp)						
-{ 
-	// First try the special cases that x goes at the end
-	const_reference last = CycleRepresentation::back();
-	if (empty() || cmp(last, x))
-	{
-		push_back(x); 
-		return;
-	}
-
-	for (iterator cur = begin(); cur != end(); ++cur)
-		if (cmp(x, *cur))
-		{
-			insert(cur, x);
-			return;
-		}
-}
-		
-template<class I, class OrderCmp, class ConsistencyCmp>
-typename Cycle<I,OrderCmp,ConsistencyCmp>::const_reference				
-Cycle<I,OrderCmp,ConsistencyCmp>::
-top(const OrderComparison& cmp) const
-{ 
-	AssertMsg(!empty(), "Cycle must not be empty for top()");
-	const_iterator min = begin();
-	for (const_iterator cur = ++begin(); cur != end(); ++cur)
-		if (cmp(*cur, *min))
-			min = cur;
-	return *min; 
-}
-
-template<class I, class OrderCmp, class ConsistencyCmp>
-void 
-Cycle<I,OrderCmp,ConsistencyCmp>::
-swap(Cycle& c)
-{
-	CycleRepresentation::swap(c);
-	std::swap(sz, c.sz);
-}
-
-template<class I, class OrderCmp, class ConsistencyCmp>
-void 
-Cycle<I,OrderCmp,ConsistencyCmp>::
-sort(const ConsistencyComparison& cmp)
-{ 
-	std::vector<Item> tmp(begin(), end());
-	std::sort(tmp.begin(), tmp.end(), cmp);
-	std::copy(tmp.begin(), tmp.end(), begin());
-}
-
-template<class I, class OrderCmp, class ConsistencyCmp>
-typename Cycle<I,OrderCmp,ConsistencyCmp>::iterator 
-Cycle<I,OrderCmp,ConsistencyCmp>::
-get_second(const OrderComparison& cmp) const
-{
-	AssertMsg(!empty(), "Cycle must not be empty for get_second()");
-	if (size() < 2)			return begin();					// Indicates that there is no second.
-
-	Dout(dc::cycle, "Looking for second");
-	AssertMsg(size() >= 2, "Cycle must have at least two elements for get_second()");
-	iterator min = begin();
-	iterator second = ++begin();
-	if (cmp(*second, *min))
-		std::swap(min, second);
-	for (iterator cur = boost::next(begin(),2); cur != end(); ++cur)
-	{
-		if (cmp(*cur, *min))
-		{
-			second = min;
-			min = cur;
-		} else if (cmp(*cur, *second))
-		{
-			second = cur;
-		}
-	}
-	
-	Dout(dc::cycle, "Looked up: " << **second);
-	return second;
-}
-
-template<typename I, class OrderCmp, class ConsistencyCmp>
-typename Cycle<I,OrderCmp,ConsistencyCmp>::const_reference				
-Cycle<I,OrderCmp,ConsistencyCmp>::
-first_between(const_reference i, const_reference j, const OrderComparison& cmp)
-{
-	// Find the first element in ConsistencyComparison order (> i and <= j)
-	const_pointer first = &i;
-	iterator cur = begin();
-	for (; cur != end(); ++cur)
-	{
-		if ((*cur == j) || (cmp(*cur, j) && cmp(i, *cur)))
-		{
-			first = &(*cur);
-			break;
-		}
-	}
-	
-	// If no such element found, then we are done
-	if (cur == end())
-		return i;
-
-	// Find first element in OrderComparison order (> i and <= j)
-	for (++cur; cur != end(); ++cur)
-	{
-		if ((*cur == j) || (cmp(*cur, j) && cmp(i, *cur)))
-		{
-			if (cmp(*cur, *first))
-				first = &(*cur);
-		}
-	}
-	return *first;
-}
-
-template<typename I, class OrderCmp, class ConsistencyCmp>
-void 
-Cycle<I,OrderCmp,ConsistencyCmp>::
-erase_between(const_reference i, const_reference j, const OrderComparison& cmp)
-{
-	for (iterator cur = begin(); cur != end(); ++cur)
-		while ((cur != end()) && ((*cur == j) || (cmp(*cur, j) && cmp(i, *cur))))
-		{
-			Dout(dc::cycle, "Iteration of the erase while loop");
-			cur = erase(cur);
-		}
-}
-
-template<typename I, class OrderCmp, class ConsistencyCmp>
-std::ostream& 
-Cycle<I,OrderCmp,ConsistencyCmp>::
-operator<<(std::ostream& out) const
-{
-	for (const_iterator cur = begin(); cur != end(); ++cur)
-	{
-		out << **cur << ", ";
-	}
-	// out << "(last: " << *last << ")";  // For debugging only
-	return out;
-}
-
-template<typename I, class OrderCmp, class ConsistencyCmp>
-std::ostream& 
-operator<<(std::ostream& out, const Cycle<I, OrderCmp, ConsistencyCmp>& c)	
-{
-	return c.operator<<(out);
-}
-
-template<typename I, class OrderCmp, class ConsistencyCmp>
-typename Cycle<I, OrderCmp, ConsistencyCmp>::Self& 
-Cycle<I, OrderCmp, ConsistencyCmp>::
-add(const Self& c, const ConsistencyCmp& cmp)
-{
-	Dout(dc::cycle, "Adding cycles: " << *this << " + " << c);
-	
-	iterator 			cur1 = begin();
-	const_iterator 		cur2 = c.begin();
-
-	while (cur2 != c.end())
-	{
-		if (cur1 == end())
-		{
-			while (cur2 != c.end())
-				push_back(*cur2++);
-			Dout(dc::cycle, "After addition: " << *this);
-			return *this;
-		}
-
-		// mod 2
-		int res = cmp.compare(*cur1, *cur2);
-		Dout(dc::cycle, "Comparison result: " << res);
-		if (res == 0)		// *cur1 == *cur2
-		{
-			Dout(dc::cycle, "Equality");
-			cur1 = erase(cur1);		// erase cur1 --- as a result cur1 will be pointing at old_cur1++
-			--sz;
-			++cur2;
-		} else if (res < 0)	// *cur1 < *cur2
-		{
-			Dout(dc::cycle, "Less than");
-			cur1++;
-		} else if (res > 0) // *cur1 > *cur2
-		{
-			Dout(dc::cycle, "Greater than");
-			insert(cur1, *cur2);
-			++cur2;
-			++sz;
-		}
-	}
-
-	Dout(dc::cycle, "After addition: " << *this);
-	return *this;
-}
-
-template<typename I, class OrderCmp, class ConsistencyCmp>
-typename Cycle<I,OrderCmp,ConsistencyCmp>::const_reference 
-Cycle<I,OrderCmp,ConsistencyCmp>::
-add_and_first_between(const Self& c, const ConsistencyComparison& consistency_cmp,
-					  const_reference i, const_reference j, const OrderComparison& order_cmp)
-{
-	add(c, consistency_cmp);
-	return first_between(i,j, order_cmp);
-}
-
-template<typename I, class OrderCmp, class ConsistencyCmp>
-typename Cycle<I,OrderCmp,ConsistencyCmp>::const_reference 
-Cycle<I,OrderCmp,ConsistencyCmp>::
-get_first(const OrderComparison& cmp) const
-{ return top(cmp); }
-
-		
-template<typename I, class OrderCmp, class ConsistencyCmp>
-template<class Archive> 
-void						
-Cycle<I,OrderCmp,ConsistencyCmp>::
-serialize(Archive& ar, version_type )
-{
-	ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Parent);
-	ar & make_nvp("size", sz);;
-}
-
-
-/*
-template<typename I, class Cmp>
-void 
-Cycle<I, Cmp>::
-insertion_sort(const Comparison& cmp)
-{
-	TemporaryCycleRepresenation tmp;
-
-	// Insertion sort into the temporary list
-	for (const_iterator cur = begin(); cur != end(); ++cur)
-	{
-		typename TemporaryCycleRepresenation::iterator tmp_cur = tmp.end();
-		typename TemporaryCycleRepresenation::iterator tmp_next = tmp_cur--;
-
-		while (tmp_next != tmp.begin())
-		{
-			if (cmp(*cur, *tmp_cur))
-				tmp_next = tmp_cur--;
-			else 
-				break;
-		}
-		tmp.insert(tmp_next, *cur);
-	}
-
-	// Copy temporary list back into ourselves
-	iterator cur = begin();
-	typename TemporaryCycleRepresenation::const_iterator tmp_cur = tmp.begin();
-	while(tmp_cur != tmp.end())
-	{
-		*cur = *tmp_cur;
-		++cur; ++tmp_cur;
-	}
-}
-*/
-
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/topology/cycles.h	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,49 @@
+#ifndef __CYCLES_H__
+#define __CYCLES_H__
+
+#include "chain.h"
+#include "utilities/circular_list.h"
+
+#if DEBUG_CONTAINERS
+    #include <debug/vector>
+    #include <debug/deque>
+    using std::__debug::vector;
+    using std::__debug::deque;
+#else
+    #include <vector>
+    #include <deque>
+    using std::vector;
+    using std::deque;
+#endif
+
+template<class OrderIndex_ = int>
+struct VectorChains
+{
+    typedef             OrderIndex_                                             OrderIndex;
+    typedef             ChainWrapper<vector<OrderIndex> >                       Chain;
+    
+    template<class U> struct rebind
+    { typedef           VectorChains<U>         other; };
+};
+
+template<class OrderIndex_ = int>
+struct DequeChains
+{
+    typedef             OrderIndex_                                             OrderIndex;
+    typedef             ChainWrapper<deque<OrderIndex> >                        Chain;
+
+    template<class U> struct rebind
+    { typedef           DequeChains<U>         other; };
+};
+
+template<class OrderIndex_ = int>
+struct ListChains
+{
+    typedef             OrderIndex_                                             OrderIndex;
+    typedef             ChainWrapper<List<OrderIndex> >                         Chain;
+    
+    template<class U> struct rebind
+    { typedef           ListChains<U>           other; };
+};
+
+#endif // __CYCLES_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/topology/dynamic-persistence.h	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,326 @@
+#ifndef __DYNAMIC_PERSISTENCE_H__
+#define __DYNAMIC_PERSISTENCE_H__
+
+#include "static-persistence.h"
+#include <utilities/types.h>
+
+#include <boost/bind.hpp>
+#include <boost/lambda/lambda.hpp>
+namespace bl = boost::lambda;
+
+#ifdef COUNTERS
+static Counter*  cTrailLength =             GetCounter("persistence/pair/traillength");     // the size of matrix U in RU decomposition
+static Counter*  cChainLength =             GetCounter("persistence/pair/chainlength");     // the size of matrix V in R=DV decomposition
+#endif // COUNTERS
+
+template<class Data_, class ChainTraits_>
+struct TrailData: public PairCycleData<Data_, ChainTraits_, TrailData<Data_, ChainTraits_> >
+{
+    typedef     Data_                                                                   Data;
+
+    typedef     PairCycleData<Data_, ChainTraits_, TrailData>                           Parent;
+    typedef     TrailData<Data_, ChainTraits_>                                          Self;
+
+    typedef     typename Parent::Index                                                  Index;
+    typedef     typename Parent::Cycle                                                  Cycle;
+    typedef     typename Parent::Chain                                                  Chain;
+    typedef     Chain                                                                   Trail;
+
+    // Modifiers
+    template<class Cmp>
+    void        trail_append(Index i, const Cmp& cmp)                                   { trail.append(i, cmp); }
+    template<class Cmp>
+    void        trail_add(const Trail& t, const Cmp& cmp)                               { trail.add(t, cmp); }
+
+    template<class Cmp>
+    void        cycle_add(const Cycle& z, const Cmp& cmp)                               { cycle.add(z, cmp); }
+
+    using       Parent::cycle;
+    Trail                                                                               trail;
+};
+
+/**
+ * Class: DynamicPersistenceTrails
+ * Derives from StaticPersistence and allows one to update persistence
+ * after a transposition of two contiguous simplices in a filtration.
+ * In addition to reduced cycles, it stores each OrderElement's trails,
+ * i.e. in addition to matrix R, it stores matrix U in vineyard notation.
+ *
+ * Template parameters:
+ *   Data_ -                auxilliary contents to store with each OrderElement
+ *   OrderDescriptor_ -     class describing how the order is stored; it defaults to <VectorOrderDescriptor>
+ *                          which serves as a prototypical class
+ */
+// TODO: perhaps Consistency should be wrapped into a ConsistencyDescriptor that somehow knows how to initialize it.
+// That way one could provide a simple consistency descriptor that just stored some integers describing the original
+// position, or one could provide consistency that is references into the complex
+template<class Data_ =                  Empty<>,
+         class ChainTraits_ =           VectorChains<>,
+         class ContainerTraits_ =       OrderConsistencyContainer<>,
+         class Element_ =               TrailData<Data_, ChainTraits_>,
+         class Comparison_ =            ElementComparison<typename ContainerTraits_::template rebind<Element_>::other::Container,
+                                                          std::greater<typename ContainerTraits_::template rebind<Element_>::other::Container::iterator> >,
+         class ConsistencyComparison_ = ElementComparison<typename ContainerTraits_::template rebind<Element_>::other::ConsistentContainer,
+                                                          std::greater<typename ContainerTraits_::template rebind<Element_>::other::ConsistentContainer::iterator> >
+        >
+class DynamicPersistenceTrails:
+    public StaticPersistence<Data_, ChainTraits_, ContainerTraits_, Element_, Comparison_>
+{
+    public:
+        typedef         Data_                                                           Data;
+        typedef         Element_                                                        Element;
+        typedef         StaticPersistence<Data_, ChainTraits_,
+                                          ContainerTraits_, Element_, Comparison_>      Parent;
+
+        typedef         typename Parent::ContainerTraits                                Traits;
+        typedef         typename Parent::Order                                          Order;
+        typedef         typename Traits::ConsistentContainer                            Consistency;
+        typedef         typename Parent::OrderComparison                                OrderComparison;
+        typedef         typename Parent::OrderIndex                                     OrderIndex;
+        typedef         ConsistencyComparison_                                          ConsistencyComparison;
+        typedef         typename Parent::iterator                                       iterator;
+
+        typedef         typename Element::Trail                                         Trail;
+        typedef         typename Element::Cycle                                         Cycle;
+
+         /* Constructor: DynamicPersistenceTrails() */
+                                        DynamicPersistenceTrails();
+
+        /**
+         * Constructor: DynamicPersistenceTrails()
+         * TODO: write a description
+         *
+         * Template parameters:
+         *   Filtration -           filtration of the complex whose persistence we are computing
+         */
+        template<class Filtration>      DynamicPersistenceTrails(const Filtration& f);
+
+        template<class Filtration>
+        void                            initialize(const Filtration& f)                 { Parent::initialize(f); }
+
+        void                            pair_simplices();
+
+        // Function: transpose(i)
+        // Tranpose i and the next element.
+        // Returns: true iff the pairing switched.
+        template<class DimensionFunctor, class Visitor>
+        bool                            transpose(iterator i, const DimensionFunctor& dimension, Visitor visitor = Visitor());
+
+        template<class DimensionFunctor>
+        bool                            transpose(iterator i, const DimensionFunctor& dimension)    { return transpose(i,dimension,TranspositionVisitor()); }
+
+        using                           Parent::begin;
+        using                           Parent::end;
+        using                           Parent::iterator_to;
+        using                           Parent::index;
+        using                           Parent::size;
+        using                           Parent::order_comparison;
+
+        template<class Iter>
+        void                            rearrange(Iter i);
+
+        // Struct: TranspositionVisitor
+        //
+        // For example, a VineardVisitor could implement this archetype.
+        struct TranspositionVisitor
+        {
+            // Function: transpose(i)
+            // This function is called before transposition is processed
+            // (at the very beginning of <transpose(i, visitor)>). It is meant to update any structures
+            // that may need to be updated, but perhaps it has other uses as well.
+            void                        transpose(iterator i) const                     {}
+
+            // Function: switched(i, type)
+            // This function is called after the transposition if the switch in pairing has occured.
+            // `i` is the index of the preceding simplex after the transposition.
+            // `type` indicates the <SwitchType>.
+            void                        switched(iterator i, SwitchType type) const     {}
+        };
+
+    protected:
+        using                           Parent::order;
+        using                           Parent::set_pair;
+        using                           Parent::swap_cycle;
+
+        Consistency&                    consistent_order()                              { return order().template get<consistency>(); }
+        const Consistency&              consistent_order() const                        { return order().template get<consistency>(); }
+
+        bool                            trail_remove_if_contains
+                                            (iterator i, OrderIndex j)                  { TrailRemover rm(j); order().modify(i, rm); return rm.result; }
+        void                            cycle_add(iterator i, const Cycle& z)           { order().modify(i, boost::bind(&Element::template cycle_add<ConsistencyComparison>, bl::_1, boost::ref(z), ccmp_)); }      // i->cycle_add(z, ccmp_)
+        void                            trail_add(iterator i, const Trail& t)           { order().modify(i, boost::bind(&Element::template trail_add<ConsistencyComparison>, bl::_1, boost::ref(t), ccmp_)); }      // i->trail_add(t, ccmp_)
+
+    private:
+        void                            swap(iterator i, iterator j);
+        void                            pairing_switch(iterator i, iterator j);
+
+        struct PairingTrailsVisitor: public Parent::PairVisitor
+        {
+                                        PairingTrailsVisitor(Order& order, ConsistencyComparison ccmp, unsigned size):
+                                            Parent::PairVisitor(size), order_(order), ccmp_(ccmp)   {}
+
+            void                        init(iterator i) const                          { order_.modify(i,                                  boost::bind(&Element::template trail_append<ConsistencyComparison>, bl::_1, &*i, ccmp_)); Count(cTrailLength); }        // i->trail_append(&*i, ccmp)
+            void                        update(iterator j, iterator i) const            { order_.modify(order_.iterator_to(*(i->pair)),     boost::bind(&Element::template trail_append<ConsistencyComparison>, bl::_1, &*j, ccmp_)); Count(cTrailLength); }        // i->pair->trail_append(&*j, ccmp)
+            void                        finished(iterator i) const                      { Parent::PairVisitor::finished(i); }
+
+            Order&                      order_;
+            ConsistencyComparison       ccmp_;
+        };
+
+        struct TrailRemover;
+
+        ConsistencyComparison           ccmp_;
+};
+
+/* Chains */
+template<class Data_, class ChainTraits_>
+struct ChainData: public PairCycleData<Data_, ChainTraits_, ChainData<Data_, ChainTraits_> >
+{
+    typedef     Data_                                                                   Data;
+
+    typedef     PairCycleData<Data_, ChainTraits_, ChainData>                           Parent;
+    typedef     ChainData<Data_, ChainTraits_>                                          Self;
+
+    typedef     typename Parent::Index                                                  Index;
+    typedef     typename Parent::Cycle                                                  Cycle;
+    typedef     typename Parent::Chain                                                  Chain;
+    typedef     Chain                                                                   Trail;
+
+    // Modifiers
+    template<class Cmp>
+    void        chain_append(Index i, const Cmp& cmp)                                   { chain.append(i, cmp); }
+    template<class Cmp>
+    void        chain_add(const Chain& c, const Cmp& cmp)                               { chain.add(c, cmp); }
+
+    template<class Cmp>
+    void        cycle_add(const Cycle& z, const Cmp& cmp)                               { cycle.add(z, cmp); }
+
+    using       Parent::cycle;
+    Chain                                                                               chain;
+};
+
+/**
+ * Class: DynamicPersistenceChains
+ *
+ * TODO: below comment is incorrect; nothing dynamic about this yet.
+ * Derives from StaticPersistence and allows one to update persistence
+ * after a transposition of two contiguous simplices in a filtration.
+ * In addition to reduced cycles, it stores each OrderElement's chains,
+ * i.e. in addition to matrix R, it stores matrix V in vineyard notation.
+ *
+ * Template parameters:
+ *   Data_ -                auxilliary contents to store with each OrderElement
+ *   OrderDescriptor_ -     class describing how the order is stored; it defaults to <VectorOrderDescriptor>
+ *                          which serves as a prototypical class
+ */
+template<class Data_ =                  Empty<>,
+         class ChainTraits_ =           VectorChains<>,
+         class ContainerTraits_ =       OrderConsistencyContainer<>,
+         class Element_ =               ChainData<Data_, ChainTraits_>,
+         class Comparison_ =            ElementComparison<typename ContainerTraits_::template rebind<Element_>::other::Container,
+                                                          std::greater<typename ContainerTraits_::template rebind<Element_>::other::Container::iterator> >,
+         class ConsistencyComparison_ = ElementComparison<typename ContainerTraits_::template rebind<Element_>::other::ConsistentContainer,
+                                                          std::greater<typename ContainerTraits_::template rebind<Element_>::other::ConsistentContainer::iterator> >
+        >
+class DynamicPersistenceChains:
+    public StaticPersistence<Data_, ChainTraits_, ContainerTraits_, Element_, Comparison_>
+{
+    public:
+        typedef         Data_                                                           Data;
+        typedef         Element_                                                        Element;
+        typedef         StaticPersistence<Data_, ChainTraits_,
+                                          ContainerTraits_, Element_, Comparison_>      Parent;
+
+        typedef         typename Parent::ContainerTraits                                Traits;
+        typedef         typename Parent::Order                                          Order;
+
+        typedef         typename Parent::OrderComparison                                OrderComparison;
+        typedef         typename Parent::OrderIndex                                     OrderIndex;
+        typedef         ConsistencyComparison_                                          ConsistencyComparison;
+        typedef         typename Parent::iterator                                       iterator;
+
+        typedef         typename Element::Chain                                         Chain;
+        typedef         typename Element::Cycle                                         Cycle;
+
+        /* Constructor: DynamicPersistenceChains() */
+                                        DynamicPersistenceChains();
+
+        /**
+         * Constructor: DynamicPersistenceChains()
+         * TODO: write a description
+         *
+         * Template parameters:
+         *   Filtration -           filtration of the complex whose persistence we are computing
+         */
+        template<class Filtration>      DynamicPersistenceChains(const Filtration& f);
+
+        template<class Filtration>
+        void                            initialize(const Filtration& f)                 { Parent::initialize(f); }
+        void                            pair_simplices();
+
+        // Function: transpose(i)
+        // Tranpose i and the next element.
+        // Returns: true iff the pairing switched.
+        // TODO
+        //bool                            transpose(OrderIndex i)                         { return transpose(i, TranspositionVisitor()); }
+
+        // TODO: the main missing piece to be dynamic
+        //template<class Visitor>
+        //bool                            transpose(OrderIndex i, Visitor& visitor = Visitor());
+
+        using                           Parent::begin;
+        using                           Parent::end;
+        using                           Parent::iterator_to;
+        using                           Parent::index;
+        using                           Parent::size;
+
+        // Struct: TranspositionVisitor
+        //
+        // For example, a VineardVisitor could implement this archetype.
+        struct TranspositionVisitor
+        {
+            // Function: transpose(i)
+            // This function is called before transposition is processed
+            // (at the very beginning of <transpose(i, visitor)>). It is meant to update any structures
+            // that may need to be updated, but perhaps it has other uses as well.
+            void                        transpose(iterator i) const                     {}
+
+            // Function: switched(i, type)
+            // This function is called after the transposition if the switch in pairing has occured.
+            // `i` is the index of the preceding simplex after the transposition.
+            // `type` indicates the <SwitchType>.
+            void                        switched(iterator i, SwitchType type) const     {}
+        };
+
+    protected:
+        using                           Parent::order;
+        using                           Parent::set_pair;
+        using                           Parent::swap_cycle;
+
+        void                            cycle_add(iterator i, const Cycle& z)           { order().modify(i, boost::bind(&Element::template cycle_add<ConsistencyComparison>, bl::_1, boost::ref(z), ccmp_)); }      // i->cycle_add(z, ccmp_)
+        void                            chain_add(iterator i, const Chain& c)           { order().modify(i, boost::bind(&Element::template chain_add<ConsistencyComparison>, bl::_1, boost::ref(c), ccmp_)); }      // i->chain_add(c, ccmp_)
+
+    private:
+        void                            swap(OrderIndex i, OrderIndex j);
+        void                            pairing_switch(OrderIndex i, OrderIndex j);
+
+        struct PairingChainsVisitor: public Parent::PairVisitor
+        {
+                                        PairingChainsVisitor(Order& order, ConsistencyComparison ccmp, unsigned size):
+                                            Parent::PairVisitor(size), order_(order), ccmp_(ccmp)       {}
+
+            void                        init(iterator i) const                          { order_.modify(i,                  boost::bind(&Element::template chain_append<ConsistencyComparison>, bl::_1, &*i, ccmp_)); }                 // i->chain_append(&*i, ccmp)
+            void                        update(iterator j, iterator i) const            { order_.modify(j,                  boost::bind(&Element::template chain_add<ConsistencyComparison>, bl::_1, i->pair->chain, ccmp_)); }         // j->chain.add(i->pair->chain, ccmp_)
+            void                        finished(iterator i) const                      { Parent::PairVisitor::finished(i); CountBy(cChainLength, i->chain.size()); }
+
+            Order&                      order_;
+            ConsistencyComparison       ccmp_;
+        };
+
+        ConsistencyComparison           ccmp_;
+};
+
+
+#include "dynamic-persistence.hpp"
+
+#endif  // __DYNAMIC_PERSISTENCE_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/topology/dynamic-persistence.hpp	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,318 @@
+#include <utilities/log.h>
+
+#ifdef LOGGING
+static rlog::RLogChannel* rlTranspositions =    DEF_CHANNEL("topology/persistence/transpositions", rlog::Log_Debug);
+#endif // LOGGING
+
+#ifdef COUNTERS
+static Counter*  cTransposition =               GetCounter("persistence/transposition");
+static Counter*  cTranspositionDiffDim =        GetCounter("persistence/transposition/diffdim");
+static Counter*  cTranspositionCase12 =         GetCounter("persistence/transposition/case/1/2");
+static Counter*  cTranspositionCase12s =        GetCounter("persistence/transposition/case/1/2/special");
+static Counter*  cTranspositionCase112 =        GetCounter("persistence/transposition/case/1/1/2");
+static Counter*  cTranspositionCase111 =        GetCounter("persistence/transposition/case/1/1/1");
+static Counter*  cTranspositionCase22 =         GetCounter("persistence/transposition/case/2/2");
+static Counter*  cTranspositionCase212 =        GetCounter("persistence/transposition/case/2/1/2");
+static Counter*  cTranspositionCase211 =        GetCounter("persistence/transposition/case/2/1/1");
+static Counter*  cTranspositionCase32 =         GetCounter("persistence/transposition/case/3/2");
+static Counter*  cTranspositionCase31 =         GetCounter("persistence/transposition/case/3/1");
+static Counter*  cTranspositionCase4 =          GetCounter("persistence/transposition/case/4");
+#endif // COUNTERS
+
+
+/* Trails */
+
+template<class D, class CT, class OT, class E, class Cmp, class CCmp>
+DynamicPersistenceTrails<D,CT,OT,E,Cmp,CCmp>::
+DynamicPersistenceTrails():
+    ccmp_(consistent_order())
+{}
+
+template<class D, class CT, class OT, class E, class Cmp, class CCmp>
+template<class Filtration>
+DynamicPersistenceTrails<D,CT,OT,E,Cmp,CCmp>::
+DynamicPersistenceTrails(const Filtration& f):
+    Parent(f), ccmp_(consistent_order())
+{}
+        
+template<class D, class CT, class OT, class E, class Cmp, class CCmp>
+void
+DynamicPersistenceTrails<D,CT,OT,E,Cmp,CCmp>::
+pair_simplices()
+{ 
+    PairingTrailsVisitor visitor(order(), ccmp_, size());
+    Parent::pair_simplices(begin(), end(), true, visitor);
+}
+
+template<class D, class CT, class OT, class E, class Cmp, class CCmp>
+template<class DimensionFunctor, class Visitor>
+bool
+DynamicPersistenceTrails<D,CT,OT,E,Cmp,CCmp>::
+transpose(iterator i, const DimensionFunctor& dimension, Visitor visitor)
+{
+#if LOGGING
+    typename Traits::OutputMap outmap(order());
+#endif
+
+    Count(cTransposition);
+    typedef                 typename Element::Trail::iterator           TrailIterator;
+
+    visitor.transpose(i);
+    
+    iterator i_prev = i++;
+
+    if (dimension(i_prev) != dimension(i))
+    {
+        swap(i_prev, i);
+        rLog(rlTranspositions, "Different dimension");
+        Count(cTranspositionDiffDim);
+        return false;
+    }
+    
+    bool si = i_prev->sign(), sii = i->sign();
+    if (si && sii)
+    {
+        rLog(rlTranspositions, "Trail prev: %s", i_prev->trail.tostring(outmap).c_str());
+
+        // Case 1
+        if (trail_remove_if_contains(i_prev, index(i)))
+            rLog(rlTranspositions, "Case 1, U[i,i+1] = 1");
+
+        iterator k = iterator_to(i_prev->pair);
+        iterator l = iterator_to(i->pair);
+        
+        // rLog(rlTranspositions, "(i_prev, k), (i, l): (%s, %s), (%s, %s)", 
+        //                         outmap(i_prev).c_str(), outmap(k).c_str(),
+        //                         outmap(i).c_str(),      outmap(l).c_str());
+
+        // Explicit treatment of unpaired simplex
+        if (l == i)
+        {
+            swap(i_prev, i);
+            rLog(rlTranspositions, "Case 1.2 --- unpaired");
+            rLog(rlTranspositions, "%s", outmap(i_prev).c_str());
+            Count(cTranspositionCase12);
+            return false;
+        } else if (k == i_prev)
+        {
+            if (!(l->cycle.contains(index(i_prev))))
+            {
+                // Case 1.2
+                swap(i_prev, i);
+                rLog(rlTranspositions, "Case 1.2 --- unpaired");
+                rLog(rlTranspositions, outmap(i_prev).c_str());
+                Count(cTranspositionCase12);
+                return false;
+            } else
+            {
+                // Case 1.2 --- special version (plain swap, but pairing switches)
+                swap(i_prev, i);
+                pairing_switch(i_prev, i);
+                visitor.switched(i, Case12);
+                rLog(rlTranspositions, "Case 1.2 --- unpaired (pairing switch)");
+                rLog(rlTranspositions, outmap(i_prev).c_str());
+                Count(cTranspositionCase12s);
+                return true;
+            }
+        }
+        
+        rLog(rlTranspositions, "l cycle: %s", l->cycle.tostring(outmap).c_str());
+        if (!(l->cycle.contains(index(i_prev))))
+        {
+            // Case 1.2
+            rLog(rlTranspositions, "k is in l: %d", (bool) l->trail.contains(index(k)));       // if true, a special update would be needed to maintain lazy decomposition
+            swap(i_prev, i);
+            rLog(rlTranspositions, "Case 1.2");
+            Count(cTranspositionCase12);
+            return false;
+        } else
+        {
+            // Case 1.1
+            if (std::not2(order_comparison())(index(k),index(l)))
+            {
+                // Case 1.1.1
+                swap(i_prev, i);
+                cycle_add(l, k->cycle);               // Add column k to l
+                trail_add(k, l->trail);               // Add row l to k
+                rLog(rlTranspositions, "Case 1.1.1");
+                Count(cTranspositionCase111);
+                return false;
+            } else
+            {
+                // Case 1.1.2
+                swap(i_prev, i);
+                cycle_add(k, l->cycle);               // Add column l to k
+                trail_add(l, k->trail);               // Add row k to l
+                pairing_switch(i_prev, i);
+                visitor.switched(i, Case112);
+                rLog(rlTranspositions, "Case 1.1.2");
+                Count(cTranspositionCase112);
+                return true;
+            }
+        }
+    } else if (!si && !sii)
+    {
+        // Case 2
+        if (!(i_prev->trail.contains(index(i))))
+        {
+            // Case 2.2
+            swap(i_prev, i);
+            rLog(rlTranspositions, "Case 2.2");
+            Count(cTranspositionCase22);
+            return false;
+        } else
+        {
+            // Case 2.1
+            iterator low_i =    iterator_to(i_prev->pair);
+            iterator low_ii =   iterator_to(i->pair);
+            trail_add(i_prev, i->trail);                   // Add row i to i_prev
+            cycle_add(i, i_prev->cycle);                   // Add column i_prev to i
+            swap(i_prev, i);    
+            if (std::not2(order_comparison())(index(low_ii), index(low_i)))
+            {
+                // Case 2.1.2
+                cycle_add(i_prev, i->cycle);               // Add column i to i_prev (after transposition)
+                trail_add(i, i_prev->trail);               // Add row i to i_prev
+                pairing_switch(i_prev, i);
+                visitor.switched(i, Case212);
+                rLog(rlTranspositions, "Case 2.1.2");
+                Count(cTranspositionCase212);
+                return true;
+            } 
+            
+            // Case 2.1.1
+            rLog(rlTranspositions, "Case 2.1.1");
+            Count(cTranspositionCase211);
+            return false;
+        }
+    } else if (!si && sii)
+    {
+        // Case 3
+        if (!(i_prev->trail.contains(index(i))))
+        {
+            // Case 3.2
+            swap(i_prev, i);
+            rLog(rlTranspositions, "Case 3.2");
+            Count(cTranspositionCase32);
+            return false;
+        } else
+        {
+            // Case 3.1
+            trail_add(i_prev, i->trail);                   // Add row i to i_prev
+            cycle_add(i, i_prev->cycle);                   // Add column i_prev to i
+            swap(i_prev, i);
+            cycle_add(i_prev, i->cycle);                   // Add column i_prev to i (after transposition)
+            trail_add(i, i_prev->trail);                   // Add row i to i_prev
+            pairing_switch(i_prev, i);
+            visitor.switched(i, Case31);
+            rLog(rlTranspositions, "Case 3.1");
+            Count(cTranspositionCase31);
+            return true;
+        }
+    } else if (si && !sii)
+    {
+        // Case 4
+        if (trail_remove_if_contains(i_prev, index(i)))
+            rLog(rlTranspositions, "Case 4, U[i,i+1] = 1");
+        swap(i_prev, i);
+        rLog(rlTranspositions, "Case 4");
+        Count(cTranspositionCase4);
+        return false;
+    }
+    
+    return false; // to avoid compiler complaints; we should never reach this point
+}
+
+
+template<class D, class CT, class OT, class E, class Cmp, class CCmp>
+template<class Iter>
+void
+DynamicPersistenceTrails<D,CT,OT,E,Cmp,CCmp>::
+rearrange(Iter i)
+{ 
+    order().rearrange(i); 
+    consistent_order().rearrange(i);
+
+    // Resort the cycles
+    Cycle z;
+    for(iterator i = begin(); i != end(); ++i)
+    {
+        Parent::swap_cycle(i, z);
+        z.sort(ccmp_);
+        Parent::swap_cycle(i, z);
+    }
+}
+
+template<class D, class CT, class OT, class E, class Cmp, class CCmp>
+void
+DynamicPersistenceTrails<D,CT,OT,E,Cmp,CCmp>::
+swap(iterator i, iterator j)
+{
+    order().relocate(i,j);
+}
+
+template<class D, class CT, class OT, class E, class Cmp, class CCmp>
+void
+DynamicPersistenceTrails<D,CT,OT,E,Cmp,CCmp>::
+pairing_switch(iterator i, iterator j)
+{
+    OrderIndex i_pair = i->pair;
+    OrderIndex j_pair = j->pair;
+
+    // rLog(rlTranspositions, "  (%x %x %x) (%x %x %x)", &*i, i->pair, i->pair->pair, &*j, j->pair, j->pair->pair);
+    if (i_pair == index(i))
+        set_pair(j, j);
+    else
+    {
+        set_pair(j, i_pair);
+        set_pair(i_pair, j);
+    }
+
+    if (j_pair == index(j))
+        set_pair(i, i);
+    else
+    {
+        set_pair(i, j_pair);
+        set_pair(j_pair, i);
+    }
+    // rLog(rlTranspositions, "  (%x %x %x) (%x %x %x)", &*i, i->pair, i->pair->pair, &*j, j->pair, j->pair->pair);
+}
+
+// Helper classes
+template<class D, class CT, class OT, class E, class Cmp, class CCmp>
+struct DynamicPersistenceTrails<D,CT,OT,E,Cmp,CCmp>::TrailRemover: 
+    public std::unary_function<Element&, void>
+{
+                                TrailRemover(OrderIndex i):
+                                    i_(i)                                       {}
+    
+    void                        operator()(Element& e)                          { result = e.trail.remove_if_contains(i_); }
+    
+    OrderIndex                  i_;
+    bool                        result;
+};
+
+
+/* Chains */
+
+template<class D, class CT, class OT, class E, class Cmp, class CCmp>
+DynamicPersistenceChains<D,CT,OT,E,Cmp,CCmp>::
+DynamicPersistenceChains():
+    ccmp_(order().template get<consistency>())
+{}
+
+template<class D, class CT, class OT, class E, class Cmp, class CCmp>
+template<class Filtration>
+DynamicPersistenceChains<D,CT,OT,E,Cmp,CCmp>::
+DynamicPersistenceChains(const Filtration& f):
+    Parent(f), ccmp_(order().template get<consistency>())
+{}
+
+template<class D, class CT, class OT, class E, class Cmp, class CCmp>
+void
+DynamicPersistenceChains<D,CT,OT,E,Cmp,CCmp>::
+pair_simplices()
+{ 
+    PairingChainsVisitor visitor(order(), ccmp_, size());
+    Parent::pair_simplices(begin(), end(), true, visitor);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/topology/field-arithmetic.h	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,68 @@
+#ifndef __FIELD_ARITHMETIC_H__
+#define __FIELD_ARITHMETIC_H__
+
+#include <vector>
+
+class ZpField
+{
+    public:
+        typedef     int                                             Element;
+
+                    ZpField(Element p = 2);
+
+        Element     id()  const                                     { return 1; }
+        Element     zero()  const                                   { return 0; }
+        Element     init(int a) const                               { return (a % p_ + p_) % p_; }
+
+        Element     neg(Element a) const                            { return p_ - a; }
+        Element     add(Element a, Element b) const                 { return (a+b) % p_; }
+
+        Element     inv(Element a) const                            { return inverses_[a]; }
+        Element     mul(Element a, Element b) const                 { return (a*b) % p_; }
+        Element     div(Element a, Element b) const                 { return mul(a, inv(b)); }
+
+        bool        is_zero(Element a) const                        { return (a % p_) == 0; }
+
+    private:
+        Element                 p_;
+        std::vector<Element>    inverses_;
+};
+
+ZpField::
+ZpField(Element p):
+    p_(p), inverses_(p_)
+{
+    for (Element i = 1; i < p_; ++i)
+        for (Element j = 1; j < p_; ++j)
+            if (mul(i,j) == 1)
+            {
+                inverses_[i] = j;
+                break;
+            }
+}
+
+#if 0                   // unused example; commented out to get rid of the artificial dependence on GMP
+#include <gmpxx.h>
+
+class QField
+{
+    public:
+        typedef     mpq_class                                       Element;
+
+                    QField()                                        {}
+
+        Element     id()  const                                     { return 1; }
+        Element     zero()  const                                   { return 0; }
+
+        Element     neg(Element a) const                            { return -a; }
+        Element     add(Element a, Element b) const                 { return (a+b); }
+
+        Element     inv(Element a) const                            { return id()/a; }
+        Element     mul(Element a, Element b) const                 { return (a*b); }
+        Element     div(Element a, Element b) const                 { return a/b; }
+
+        bool        is_zero(Element a) const                        { return a == 0; }
+};
+#endif
+ 
+#endif // __FIELD_ARITHMETIC_H__
--- a/include/topology/filtration.h	Fri Aug 24 16:58:25 2007 -0400
+++ b/include/topology/filtration.h	Tue Jun 27 09:37:05 2017 -0700
@@ -1,135 +1,156 @@
-/*
- * Author: Dmitriy Morozov
- * Department of Computer Science, Duke University, 2005 -- 2006
- */
-
 #ifndef __FILTRATION_H__
 #define __FILTRATION_H__
 
-#include "utilities/sys.h"
-#include "utilities/debug.h"
+#include <vector>
+#include <iostream>
+
+#include "complex-traits.h"
 
-#include "filtrationcontainer.h"
-#include "filtrationsimplex.h"
-#include "vineyard.h"
+#include "utilities/indirect.h"
+#include "utilities/property-maps.h"
+#include "utilities/types.h"
 
-#include <map>
-#include <vector>
+#include <boost/multi_index_container.hpp>
+#include <boost/multi_index/ordered_index.hpp>
+#include <boost/multi_index/identity.hpp>
+#include <boost/multi_index/random_access_index.hpp>
 
 #include <boost/serialization/access.hpp>
+#include <boost/serialization/nvp.hpp>
+#include <boost/serialization/serialization.hpp>
 
-/**
- * Filtration class. Serves as an (ordered) container for the simplices, 
- * and provides pair_simplices() method that computes the RU-decomposition
- * for the simplex order stored in the filtration. Iterators remain valid 
- * through all the operations.
- */
-template<class Smplx, class FltrSmplx = FiltrationSimplex<Smplx>, class Vnrd = Vineyard<FltrSmplx> >
-class Filtration: public FltrSmplx::Container
+
+namespace b = boost;
+namespace bmi = boost::multi_index;
+
+
+// Class: Filtration
+//
+// Filtration keeps track of the ordering of the simplices in a complex.
+// The most significant function it provides is <boundary()> which converts
+// the boundary of a simplex at a given index into a list of indices.
+template<class Simplex_,
+         class SimplexOrderIndex_ = bmi::ordered_unique<bmi::identity<Simplex_>,
+                                                        typename Simplex_::VertexComparison> >
+class Filtration
 {
-	public:
-		typedef 	Smplx															Simplex;
-		typedef		FltrSmplx														FiltrationSimplex;
-		typedef		Vnrd															Vineyard;
-		
-		/// \name Container Types
-		/// @{
-		/** The actual container type (which is the parent of the Filtration) */
-		typedef		typename FiltrationSimplex::Container							FiltrationContainer;
-		typedef		typename FiltrationContainer::Index								Index;
-		typedef		typename FiltrationContainer::const_Index						const_Index;
-		typedef		Index															iterator;
-		typedef		const_Index														const_iterator;
-		/// @}
-		
-		/// \name Cycles and Trails 
-		/// @{
-		typedef		typename FiltrationContainer::GreaterThanComparison				CyclesComparator;
-		typedef		typename FiltrationContainer::LessThanComparison				TrailsComparator;
-		typedef		typename FiltrationContainer::ConsistencyComparison 			ConsistencyComparator;
-		typedef		typename FiltrationContainer::Cycle								Cycle;
-		typedef		typename FiltrationContainer::Trail								Trail;
-		typedef		typename Cycle::iterator										CycleIterator;
-		typedef		typename Trail::iterator										TrailIterator;
-		/// @}
-		
-		typedef		Filtration<Simplex, FiltrationSimplex, Vineyard>				Self;
-		typedef		FiltrationContainer												Parent;
+    private:
+        struct                  order {};           // tag
+
+    public:
+        // Typedefs: Template parameters
+        typedef                 Simplex_                                        Simplex;
+        typedef                 SimplexOrderIndex_                              SimplexOrderIndex;
+
+        typedef                 b::multi_index_container<Simplex,
+                                                         bmi::indexed_by<SimplexOrderIndex,
+                                                                         bmi::random_access<bmi::tag<order> >
+                                                                        >
+                                                        >                       Container;
+        typedef                 typename Container::value_type                  value_type;
+
+        // Typedefs: Complex and Order views
+        typedef                 typename Container::template nth_index<0>::type Complex;
+        typedef                 typename Container::template nth_index<1>::type Order;
+        typedef                 typename Order::const_iterator                  Index;
+
+                                Filtration()                                    {}
+
+        // Constructor: Filtration(bg, end, cmp)
+                                template<class ComplexIndex>
+                                Filtration(ComplexIndex bg, ComplexIndex end):
+                                    container_(bg, end)                         {}
+
+        // Constructor: Filtration(bg, end, cmp)
+                                template<class ComplexIndex, class Comparison>
+                                Filtration(ComplexIndex bg, ComplexIndex end, const Comparison& cmp = Comparison()):
+                                    container_(bg, end)                         { sort(cmp); }
+
+        // Lookup
+        const Simplex&          simplex(Index i) const                          { return *i; }
+        Index                   find(const Simplex& s) const                    { return bmi::project<order>(container_, container_.find(s)); }
+
+        // Modifiers
+        template<class Comparison>
+        void                    sort(const Comparison& cmp = Comparison())      { container_.template get<order>().sort(cmp); }
+        void                    push_back(const Simplex& s)                     { container_.template get<order>().push_back(s); }
+        void                    transpose(Index i)                              { container_.template get<order>().relocate(i, i+1); }
+        void                    clear()                                         { container_.template get<order>().clear(); }
+        template<class Iter>
+        void                    rearrange(Iter i)                               { container_.template get<order>().rearrange(i); }
+
+        Index                   begin() const                                   { return container_.template get<order>().begin(); }
+        Index                   end() const                                     { return container_.template get<order>().end(); }
+        size_t                  size() const                                    { return container_.size(); }
 
-	public:
-										Filtration(Vineyard* vineyard);
-	
-		/// \name Core Functionality
-		/// @{
-		/// Computes RU decomposition of the simplices in [bg, end) range, assuming that everything before bg has been paired 
-		void 							pair_simplices(Index bg, Index end);
-		void 							pair_simplices()							{ pair_simplices(begin(), end()); }
-		bool							transpose(Index i, bool maintain_lazy = true);
-		bool							is_paired() const;
-		Index							append(const Simplex& s);					///< Appends s to the filtration
-		Index							insert(Index prior, const Simplex& s);		///< Inserts s after prior
-		const_Index						get_index(const Simplex& s) const;			/**< Returns the iterator pointing to s 
-																						 (end() if s not in filtration) */
-		Index							get_index(const Simplex& s);				///< \overload
-		void							fill_simplex_index_map();					///< Fills the mapping for get_index()
-		/// @}
-		
-		/// \name Accessors
-		/// @{
-		Vineyard*						vineyard()									{ return vineyard_; }
-		const Vineyard*					vineyard() const							{ return vineyard_; }
-		/// @}
-	
-	protected:
-		using 							Parent::swap;
-		bool 							transpose_simplices(Index i, bool maintain_lazy);				
+        std::ostream&           operator<<(std::ostream& out) const             { std::copy(begin(), end(), std::ostream_iterator<Simplex>(out, "\n")); return out; }
+
+    private:
+        Container               container_;
+
+    private:
+        // Serialization
+        friend class                            boost::serialization::access;
+        template<class Archive>
+        void                                    serialize(Archive& ar, const unsigned int)
+        { ar & boost::serialization::make_nvp("order", container_); }
+};
+
+template<class S, class SOI>
+std::ostream&
+operator<<(std::ostream& out, const Filtration<S,SOI>& f)                       { return f.operator<<(out); }
+
+
+template<class Functor_, class Filtration_>
+class ThroughFiltration
+{
+    public:
+        typedef                 Filtration_                                     Filtration;
+        typedef                 Functor_                                        Functor;
+
+        typedef                 typename Functor::result_type                   result_type;
+        typedef                 typename Filtration::Index                      first_argument_type;
+
+                                ThroughFiltration(const Filtration& filtration,
+                                                  const Functor&    functor):
+                                    filtration_(filtration),
+                                    functor_(functor)                           {}
 
-	public:
-		/// \name Container Operations
-		/// @{
-		using Parent::size;
-		using Parent::begin;
-		using Parent::end;
-		/// @}
-		
-		std::ostream& 					operator<<(std::ostream& out) const;
+        result_type             operator()(first_argument_type a) const         { return functor_(filtration_.simplex(a)); }
 
-	protected:
-		/// \name Comparator accessors (protected)
-		/// @{
-		const ConsistencyComparator& 	get_consistency_cmp() const					{ return consistency_cmp; }
-		const CyclesComparator& 		get_cycles_cmp() const						{ return cycles_cmp; }
-		const TrailsComparator& 		get_trails_cmp() const						{ return trails_cmp; }
-		/// @}
+    private:
+        const Filtration&       filtration_;
+        const Functor&          functor_;
+};
 
-	private:
-		typedef							std::map<Simplex, Index>					SimplexMap;
+template<class Filtration, class Functor>
+ThroughFiltration<Functor, Filtration>
+evaluate_through_filtration(const Filtration& filtration, const Functor& functor)
+{ return ThroughFiltration<Functor, Filtration>(filtration, functor); }
+
 
-		/// Initializes the cycle  with the indices of the simplices in the boundary, and the trail with the index of this simplex
-		void							init_cycle_trail(Index j);
-		void							pairing_switch(Index i, Index j);
-		
-		bool 							paired;
-		SimplexMap						inverse_simplices;
+template<class Map, class Filtration>
+class DimensionFunctor
+{
+    public:
+                                DimensionFunctor(const Map& map, const Filtration& filtration):
+                                    map_(map), filtration_(filtration)
+                                {}
 
-		Vineyard*						vineyard_;
+        template<class key_type>
+        Dimension               operator()(key_type i) const                    { return filtration_.simplex(map_[i]).dimension(); }
 
-		CyclesComparator				cycles_cmp;
-		TrailsComparator				trails_cmp;
-		ConsistencyComparator			consistency_cmp;
+    private:
+        const Map&              map_;
+        const Filtration&       filtration_;
+};
 
-	private:
-		/* Serialization */
-		friend class boost::serialization::access;
-										
-		typedef		std::map<const_Index, SizeType, ConsistencyComparator>			IndexIntMap;
-		typedef		std::vector<Index>												IndexVector;
-		
-		template<class Archive> void 	save(Archive& ar, version_type ) const;
-		template<class Archive>	void 	load(Archive& ar, version_type );
-		BOOST_SERIALIZATION_SPLIT_MEMBER()
-};
+template<class Map, class Filtration>
+DimensionFunctor<Map, Filtration>
+make_dimension_functor(const Map& map, const Filtration& filtration)
+{ return DimensionFunctor<Map, Filtration>(map, filtration); }
+
 
 #include "filtration.hpp"
 
-#endif	// __FILTRATION_H__
+#endif // __FILTRATION_H__
--- a/include/topology/filtration.hpp	Fri Aug 24 16:58:25 2007 -0400
+++ b/include/topology/filtration.hpp	Tue Jun 27 09:37:05 2017 -0700
@@ -1,463 +1,6 @@
-#include "utilities/counter.h"
-#include "utilities/types.h"
-#include <algorithm>
-
-#include <boost/utility.hpp>
-#include <boost/serialization/vector.hpp>
-#include <boost/serialization/nvp.hpp>
-#include <boost/serialization/list.hpp>
-#include <boost/serialization/is_abstract.hpp>
-
-using boost::serialization::make_nvp;
-
-/* Filtration Public */
-
-template<class S, class FS, class V>
-Filtration<S, FS, V>::
-Filtration(Vineyard* vnrd = 0): paired(false), vineyard_(vnrd)
-{}
-	
-template<class S, class FS, class V>
-void 
-Filtration<S, FS, V>::
-pair_simplices(Index bg, Index end)
-{
-	Dout(dc::filtration, "Entered: compute_pairing");
-	for (Index j = bg; j != end; ++j)
-	{
-		Dout(dc::filtration|flush_cf|continued_cf, *j << ": ");
-		init_cycle_trail(j); 
-		Cycle& bdry = j->cycle();
-		Dout(dc::finish, bdry);
-		
-		CountNum("Boundaries", j->dimension());
-		Count("SimplexCount");
-
-		while(!bdry.empty())
-		{
-			Index i = bdry.top(cycles_cmp);
-			Dout(dc::filtration, *i << ": " << *(i->pair()));
-			AssertMsg(!cycles_cmp(i, j), "Simplices in the cycle must precede current simplex: " << 
-										 "(" << *i << " in cycle of " << *j << ")");
-
-			// i is not paired, so we pair j with i
-			if (i->pair() == i)
-			{
-				Dout(dc::filtration, "Pairing " << *i << " and " << *j << " with cycle " << j->cycle());
-				i->set_pair(j);
-				j->set_pair(i);
-				CountNum("DepositedCycleLength", j->cycle().size());
-				break;
-			}
-
-			// continue searching --- change the Dout to the continued mode with newlines FIXME
-			Dout(dc::filtration, "  Adding: [" << bdry << "] + ");
-			Dout(dc::filtration, "          [" << i->pair()->cycle() << "]");
-			bdry.add(i->pair()->cycle(), get_consistency_cmp());
-			i->pair()->trail().append(j, get_consistency_cmp());
-			Dout(dc::filtration, "After addition: " << bdry);
-		}
-		Dout(dc::filtration, "Finished with " << *j << ": " << *(j->pair()));
-	}
-	paired = true;
-}
-
-template<class S, class FS, class V>
-bool							
-Filtration<S, FS, V>::
-is_paired() const
-{ return paired; }
-
-/**
- * Transposes simplices at i and i+1, and records the knee in the vineyard if there is a change in pairing. 
- * Returns true if the pairing changed.
- */
-template<class S, class FS, class V>
-bool
-Filtration<S,FS,V>::
-transpose(Index i, bool maintain_lazy)
-{
-	AssertMsg(vineyard() != 0, "We must have a vineyard for transpositions");
-	
-	Index i_orig = i++;
-	
-	AssertMsg(i_orig->pair() != i, "Transposing simplices must not be paired");
-	bool result = transpose_simplices(i_orig, maintain_lazy);
-	AssertMsg(i_orig == boost::next(i), "Wrong indices after transposition");
-	
-	if (result) vineyard()->switched(i, i_orig);
-	return result;
-}
-
-template<class S, class FS, class V>
-typename Filtration<S, FS, V>::Index 
-Filtration<S, FS, V>::
-append(const Simplex& s)
-{ 
-	Index i = push_back(FiltrationSimplex(s)); 
-	return i;
-}
-
-template<class S, class FS, class V>
-typename Filtration<S, FS, V>::Index 
-Filtration<S, FS, V>::
-insert(Index prior, const Simplex& s)
-{ 
-	Index i = Parent::insert(prior, FiltrationSimplex(s)); 
-	paired = false;
-
-	return i;
-}
-		
-template<class S, class FS, class V>
-typename Filtration<S, FS, V>::const_Index 
-Filtration<S, FS, V>::
-get_index(const Simplex& s) const
-{ 
-	typename SimplexMap::const_iterator i = inverse_simplices.find(s); 
-	if (i == inverse_simplices.end())
-		return end();
-	else
-		return i->second;
-}
-
-template<class S, class FS, class V>
-typename Filtration<S, FS, V>::Index 
-Filtration<S, FS, V>::
-get_index(const Simplex& s)
-{ 
-	typename SimplexMap::const_iterator i = inverse_simplices.find(s); 
-	if (i == inverse_simplices.end())
-		return end();
-	else
-		return i->second;
-}
-
-template<class S, class FS, class V>
-void
-Filtration<S, FS, V>::
-fill_simplex_index_map()
-{
-	for (Index i = begin(); i != end(); ++i)
-		inverse_simplices[*i] = i;
-}
-
-template<class S, class FS, class V>
-std::ostream& 
-Filtration<S, FS, V>::
-operator<<(std::ostream& out) const
-{
-	out << "Pairing: " << std::endl;
-	for (const_Index i = begin(); i != end(); ++i)
-	{
-		out << "(" << *i << ", " << *(i->pair()) << "): ";
-		out << i->cycle() << std::endl;
-	}
-	out << std::endl << std::endl;
-
-	return out;
-}
-
-
-/* Filtration Protected */
-/// Transposes simplices at i and i+1. Returns true if the pairing switched.
-template<class S, class FS, class V>
-bool 
-Filtration<S,FS,V>::
-transpose_simplices(Index i, bool maintain_lazy)
-{
-	AssertMsg(is_paired(), "Pairing must be computed before transpositions");
-	Count("SimplexTransposition");
-	
-	Index i_prev = i++;
-
-	if (i_prev->dimension() != i->dimension())
-	{
-		swap(i_prev, i);
-		Dout(dc::transpositions, "Different dimension");
-		Count("Case DiffDim");
-		return false;
-	}
-	
-	bool si = i_prev->sign(), sii = i->sign();
-	if (si && sii)
-	{
-		Dout(dc::transpositions, "Trail prev: " << i_prev->trail());
-
-		// Case 1
-		TrailIterator i_in_i_prev = std::find(i_prev->trail().begin(), i_prev->trail().end(), i);
-		if (i_in_i_prev != i_prev->trail().end())
-		{
-			Dout(dc::transpositions, "Case 1, U[i,i+1] = 1");
-			i_prev->trail().erase(i_in_i_prev);
-		}
-
-		Index k = i_prev->pair();
-		Index l = i->pair();
+#include <utilities/log.h>
 
-		// Explicit treatment of unpaired simplex
-		if (l == i)
-		{
-			swap(i_prev, i);
-			Dout(dc::transpositions, "Case 1.2 --- unpaired");
-			Dout(dc::transpositions, *i_prev);
-			Count("Case 1.2");
-			return false;
-		} else if (k == i_prev)
-		{
-			if (std::find(l->cycle().begin(), l->cycle().end(), i_prev) == l->cycle().end())
-			{
-				// Case 1.2
-				swap(i_prev, i);
-				Dout(dc::transpositions, "Case 1.2 --- unpaired");
-				Dout(dc::transpositions, *i_prev);
-				Count("Case 1.2");
-				return false;
-			} else
-			{
-				// Case 1.1.2 --- special version (plain swap, but pairing switches)
-				swap(i_prev, i);
-				pairing_switch(i_prev, i);
-				Dout(dc::transpositions, "Case 1.1.2 --- unpaired");
-				Dout(dc::transpositions, *i_prev);
-				Count("Case 1.1.2");
-				return true;
-			}
-		}
-		
-		Dout(dc::transpositions, "l cycle: " << l->cycle());
-		if (std::find(l->cycle().begin(), l->cycle().end(), i_prev) == l->cycle().end())
-		{
-			// Case 1.2
-			if (maintain_lazy)
-			{
-				TrailIterator k_in_l = std::find(l->trail().begin(), l->trail().end(), k);
-				if (k_in_l != l->trail().end())
-				{
-					l->trail().add(k->trail(), Filtration::get_consistency_cmp());		// Add row k to l
-					k->cycle().add(l->cycle(), Filtration::get_consistency_cmp());		// Add column l to k
-				}
-			}
-			swap(i_prev, i);
-			Dout(dc::transpositions, "Case 1.2");
-			Count("Case 1.2");
-			return false;
-		} else
-		{
-			// Case 1.1
-			if (trails_cmp(k,l))
-			{
-				// Case 1.1.1
-				swap(i_prev, i);
-				l->cycle().add(k->cycle(), Filtration::get_consistency_cmp());		// Add column k to l
-				k->trail().add(l->trail(), Filtration::get_consistency_cmp());		// Add row l to k
-				Dout(dc::transpositions, "Case 1.1.1");
-				Count("Case 1.1.1");
-				return false;
-			} else
-			{
-				// Case 1.1.2
-				swap(i_prev, i);
-				k->cycle().add(l->cycle(), Filtration::get_consistency_cmp());		// Add column l to k
-				l->trail().add(k->trail(), Filtration::get_consistency_cmp());		// Add row k to l
-				pairing_switch(i_prev, i);
-				Dout(dc::transpositions, "Case 1.1.2");
-				Count("Case 1.1.2");
-				return true;
-			}
-		}
-	} else if (!si && !sii)
-	{
-		// Case 2
-		if (std::find(i_prev->trail().begin(), i_prev->trail().end(), i) == i_prev->trail().end())
-		{
-			// Case 2.2
-			swap(i_prev, i);
-			Dout(dc::transpositions, "Case 2.2");
-			Count("Case 2.2");
-			return false;
-		} else
-		{
-			// Case 2.1
-			Index low_i = i_prev->pair();
-			Index low_ii = i->pair();
-			i_prev->trail().add(i->trail(), Filtration::get_consistency_cmp());			// Add row i to i_prev
-			i->cycle().add(i_prev->cycle(), Filtration::get_consistency_cmp());			// Add column i_prev to i
-			swap(i_prev, i);	
-			if (Filtration::get_trails_cmp()(low_ii, low_i))
-			{
-				// Case 2.1.2
-				i_prev->cycle().add(i->cycle(), Filtration::get_consistency_cmp());		// Add column i to i_prev (after transposition)
-				i->trail().add(i_prev->trail(), Filtration::get_consistency_cmp());			// Add row i to i_prev
-				pairing_switch(i_prev, i);
-				Dout(dc::transpositions, "Case 2.1.2");
-				Count("Case 2.1.2");
-				return true;
-			} 
-			
-			// Case 2.1.1
-			Dout(dc::transpositions, "Case 2.1.1");
-			Count("Case 2.1.1");
-			return false;
-		}
-	} else if (!si && sii)
-	{
-		// Case 3
-		if (std::find(i_prev->trail().begin(), i_prev->trail().end(), i) == i_prev->trail().end())
-		{
-			// Case 3.2
-			swap(i_prev, i);
-			Dout(dc::transpositions, "Case 3.2");
-			Count("Case 3.2");
-			return false;
-		} else
-		{
-			// Case 3.1
-			i_prev->trail().add(i->trail(), Filtration::get_consistency_cmp());			// Add row i to i_prev
-			i->cycle().add(i_prev->cycle(), Filtration::get_consistency_cmp());			// Add column i_prev to i
-			swap(i_prev, i);
-			i_prev->cycle().add(i->cycle(), Filtration::get_consistency_cmp());			// Add column i_prev to i (after transposition)
-			i->trail().add(i_prev->trail(), Filtration::get_consistency_cmp());			// Add row i to i_prev
-			pairing_switch(i_prev, i);
-			Dout(dc::transpositions, "Case 3.1");
-			Count("Case 3.1");
-			return true;
-		}
-	} else if (si && !sii)
-	{
-		// Case 4
-		TrailIterator i_in_i_prev = std::find(i_prev->trail().begin(), i_prev->trail().end(), i);
-		if (i_in_i_prev != i_prev->trail().end())
-		{
-			Dout(dc::transpositions, "Case 4, U[i,i+1] = 1");
-			i_prev->trail().erase(i_in_i_prev);
-		}
-		swap(i_prev, i);
-		Dout(dc::transpositions, "Case 4");
-		Count("Case 4");
-		return false;
-	}
-	
-	return false; // to avoid compiler complaints, should never reach this point
-}
-
-
-/* Filtration Private */
-template<class S, class FS, class V>
-void
-Filtration<S, FS, V>::
-init_cycle_trail(Index j)
-{
-	typename Simplex::Cycle bdry = j->boundary();
-
-	for (typename Simplex::Cycle::const_iterator cur = bdry.begin(); cur != bdry.end(); ++cur)
-	{
-		Dout(dc::filtration, "Appending in init_cycle_trail(): " << *cur);
-		AssertMsg(get_index(*cur) != end(), "Non-existent simplex in the cycle");
-		j->cycle().append(get_index(*cur), get_consistency_cmp());
-	}
-	j->trail().append(j, get_consistency_cmp());
-	j->set_pair(j);
-}
-
-/// Update the pairing, so that whoever was paired with i is now paired with j and vice versa.
-template<class S, class FS, class V>
-void 
-Filtration<S,FS,V>::
-pairing_switch(Index i, Index j)
-{
-	Index i_pair = i->pair();
-	Index j_pair = j->pair();
-
-	if (i_pair == i)
-		j->set_pair(j);
-	else
-	{
-		j->set_pair(i_pair);
-		i_pair->set_pair(j);
-	}
-
-	if (j_pair == j)
-		i->set_pair(i);
-	else
-	{
-		i->set_pair(j_pair);
-		j_pair->set_pair(i);
-	}
-}
-
-/* Serialization */
-template<class S, class FS, class V>
-template<class Archive> 
-void 
-Filtration<S, FS, V>::
-save(Archive& ar, version_type ) const
-{
-	ar << BOOST_SERIALIZATION_NVP(paired);
-	ar << BOOST_SERIALIZATION_NVP(cycles_cmp);
-	ar << BOOST_SERIALIZATION_NVP(trails_cmp);
-	ar << BOOST_SERIALIZATION_NVP(consistency_cmp);
-
-	SizeType sz = size();
-	ar << make_nvp("size", sz);
-	Dout(dc::filtration, "Size: " << sz);
-
-	/* Record integer indices */
-	IndexIntMap index_map; SizeType i = 0;
-	for (const_Index cur = begin(); cur != end(); ++cur)
-	{ index_map[cur] = i++; }
-	
-	/* Save the simplices */
-	int count = 0;
-	for (const_Index cur = begin(); cur != end(); ++cur)
-	{ 
-		count++;
-		// FIXME
-		//FiltrationSimplexSerialization simplex = FiltrationSimplexSerialization(*cur, index_map);
-		//ar << make_nvp("FiltrationSimplex", simplex);	
-	}
-	Dout(dc::filtration, count << " simplices serialized");
-}
-
-template<class S, class FS, class V>
-template<class Archive>	
-void 
-Filtration<S, FS, V>::
-load(Archive& ar, version_type )
-{
-	Dout(dc::filtration, "Starting to read filtration");
-	ar >> BOOST_SERIALIZATION_NVP(paired);
-	ar >> BOOST_SERIALIZATION_NVP(cycles_cmp);
-	ar >> BOOST_SERIALIZATION_NVP(trails_cmp);
-	ar >> BOOST_SERIALIZATION_NVP(consistency_cmp);
-	Dout(dc::filtration, "In Filtration: first block read");
-
-	SizeType sz;
-	ar >> make_nvp("size", sz);
-	Dout(dc::filtration, "In Filtration: size read " << sz);
-	
-	IndexVector index_vector(sz);
-	for (SizeType i = 0; i < sz; ++i)
-	{
-		index_vector[i] = append(Simplex());
-	}
-		
-	int count = 0;
-	for (SizeType i = 0; i < sz; ++i)
-	{
-		// FIXME
-		//FiltrationSimplexSerialization simplex;
-		//ar >> make_nvp("FiltrationSimplex", simplex);
-		count++;
-		Dout(dc::filtration, "In Filtration: simplex read (" << count << ")");
-		//simplex.set_filtration_simplex(*index_vector[i], index_vector);
-	}
-	Dout(dc::filtration, "In Filtration: simplices read");
-}
-
-template<class S, class FS, class V>
-std::ostream& 
-operator<<(std::ostream& out, const Filtration<S, FS, V>& f)					
-{ return f.operator<<(out); }
-
-
+#ifdef LOGGING
+static rlog::RLogChannel* rlFiltration =                    DEF_CHANNEL("topology/filtration/info", rlog::Log_Debug);
+static rlog::RLogChannel* rlFiltrationDebug =               DEF_CHANNEL("topology/filtration/debug", rlog::Log_Debug);
+#endif // LOGGING
--- a/include/topology/filtrationcontainer.h	Fri Aug 24 16:58:25 2007 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-/*
- * Author: Dmitriy Morozov
- * Department of Computer Science, Duke University, 2006
- */
-
-#ifndef __FILTRATIONCONTAINER_H__
-#define __FILTRATIONCONTAINER_H__
-
-#include "utilities/consistencylist.h"
-#include "cycle.h"
-
-/**
- * FiltrationContainer class. Serves as a parent of Filtration that 
- * describes the container functionality. Used by FiltrationSimplex 
- * to get Cycle representation.
- */
-template<class FltrSmplx>
-class FiltrationContainer: public ConsistencyList<FltrSmplx>
-{
-	public:
-		typedef		FltrSmplx														FiltrationSimplex;
-		typedef		ConsistencyList<FiltrationSimplex>								ConsistencyList;
-		
-		/// \name Cycles and Trails 
-		/// @{
-		/// Index is and therfore acts like an iterator. The name is preserved for historical reasons.
-		typedef		typename ConsistencyList::iterator								Index;
-		/// const_Index is a const_iterator
-		typedef		typename ConsistencyList::const_iterator						const_Index;
-		/// @}
-
-		/// \name Cycles and Trails 
-		/// @{
-		typedef		typename ConsistencyList::GreaterThanComparison					CyclesComparator;
-		typedef		typename ConsistencyList::LessThanComparison					TrailsComparator;
-		typedef		typename ConsistencyList::ConsistencyComparison 				ConsistencyComparator;
-		typedef		::Cycle<Index, CyclesComparator, ConsistencyComparator>			Cycle;
-		typedef		::Cycle<Index, TrailsComparator, ConsistencyComparator>			Trail;
-		/// @}
-
-		template<class U>
-		struct rebind { typedef FiltrationContainer<U> other; };
-};
-
-#endif // __FILTRATIONCONTAINER_H__
--- a/include/topology/filtrationsimplex.h	Fri Aug 24 16:58:25 2007 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,91 +0,0 @@
-/*
- * Author: Dmitriy Morozov
- * Department of Computer Science, Duke University, 2006
- */
-
-#ifndef __FILTRATIONSIMPLEX_H__
-#define __FILTRATIONSIMPLEX_H__
-
-#include "utilities/sys.h"
-#include "utilities/debug.h"
-
-#include "filtrationcontainer.h"
-#include "vineyard.h"
-#include "utilities/types.h"
-
-#include <list>
-
-#if 0
-#include <boost/serialization/access.hpp>
-#include <boost/serialization/nvp.hpp>
-#include <boost/serialization/list.hpp>
-#endif
-
-/**
- * Evaluator is a base class for the structures that are able to return a value
- * given a simplex.
- */
-template<class Smplx>
-class Evaluator
-{
-	public:
-		typedef					Smplx										Simplex;
-
-		virtual RealType		time() const								{ return 0; }
-		virtual RealType		value(const Simplex& s) const				{ return 0; }
-
-		virtual					~Evaluator()								{}
-};
-
-/**
- * FiltrationSimplex stores information needed for the RU-decomposition: 
- * cycle (column of R), trail (row of U), and pair.
- */
-template<class Smplx>
-class FiltrationSimplex: public Smplx
-{
-	public:
-		typedef		Smplx													Simplex;
-		typedef		FiltrationSimplex<Simplex>								Self;
-		typedef		FiltrationContainer<Self>								Container;
-		typedef		Simplex													Parent;
-		
-		typedef		Vine<Simplex>											Vine;
-		typedef		typename Container::Cycle								Cycle;
-		typedef		typename Container::Trail								Trail;
-		typedef		typename Container::Index								Index;
-
-		typedef		Evaluator<Simplex>										Evaluator;
-		
-		FiltrationSimplex(const Simplex& s): 
-			Simplex(s), vine_(0)											{}
-		
-
-		/// \name Core functionality
-		/// @{
-		void					set_pair(Index pair)						{ pair_ = pair; }
-		bool					sign() const								{ return cycles_column.empty(); }
-		bool					is_paired() const							{ return pair() != pair()->pair(); }
-		void					set_vine(Vine* v)							{ vine_ = v; }
-		using 					Parent::dimension;
-		/// @}
-
-
-		/// \name Accessors
-		/// @{
-		Cycle&					cycle()										{ return cycles_column; }
-		Trail&					trail()										{ return trails_row; }
-		const Cycle&			cycle()	const								{ return cycles_column; }
-		const Trail&			trail()	const								{ return trails_row; }
-		Index					pair() const								{ return pair_; }
-		Vine*					vine() const								{ return vine_; }
-		/// @}
-
-	private:
-		Cycle																cycles_column;
-		Trail																trails_row; 
-		Index																pair_;
-		Vine*																vine_;
-};
-
-#endif // __FILTRATIONSIMPLEX_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/topology/image-zigzag-persistence.h	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,106 @@
+#ifndef __IMAGE_ZIGZAG_PERSISTENCE_H__
+#define __IMAGE_ZIGZAG_PERSISTENCE_H__
+
+#include "zigzag-persistence.h"
+#include <limits>
+
+struct SimplexSubcomplexData
+{
+                SimplexSubcomplexData(bool sc = false):
+                    subcomplex(sc)                              {}
+
+    bool        subcomplex;
+};
+
+template<class BirthID_ = Empty<> >
+class ImageZigzagPersistence: public ZigzagPersistence<BirthID_, SimplexSubcomplexData>
+{
+    public:
+        typedef                 BirthID_                                                    BirthID;
+        typedef                 ZigzagPersistence<BirthID, SimplexSubcomplexData>           Parent;
+
+        typedef                 typename Parent::IndexDeathPair                             IndexDeathPair;
+        typedef                 typename Parent::Death                                      Death;
+
+        typedef                 typename Parent::ZIndex                                     ZIndex;
+        typedef                 typename Parent::BIndex                                     BIndex;
+        typedef                 typename Parent::SimplexIndex                               SimplexIndex;
+        typedef                 typename Parent::ZColumn                                    ZColumn;
+        typedef                 typename Parent::BColumn                                    BColumn;
+        typedef                 typename Parent::BRow                                       BRow;
+        typedef                 typename Parent::CRow                                       CRow;
+        typedef                 typename Parent::ZNode                                      ZNode;
+        typedef                 typename Parent::BNode                                      BNode;
+        typedef                 typename Parent::SimplexNode                                SimplexNode;
+
+
+                                ImageZigzagPersistence():
+                                    im_last(Parent::z_list.end()), cok_begin(Parent::z_list.end()),
+                                    im_order_begin(std::numeric_limits<int>::min()/2),
+                                    cok_order_begin(std::numeric_limits<int>::max()/2)
+                                {}
+
+        IndexDeathPair          add(ZColumn         bdry,
+                                    bool            subcomplex,
+                                    const BirthID&  birth = BirthID())                      { ImageZZVisitor zzv(subcomplex); return Parent::add(bdry, birth, zzv); }
+
+        Death                   remove(SimplexIndex s, const BirthID& birth = BirthID())    { ImageZZVisitor zzv(s->subcomplex); return Parent::remove(s, birth, zzv); }
+
+
+        ZIndex                  image_begin()                                               { return Parent::z_list.begin(); }
+        ZIndex                  image_end()                                                 { return cok_begin; }
+        BIndex                  boundary_end()                                              { return Parent::b_list.end(); }
+
+
+        // Class: ImageZZVisitor
+        // Contains all the tweaks to the normal zigzag algorithm to make it compute image zigzag
+        class ImageZZVisitor: public Parent::ZigzagVisitor
+        {
+            public:
+                                    ImageZZVisitor(bool sc = false):
+                                        subcomplex(sc), birth_in_image(false)                   {}
+
+                // Sets the subcomplex property of the new simplex
+                SimplexIndex        new_simplex(Parent& zz);
+
+                // Decides where to put the new column (image or cokernel)
+                ZIndex              new_z_in_add(Parent& zz, const ZColumn& z, const BRow& u);
+
+                // Checks if there is a boundary entirely in the subcomplex, and sets birth_in_image accordingly
+                BIndex              select_j_in_remove(Parent& zz, const CRow& c_row);
+
+                ZIndex              new_z_in_remove(Parent& zz);
+
+                // Updates im_last and cok_begin if necessary
+                void                erasing_z(Parent& zz, ZIndex j);
+
+                // Determines if there is a death in the image
+                Death               death(Parent& zz, ZIndex dying_z);
+
+            private:
+                ZIndex              append_in_image(Parent& zz);
+                ZIndex              append_in_cokernel(Parent& zz);
+                ZIndex              prepend_in_image(Parent& zz);
+                ZIndex              prepend_in_cokernel(Parent& zz);
+                bool                in_subcomplex(const ZColumn& z);
+
+                bool                subcomplex, birth_in_image;
+        };
+
+        const int                   im_order_begin;
+        const int                   cok_order_begin;
+
+    private:
+        using                   Parent::make_remover;
+        using                   Parent::make_appender;
+        using                   Parent::make_adder;
+
+    private:
+        ZIndex                  im_last;                // index of the last image cycle
+        ZIndex                  cok_begin;              // index of the first cokernel cycle
+};
+
+
+#include "image-zigzag-persistence.hpp"
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/topology/image-zigzag-persistence.hpp	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,213 @@
+#ifdef LOGGING
+static rlog::RLogChannel* rlImageZigzag =                   DEF_CHANNEL("topology/persistence/zigzag/image",        rlog::Log_Debug);
+#endif // LOGGING
+
+
+template<class BID>
+typename ImageZigzagPersistence<BID>::SimplexIndex
+ImageZigzagPersistence<BID>::ImageZZVisitor::
+new_simplex(Parent& zz)
+{
+    SimplexIndex si = Parent::ZigzagVisitor::new_simplex(zz);
+    si->subcomplex = subcomplex;
+    rLog(rlImageZigzag,     "New simplex %d (inL=%d)", si->order, si->subcomplex);
+    return si;
+}
+
+template<class BID>
+typename ImageZigzagPersistence<BID>::ZIndex
+ImageZigzagPersistence<BID>::ImageZZVisitor::
+new_z_in_add(Parent& zz, const ZColumn& z, const BRow& u)
+{ 
+    ImageZigzagPersistence& izz = static_cast<ImageZigzagPersistence&>(zz); 
+
+    // Check if z is entirely in the subcomplex
+    if (in_subcomplex(z))
+        return append_in_image(zz);
+    else
+    {
+        append_in_cokernel(zz);
+        
+        // Simplex we are adding is in the subcomplex
+        if (subcomplex)
+        {
+            rLog(rlImageZigzag,     "Modifying boundaries");
+
+            SimplexIndex s      = boost::prior(izz.s_list.end());
+            AssertMsg(s->subcomplex,        "The new simplex must be in the subcomplex");
+            rLog(rlImageZigzag,     "  s=%d", s->order);
+            rLog(rlImageZigzag,     "  u=[%s]", u.tostring(izz.out).c_str());
+
+            BIndex max = u.front();
+            for (typename BRow::const_iterator cur = u.begin(); cur != u.end(); ++cur)
+                if ((*cur)->b_column.back()->order > max->b_column.back()->order)     
+                    max = *cur;
+            
+            // Replace B[max] with sum of b_columns from u
+            BColumn sum;
+            std::for_each(u.begin(), u.end(), izz.make_adder(&BNode::b_column, sum));
+#if ZIGZAG_CONSISTENCY
+            AssertMsg(in_subcomplex(s->boundary), "Boundary of s must be in the subcomplex");
+#endif
+            std::for_each(max->b_column.begin(), max->b_column.end(), izz.make_remover(&ZNode::b_row, max));
+            rLog(rlImageZigzag,     "max->b_column=[%s]", max->b_column.tostring(izz.out).c_str());
+            rLog(rlImageZigzag,     "          sum=[%s]", sum.tostring(izz.out).c_str());
+            AssertMsg(sum.back() == max->b_column.back(), "Must be replacing by a column with the same low");
+            max->b_column.swap(sum);
+            std::for_each(max->b_column.begin(), max->b_column.end(), izz.make_appender(&ZNode::b_row, max));
+            // NB: low doesn't need to be adjusted (see AssertMsg above)
+
+            // Wipe out C[max], and replace it with s
+            std::for_each(max->c_column.begin(), max->c_column.end(), izz.make_remover(&SimplexNode::c_row, max));
+            max->c_column.clear();
+            max->c_column.append(s, izz.cmp);
+            AssertMsg(s->c_row.empty(),     "s was just added, so it cannot appear in any bounding chain");
+            s->c_row.append(max, izz.cmp);
+        }
+        
+        return boost::prior(izz.z_list.end());
+    }
+}
+
+
+template<class BID>
+typename ImageZigzagPersistence<BID>::BIndex
+ImageZigzagPersistence<BID>::ImageZZVisitor::
+select_j_in_remove(Parent& zz, const CRow& c_row)
+{
+    ImageZigzagPersistence& izz = static_cast<ImageZigzagPersistence&>(zz); 
+    for (typename CRow::const_iterator cur = c_row.begin(); cur != c_row.end(); ++cur)
+        if ((*cur)->b_column.back()->order <= izz.im_last->order)
+        {
+            birth_in_image = true;
+            return *cur;
+        }
+
+    return Parent::ZigzagVisitor::select_j_in_remove(zz, c_row);
+}
+
+template<class BID>
+typename ImageZigzagPersistence<BID>::ZIndex
+ImageZigzagPersistence<BID>::ImageZZVisitor::
+new_z_in_remove(Parent& zz)
+{ 
+    if (birth_in_image)
+        return prepend_in_image(zz);
+    else
+        return prepend_in_cokernel(zz);
+}
+
+template<class BID>
+void
+ImageZigzagPersistence<BID>::ImageZZVisitor::
+erasing_z(Parent& zz, ZIndex j)
+{ 
+    ImageZigzagPersistence& izz = static_cast<ImageZigzagPersistence&>(zz); 
+    if          (j == izz.im_last)          --(izz.im_last);
+    else if     (j == izz.cok_begin)        ++(izz.cok_begin);
+}
+
+template<class BID>
+typename ImageZigzagPersistence<BID>::Death
+ImageZigzagPersistence<BID>::ImageZZVisitor::
+death(Parent& zz, ZIndex dying_z)
+{
+    ImageZigzagPersistence& izz = static_cast<ImageZigzagPersistence&>(zz); 
+    if (izz.im_last == izz.z_list.end() || dying_z->order > izz.im_last->order)
+        return Death();
+    else
+        return Death(dying_z->birth);
+}
+
+template<class BID>
+typename ImageZigzagPersistence<BID>::ZIndex
+ImageZigzagPersistence<BID>::ImageZZVisitor::
+append_in_image(Parent& zz)
+{
+    rLog(rlImageZigzag,     "Appending in image");
+    ImageZigzagPersistence& izz = static_cast<ImageZigzagPersistence&>(zz); 
+
+    // if no cycles in the image
+    if (izz.im_last == izz.z_list.end())
+    {
+        izz.z_list.push_front(ZNode(izz.im_order_begin, izz.b_list.end()));
+        return (izz.im_last = izz.z_list.begin());
+    } else
+    {
+        izz.z_list.insert(boost::next(izz.im_last), ZNode(izz.im_last->order + 1, izz.b_list.end()));
+        return ++(izz.im_last);
+    }
+}
+
+template<class BID>
+typename ImageZigzagPersistence<BID>::ZIndex
+ImageZigzagPersistence<BID>::ImageZZVisitor::
+append_in_cokernel(Parent& zz)
+{
+    rLog(rlImageZigzag,     "Appending in cokernel");
+    ImageZigzagPersistence& izz = static_cast<ImageZigzagPersistence&>(zz); 
+
+    // if no cycles in the cokernel
+    if (izz.cok_begin == izz.z_list.end())
+    {
+        izz.z_list.push_back(ZNode(izz.cok_order_begin, izz.b_list.end()));
+        izz.cok_begin = boost::prior(izz.z_list.end());
+    } else
+    {
+        izz.z_list.push_back(ZNode(boost::prior(izz.z_list.end())->order + 1, izz.b_list.end()));
+    }
+
+    return boost::prior(izz.z_list.end());
+}
+
+template<class BID>
+typename ImageZigzagPersistence<BID>::ZIndex
+ImageZigzagPersistence<BID>::ImageZZVisitor::
+prepend_in_image(Parent& zz)
+{
+    rLog(rlImageZigzag,     "Prepending in image");
+    ImageZigzagPersistence& izz = static_cast<ImageZigzagPersistence&>(zz); 
+
+    // if no cycles in the image
+    if (izz.im_last == izz.z_list.end())
+    {
+        izz.z_list.push_front(ZNode(izz.im_order_begin, izz.b_list.end()));
+        return (izz.im_last = izz.z_list.begin());
+    } else
+    {
+        izz.z_list.push_front(ZNode(izz.z_list.begin()->order - 1, izz.b_list.end()));
+        return izz.z_list.begin();
+    }
+}
+
+template<class BID>
+typename ImageZigzagPersistence<BID>::ZIndex
+ImageZigzagPersistence<BID>::ImageZZVisitor::
+prepend_in_cokernel(Parent& zz)
+{
+    rLog(rlImageZigzag,     "Prepending in cokernel");
+    ImageZigzagPersistence& izz = static_cast<ImageZigzagPersistence&>(zz); 
+
+    // if no cycles in the cokernel
+    if (izz.cok_begin == izz.z_list.end())
+    {
+        izz.z_list.push_back(ZNode(izz.cok_order_begin, izz.b_list.end()));
+        izz.cok_begin = boost::prior(izz.z_list.end());
+    } else
+    {
+        izz.z_list.insert(izz.cok_begin, ZNode(izz.cok_begin->order - 1, izz.b_list.end()));
+        --(izz.cok_begin);
+    }
+    return izz.cok_begin;
+}
+
+template<class BID>
+bool
+ImageZigzagPersistence<BID>::ImageZZVisitor::
+in_subcomplex(const ZColumn& z)
+{
+    for (typename ZColumn::const_iterator cur = z.begin(); cur != z.end(); ++cur)
+        if (!((*cur)->subcomplex))
+            return false;
+    return true;
+}
--- a/include/topology/lowerstarfiltration.h	Fri Aug 24 16:58:25 2007 -0400
+++ b/include/topology/lowerstarfiltration.h	Tue Jun 27 09:37:05 2017 -0700
@@ -1,114 +1,69 @@
 /*
  * Author: Dmitriy Morozov
- * Department of Computer Science, Duke University, 2005 -- 2006
+ * Department of Computer Science, Duke University, 2005 -- 2008
  */
 
 #ifndef __LOWERSTARFILTRATION_H__
 #define __LOWERSTARFILTRATION_H__
 
-#include "utilities/sys.h"
-#include "utilities/debug.h"
-
-#include "filtration.h"
-#include "simplex.h"
-#include "utilities/consistencylist.h"
-#include <boost/utility.hpp>
-#include <list>
-#include "utilities/types.h"
-
 #include <boost/serialization/access.hpp>
 #include <boost/serialization/vector.hpp>
-#include <boost/serialization/map.hpp>
-#include <boost/serialization/base_object.hpp>
 #include <boost/serialization/nvp.hpp>
 
+/**
+ * Struct: MaxVertexComparison
+ *
+ * Functor that determines which simplex has a higher vertex with respect to VertexComparison_, breaking ties by dimension
+ */
+template<class Simplex_, class VertexComparison_>
+struct MaxVertexComparison
+{
+    typedef                     VertexComparison_                                   VertexComparison;
+    typedef                     Simplex_                                            Simplex;
+    typedef                     typename Simplex::Vertex                            Vertex;
+
+                                MaxVertexComparison(const VertexComparison& vcmp):
+                                    vcmp_(vcmp)                                     {}
+
+    bool                        operator()(const Simplex& s1, const Simplex& s2) const
+    {
+        const Vertex& max1 = *std::max_element(s1.vertices().begin(), s1.vertices().end(), vcmp_);
+        const Vertex& max2 = *std::max_element(s2.vertices().begin(), s2.vertices().end(), vcmp_);
+        
+        bool less = vcmp_(max1, max2), 
+             more = vcmp_(max2, max1);
+        
+        if (!less && !more)     // equal
+            return s1.dimension() < s2.dimension();
+
+        return less;
+    }
+
+    VertexComparison            vcmp_;
+};
+
 
-template<class VI, 
-		 class Smplx = SimplexWithAttachment<VI>, 
-		 class FltrSmplx = FiltrationSimplex<Smplx>,
-		 class Vnrd = Vineyard<FltrSmplx> >
-class LowerStarFiltration: public Filtration<Smplx, FltrSmplx, Vnrd>
+/**
+ * Map from i-th vertex to its index in the filtration.
+ */
+template<class Index_, class Filtration_>
+class VertexSimplexMap
 {
-	public:
-		// Treat VertexIndex as an iterator
-		typedef					VI													VertexIndex;		
-		typedef					Smplx												Simplex;
-		typedef					Filtration<Simplex>									Parent;
-		typedef					typename Parent::Vineyard							Vineyard;
-
-		typedef					typename Parent::Index								Index;
-		typedef					typename Parent::const_Index						const_Index;
-		typedef					typename Parent::Cycle								Cycle;
-		typedef					typename Parent::Trail								Trail;
-		typedef					typename Simplex::Cycle 							SimplexBoundaryCycle;
-
-		struct 					VertexDescriptor;
-		typedef					ConsistencyList<VertexDescriptor>					VertexOrder;
-		typedef					typename VertexOrder::iterator						VertexOrderIndex;
-		typedef					typename VertexOrder::const_iterator				const_VertexOrderIndex;
-		typedef 				typename VertexOrder::LessThanComparison			VertexOrderComparison;
-		struct					SimplexAttachmentComparison;
-
-	public:
-								template<class VertexCmp>							
-								LowerStarFiltration(VertexIndex begin, VertexIndex end, const VertexCmp& cmp, Vineyard* vineyard);
+    public:
+        typedef                 Index_                                              Index;
+        typedef                 Filtration_                                         Filtration;
+        typedef                 std::vector<Index>                                  VertexVector;
+                                
+                                VertexSimplexMap(Index begin, Index end, const Filtration& f)
+        {
+            for (Index cur = begin; cur != end; ++cur)
+                if (f.simplex(cur).dimension() == 0)
+                    vertices_.push_back(cur);
+        }
 
-		using 					Parent::size;
-		using 					Parent::begin;
-		using 					Parent::end;
-		VertexIndex				num_vertices() const								{ return vertex_order.size(); }
-		const VertexOrderComparison& 
-								get_vertex_cmp() const								{ return vertex_cmp; }
-		
-		Index 					append(const Simplex& s);
-		bool					transpose_vertices(const VertexOrderIndex& voi);
-
-	protected:
-		/// Hint function: if unsure, should return true
-		virtual bool			neighbors(VertexIndex v1, VertexIndex v2) const		{ return true; }
-
-	private:
-		bool 					transpose(Index i);
-		void					assert_pairing(Index i);
-		
-	private:
-		VertexOrder				vertex_order;	
-		VertexOrderComparison	vertex_cmp;
-	
-	/* Serialization */
-	protected:
-		LowerStarFiltration()														{}
-		
-	private:
-		friend class boost::serialization::access;
-			
-		template<class Archive>
-		void save(Archive& ar, version_type ) const									{ ar << BOOST_SERIALIZATION_BASE_OBJECT_NVP(Parent); }
-
-		template<class Archive>
-		void load(Archive& ar, version_type );
-
-		BOOST_SERIALIZATION_SPLIT_MEMBER()
+    private:
+        VertexVector            vertices_;
 };
 
-template<class VI, class Smplx, class FltrSmplx, class Vnrd>
-struct LowerStarFiltration<VI,Smplx,FltrSmplx,Vnrd>::VertexDescriptor
-{
-	VertexDescriptor(VertexIndex vi, Index si): 
-		vertex_index(vi), simplex_index(si)		
-	{}
-	
-	VertexIndex			vertex_index;
-	Index				simplex_index;
-};
-
-template<class VI, class Smplx, class FltrSmplx, class Vnrd>
-struct LowerStarFiltration<VI,Smplx,FltrSmplx,Vnrd>::SimplexAttachmentComparison
-{
-	bool operator()(const Simplex& first, const Simplex& second) const;
-	VertexOrderComparison	vertex_cmp;
-};
-
-#include "lowerstarfiltration.hpp"
 
 #endif // __LOWERSTARFILTRATION_H__
--- a/include/topology/lowerstarfiltration.hpp	Fri Aug 24 16:58:25 2007 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,217 +0,0 @@
-/* Implementations */
-
-template<class VI, class Smplx, class FltrSmplx, class Vnrd>
-template<class VertexCmp>
-LowerStarFiltration<VI,Smplx,FltrSmplx,Vnrd>::
-LowerStarFiltration(VertexIndex begin, VertexIndex end, const VertexCmp& cmp, Vineyard* vineyard):
-	Parent(vineyard)
-{
-	// Record VertexIndexes in a temporary list
-	typedef std::list<VertexIndex> VertexIndexList;
-	VertexIndexList tmp_list;
-	while (begin != end)
-		tmp_list.push_back(begin++);
-
-	// Sort the temporary list
-	tmp_list.sort(cmp);
-
-	// Record vertex order
-	for(typename VertexIndexList::const_iterator cur = tmp_list.begin(); cur != tmp_list.end(); ++cur)
-		(*cur)->set_order(vertex_order.push_back(VertexDescriptor(*cur, Parent::append(Simplex(*cur)))));
-}
-
-template<class VI, class Smplx, class FltrSmplx, class Vnrd>
-typename LowerStarFiltration<VI,Smplx,FltrSmplx,Vnrd>::Index 
-LowerStarFiltration<VI,Smplx,FltrSmplx,Vnrd>::
-append(const Simplex& s)
-{
-	AssertMsg(s.dimension() != 0, "All vertices must have been inserted in the constructor");
-	
-	// Find the highest vertex
-	typename Simplex::VertexContainer::const_iterator cur = s.vertices().begin(), max = cur++;
-	for (; cur != s.vertices().end(); ++cur)
-		if (!vertex_cmp((*cur)->get_order(), (*max)->get_order()))
-			max = cur;
-
-	Index ms = (*max)->get_order()->simplex_index;	Index prior;
-	do { prior = ms++; } while (ms->dimension() <= s.dimension() && ms != Parent::end() && ms->get_attachment() == *max);
-	
-	Index i = Parent::insert(prior, s);
-	i->set_attachment(*max);
-
-	return i;
-}
-
-template<class VI, class Smplx, class FltrSmplx, class Vnrd>
-bool
-LowerStarFiltration<VI,Smplx,FltrSmplx,Vnrd>::SimplexAttachmentComparison::
-operator()(const Simplex& first, const Simplex& second) const
-{
-	int cmp = vertex_cmp.compare(first.get_attachment()->get_order(), second.get_attachment()->get_order());
-	if (cmp == 0)
-		return first.dimension() < second.dimension();
-	else
-		return cmp == -1;
-}
-
-template<class VI, class Smplx, class FltrSmplx, class Vnrd>
-bool 
-LowerStarFiltration<VI,Smplx,FltrSmplx,Vnrd>::
-transpose_vertices(const VertexOrderIndex& order)
-{
-	Count("VertexTransposition");
-
-#if COUNTERS
-	if ((counters.lookup("VertexTransposition") % 1000000) == 0)
-	{
-		Dout(dc::lsfiltration, "Vertex transpositions:  " << counters.lookup("VertexTransposition"));
-		Dout(dc::lsfiltration, "Simplex transpositions: " << counters.lookup("SimplexTransposition"));
-		Dout(dc::lsfiltration, "Attachment changed:     " << counters.lookup("ChangedAttachment"));
-		Dout(dc::lsfiltration, "Regular disconnected:   " << counters.lookup("RegularDisconnected"));
-		Dout(dc::lsfiltration, "Pairing Changed:        " << counters.lookup("ChangedPairing"));
-		Dout(dc::lsfiltration, "------------------------");
-	}
-#endif // COUNTERS
-	
-	Dout(dc::lsfiltration, "Transposing vertices (" << order->vertex_index << ", " 
-													<< boost::next(order)->vertex_index << ")");
-
-	Index i = order->simplex_index;
-	Index i_prev = boost::prior(i);
-	Index i_next = boost::next(order)->simplex_index;
-	Index i_next_prev = boost::prior(i_next);			// transpositions are done in terms of the first index in the pair
-	Index j = boost::next(i_next);
-	
-	const VertexIndex& v_i = order->vertex_index;
-	const VertexIndex& v_i_next = boost::next(order)->vertex_index;
-	bool nbghrs = neighbors(v_i, v_i_next);
-	
-	bool result = false;
-	
-	// First, move the vertex --- this can be sped up if we devise special "vertex transpose" operation
-	while (i_next_prev != i_prev)						
-	{ 
-		result |= transpose(i_next_prev);
-		i_next_prev = boost::prior(i_next);
-	}
-	Dout(dc::lsfiltration, "Done moving the vertex");
-
-	// Second, move the simplices attached to it
-	Dout(dc::lsfiltration, "Moving attached simplices");
-	while (j != Parent::end() && j->get_attachment() == v_i_next)
-	{
-		Dout(dc::lsfiltration, "  Considering " << *j);
-		if (nbghrs && j->contains(v_i))			// short circuit
-		{
-			Count("ChangedAttachment");
-			Dout(dc::lsfiltration, "  Attachment changed for " << *j);
-			j->set_attachment(v_i);
-			++j;
-			continue;
-		}	
-
-		Index j_prev = j; ++j;
-		while ((--j_prev)->get_attachment() != v_i_next) 		// i.e., until we have reached v_i_next 
-															// (and the simplices that follow it) again
-		{
-			Dout(dc::lsfiltration, "    Moving: " << *j_prev << ", " << *boost::next(j_prev));
-			AssertMsg(j_prev->get_attachment() == v_i, "Simplex preceding the one being moved must be attached to v_i");
-			result |= transpose(j_prev);
-			--j_prev;
-		}
-	}
-	Dout(dc::lsfiltration, "Done moving attached simplices");
-	vertex_order.swap(order, boost::next(order));
-	
-	return result;
-}
-
-template<class VI, class Smplx, class FltrSmplx, class Vnrd>
-bool 
-LowerStarFiltration<VI,Smplx,FltrSmplx,Vnrd>::
-transpose(Index i)
-{
-	Index j = boost::next(i);
-	
-	Dout(dc::lsfiltration, "    Transposing (" << *i << ", " << *(i->pair()) << ") and (" 
-											   << *j << ", " << *(j->pair()) << ")");
-
-	assert_pairing(i);
-	assert_pairing(j);
-
-	bool res = Parent::transpose(i, false);
-	Dout(dc::lsfiltration, "    " << *j << ": " << *(j->pair()) << ", " << *i << ": " << *(i->pair()));
-
-	assert_pairing(j);
-	assert_pairing(i);
-
-	return res;
-}
-
-template<class VI, class Smplx, class FltrSmplx, class Vnrd>
-void 
-LowerStarFiltration<VI,Smplx,FltrSmplx,Vnrd>::
-assert_pairing(Index i)
-{
-#ifndef NDEBUG
-	AssertMsg(i != Parent::end(), "Cannot assert pairing of end()");
-	if (!i->sign())
-	{
-		if (i->pair() != i->cycle().top(Parent::get_cycles_cmp()))
-		{
-			Dout(dc::lsfiltration, "i (negative): " << *i);
-			Dout(dc::lsfiltration, "pair(i): " << *(i->pair()));
-			Dout(dc::lsfiltration, "i->cycle().top(): " << *(i->cycle().top(Parent::get_cycles_cmp())));
-			DoutFatal(dc::fatal, "Pairing not matching the matrix at " << *i);
-		}
-	} else
-	{
-		if (i->pair() != i)
-		{
-			if (i->pair()->cycle().top(Parent::get_cycles_cmp()) != i)
-			{
-				Dout(dc::lsfiltration, "i (positive): " << *i);
-				Dout(dc::lsfiltration, "pair(i): " << *(i->pair()));
-				Dout(dc::lsfiltration, "pair(i)->cycle(): " << i->pair()->cycle());
-				Dout(dc::lsfiltration, "pair->cycle().top(): " << *(i->pair()->cycle().top(Parent::get_cycles_cmp())));
-				DoutFatal(dc::fatal, "Pairing not matching the matrix at " << *(i->pair()));
-			}
-		}
-	}
-#endif
-}
-
-
-template<class VI, class Smplx, class FltrSmplx, class Vnrd>
-template<class Archive>
-void 
-LowerStarFiltration<VI,Smplx,FltrSmplx,Vnrd>::
-load(Archive& ar, version_type )
-{
-/*
-	ar >> BOOST_SERIALIZATION_BASE_OBJECT_NVP(Parent);
-	
-	// Count the number of vertices
-	VertexIndex num_vertices = 0;
-	for (Index cur = begin(); cur != end(); ++cur)
-		if (dimension(cur) == 0)	
-			num_vertices++;
-
-	// Second pass to record vertex_order
-	vertex_order.resize(num_vertices);
-	inverse_vertex_order.resize(num_vertices);
-	num_vertices = 0;
-	for (Index cur = begin(); cur != end(); ++cur)
-	{
-		if (dimension(cur) == 0)
-		{
-			vertex_order[num_vertices].index = cur;
-			vertex_order[num_vertices].vertex_index = *(cur->get_vertices().begin());
-			inverse_vertex_order[vertex_order[num_vertices].vertex_index] = num_vertices;
-			++num_vertices;
-		}
-	}
-*/
-}
-
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/topology/lsvineyard.h	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,255 @@
+/**
+ * Author: Dmitriy Morozov
+ * Department of Computer Science, Duke University, 2005 -- 2010
+ */
+
+#ifndef __LSVINEYARD_H__
+#define __LSVINEYARD_H__
+
+#include <iostream>
+
+#include "topology/simplex.h"
+#include "topology/dynamic-persistence.h"
+#include "topology/lowerstarfiltration.h"
+#include "topology/vineyard.h"
+
+#include <utilities/indirect.h>
+
+#include <geometry/simulator.h>
+#include <geometry/kinetic-sort.h>
+#include <geometry/linear-kernel.h>
+
+#include <boost/tuple/tuple.hpp>
+namespace b  = boost;
+
+
+template<class Vertex_, class VertexEvaluator_, class Simplex_ = Simplex<Vertex_>, class Filtration_ = Filtration<Simplex_> >
+class LSVineyard
+{
+    public:
+        typedef                     LSVineyard                                          Self;
+
+        typedef                     Vertex_                                             Vertex;
+        typedef                     VertexEvaluator_                                    VertexEvaluator;
+        typedef                     typename VertexEvaluator::result_type               VertexValue;
+
+        typedef                     Simplex_                                            Simplex;
+        typedef                     Filtration_                                         LSFiltration;
+        typedef                     typename LSFiltration::Index                        LSFIndex;
+
+        typedef                     LinearKernel<VertexValue>                           KineticKernel;
+        typedef                     Simulator<KineticKernel>                            KineticSimulator;
+        class                       KineticVertexType;
+        class                       KineticVertexComparison;
+        class                       TrajectoryExtractor;
+        typedef                     typename OrderContainer<KineticVertexType>::Container
+                                                                                        VertexContainer;
+        typedef                     typename VertexContainer::iterator                  VertexIndex;
+
+        struct                      AttachmentData: public VineData
+        {
+            void                    set_attachment(VertexIndex v)                       { attachment = v; }
+            VertexIndex             attachment;
+        };
+        typedef                     DynamicPersistenceTrails<AttachmentData>            Persistence;
+        typedef                     typename Persistence::OrderIndex                    Index;
+        typedef                     typename Persistence::iterator                      iterator;
+
+        typedef                     typename Persistence::template SimplexMap<LSFiltration>
+                                                                                        PFMap;
+
+        class                       Evaluator;
+        class                       StaticEvaluator;
+        class                       KineticEvaluator;
+        class                       DimensionFromIterator;
+
+        typedef                     std::map<Vertex, LSFIndex>                          VertexLSFIndexMap;
+        typedef                     ThroughEvaluatorComparison<VertexEvaluator>         VertexComparison;
+        class                       VertexAttachmentComparison;
+        typedef                     MaxVertexComparison<Simplex, VertexComparison>      SimplexComparison;
+
+        class                       TranspositionVisitor;
+        friend class                TranspositionVisitor;
+
+        typedef                     Vineyard<Index, iterator, Evaluator>                Vnrd;
+
+    public:
+        template<class VertexIterator>
+                                    LSVineyard(VertexIterator begin, VertexIterator end,
+                                               LSFiltration& filtration,
+                                               const VertexEvaluator& veval = VertexEvaluator());
+                                    ~LSVineyard();
+
+        void                        compute_vineyard(const VertexEvaluator& veval);
+        bool                        transpose_vertices(VertexIndex vi);
+
+        const LSFiltration&         filtration() const                                  { return filtration_; }
+        const Vnrd&                 vineyard() const                                    { return vineyard_; }
+        const Persistence&          persistence() const                                 { return persistence_; }
+        const VertexComparison&     vertex_comparison() const                           { return vcmp_; }
+        const VertexEvaluator&      vertex_evaluator() const                            { return veval_; }
+        const SimplexComparison&    simplex_comparison() const                          { return scmp_; }
+
+        VertexValue                 vertex_value(const Vertex& v) const                 { return veval_(v); }
+        VertexValue                 simplex_value(const Simplex& s) const               { return vertex_value(*std::max_element(s.vertices().begin(), s.vertices().end(), vcmp_)); }
+        const Simplex&              pfmap(iterator i) const                             { return pfmap_[i]; }
+        const Simplex&              pfmap(Index i) const                                { return pfmap_[i]; }
+        VertexIndex                 filtration_attachment(LSFIndex i) const             { return (persistence().begin() + (i - filtration().begin()))->attachment; }
+
+        Index                       index(iterator i) const                             { return persistence_.index(i); }
+
+    public:
+        // For Kinetic Sort
+        void                        swap(VertexIndex a, KineticSimulator* simulator);
+
+    private:
+        void                        change_evaluator(Evaluator* eval);
+        void                        set_attachment(iterator i, VertexIndex vi)          { persistence_.modifier()(i, boost::bind(&AttachmentData::set_attachment, bl::_1, vi)); }
+        void                        transpose_filtration(iterator i)                    { filtration_.transpose(filtration_.begin() + (i - persistence_.begin())); }
+
+        bool                        verify_pairing() const;
+
+        typedef                     b::tuple< b::reference_wrapper<const Simplex>,
+                                              b::reference_wrapper<const typename Persistence::Element> >
+                                                                                        SimplexPersistenceElementTuple;
+        struct                      AttachmentCmp;
+
+    private:
+        VertexContainer             vertices_;
+
+        VertexEvaluator             veval_;
+        VertexComparison            vcmp_;
+        SimplexComparison           scmp_;
+
+        LSFiltration&               filtration_;
+        Persistence                 persistence_;
+        PFMap                       pfmap_;
+
+        Vnrd                        vineyard_;
+        Evaluator*                  evaluator_;
+        unsigned                    time_count_;
+
+#if 0
+    private:
+        // Serialization
+        friend class boost::serialization::access;
+
+        LSVineyard()                                                                    {}
+
+        template<class Archive>
+        void serialize(Archive& ar, version_type )
+        {
+            ar & BOOST_SERIALIZATION_NVP(grid_stack_);
+            ar & BOOST_SERIALIZATION_NVP(vertices_);
+            ar & BOOST_SERIALIZATION_NVP(filtration_);
+        };
+#endif
+};
+
+//BOOST_CLASS_EXPORT(LSVineyard)
+
+template<class V, class VE, class S, class C>
+std::ostream&
+operator<<(std::ostream& out, const typename LSVineyard<V,VE,S,C>::VertexIndex& vi)
+{ return out << vi->vertex(); }
+
+template<class V, class VE, class S, class C>
+std::ostream&
+operator<<(std::ostream& out, const typename LSVineyard<V,VE,S,C>::KineticVertexType& v)
+{ return out << v.vertex(); }
+
+template<class V, class VE, class S, class C>
+class LSVineyard<V,VE,S,C>::KineticVertexType
+{
+    public:
+                                KineticVertexType(const Vertex& v):
+                                    vertex_(v)                                              {}
+
+        Vertex                  vertex() const                                              { return vertex_; }
+        void                    set_vertex(Vertex v)                                        { vertex_ = v; }
+
+        LSFIndex                simplex_index() const                                       { return simplex_index_; }
+        void                    set_simplex_index(LSFIndex i)                               { simplex_index_ = i; }
+
+    private:
+        Vertex                  vertex_;
+        LSFIndex                simplex_index_;
+};
+
+template<class V, class VE, class S, class C>
+class LSVineyard<V,VE,S,C>::TrajectoryExtractor: public std::unary_function<VertexIndex, typename KineticSimulator::Function>
+{
+    public:
+        typedef                 typename KineticSimulator::Function                         Function;
+
+                                TrajectoryExtractor(const VertexEvaluator& veval0,
+                                                    const VertexEvaluator& veval1):
+                                    veval0_(veval0), veval1_(veval1)                        {}
+
+
+        Function                operator()(VertexIndex i) const                             { VertexValue v0 = veval0_(i->vertex()), v1 = veval1_(i->vertex()); return Function(v0, v1 - v0); }
+
+    private:
+        const VertexEvaluator&  veval0_, veval1_;
+};
+
+template<class V, class VE, class S, class C>
+class LSVineyard<V,VE,S,C>::KineticVertexComparison: public std::binary_function<const KineticVertexType&, const KineticVertexType&, bool>
+{
+    public:
+                                KineticVertexComparison(const VertexComparison& vcmp):
+                                    vcmp_(vcmp)                                             {}
+
+        bool                    operator()(const KineticVertexType& v1, const KineticVertexType& v2) const
+        { return vcmp_(v1.vertex(), v2.vertex()); }
+
+    private:
+        VertexComparison            vcmp_;
+};
+
+template<class V, class VE, class S, class C>
+class LSVineyard<V,VE,S,C>::TranspositionVisitor: public Persistence::TranspositionVisitor
+{
+    public:
+        typedef                 typename Persistence::TranspositionVisitor                  Parent;
+        typedef                 typename LSVineyard<V,VE,S,C>::iterator                     iterator;
+        typedef                 typename LSVineyard<V,VE,S,C>::Index                        Index;
+
+                                TranspositionVisitor(LSVineyard& v): lsvineyard_(v)         {}
+
+        void                    transpose(iterator i)                                       { lsvineyard_.transpose_filtration(i); }
+        void                    switched(iterator i, SwitchType type)                       { lsvineyard_.vineyard_.switched(index(i), index(boost::next(i))); }
+
+    private:
+        Index                   index(iterator i)                                           { return lsvineyard_.index(i); }
+
+        LSVineyard&             lsvineyard_;
+};
+
+template<class V, class VE, class S, class C>
+class LSVineyard<V,VE,S,C>::Evaluator: public std::unary_function<Index, RealType>
+{
+    public:
+        virtual ~Evaluator() {}
+        virtual RealType        time() const                                                =0;
+        virtual RealType        operator()(Index i) const                                   =0;
+        virtual Dimension       dimension(Index i) const                                    =0;
+        virtual RealType        operator()(iterator i) const                                { return operator()(&*i); }
+        virtual Dimension       dimension(iterator i) const                                 { return dimension(&*i); }
+};
+
+template<class V, class VE, class S, class C>
+class LSVineyard<V,VE,S,C>::DimensionFromIterator: std::unary_function<iterator, Dimension>
+{
+    public:
+                                DimensionFromIterator(const PFMap& pfmap): pfmap_(pfmap)    {}
+
+        Dimension               operator()(iterator i) const                                { return pfmap_[i].dimension(); }
+
+    private:
+        const PFMap&            pfmap_;
+};
+
+#include "lsvineyard.hpp"
+
+#endif // __LSVINEYARD_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/topology/lsvineyard.hpp	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,358 @@
+#include <utilities/log.h>
+
+#include <boost/function.hpp>
+#include <boost/bind.hpp>
+#include <boost/lambda/lambda.hpp>
+namespace bl = boost::lambda;
+
+#include <boost/iterator/zip_iterator.hpp>
+#include <boost/iterator/transform_iterator.hpp>
+#include <boost/foreach.hpp>
+
+#ifdef LOGGING
+static rlog::RLogChannel* rlLSVineyard =            DEF_CHANNEL("lsvineyard/info", rlog::Log_Debug);
+static rlog::RLogChannel* rlLSVineyardDebug =       DEF_CHANNEL("lsvineyard/debug", rlog::Log_Debug);
+#endif // LOGGING
+
+#ifdef COUNTERS
+static Counter*  cVertexTransposition =                     GetCounter("lsfiltration/transposition");       // counts number of vertex transpositions
+static Counter*  cAttachment =                              GetCounter("lsfiltration/attachment");          // counts the number of attachment changes
+#endif
+
+
+template<class V, class VE, class S, class F>
+template<class VertexIterator>
+LSVineyard<V,VE,S,F>::
+LSVineyard(VertexIterator begin, VertexIterator end, 
+           LSFiltration& fltr,
+           const VertexEvaluator& veval):
+    filtration_(fltr),
+    vertices_(begin, end),
+    persistence_(filtration_),
+    veval_(veval), vcmp_(veval_), scmp_(vcmp_),
+    pfmap_(persistence_.make_simplex_map(filtration_)),
+    time_count_(0)
+{
+    vertices_.sort(KineticVertexComparison(vcmp_));     // sort vertices w.r.t. vcmp_
+#if LOGGING    
+    rLog(rlLSVineyardDebug, "Vertex order:");
+    for (typename VertexContainer::iterator cur = vertices_.begin(); cur != vertices_.end(); ++cur)
+        rLog(rlLSVineyardDebug, "  %d", cur->vertex());
+#endif
+
+    // Record Vertex -> LSFIndex map
+    VertexLSFIndexMap vimap;
+    for (LSFIndex i = filtration().begin(); i != filtration().end(); ++i)
+    {
+        const Simplex& s = *i;
+        rLog(rlLSVineyardDebug, "Simplex: %s", tostring(*i).c_str());
+        if (s.dimension() == 0)
+            vimap[s.vertices().front()] = i;
+    }
+
+    // Assign vertex attachments and simplex_index
+    OffsetMap<LSFIndex, iterator>   fpmap(filtration().begin(), persistence().begin());
+    for (typename VertexContainer::iterator vi = vertices_.begin(); vi != vertices_.end(); ++vi)
+    {
+        LSFIndex i = vimap[vi->vertex()];
+        const Simplex& s = *i;
+        AssertMsg(s.vertices().front() == vi->vertex(), "In constructor, simplices and vertices must match.");
+        vertices_.modify(vi,    b::bind(&KineticVertexType::set_simplex_index, bl::_1, i));    // vi->set_simplex_index(i)
+        set_attachment(fpmap[i], vi);
+        rLog(rlLSVineyardDebug, "%s attached to %d", tostring(*i).c_str(), vi->vertex());
+    }
+
+    // Assign attachments for all the simplices
+    VertexAttachmentComparison  vacmp(vimap, *this);
+    for (LSFIndex i = filtration().begin(); i != filtration().end(); ++i)
+        set_attachment(fpmap[i], fpmap[vimap[*std::max_element(i->vertices().begin(), i->vertices().end(), vacmp)]]->attachment);
+
+    // Order filtration_ and persistence_ based on attachment
+    rLog(rlLSVineyardDebug, "Ordering the simplices");
+   
+    std::vector<SimplexPersistenceElementTuple> fporder
+                (b::make_zip_iterator(b::make_tuple(filtration().begin(),    persistence().begin())),
+                 b::make_zip_iterator(b::make_tuple(filtration().end(),      persistence().end())));
+    std::sort(fporder.begin(), fporder.end(), AttachmentCmp());
+
+    // Rearrage filtration
+    std::vector< b::reference_wrapper<const Simplex> >                sv; 
+    BOOST_FOREACH(const SimplexPersistenceElementTuple& t, fporder)   sv.push_back(b::get<0>(t));
+    filtration_.rearrange (sv.begin());
+
+    // Rearrange persistence
+    std::vector< b::reference_wrapper<const typename Persistence::Element> >    pev; 
+    BOOST_FOREACH(const SimplexPersistenceElementTuple& t, fporder)   pev.push_back(b::get<1>(t));
+    persistence_.rearrange(pev.begin());
+
+#if LOGGING
+    rLog(rlLSVineyardDebug, "Simplices:");
+    for(iterator i = persistence().begin(); i != persistence().end(); ++i)
+        rLog(rlLSVineyardDebug, "  %s attached to %d", tostring(pfmap(i)).c_str(), i->attachment->vertex());
+#endif
+
+    // Pair simplices
+    rLog(rlLSVineyardDebug, "Initializing LSVineyard");
+    persistence_.pair_simplices();
+    rLog(rlLSVineyardDebug, "Simplices paired");
+
+    evaluator_ = new StaticEvaluator(*this, time_count_);
+    vineyard_.set_evaluator(evaluator_);
+    vineyard_.start_vines(persistence_.begin(), persistence_.end());
+}
+
+template<class V, class VE, class S, class F>
+LSVineyard<V,VE,S,F>::
+~LSVineyard()
+{
+    delete evaluator_;
+}
+
+template<class V, class VE, class S, class F_>
+void                    
+LSVineyard<V,VE,S,F_>::
+compute_vineyard(const VertexEvaluator& veval)
+{
+    typedef     KineticSort<VertexIndex, TrajectoryExtractor, KineticSimulator>       KineticSortDS;
+    
+    // Setup the (linear) trajectories
+    rLog(rlLSVineyard, "Setting up trajectories");
+    KineticSimulator    simulator;
+    TrajectoryExtractor traj(veval_, veval);
+    
+    KineticSortDS       sort(vertices_.begin(), vertices_.end(), 
+                             boost::bind(&LSVineyard::swap, this, bl::_1, bl::_2),
+                             &simulator, traj);
+    
+    // Process all the events (compute the vineyard in the process)
+    change_evaluator(new KineticEvaluator(*this, simulator, time_count_, traj));
+    while (!simulator.reached_infinity() && simulator.next_event_time() < 1)
+    {
+        rLog(rlLSVineyardDebug, "Next event time: %f", simulator.next_event_time());
+        simulator.process();
+        rLog(rlLSVineyardDebug, "Processed event");
+    }
+    rLog(rlLSVineyard, "Processed %d events", simulator.event_count());
+    // AssertMsg(sort.audit(&simulator), "Sort audit should succeed");
+    
+    veval_ = veval;
+    change_evaluator(new StaticEvaluator(*this, ++time_count_));
+    vineyard_.record_diagram(persistence().begin(), persistence().end());
+}
+        
+template<class V, class VE, class S, class F>
+void                    
+LSVineyard<V,VE,S,F>::
+swap(VertexIndex a, KineticSimulator* simulator)
+{
+    VertexIndex b = boost::next(a);
+    rLog(rlLSVineyardDebug, "Entered swap");
+    rLog(rlLSVineyardDebug, "Vertices: %d %d compare %d", a->vertex(), b->vertex(), vcmp_(a->vertex(), b->vertex()));
+    AssertMsg(!vcmp_(b->vertex(), a->vertex()), "In swap(a,b), a must precede b");      // true since we are using linear iterpolation
+    AssertMsg(a < b, "In swap(a,b), a must precede b");
+    transpose_vertices(a);
+    AssertMsg(b < a, "In swap(a,b), b must precede a after the transposition");
+}
+
+template<class V, class VE, class S, class F>
+void
+LSVineyard<V,VE,S,F>::
+change_evaluator(Evaluator* eval)
+{
+    AssertMsg(evaluator_ != 0, "change_evaluator() assumes that existing evaluator is not null");
+        
+    delete evaluator_;
+    evaluator_ = eval;
+    vineyard_.set_evaluator(evaluator_);
+}
+
+template<class V, class VE, class S, class F>
+bool
+LSVineyard<V,VE,S,F>::
+transpose_vertices(VertexIndex vi)
+{
+    Count(cVertexTransposition);
+    rLog(rlLSVineyard, "Transposing vertices (%d:%d, %d:%d)", vi->vertex(),             (vi -  vertices_.begin()),
+                                                              b::next(vi)->vertex(),    (b::next(vi) - vertices_.begin()));
+
+    DimensionFromIterator                       dim(pfmap_);
+    TranspositionVisitor                        visitor(*this);
+
+    OffsetMap<LSFIndex, iterator>   fpmap(filtration().begin(), persistence().begin());
+    iterator i = fpmap[vi->simplex_index()];
+    iterator i_prev = b::prior(i);
+    iterator i_next = fpmap[b::next(vi)->simplex_index()];
+    iterator i_next_prev = b::prior(i_next);           // transpositions are done in terms of the first index in the pair
+    iterator j = b::next(i_next);
+    
+    VertexIndex     vi_next = b::next(vi);
+    const Vertex&   v = vi->vertex();
+    
+    bool result = false;        // has a switch in pairing occurred
+    
+    // First move the vertex --- this can be sped up if we devise special "vertex transpose" operation
+    rLog(rlLSVineyardDebug, "Starting to move the vertex");
+    while (i_next_prev != i_prev)                       
+    { 
+        rLog(rlLSVineyardDebug, "  Transposing %s %s", tostring(pfmap(i_next_prev)).c_str(),
+                                                       tostring(pfmap(b::next(i_next_prev))).c_str());
+        result |= persistence_.transpose(i_next_prev, dim, visitor);
+        AssertMsg((i_next_prev  <= persistence().iterator_to(i_next_prev->pair)) == i_next_prev->sign(), "Pairing must respect order");
+        AssertMsg((i_next       <= persistence().iterator_to(i_next->pair))      == i_next->sign(),      "Pairing must respect order");
+        i_next_prev = b::prior(i_next);
+    }
+    rLog(rlLSVineyardDebug, "Done moving the vertex");
+
+    // Second, move the simplices attached to it
+    rLog(rlLSVineyardDebug, "Moving attached simplices");
+    // rLog(rlLSVineyardDebug, "  Considering %s", tostring(pfmap(j)).c_str());
+    // rLog(rlLSVineyardDebug, "    attachment %d", j->attachment->vertex());
+    while (j != persistence_.end() && j->attachment == vi_next)
+    {
+        rLog(rlLSVineyardDebug, "  Considering %s", tostring(pfmap(j)).c_str());
+        if (pfmap(j).contains(v))       // j becomes attached to v and does not move
+        {
+            Count(cAttachment);
+            rLog(rlLSVineyardDebug, "  Attachment changed for %s to %d", tostring(pfmap(j)).c_str(), vi->vertex());
+            set_attachment(j, vi);
+            AssertMsg(fpmap[vi->simplex_index()] < j, "The simplex must be attached to a preceding vertex");
+            ++j;
+            continue;
+        }   
+
+        iterator j_prev = j; ++j;
+        while ((--j_prev)->attachment != vi_next)                // i.e., until we have reached vi_next (and the simplices that follow it) again
+        {
+            rLog(rlLSVineyardDebug, "    Moving: %s, %s", 
+                                      tostring(pfmap(j_prev)).c_str(),
+                                      tostring(pfmap(b::next(j_prev))).c_str());
+            AssertMsg(j_prev->attachment == vi, "Simplex preceding the one being moved must be attached to v");
+            result |= persistence_.transpose(j_prev, dim, visitor);
+            AssertMsg((j_prev  <= persistence().iterator_to(j_prev->pair)) == j_prev->sign(), "Pairing must respect order");
+            --j_prev;
+        }
+    }
+    rLog(rlLSVineyard, "Done moving attached simplices");
+    vertices_.relocate(vi, vi_next);                    // swap vi and vi_next
+    
+#if LSVINEYARD_CONSISTENCY    
+    AssertMsg(verify_pairing(), "Pairing must be correct after vertex transposition");
+#endif
+
+    return result;
+}
+
+template<class V, class VE, class S, class F>
+bool
+LSVineyard<V,VE,S,F>::
+verify_pairing() const
+{
+    rLog(rlLSVineyardDebug, "Verifying pairing");
+    StaticPersistence<> p(filtration());
+    p.pair_simplices(false);
+    iterator                        i     = persistence().begin();
+    StaticPersistence<>::iterator   ip    = p.begin();
+    StaticPersistence<>::SimplexMap<LSFiltration>       m = p.make_simplex_map(filtration());
+
+    while (ip != p.end())
+    {
+        if (&pfmap(i) != &m[ip])
+        {
+            rError("DP: %s %s", tostring(pfmap(i)).c_str(), tostring(pfmap(i->pair)).c_str());
+            rError("SP: %s %s", tostring(m[ip]).c_str(), tostring(m[ip->pair]).c_str());
+            rError("The order must match");
+            return false;
+        }
+        if (&pfmap(i->pair) != &m[ip->pair])
+        {
+            rError("DP: %s %s", tostring(pfmap(i)).c_str(), tostring(pfmap(i->pair)).c_str());
+            rError("SP: %s %s", tostring(m[ip]).c_str(), tostring(m[ip->pair]).c_str());
+            rError("The pairing must match");
+            return false;
+        }
+        ++i; ++ip;
+    }
+
+    return true;
+}
+
+
+/* Evaluators */
+template<class V, class VE, class S, class C>
+class LSVineyard<V,VE,S,C>::StaticEvaluator: public Evaluator
+{
+    public:
+                                StaticEvaluator(const LSVineyard& v, RealType time): 
+                                    time_(time), vineyard_(v)                               {}
+
+        virtual RealType        time() const                                                { return time_; }
+        virtual RealType        operator()(Index i) const                                   { return vineyard_.simplex_value(vineyard_.pfmap(i)); }
+        virtual Dimension       dimension(Index i) const                                    { return vineyard_.pfmap(i).dimension(); }
+                                
+    private:
+        RealType                time_;
+        const LSVineyard&       vineyard_;
+};
+
+template<class V, class VE, class S, class C>
+class LSVineyard<V,VE,S,C>::KineticEvaluator: public Evaluator
+{
+    public:
+        typedef                 typename KineticSimulator::Time                             Time;
+
+                                KineticEvaluator(const LSVineyard& v, const KineticSimulator& sp, RealType time_offset, const TrajectoryExtractor& traj): 
+                                    vineyard_(v), sp_(sp), 
+                                    time_offset_(time_offset), traj_(traj)                  {}
+
+        virtual RealType        time() const                                                { return time_offset_ + get_time(); }
+        virtual RealType        operator()(Index i) const                                   
+        {
+            rLog(rlLSVineyard, "%s (attached to %d): %s(%f) = %f", tostring(vineyard_.pfmap(i)).c_str(),
+                                                                   i->attachment->vertex(),
+                                                                   tostring(traj_(i->attachment)).c_str(),
+                                                                   get_time(),
+                                                                   traj_(i->attachment)(get_time()));
+            return traj_(i->attachment)(get_time()); 
+        }
+        virtual Dimension       dimension(Index i) const                                    { return vineyard_.pfmap(i).dimension(); }
+
+    private:
+        Time                    get_time() const                                            { return sp_.current_time(); }
+        
+        const LSVineyard&           vineyard_;
+        const KineticSimulator&     sp_;
+        const TrajectoryExtractor&  traj_;
+        RealType                    time_offset_;
+};
+
+
+template<class V, class VE, class S, class C>
+class LSVineyard<V,VE,S,C>::VertexAttachmentComparison: 
+    public std::binary_function<Vertex, Vertex, bool>
+{
+    public:
+                                VertexAttachmentComparison(const VertexLSFIndexMap& vimap, 
+                                                           const LSVineyard& vnrd):
+                                    vimap_(vimap), vnrd_(vnrd)                              {}
+        bool                    operator()(Vertex v1, Vertex v2) const                      
+        { return vnrd_.filtration_attachment(vimap_.find(v1)->second) < vnrd_.filtration_attachment(vimap_.find(v2)->second); }
+
+    private:
+        const VertexLSFIndexMap&    vimap_;
+        const LSVineyard&           vnrd_;
+};
+
+
+template<class V, class VE, class S, class C>
+struct LSVineyard<V,VE,S,C>::AttachmentCmp: 
+    public std::binary_function<const SimplexPersistenceElementTuple&, const SimplexPersistenceElementTuple&, bool>
+{
+    bool        operator()(const SimplexPersistenceElementTuple& t1, const SimplexPersistenceElementTuple& t2) const
+    {
+        if (b::get<1>(t1).get().attachment == b::get<1>(t2).get().attachment)
+            return b::get<0>(t1).get().dimension() < b::get<0>(t2).get().dimension();
+        else
+            return b::get<1>(t1).get().attachment  < b::get<1>(t2).get().attachment;
+    }
+};
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/topology/order.h	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,113 @@
+#ifndef __ORDER_H__
+#define __ORDER_H__
+
+#include "utilities/types.h"
+#include "utilities/indirect.h"
+#include "utilities/property-maps.h"
+
+#include <vector>
+#include <list>
+
+#include <boost/multi_index_container.hpp>
+#include <boost/multi_index/random_access_index.hpp>
+namespace bmi = boost::multi_index;
+
+//#include <iostream>
+#include <sstream>
+#include <string>
+
+
+/* Tags */
+// TODO: pollutes global namespace; find a place to localize
+struct  order           {};
+struct  consistency     {};
+
+template<class Container>
+class OffsetOutputMap
+{
+    public:
+        typedef             const typename Container::value_type*   const_element_pointer;
+        typedef             typename Container::iterator            iterator;
+            
+                            OffsetOutputMap(const Container& order):
+                                om(order.begin(),0), order_(order)  {}
+
+        // returns a string with (i - bg_)                                
+        std::string         operator()(iterator i) const                       
+        { 
+            std::stringstream s; 
+            s << om[i];
+            return s.str();
+        }
+        
+        std::string         operator()(const_element_pointer p) const
+        { 
+            return (*this)(order_.iterator_to(*p));
+        }
+
+    private:
+        OffsetMap<typename Container::iterator, unsigned>           om;
+        const Container&                                            order_;
+};
+
+template<class Element_ = Empty<> >
+struct OrderContainer
+{
+    typedef             Element_                                                        Element;
+    typedef             boost::multi_index_container<Element,
+                                                     bmi::indexed_by<
+                                                        bmi::random_access<bmi::tag<order> >             /* order index */
+                                                     > 
+                                                    >                                   Container;
+    typedef             typename Container::template index<order>::type                 OrderedContainer;
+
+    typedef             OffsetOutputMap<Container>                                      OutputMap;
+
+    template<class U> struct rebind
+    { typedef           OrderContainer<U>                                               other; };
+};
+
+
+template<class Container_, class Comparison_>
+struct  ElementComparison: public std::binary_function<const typename Container_::value_type*,
+                                                       const typename Container_::value_type*,
+                                                       bool>
+{
+    typedef             Container_                                                      Container;
+    typedef             Comparison_                                                     Comparison;
+    typedef             typename Container::value_type                                  Element;
+
+                        ElementComparison(const Container& container, 
+                                          const Comparison& cmp = Comparison()): 
+                            container_(container), cmp_(cmp)                            {}
+    
+    bool                operator()(const Element* a, const Element* b) const            { return cmp_(container_.iterator_to(*a), container_.iterator_to(*b)); }
+    
+    const Container&    container_;
+    const Comparison&   cmp_;
+};
+
+
+
+template<class Element_ = Empty<> >
+struct OrderConsistencyContainer
+{
+    typedef             Element_                                                        Element;
+    typedef             boost::multi_index_container<Element,
+                                                     bmi::indexed_by<
+                                                        bmi::random_access<bmi::tag<order> >,            /* current index */
+                                                        bmi::random_access<bmi::tag<consistency> >       /* original index */
+                                                     > 
+                                                    >                                   Container;
+    
+    typedef             typename Container::template index<order>::type                 OrderedContainer;
+    typedef             typename Container::template index<consistency>::type           ConsistentContainer;
+    
+    typedef             OffsetOutputMap<Container>                                      OutputMap;
+    
+    template<class U> struct rebind
+    { typedef           OrderConsistencyContainer<U>                                    other; };
+};
+
+
+#endif // __ORDER_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/topology/persistence-diagram.h	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,178 @@
+#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__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/topology/persistence-diagram.hpp	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,326 @@
+#include <boost/serialization/vector.hpp>
+#include <boost/serialization/nvp.hpp>
+
+#include "utilities/munkres/munkres.h"
+
+using boost::serialization::make_nvp;
+
+template<class D>
+PDPoint<D>::
+PDPoint(RealType x, RealType y, const Data& data)
+{
+    point_.first().first = x;
+    point_.first().second = y;
+    point_.second() = data;
+}
+
+
+template<class D>
+template<class OtherData>
+PersistenceDiagram<D>::
+PersistenceDiagram(const PersistenceDiagram<OtherData>& other)
+{
+    points_.reserve(other.size());
+    for (typename PersistenceDiagram<OtherData>::PointVector::const_iterator cur = points_.begin();
+                                                                             cur != points_.end(); ++cur)
+        push_back(Point(cur->x(), cur->y()));
+}
+
+template<class D>
+template<class Iterator, class Evaluator>
+PersistenceDiagram<D>::
+PersistenceDiagram(Iterator bg, Iterator end, const Evaluator& eval)
+{
+    init(bg, end, eval, Point::Visitor());
+}
+
+template<class D>
+template<class Iterator, class Evaluator, class Visitor>
+PersistenceDiagram<D>::
+PersistenceDiagram(Iterator bg, Iterator end, const Evaluator& eval, const Visitor& visitor)
+{
+    init(bg, end, eval, visitor);
+}
+
+template<class D>
+template<class Iterator, class Evaluator, class Visitor>
+void
+PersistenceDiagram<D>::
+init(Iterator bg, Iterator end, const Evaluator& evaluator, const Visitor& visitor)
+{
+    for (Iterator cur = bg; cur != end; ++cur)
+        if (cur->sign())
+        {
+            boost::optional<Point> p = make_point(cur, evaluator, visitor);
+            if (p)  push_back(*p);
+        }
+}
+
+template<class Point, class Iterator, class Evaluator, class Visitor>
+boost::optional<Point>
+make_point(Iterator i, const Evaluator& evaluator, const Visitor& visitor)
+{
+    RealType x = evaluator(&*i);
+    RealType y = Infinity;
+    if (&*(i->pair) != &*i)
+        y = evaluator(&*(i->pair));
+
+    Point p(x,y);
+    visitor.point(i, p);
+
+    if (x == y) return boost::optional<Point>();
+
+    return p;
+}
+
+template<class Diagrams, class Iterator, class Evaluator, class DimensionExtractor>
+void    init_diagrams(Diagrams& diagrams,
+                      Iterator bg, Iterator end,
+                      const Evaluator& evaluator,
+                      const DimensionExtractor& dimension)
+{
+    // FIXME: this is specialized for Diagrams that is std::map
+    typedef             typename Diagrams::mapped_type              PDiagram;
+
+    init_diagrams(diagrams, bg, end, evaluator, dimension, typename PDiagram::Point::Visitor());
+}
+
+template<class Diagrams, class Iterator, class Evaluator, class DimensionExtractor, class Visitor>
+void    init_diagrams(Diagrams& diagrams,
+                      Iterator bg, Iterator end,
+                      const Evaluator& evaluator,
+                      const DimensionExtractor& dimension,
+                      const Visitor& visitor)
+{
+    // FIXME: this is specialized for Diagrams that is std::map
+    typedef             typename Diagrams::mapped_type              PDiagram;
+
+    for (Iterator cur = bg; cur != end; ++cur)
+        if (cur->sign())
+        {
+            boost::optional<typename PDiagram::Point> p = make_point<typename PDiagram::Point>(cur, evaluator, visitor);
+            if (p)
+                diagrams[dimension(&*cur)].push_back(*p);
+        }
+}
+
+template<class D>
+std::ostream&
+PersistenceDiagram<D>::
+operator<<(std::ostream& out) const
+{
+    for (const_iterator cur = begin(); cur != end(); ++cur)
+        out << *cur << std::endl;
+    return out;
+}
+
+template<class D>
+template<class Archive>
+void
+PDPoint<D>::
+serialize(Archive& ar, version_type )
+{
+    ar & make_nvp("x", x());
+    ar & make_nvp("y", y());
+    ar & make_nvp("data", data());
+}
+
+template<class D>
+template<class Archive>
+void
+PersistenceDiagram<D>::
+serialize(Archive& ar, version_type )
+{
+    ar & make_nvp("points", points_);
+}
+
+
+/**
+ * Some structures to compute bottleneck distance between two persistence diagrams (in bottleneck_distance() function below)
+ * by setting up bipartite graphs, and finding maximum cardinality matchings in them using Boost Graph Library.
+ */
+#include <boost/iterator/counting_iterator.hpp>
+#include <boost/graph/adjacency_list.hpp>
+#include <boost/graph/max_cardinality_matching.hpp>
+
+struct Edge: public std::pair<unsigned, unsigned>
+{
+    typedef         std::pair<unsigned, unsigned>                       Parent;
+
+                    Edge(unsigned v1, unsigned v2, RealType d):
+                        Parent(v1, v2), distance(d)                     {}
+
+    bool            operator<(const Edge& other) const                  { return distance < other.distance; }
+
+    RealType        distance;
+};
+typedef std::vector<Edge>               EdgeVector;
+typedef EdgeVector::const_iterator      EV_const_iterator;
+
+struct CardinaliyComparison
+{
+    typedef         boost::adjacency_list<boost::vecS, boost::vecS, boost::undirectedS>         Graph;
+    typedef         std::vector<boost::graph_traits<Graph>::vertex_descriptor>                  MatchingVector;
+
+                    CardinaliyComparison(unsigned size, EV_const_iterator begin):
+                        max_size(size), bg(begin), last(bg), g(2*max_size), mates(2*max_size)
+                    { boost::add_edge(bg->first, bg->second, g); }
+
+    bool            operator()(EV_const_iterator i1, EV_const_iterator i2)
+    {
+        //std::cout << "Max size: " << max_size << std::endl;
+        //std::cout << "Comparing: (" << i1->first << ", " << i1->second << ") and "
+        //          <<            "(" << i2->first << ", " << i2->second << ")" << std::endl;
+
+        // FIXME: the matching is being recomputed from scratch every time, this should be fixed
+        if (i2 > last)
+            do
+            {
+                ++last;
+                boost::add_edge(last->first, last->second, g);
+            } while (last != i2);
+        else
+            do
+            {
+                boost::remove_edge(last->first, last->second, g);
+            } while (--last != i2);
+
+        edmonds_maximum_cardinality_matching(g, &mates[0]);
+        //std::cout << "Found matching of size: " << matching_size(g, &mates[0]) << std::endl;
+        return matching_size(g, &mates[0]) == max_size;
+    }
+
+    unsigned                max_size;
+    EV_const_iterator       bg;
+    EV_const_iterator       last;
+    Graph                   g;
+    MatchingVector          mates;
+};
+
+// Bottleneck distance
+template<class Diagram1, class Diagram2, class Norm>
+RealType                bottleneck_distance(const Diagram1& dgm1, const Diagram2& dgm2, const Norm& norm)
+{
+    typedef         typename Diagram1::const_iterator                   Citer1;
+    typedef         typename Diagram2::const_iterator                   Citer2;
+
+    const unsigned  max_size = dgm1.size() + dgm2.size();
+
+    // Compute all the edges and sort them by distance
+    EdgeVector   edges;
+
+    // Connect all diagonal points to each other
+    for (unsigned i = dgm1.size(); i < max_size; ++i)
+        for (unsigned j = max_size + dgm2.size(); j < 2*max_size; ++j)
+            edges.push_back(Edge(i, j, 0));
+
+    // Edges between real points
+    unsigned i = 0;
+    for (Citer1 cur1 = dgm1.begin(); cur1 != dgm1.end(); ++cur1)
+    {
+        unsigned j = max_size;
+        for (Citer2 cur2 = dgm2.begin(); cur2 != dgm2.end(); ++cur2)
+            edges.push_back(Edge(i,j++, norm(*cur1, *cur2)));
+
+        ++i;
+    }
+
+    // Edges between real points and their corresponding diagonal points
+    i = 0;
+    for (Citer1 cur1 = dgm1.begin(); cur1 != dgm1.end(); ++cur1, ++i)
+        edges.push_back(Edge(i, max_size + dgm2.size() + i, norm.diagonal(*cur1)));
+    i = max_size;
+    for (Citer2 cur2 = dgm2.begin(); cur2 != dgm2.end(); ++cur2, ++i)
+        edges.push_back(Edge(dgm1.size() + (i - max_size), i, norm.diagonal(*cur2)));
+
+
+    std::sort(edges.begin(), edges.end());
+    //for (i = 0; i < edges.size(); ++i)
+    //    std::cout << "Edge: " << edges[i].first << " " << edges[i].second << " " << edges[i].distance << std::endl;
+
+    // Perform cardinality based binary search
+    typedef boost::counting_iterator<EV_const_iterator>         EV_counting_const_iterator;
+    EV_counting_const_iterator bdistance = std::upper_bound(EV_counting_const_iterator(edges.begin()),
+                                                            EV_counting_const_iterator(edges.end()),
+                                                            edges.begin(),
+                                                            CardinaliyComparison(max_size, edges.begin()));
+
+    return (*bdistance)->distance;
+}
+
+// Wasserstein distance
+template<class Diagram>
+RealType
+wasserstein_distance(const Diagram& dgm1, const Diagram& dgm2, unsigned p)
+{
+    typedef         RealType                    Distance;
+    typedef         typename Diagram::Point     Point;
+    typedef         Linfty<Point, Point>        Norm;
+
+    unsigned size = dgm1.size() + dgm2.size();
+    Norm norm;
+
+    // Setup the matrix
+    Matrix<Distance>        m(size,size);
+    for (unsigned i = 0; i < dgm1.size(); ++i)
+        for (unsigned j = 0; j < dgm2.size(); ++j)
+        {
+            const Point& p1 = *(dgm1.begin() + i);
+            const Point& p2 = *(dgm2.begin() + j);
+            m(i,j) = pow(norm(p1, p2),  p);
+            m(j + dgm1.size(), i + dgm2.size()) = 0;
+        }
+
+    for (unsigned i = 0; i < dgm1.size(); ++i)
+        for (unsigned j = dgm2.size(); j < size; ++j)
+        {
+            const Point& p1 = *(dgm1.begin() + i);
+            m(i,j) = pow(norm.diagonal(p1), p);
+        }
+
+    for (unsigned j = 0; j < dgm2.size(); ++j)
+        for (unsigned i = dgm1.size(); i < size; ++i)
+        {
+            const Point& p2 = *(dgm2.begin() + j);
+            m(i,j) = pow(norm.diagonal(p2), p);
+        }
+
+    // Compute weighted matching
+    Munkres munkres;
+    munkres.solve(m);
+
+    // Assume everything is assigned (i.e., that we have a perfect matching)
+    Distance sum = 0;
+    for (unsigned i = 0; i < size; i++)
+        for (unsigned j = 0; j < size; j++)
+            if (m(i,j) == 0)
+            {
+                //std::cout << i << ": " << j << '\n';
+                //sum += m[i][j];
+                if (i >= dgm1.size())
+                {
+                    if (j >= dgm2.size())
+                        sum += 0;
+                    else
+                    {
+                        const Point& p2 = *(dgm2.begin() + j);
+                        sum += pow(norm.diagonal(p2), p);
+                    }
+                } else
+                {
+                    if (j >= dgm2.size())
+                    {
+                        const Point& p1 = *(dgm1.begin() + i);
+                        sum += pow(norm.diagonal(p1), p);
+                    } else
+                    {
+                        const Point& p1 = *(dgm1.begin() + i);
+                        const Point& p2 = *(dgm2.begin() + j);
+                        sum += pow(norm(p1, p2),  p);
+                    }
+                }
+                break;
+            }
+
+    return sum;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/topology/rips.h	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,176 @@
+#ifndef __RIPS_H__
+#define __RIPS_H__
+
+#include <vector>
+#include <string>
+#include "simplex.h"
+#include <boost/iterator/counting_iterator.hpp>
+
+
+/**
+ * Rips class
+ *
+ * Class providing basic operations to work with Rips complexes. It implements Bron-Kerbosch algorithm, 
+ * and provides simple wrappers for various functions.
+ *
+ * Distances_ is expected to define types IndexType and DistanceType as well as 
+ *               provide operator()(...) which given two IndexTypes should return 
+ *               the distance between them. There should be methods begin() and end() 
+ *               for iterating over IndexTypes as well as a method size().
+ */
+template<class Distances_, class Simplex_ = Simplex<typename Distances_::IndexType> >
+class Rips
+{
+    public:
+        typedef             Distances_                                      Distances; 
+        typedef             typename Distances::IndexType                   IndexType;
+        typedef             typename Distances::DistanceType                DistanceType;
+
+        typedef             Simplex_                                        Simplex;
+        typedef             typename Simplex::Vertex                        Vertex;             // should be the same as IndexType
+        typedef             typename Simplex::VertexContainer               VertexContainer;
+
+        class               Evaluator;
+        class               Comparison;
+        class               ComparePair;       
+
+    public:
+                            Rips(const Distances& distances):
+                                distances_(distances)                       {}
+
+        // Calls functor f on each simplex in the k-skeleton of the Rips complex
+        template<class Functor, class Iterator>
+        void                generate(Dimension k, DistanceType max, const Functor& f, 
+                                     Iterator candidates_begin, Iterator candidates_end) const;
+        
+        // Calls functor f on all the simplices of the Rips complex that contain the given vertex v
+        template<class Functor, class Iterator>
+        void                vertex_cofaces(IndexType v, Dimension k, DistanceType max, const Functor& f, 
+                                           Iterator candidates_begin, Iterator candidates_end) const;
+
+        // Calls functor f on all the simplices of the Rips complex that contain the given edge [u,v]
+        template<class Functor, class Iterator>
+        void                edge_cofaces(IndexType u, IndexType v, Dimension k, DistanceType max, const Functor& f, 
+                                         Iterator candidates_begin, Iterator candidates_end) const;
+        
+        // Calls functor f on all the simplices of the Rips complex that contain the given Simplex s
+        // (unlike the previous methods it does not call the functor on the Simplex s itself)
+        template<class Functor, class Iterator>
+        void                cofaces(const Simplex& s, Dimension k, DistanceType max, const Functor& f,
+                                    Iterator candidates_begin, Iterator candidates_end) const;
+
+        
+        /* No Iterator argument means Iterator = IndexType and the range is [distances().begin(), distances().end()) */
+        template<class Functor>
+        void                generate(Dimension k, DistanceType max, const Functor& f) const
+        { generate(k, max, f, boost::make_counting_iterator(distances().begin()), boost::make_counting_iterator(distances().end())); }
+        
+        template<class Functor>
+        void                vertex_cofaces(IndexType v, Dimension k, DistanceType max, const Functor& f) const
+        { vertex_cofaces(v, k, max, f, boost::make_counting_iterator(distances().begin()), boost::make_counting_iterator(distances().end())); }
+
+        template<class Functor>
+        void                edge_cofaces(IndexType u, IndexType v, Dimension k, DistanceType max, const Functor& f) const
+        { edge_cofaces(u, v, k, max, f, boost::make_counting_iterator(distances().begin()), boost::make_counting_iterator(distances().end())); }
+
+        template<class Functor>
+        void                cofaces(const Simplex& s, Dimension k, DistanceType max, const Functor& f) const
+        { cofaces(s, k, max, f, boost::make_counting_iterator(distances().begin()), boost::make_counting_iterator(distances().end())); }
+
+        
+        const Distances&    distances() const                               { return distances_; }
+        DistanceType        max_distance() const;
+        
+        DistanceType        distance(const Simplex& s1, const Simplex& s2) const;
+
+
+    protected:
+        class               WithinDistance;
+
+        template<class Functor, class NeighborTest>
+        void                bron_kerbosch(VertexContainer&                          current, 
+                                          const VertexContainer&                    candidates, 
+                                          typename VertexContainer::const_iterator  excluded,
+                                          Dimension                                 max_dim,
+                                          const NeighborTest&                       neighbor,
+                                          const Functor&                            functor,
+                                          bool                                      check_initial = true) const;
+        
+    protected:
+        const Distances&    distances_;
+};
+        
+
+template<class Distances_, class Simplex_>
+class Rips<Distances_, Simplex_>::WithinDistance: public std::binary_function<Vertex, Vertex, bool>
+{
+    public:
+                            WithinDistance(const Distances_&    distances, 
+                                           DistanceType         max):
+                                distances_(distances), max_(max)                        {}
+
+        bool                operator()(Vertex u, Vertex v) const                        { return distances_(u, v) <= max_; }
+
+    protected:
+        const Distances&    distances_;  
+        DistanceType        max_;
+};
+
+template<class Distances_, class Simplex_>
+class Rips<Distances_, Simplex_>::Evaluator: public std::unary_function<const Simplex&, DistanceType>
+{
+    public:
+        typedef             Simplex_                                        Simplex;
+
+                            Evaluator(const Distances& distances): 
+                                distances_(distances)                       {}
+
+        DistanceType        operator()(const Simplex& s) const;
+
+    protected:
+        const Distances&    distances_;
+};
+
+template<class Distances_, class Simplex_>
+class Rips<Distances_, Simplex_>::Comparison: public std::binary_function<const Simplex&, const Simplex&, bool>
+{
+    public:
+        typedef             Simplex_                                        Simplex;
+
+                            Comparison(const Distances& distances):
+                                eval_(distances)                            {}
+
+        bool                operator()(const Simplex& s1, const Simplex& s2) const    
+        { 
+            DistanceType e1 = eval_(s1), 
+                         e2 = eval_(s2);
+            if (e1 == e2)
+                return s1.dimension() < s2.dimension();
+
+            return e1 < e2;
+        }
+
+    protected:
+        Evaluator           eval_;
+};
+
+template<class Distances_, class Simplex_>
+struct Rips<Distances_, Simplex_>::ComparePair: 
+    public std::binary_function<const std::pair<IndexType, IndexType>&,
+                                const std::pair<IndexType, IndexType>&,
+                                bool>
+{
+                            ComparePair(const Distances& distances): 
+                                distances_(distances)                       {}
+
+        bool                operator()(const std::pair<IndexType, IndexType>& a,
+                                       const std::pair<IndexType, IndexType>& b)            {  return   distances_(a.first, a.second) <
+                                                                                                        distances_(b.first, b.second);  }
+
+        const Distances&    distances_;
+};
+
+
+#include "rips.hpp"
+
+#endif // __RIPS_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/topology/rips.hpp	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,197 @@
+#include <algorithm>
+#include <utility>
+#include <boost/utility.hpp>
+#include <iostream>
+#include <utilities/log.h>
+#include <utilities/counter.h>
+#include <utilities/indirect.h>
+#include <boost/iterator/counting_iterator.hpp>
+#include <functional>
+
+#ifdef LOGGING
+static rlog::RLogChannel* rlRips =                  DEF_CHANNEL("rips/info", rlog::Log_Debug);
+static rlog::RLogChannel* rlRipsDebug =             DEF_CHANNEL("rips/debug", rlog::Log_Debug);
+#endif // LOGGING
+
+#ifdef COUNTERS
+static Counter*  cClique =                          GetCounter("rips/clique");
+#endif // COUNTERS
+
+template<class D, class S>
+template<class Functor, class Iterator>
+void
+Rips<D,S>::
+generate(Dimension k, DistanceType max, const Functor& f, Iterator bg, Iterator end) const
+{
+    rLog(rlRipsDebug,       "Entered generate with %d indices", distances().size());
+
+    WithinDistance neighbor(distances(), max);
+
+    // current      = empty
+    // candidates   = everything
+    VertexContainer current;
+    VertexContainer candidates(bg, end);
+    bron_kerbosch(current, candidates, boost::prior(candidates.begin()), k, neighbor, f);
+}
+
+template<class D, class S>
+template<class Functor, class Iterator>
+void
+Rips<D,S>::
+vertex_cofaces(IndexType v, Dimension k, DistanceType max, const Functor& f, Iterator bg, Iterator end) const
+{
+    WithinDistance neighbor(distances(), max);
+
+    // current      = [v]
+    // candidates   = everything - [v]
+    VertexContainer current; current.push_back(v);
+    VertexContainer candidates;
+    for (Iterator cur = bg; cur != end; ++cur)
+        if (*cur != v && neighbor(v, *cur))
+            candidates.push_back(*cur);
+    bron_kerbosch(current, candidates, boost::prior(candidates.begin()), k, neighbor, f);
+}
+
+template<class D, class S>
+template<class Functor, class Iterator>
+void
+Rips<D,S>::
+edge_cofaces(IndexType u, IndexType v, Dimension k, DistanceType max, const Functor& f, Iterator bg, Iterator end) const
+{
+    rLog(rlRipsDebug,   "In edge_cofaces(%d, %d)", u, v);
+
+    WithinDistance neighbor(distances(), max);
+    AssertMsg(neighbor(u,v), "The new edge must be in the complex");
+
+    // current      = [u,v]
+    // candidates   = everything - [u,v]
+    VertexContainer current; current.push_back(u); current.push_back(v);
+
+    VertexContainer candidates;
+    for (Iterator cur = bg; cur != end; ++cur)
+        if (*cur != u && *cur != v && neighbor(v,*cur) && neighbor(u,*cur))
+        {
+            candidates.push_back(*cur);
+            rLog(rlRipsDebug,   "  added candidate: %d", *cur);
+        }
+
+    bron_kerbosch(current, candidates, boost::prior(candidates.begin()), k, neighbor, f);
+}
+
+template<class D, class S>
+template<class Functor, class Iterator>
+void
+Rips<D,S>::
+cofaces(const Simplex& s, Dimension k, DistanceType max, const Functor& f, Iterator bg, Iterator end) const
+{
+    rLog(rlRipsDebug,   "In cofaces(%s)", tostring(s).c_str());
+
+    WithinDistance neighbor(distances(), max);
+
+    // current      = s.vertices()
+    VertexContainer current(s.vertices().begin(), s.vertices().end());
+    
+    // candidates   = everything - s.vertices()     that is a neighbor() of every vertex in the simplex
+    VertexContainer candidates;
+    typedef difference_iterator<Iterator, 
+                                typename VertexContainer::const_iterator, 
+                                std::less<Vertex> >                     DifferenceIterator;
+    for (DifferenceIterator cur =  DifferenceIterator(bg, end, s.vertices().begin(), s.vertices().end()); 
+                            cur != DifferenceIterator(end, end, s.vertices().end(), s.vertices().end()); 
+                            ++cur)
+    {
+        bool nghbr = true;
+        for (typename VertexContainer::const_iterator v = s.vertices().begin(); v != s.vertices().end(); ++v)
+            if (!neighbor(*v, *cur))        { nghbr = false; break; }
+
+        if (nghbr)  
+        {
+            candidates.push_back(*cur);
+            rLog(rlRipsDebug,   "  added candidate: %d", *cur);
+        }
+    }
+
+    bron_kerbosch(current, candidates, boost::prior(candidates.begin()), k, neighbor, f, false);
+}
+
+
+template<class D, class S>
+template<class Functor, class NeighborTest>
+void
+Rips<D,S>::
+bron_kerbosch(VertexContainer&                          current,    
+              const VertexContainer&                    candidates,     
+              typename VertexContainer::const_iterator  excluded,
+              Dimension                                 max_dim,    
+              const NeighborTest&                       neighbor,       
+              const Functor&                            functor,
+              bool                                      check_initial) const
+{
+    rLog(rlRipsDebug,       "Entered bron_kerbosch");
+    
+    if (check_initial && !current.empty())
+    {
+        Simplex s(current);
+        rLog(rlRipsDebug,   "Reporting simplex: %s", tostring(s).c_str());
+        functor(s);
+    }
+
+    if (current.size() == static_cast<size_t>(max_dim) + 1) 
+        return;
+
+    rLog(rlRipsDebug,       "Traversing %d vertices", candidates.end() - boost::next(excluded));
+    for (typename VertexContainer::const_iterator cur = boost::next(excluded); cur != candidates.end(); ++cur)
+    {
+        current.push_back(*cur);
+        rLog(rlRipsDebug,   "  current.size() = %d, current.back() = %d", current.size(), current.back());
+
+        VertexContainer new_candidates;
+        for (typename VertexContainer::const_iterator ccur = candidates.begin(); ccur != cur; ++ccur)
+            if (neighbor(*ccur, *cur))
+                new_candidates.push_back(*ccur);
+        size_t ex = new_candidates.size();
+        for (typename VertexContainer::const_iterator ccur = boost::next(cur); ccur != candidates.end(); ++ccur)
+            if (neighbor(*ccur, *cur))
+                new_candidates.push_back(*ccur);
+        excluded  = new_candidates.begin() + (ex - 1);
+
+        bron_kerbosch(current, new_candidates, excluded, max_dim, neighbor, functor);
+        current.pop_back();
+    }
+}
+
+template<class Distances_, class Simplex_>
+typename Rips<Distances_, Simplex_>::DistanceType
+Rips<Distances_, Simplex_>::
+distance(const Simplex& s1, const Simplex& s2) const
+{
+    DistanceType mx = 0;
+    for (typename Simplex::VertexContainer::const_iterator      a = s1.vertices().begin();   a != s1.vertices().end();    ++a)
+        for (typename Simplex::VertexContainer::const_iterator  b = s2.vertices().begin();   b != s2.vertices().end();    ++b)
+            mx = std::max(mx, distances_(*a,*b));
+    return mx;
+}
+
+template<class Distances_, class Simplex_>
+typename Rips<Distances_, Simplex_>::DistanceType
+Rips<Distances_, Simplex_>::
+max_distance() const
+{
+    DistanceType mx = 0;
+    for (IndexType a = distances_.begin(); a != distances_.end(); ++a)
+        for (IndexType b = boost::next(a); b != distances_.end(); ++b)
+            mx = std::max(mx, distances_(a,b));
+    return mx;
+}
+
+template<class Distances_, class Simplex_>
+typename Rips<Distances_, Simplex_>::DistanceType
+Rips<Distances_, Simplex_>::Evaluator::
+operator()(const Simplex& s) const
+{
+    DistanceType mx = 0;
+    for (typename Simplex::VertexContainer::const_iterator      a = s.vertices().begin();   a != s.vertices().end();    ++a)
+        for (typename Simplex::VertexContainer::const_iterator  b = boost::next(a);         b != s.vertices().end();    ++b)
+            mx = std::max(mx, distances_(*a,*b));
+    return mx;
+}
--- a/include/topology/simplex.h	Fri Aug 24 16:58:25 2007 -0400
+++ b/include/topology/simplex.h	Tue Jun 27 09:37:05 2017 -0700
@@ -1,170 +1,223 @@
 /*
  * Author: Dmitriy Morozov
- * Department of Computer Science, Duke University, 2005 -- 2006
+ * Department of Computer Science, Duke University, 2005 -- 2008
  */
 
 #ifndef __SIMPLEX_H__
 #define __SIMPLEX_H__
 
-#include "utilities/sys.h"
-#include "utilities/debug.h"
-
-#include <set>
+#include <vector>
+#include <algorithm>
 #include <list>
 #include <iostream>
 
 #include "utilities/types.h"
 
+#include <boost/compressed_pair.hpp>
+#include <boost/iterator/iterator_adaptor.hpp>
 #include <boost/serialization/access.hpp>
 
 
 /**
- * SimplexWithVertices is a basic simplex class. It stores vertices of a given type, 
- * and knows how to compute its own boundary. It should probably be used as a base 
- * class for any explicit simplex representation.
+ * Class: Simplex
+ * Basic simplex class. It stores vertices and data of the given types in 
+ * a `boost::compressed_pair` (so if data is an Empty class which is the default, 
+ * it incurs no space overhead). The class knows how to compute its own <boundary()>. 
+ *
+ * Parameter:
+ *   V -            vertex type
+ *   T -            data type
+ *
+ * \ingroup topology
  */
-template<class V>
-class SimplexWithVertices
+template<class V, class T = Empty<> >
+class Simplex
 {
-	public:
-		typedef		V																Vertex;
-		typedef		SimplexWithVertices<Vertex>										Self;
-	
-		typedef		std::set<Vertex>												VertexContainer;
-		typedef		std::list<Self>													Cycle;
-		
-		/// \name Constructors 
-		/// @{
-		SimplexWithVertices()														{}
-		SimplexWithVertices(const Self& s):	
-			vertices_(s.vertices_)													{}
-		template<class Iterator>
-		SimplexWithVertices(Iterator bg, Iterator end):
-			vertices_(bg, end)														{}
-		SimplexWithVertices(const VertexContainer& v):	
-			vertices_(v)															{}
-		SimplexWithVertices(Vertex v):	
-			vertices_()																{ vertices_.insert(v); }
-		/// @}
-		
-		/// \name Core 
-		/// @{
-		Cycle					boundary() const;
-		Dimension				dimension() const									{ return vertices_.size()-1; }
-		/// @}
-		
-		/// \name Vertex manipulation
-		/// @{
-		bool					contains(const Vertex& v) const						{ return (vertices_.find(v) != vertices_.end()); }
-		const VertexContainer&	vertices() const									{ return vertices_; }
-		void					add(const Vertex& v) 								{ vertices_.insert(v); }
-		/// @}
+    public:
+        /* Typedefs: Public Types
+         *
+         *    Vertex -              vertex type (template parameter V)
+         *    Data -                data type (template parameter T)
+         *    Self -
+         *    Boundary -            type in which the boundary is stored
+         */
+        typedef     V                                                               Vertex;
+        typedef     T                                                               Data;
+        typedef     Simplex<Vertex, Data>                                           Self;
+        class BoundaryIterator;
 
-		/// \name Assignment and comparison
-		/// Gives an ordering on simplices (for example, so that simplices can be used as keys for std::map)
-		/// @{
-		const Self&				operator=(const Self& s)							{ vertices_ = s.vertices_; return *this; }
-		bool					operator==(const Self& s) const						{ return vertices_ == s.vertices_; }
-		bool 					operator<(const Self& s) const						{ return vertices_ < s.vertices_; }
-		/// @}
+        /* Typedefs: Internal representation
+         *
+         *    VertexContainer -     internal representation of the vertices
+         *    VerticesDataPair -    `compressed_pair` of VertexContainer and Data
+         */
+        typedef     std::vector<Vertex>                                             VertexContainer;
+        typedef     boost::compressed_pair<VertexContainer, Data>                   VerticesDataPair;
+        
+        /// \name Constructors 
+        /// @{
+        //
+        /// Constructor: Simplex()
+        /// Default constructor
+        Simplex()                                                                   {}
+        /// Constructor: Simplex(Self other)
+        /// Copy constructor
+        Simplex(const Self& other): 
+            vdpair_(other.vertices(), other.data())                                 {}
+        /// Constructor: Simplex(Data d)
+        /// Initialize simplex with data
+        Simplex(const Data& d)                                                      { data() = d; }
+        /// Constructor: Simplex(Iterator bg, Iterator end)
+        /// Initialize simplex by copying vertices in range [bg, end)
+        template<class Iterator>
+        Simplex(Iterator bg, Iterator end, const Data& d = Data())                  { join(bg, end); data() = d; }
+        /// Constructor: Simplex(VertexContainer v)
+        /// Initialize simplex by copying the given VertexContainer
+        Simplex(const VertexContainer& v, const Data& d = Data()):  
+            vdpair_(v, d)                                                           { std::sort(vertices().begin(), vertices().end()); }
+        /// @}
+        
+        /// \name Core 
+        /// @{
+        ///
+        /// Functions: boundary_begin(), boundary_end()
+        /// Returns the iterators over the boundary of the simplex
+        BoundaryIterator        boundary_begin() const;
+        BoundaryIterator        boundary_end() const;
+        /// Function: dimension()
+        /// Returns the dimension of the simplex
+        Dimension               dimension() const                                   { return vertices().size() - 1; }
+        /// @}
+        
+        const Data&             data() const                                        { return vdpair_.second(); }
+        Data&                   data()                                              { return vdpair_.second(); }
+        const VertexContainer&  vertices() const                                    { return vdpair_.first(); }
+        
+        /// \name Vertex manipulation
+        /// @{
+        bool                    contains(const Vertex& v) const;
+        bool                    contains(const Self& s) const;
+        void                    add(const Vertex& v);
+        template<class Iterator>
+        void                    join(Iterator bg, Iterator end);
+        void                    join(const Self& other)                             { join(other.vertices().begin(), other.vertices().end()); }
+        /// @}
 
-		std::ostream&			operator<<(std::ostream& out) const;
-	
-	private:
-		VertexContainer			vertices_;
+        const Self&             operator=(const Self& s)                            { vdpair_ = s.vdpair_; return *this; }
+
+        std::ostream&           operator<<(std::ostream& out) const;
+
+        /* Classes: Comparisons
+         *
+         * VertexComparison -           compare simplices based on the lexicographic ordering of their <vertices()>
+         * VertexDimensionComparison -  compare simplices based on the lexicographic ordering of their <vertices()> within each dimension
+         * DataComparison -             compare simplices based on their <data()>
+         * DataDimensionComparison -    compare simplices based on their <data()> within each <dimension()>
+         */
+        struct VertexComparison;
+        struct VertexDimensionComparison;
+        struct DataComparison;
+        struct DataDimensionComparison;
 
-	private:
-		/* Serialization */
-		friend class boost::serialization::access;
-		
-		template<class Archive>
-		void 					serialize(Archive& ar, version_type );
+        /* Classes: Functors
+         *
+         * DataEvaluator -              return data given a simplex
+         * DimensionExtractor -         return dimesnion given a simplex
+         */
+        struct DataEvaluator;
+        struct DimensionExtractor;
+    
+    protected:
+        VertexContainer&        vertices()                                          { return vdpair_.first(); }
+
+        VerticesDataPair        vdpair_;
+
+    protected:
+        /* Serialization */
+        friend class boost::serialization::access;
+        
+        template<class Archive>
+        void                    serialize(Archive& ar, version_type );
 };
 
-/**
- * SimplexWithValue explicitly adds a RealType value to the SimplexWithVertices.
- */
-template<class Vert>
-class SimplexWithValue: public SimplexWithVertices<Vert>
+
+template<class V, class T>
+struct Simplex<V,T>::VertexComparison
 {
-	public:
-		typedef		Vert															Vertex;
-		typedef		RealType														Value;
-		typedef		SimplexWithValue<Vertex>										Self;
-		typedef		SimplexWithVertices<Vertex>										Parent;
+        typedef                 Self                    first_argument_type;
+        typedef                 Self                    second_argument_type;
+        typedef                 bool                    result_type;
+
+        bool                    operator()(const Self& a, const Self& b) const       { return a.vertices() < b.vertices(); }
+};
+
+template<class V, class T>
+struct Simplex<V,T>::VertexDimensionComparison
+{
+        typedef                 Self                    first_argument_type;
+        typedef                 Self                    second_argument_type;
+        typedef                 bool                    result_type;
 
-		typedef		typename Parent::VertexContainer								VertexContainer;
-	
-		/// \name Constructors
-		/// @{
-		SimplexWithValue(Value value = 0): val(value)								{}
-		SimplexWithValue(const Self& s):
-			Parent(s), val(s.val)													{}
-		SimplexWithValue(const Parent& s, Value value = 0): 
-			Parent(s), val(value)													{}
-		template<class Iterator>
-		SimplexWithValue(Iterator bg, Iterator end, Value value = 0):
-			Parent(bg, end), val(value)												{}
-		SimplexWithValue(const VertexContainer& v, Value value = 0):
-			Parent(v), val(value)													{}
-		/// @}
+        bool                    operator()(const Self& a, const Self& b) const       
+        { 
+            if (a.dimension() == b.dimension())
+                return a.vertices() < b.vertices();
+            else
+                return a.dimension() < b.dimension();
+        }
+};
 
-		/// \name Core
-		/// @{
-		void 					set_value(Value value)								{ val = value; }
-		Value					get_value() const									{ return val; }
-		/// @}
-		
-		const Self&				operator=(const Self& s);
-		std::ostream&			operator<<(std::ostream& out) const;
+template<class V, class T>
+struct Simplex<V,T>::DataComparison
+{
+        typedef                 Self                    first_argument_type;
+        typedef                 Self                    second_argument_type;
+        typedef                 bool                    result_type;
 
-	private:
-		Value					val;
-
-		/* Serialization */
-		friend class boost::serialization::access;
-		
-		template<class Archive>
-		void 					serialize(Archive& ar, version_type );
+        bool                    operator()(const Self& a, const Self& b) const       { return a.data() < b.data(); }
 };
 
-/**
- * SimplexWithAttachment stores the vertex to which the simplex is attached (meant for lower-star filtrations)
- */
-template<typename V>
-class SimplexWithAttachment: public SimplexWithVertices<V>
+template<class S>
+struct DataDimensionComparison
+{
+        typedef                 S                       Simplex;
+        typedef                 Simplex                 first_argument_type;
+        typedef                 Simplex                 second_argument_type;
+        typedef                 bool                    result_type;
+
+        bool                    operator()(const Simplex& a, const Simplex& b) const       
+        {
+            if (a.dimension() == b.dimension())
+                return a.data() < b.data();
+            else
+                return a.dimension() < b.dimension();
+        }
+};
+        
+template<class V, class T>
+struct Simplex<V,T>::DataEvaluator
 {
-	public:
-		typedef 	V																VertexIndex;
-		typedef		SimplexWithVertices<VertexIndex>								Parent;
-	
-		/// \name Constructors 
-		/// @{
-		SimplexWithAttachment():
-			attachment(VertexIndex())												{}
-		template<class Iterator>
-		SimplexWithAttachment(Iterator bg, Iterator end):
-			Parent(bg, end)															{}
-		SimplexWithAttachment(const Parent& s):
-			Parent(s)																{}
-		SimplexWithAttachment(VertexIndex vi):
-			Parent(vi), attachment(vi)												{}
-		/// @}
+        typedef                 Self                    first_argument_type;
+        typedef                 Data                    result_type;
+
+        result_type             operator()(const first_argument_type& s) const      { return s.data(); }
+};
 
-		void 					set_attachment(VertexIndex v)						{ attachment = v; }
-		VertexIndex				get_attachment() const								{ return attachment; }
-		
-	private:
-		VertexIndex				attachment;
-	
-	private:
-		// Serialization
-		friend class boost::serialization::access;
+template<class V, class T>
+struct Simplex<V,T>::DimensionExtractor
+{
+        typedef                 Self                    first_argument_type;
+        typedef                 Dimension               result_type;
 
-		template<class Archive>
-		void 					serialize(Archive& ar, version_type );
+        result_type             operator()(const first_argument_type& s) const      { return s.dimension(); }
 };
 
+
+// TODO: class DirectSimplex - class which stores indices of the simplices in its boundary
+// TODO: class CompactSimplex<V, T, N> - uses arrays instead of vectors to store simplices 
+//       (dimension N must be known at compile time)
+
+
 #include "simplex.hpp"
 
 #endif // __SIMPLEX_H__
--- a/include/topology/simplex.hpp	Fri Aug 24 16:58:25 2007 -0400
+++ b/include/topology/simplex.hpp	Tue Jun 27 09:37:05 2017 -0700
@@ -1,94 +1,128 @@
+#include <boost/serialization/serialization.hpp>
 #include <boost/serialization/base_object.hpp>
 #include <boost/serialization/set.hpp>
 #include <boost/serialization/nvp.hpp>
 
+#include <boost/iterator/filter_iterator.hpp>
+#include <functional>
 
 /* Implementations */
 
-/* SimplexWithVertices */
-template<class V>
-typename SimplexWithVertices<V>::Cycle	
-SimplexWithVertices<V>::
-boundary() const
+template<class V, class T>
+struct Simplex<V,T>::BoundaryIterator: public boost::iterator_adaptor<BoundaryIterator,                                 // Derived
+                                                                      typename VertexContainer::const_iterator,         // Base
+                                                                      Simplex<V,T>,                                     // Value
+                                                                      boost::use_default,
+                                                                      Simplex<V,T> >
 {
-	Cycle bdry;
-	if (dimension() == 0)	return bdry;
+    public:
+        typedef     typename VertexContainer::const_iterator                Iterator;
+        typedef     boost::iterator_adaptor<BoundaryIterator,
+                                            Iterator,
+                                            Simplex<V,T>,
+                                            boost::use_default,
+                                            Simplex<V,T> >                  Parent;
+
+                    BoundaryIterator()                                      {}
+        explicit    BoundaryIterator(Iterator iter, const VertexContainer& vertices):
+                        Parent(iter), vertices_(vertices)                   {}
 
-	for (typename VertexContainer::const_iterator cur = vertices_.begin(); cur != vertices_.end(); ++cur)
-	{
-		bdry.push_back(*this);
-		Self& s = bdry.back();
-		s.vertices_.erase(*cur);
-	}
+    private:
+        friend class    boost::iterator_core_access;
+        Simplex<V,T>    dereference() const
+        {
+            typedef     std::not_equal_to<Vertex>                           NotEqualVertex;
+
+            return      Self(boost::make_filter_iterator(std::bind2nd(NotEqualVertex(), *(this->base())), vertices_.begin(), vertices_.end()),
+                             boost::make_filter_iterator(std::bind2nd(NotEqualVertex(), *(this->base())), vertices_.end(),   vertices_.end()));
+        }
 
-	return bdry;
+        const VertexContainer&      vertices_;
+};
+
+/* Simplex */
+template<class V, class T>
+typename Simplex<V,T>::BoundaryIterator
+Simplex<V,T>::
+boundary_begin() const
+{
+    if (dimension() == 0)   return boundary_end();
+    return BoundaryIterator(vertices().begin(), vertices());
 }
 
-template<class V>
-std::ostream&			
-SimplexWithVertices<V>::
+template<class V, class T>
+typename Simplex<V,T>::BoundaryIterator
+Simplex<V,T>::
+boundary_end() const
+{
+    return BoundaryIterator(vertices().end(), vertices());
+}
+
+template<class V, class T>
+bool
+Simplex<V,T>::
+contains(const Vertex& v) const
+{
+    // TODO: would std::find() be faster? (since most simplices we deal with are low dimensional)
+    typename VertexContainer::const_iterator location = std::lower_bound(vertices().begin(), vertices().end(), v);
+    return ((location != vertices().end()) && (*location == v));
+}
+
+template<class V, class T>
+bool
+Simplex<V,T>::
+contains(const Self& s) const
+{
+    return std::includes(  vertices().begin(),   vertices().end(),
+                         s.vertices().begin(), s.vertices().end());
+}
+
+template<class V, class T>
+void
+Simplex<V,T>::
+add(const Vertex& v)
+{
+    // TODO: would find() or lower_bound() followed by insert be faster?
+    vertices().push_back(v); std::sort(vertices().begin(), vertices().end());
+}
+
+template<class V, class T>
+template<class Iterator>
+void
+Simplex<V,T>::
+join(Iterator bg, Iterator end)
+{
+    vertices().insert(vertices().end(), bg, end);
+    std::sort(vertices().begin(), vertices().end());
+}
+
+template<class V, class T>
+std::ostream&
+Simplex<V,T>::
 operator<<(std::ostream& out) const
 {
-	for (typename VertexContainer::const_iterator cur = vertices_.begin(); cur != vertices_.end(); ++cur)
-		out << *cur << ' ';
-	
-	return out;
-}
-		
-template<class V>
-template<class Archive>
-void 
-SimplexWithVertices<V>::
-serialize(Archive& ar, version_type )									
-{ ar & BOOST_SERIALIZATION_NVP(vertices_); }
+    typename VertexContainer::const_iterator cur = vertices().begin();
+    out << "<" << *cur;
+    for (++cur; cur != vertices().end(); ++cur)
+    {
+        out << ", " << *cur;
+    }
+    out << ">";
+    // out << " [" << data() << "] ";
 
-template<class V>
-std::ostream& operator<<(std::ostream& out, const SimplexWithVertices<V>& s)		
-{ return s.operator<<(out); }
-
-
-/* SimplexWithValue */
-template<class V>
-std::ostream&
-SimplexWithValue<V>::
-operator<<(std::ostream& out) const
-{
-	Parent::operator<<(out);
-	out << "(val = " << val << ")";
-	return out;
+    return out;
 }
 
-template<class V>
-const typename SimplexWithValue<V>::Self&	
-SimplexWithValue<V>::
-operator=(const Self& s)									
-{ 
-	Parent::operator=(s); 
-	val = s.val; 
-	return *this; 
-}
-		
-template<class V>
+template<class V, class T>
 template<class Archive>
-void 
-SimplexWithValue<V>::
-serialize(Archive& ar, version_type )								
-{ 
-	ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Parent);
-	ar & BOOST_SERIALIZATION_NVP(val);
+void
+Simplex<V,T>::
+serialize(Archive& ar, version_type )
+{
+    ar & boost::serialization::make_nvp("vertices", vertices());
+    ar & boost::serialization::make_nvp("data", data());
 }
 
-template<typename V>
-template<class Archive>
-void 
-SimplexWithAttachment<V>::
-serialize(Archive& ar, version_type )
-{			
-	ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Parent);
-	ar & BOOST_SERIALIZATION_NVP(attachment);
-}
-
-
-template<class V>
-std::ostream& operator<<(std::ostream& out, const SimplexWithValue<V>& s)		
+template<class V, class T>
+std::ostream& operator<<(std::ostream& out, const Simplex<V,T>& s)
 { return s.operator<<(out); }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/topology/static-persistence.h	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,184 @@
+#ifndef __STATIC_PERSISTENCE_H__
+#define __STATIC_PERSISTENCE_H__
+
+#include "order.h"
+#include "cycles.h"
+#include "filtration.h"
+
+#include <boost/ref.hpp>
+#include <boost/lambda/lambda.hpp>
+namespace bl = boost::lambda;
+
+#include <utilities/types.h>
+
+#include <boost/progress.hpp>
+
+
+// Element_ should derive from PairCycleData
+template<class Data_, class ChainTraits_, class Element_ = use_default>
+struct PairCycleData: public Data_
+{
+    typedef     Data_                                                                   Data;
+    typedef     typename if_default<Element_, PairCycleData>::type                      Element;
+
+    typedef     const Element*                                                          Index;
+    typedef     typename ChainTraits_::template rebind<Index>::other                    ChainTraits;
+    typedef     typename ChainTraits::Chain                                             Chain;
+    typedef     Chain                                                                   Cycle;
+
+                PairCycleData(Index p = Index(), const Cycle& z = Cycle(), const Data& d = Data()):
+                    Data(d), pair(p), cycle(z)
+                {}
+    
+    bool        sign() const                                                            { return cycle.empty(); }
+    bool        unpaired() const                                                        { return pair == this; }
+    
+    void        swap_cycle(Cycle& z)                                                    { cycle.swap(z); }
+    void        set_pair(Index i)                                                       { pair = i; }
+
+    Index       pair;
+    Cycle       cycle;
+};
+
+/**
+ * Class: StaticPersistence
+ * The class that encapsulates order and pairing information as well as 
+ * implements methods to compute and maintain the pairing. Its most 
+ * significant method is <pair_simplices()>.
+ *
+ * Template parameters:
+ *   Data_ -                auxilliary contents to store with each OrderElement
+ *   OrderDescriptor_ -     class describing how the order is stored; it defaults to <VectorOrderDescriptor> 
+ *                          which serves as a prototypical class
+ */
+template<class Data_ =              Empty<>,
+         class ChainTraits_ =       VectorChains<>,
+         class ContainerTraits_ =   OrderContainer<>,
+         class Element_ =           PairCycleData<Data_, ChainTraits_>,
+         class Comparison_ =        ElementComparison<typename ContainerTraits_::template rebind<Element_>::other::Container,
+                                                      std::greater<typename ContainerTraits_::template rebind<Element_>::other::Container::iterator> > >
+class StaticPersistence
+{
+    public:
+        // Typedef: Data
+        // The data type stored in each order element
+        typedef                         Data_                                                   Data;
+
+        typedef                         Element_                                                Element;
+        typedef                         typename ContainerTraits_::
+                                                    template rebind<Element>::other             ContainerTraits;
+        typedef                         typename ContainerTraits::Container                     Container;
+        typedef                         Container                                               Order;
+        typedef                         typename Element::Index                                 OrderIndex;
+        typedef                         Element                                                 OrderElement;
+        typedef                         typename Order::iterator                                iterator;
+
+        typedef                         typename ChainTraits_::
+                                                    template rebind<OrderIndex>::other          ChainTraits;
+        typedef                         typename ChainTraits::Chain                             Chain;
+        typedef                         Chain                                                   Cycle;
+        
+        typedef                         Comparison_                                             OrderComparison;
+
+        /* Constructor: StaticPersistence() */
+                                        StaticPersistence(): ocmp_(order_)                      {}
+
+        /* Constructor: StaticPersistence()
+         * TODO: write a description
+         *
+         * Template parameters:
+         *   Filtration -           filtration of the complex whose persistence we are computing
+         */
+        template<class Filtration>      StaticPersistence(const Filtration& f): ocmp_(order_)   { initialize(f); }
+
+        // Function: initialize(const Filtration& f)
+        // Initialize the boundary map from the Filtration
+        template<class Filtration>
+        void                            initialize(const Filtration& f);
+        
+        // Function: pair_simplices()                                        
+        // Compute persistence of the filtration
+        void                            pair_simplices(bool progress = true);
+
+        // Functions: Accessors
+        //   begin() -              returns OrderIndex of the first element
+        //   end() -                returns OrderIndex of one past the last element
+        //   size() -               number of elements in the StaticPersistence
+        iterator                        begin() const                                           { return order_.begin(); }
+        iterator                        end() const                                             { return order_.end(); }
+        iterator                        iterator_to(OrderIndex i) const                         { return order_.iterator_to(*i); }
+        OrderIndex                      index(iterator i) const                                 { return &*i; }
+        size_t                          size() const                                            { return order_.size(); }
+        const OrderComparison&          order_comparison() const                                { return ocmp_; }
+
+        // A map to extract simplices
+        template<class Filtration>      class SimplexMap;
+        template<class Filtration>
+        SimplexMap<Filtration>          make_simplex_map(const Filtration& filtration) const    { return SimplexMap<Filtration>(*this, filtration); }
+
+        class                           OrderModifier
+        {
+            public:
+                                        OrderModifier(Order& order): order_(order)              {}
+                template<class Functor> 
+                void                    operator()(iterator i, const Functor& f)                { order_.modify(i, f); }
+
+            private:
+                Order&                  order_;
+        };
+        OrderModifier                   modifier()                                              { return OrderModifier(order()); }
+
+        // Function: pair_simplices(bg, end)
+        // Compute persistence of the simplices in filtration between bg and end
+        template<class Visitor>
+        void                            pair_simplices(iterator bg, iterator end, bool store_negative = false, const Visitor& visitor = Visitor());
+
+        // Struct: PairVisitor
+        // Acts as an archetype and if necessary a base class for visitors passed to <pair_simplices(bg, end, visitor)>.
+        struct                          PairVisitor
+        {
+                                        PairVisitor(unsigned size): show_progress(size)         {}
+            // Function: init(i)
+            // Called after OrderElement pointed to by `i` has been initialized 
+            // (its cycle is set to be its boundary, and pair is set to self, i.e. `i`)
+            void                        init(iterator i) const                                  {}
+            
+            // Function: update(j, i)
+            // Called after the cycle of `i` has been added to the cycle of `j`, 
+            // this allows the derived class to perform the necessary updates 
+            // (e.g., add `i`'s chain to `j`'s chain)
+            void                        update(iterator j, iterator i) const                    {}
+
+            // Function: finished(j)
+            // Called after the processing of `j` is finished.
+            void                        finished(iterator j) const                              { ++show_progress; }
+            mutable boost::progress_display     
+                                        show_progress;
+        };
+        
+        struct                          PairVisitorNoProgress
+        {
+                                        PairVisitorNoProgress()                                 {}
+            void                        init(iterator i) const                                  {}
+            void                        update(iterator j, iterator i) const                    {}
+            void                        finished(iterator j) const                              {}
+        };
+
+    protected:
+        const Order&                    order() const                                           { return order_; }
+        Order&                          order()                                                 { return order_; }
+
+        void                            set_pair(iterator i,    iterator j)                     { set_pair(i, &*j); }
+        void                            set_pair(iterator i,    OrderIndex j)                   { order_.modify(i, boost::bind(&OrderElement::set_pair, bl::_1, j)); }                  // i->set_pair(j)
+        void                            set_pair(OrderIndex i,  iterator j)                     { set_pair(iterator_to(i), &*j); }
+        void                            set_pair(OrderIndex i,  OrderIndex j)                   { set_pair(iterator_to(i), j); }
+        void                            swap_cycle(iterator i,  Cycle& z)                       { order_.modify(i, boost::bind(&OrderElement::swap_cycle, bl::_1, boost::ref(z))); }    // i->swap_cycle(z)
+
+    private:
+        Order                           order_;
+        OrderComparison                 ocmp_;
+};
+
+#include "static-persistence.hpp"
+
+#endif // __STATIC_PERSISTENCE_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/topology/static-persistence.hpp	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,156 @@
+#include <utilities/log.h>
+#include <utilities/containers.h>
+#include <utilities/property-maps.h>
+
+#include <boost/utility/enable_if.hpp>
+#include <boost/utility.hpp>
+#include <boost/foreach.hpp>
+
+#include <boost/foreach.hpp>
+
+#ifdef LOGGING
+static rlog::RLogChannel* rlPersistence =                   DEF_CHANNEL("topology/persistence", rlog::Log_Debug);
+#endif // LOGGING
+
+#ifdef COUNTERS
+static Counter*  cPersistencePair =                         GetCounter("persistence/pair");
+static Counter*  cPersistencePairBoundaries =               GetCounter("persistence/pair/boundaries");
+static Counter*  cPersistencePairCycleLength =              GetCounter("persistence/pair/cyclelength");
+#endif // COUNTERS
+
+template<class D, class CT, class OT, class E, class Cmp>
+template<class Filtration>
+void
+StaticPersistence<D, CT, OT, E, Cmp>::
+initialize(const Filtration& filtration)
+{ 
+    order_.assign(filtration.size(), OrderElement());
+    rLog(rlPersistence, "Initializing persistence");
+
+    OffsetMap<typename Filtration::Index, iterator>                         om(filtration.begin(), begin());
+    for (typename Filtration::Index cur = filtration.begin(); cur != filtration.end(); ++cur)
+    {
+        Cycle z;   
+        BOOST_FOREACH(const typename Filtration::Simplex& s, std::make_pair(cur->boundary_begin(), cur->boundary_end()))
+            z.push_back(index(om[filtration.find(s)]));
+        z.sort(ocmp_); 
+
+        iterator ocur = om[cur];
+        swap_cycle(ocur, z);
+        set_pair(ocur,   ocur);
+    }
+}
+                    
+template<class D, class CT, class OT, class E, class Cmp>
+void 
+StaticPersistence<D, CT, OT, E, Cmp>::
+pair_simplices(bool progress)
+{ 
+    if (progress) 
+    {
+        PairVisitor visitor(size());
+        pair_simplices<PairVisitor>(begin(), end(), false, visitor); 
+    }
+    else
+    {
+        PairVisitorNoProgress visitor;
+        pair_simplices<PairVisitorNoProgress>(begin(), end(), false, visitor);
+    }
+}
+
+template<class D, class CT, class OT, class E, class Cmp>
+template<class Visitor>
+void 
+StaticPersistence<D, CT, OT, E, Cmp>::
+pair_simplices(iterator bg, iterator end, bool store_negative, const Visitor& visitor)
+{
+#if LOGGING
+    typename ContainerTraits::OutputMap outmap(order_);
+#endif
+
+    // FIXME: need sane output for logging
+    rLog(rlPersistence, "Entered: pair_simplices");
+    for (iterator j = bg; j != end; ++j)
+    {
+        visitor.init(j);
+        rLog(rlPersistence, "Simplex %s", outmap(j).c_str());
+
+        Cycle z;
+        swap_cycle(j, z);
+        rLog(rlPersistence, "  has boundary: %s", z.tostring(outmap).c_str());
+
+        // Sparsify the cycle by removing the negative elements
+        if (!store_negative)
+        {
+            typename OrderElement::Cycle zz;
+            BOOST_FOREACH(OrderIndex i, z)
+                if (i->sign())           // positive
+                    zz.push_back(i);
+            z.swap(zz);
+        }
+        // --------------------------
+        
+        CountNum(cPersistencePairBoundaries, z.size());
+        Count(cPersistencePair);
+
+        while(!z.empty())
+        {
+            OrderIndex i = z.top(ocmp_);            // take the youngest element with respect to the OrderComparison
+            rLog(rlPersistence, "  %s: %s", outmap(i).c_str(), outmap(i->pair).c_str());
+            // TODO: is this even a meaningful assert?
+            AssertMsg(!ocmp_(i, index(j)), 
+                      "Simplices in the cycle must precede current simplex: (%s in cycle of %s)",
+                      outmap(i).c_str(), outmap(j).c_str());
+
+            // i is not paired, so we pair j with i
+            if (iterator_to(i->pair) == iterator_to(i))
+            {
+                rLog(rlPersistence, "  Pairing %s and %s with cycle %s", 
+                                   outmap(i).c_str(), outmap(j).c_str(), 
+                                   z.tostring(outmap).c_str());
+             
+                set_pair(i, j);
+                swap_cycle(j, z);
+                set_pair(j, i);
+                
+                CountNum(cPersistencePairCycleLength,   j->cycle.size());
+                CountBy (cPersistencePairCycleLength,   j->cycle.size());
+                break;
+            }
+
+            // update element
+            z.add(i->pair->cycle, ocmp_);
+            visitor.update(j, iterator_to(i));
+            rLog(rlPersistence, "    new cycle: %s", z.tostring(outmap).c_str());
+        }
+        // if z was empty, so is (already) j->cycle, so nothing to do
+        visitor.finished(j);
+        rLog(rlPersistence, "Finished with %s: %s", 
+                            outmap(j).c_str(), outmap(j->pair).c_str());
+    }
+}
+
+template<class D, class CT, class OT, class E, class Cmp>
+template<class Filtration>
+class StaticPersistence<D, CT, OT, E, Cmp>::SimplexMap
+{
+    public:
+        typedef                             OrderIndex                              key_type;
+        // typedef                             iterator                                key_type;
+        typedef                             const typename Filtration::Simplex&     value_type;
+
+
+                                            SimplexMap(const StaticPersistence& persistence,
+                                                       const Filtration&        filtration):
+                                                persistence_(persistence), 
+                                                filtration_(filtration)             {}
+
+        value_type                          operator[](OrderIndex k) const          { return (*this)[persistence_.iterator_to(k)]; }
+        value_type                          operator[](iterator i) const            { return filtration_.simplex(filtration_.begin() + (i - persistence_.begin())); } 
+
+    private:
+        const StaticPersistence&            persistence_;
+        const Filtration&                   filtration_;
+};
+
+/* Private */
--- a/include/topology/vineyard.h	Fri Aug 24 16:58:25 2007 -0400
+++ b/include/topology/vineyard.h	Tue Jun 27 09:37:05 2017 -0700
@@ -1,6 +1,6 @@
 /*
  * Author: Dmitriy Morozov
- * Department of Computer Science, Duke University, 2005 -- 2006
+ * Department of Computer Science, Duke University, 2005 -- 2009
  */
 
 #ifndef __VINEYARD_H__
@@ -14,129 +14,141 @@
 #include <boost/serialization/vector.hpp>
 #include <boost/serialization/nvp.hpp>
 #include <boost/serialization/list.hpp>
-#include <boost/serialization/is_abstract.hpp>
-	
+    
+#include <boost/iterator/iterator_traits.hpp>
 
-template<class Smplx>	class Knee;
-template<class Smplx>	class Vine;
+
+class Knee;
+class Vine;
 
 /**
  * Vineyard class. Keeps track of vines and knees. switched() is the key function called
- * by filtration when pairing switches after a Filtration::transpose().
+ * when pairing switches.
+ *
+ * \ingroup topology
  */
-template<class FltrSmplx>
+template<class Index_, class Iterator_, class Evaluator_>
 class Vineyard
 {
-	public:
-		typedef							FltrSmplx									FiltrationSimplex;
-		typedef							typename FiltrationSimplex::Simplex			Simplex;
-		typedef							Vine<Simplex>								Vine;
-		typedef							Knee<Simplex>								Knee;
-		typedef							std::list<Vine>								VineList;
-		typedef							std::vector<VineList>						VineListVector;
-		typedef							typename FiltrationSimplex::Cycle			Cycle;
+    public:
+        typedef                         Index_                                          Index;
+        typedef                         Iterator_                                       Iterator;
+        typedef                         Evaluator_                                      Evaluator;
 
-		typedef							typename FiltrationSimplex::Index			Index;
-		typedef							typename FiltrationSimplex::Evaluator		Evaluator;
-										
-	public:
-										Vineyard(Evaluator* eval = 0): 
-											evaluator(eval)							{}
+        typedef                         std::list<Vine>                                 VineList;
+        typedef                         std::list<VineList>                             VineListList;
+        typedef                         std::vector<VineListList::iterator>             VineListVector;
+                                        
+    public:
+                                        Vineyard(Evaluator* eval = 0): 
+                                            evaluator(eval)                             {}
 
-		void							start_vines(Index bg, Index end);
-		void							switched(Index i, Index j);
-		void							record_diagram(Index bg, Index end);
+        void                            start_vines(Iterator bg, Iterator end);
+        void                            switched(Index i, Index j);
+        template<class Iter>
+        void                            record_knee(Iter i);
+        void                            record_diagram(Iterator bg, Iterator end);
 
-		void							set_evaluator(Evaluator* eval)				{ evaluator = eval; }
-
-		void							save_edges(const std::string& filename) const;
+        void                            set_evaluator(Evaluator* eval)                  { evaluator = eval; }
 
-	protected:
-		typename Knee::SimplexList  	resolve_cycle(Index i) const;
+        void                            save_edges(const std::string& filename, bool skip_infinite = false) const;
+        void                            save_vines(const std::string& filename, bool skip_infinite = false) const;
 
-	private:
-		void							record_knee(Index i);
-		void							start_vine(Index i);
+    private:
+        template<class Iter>
+        void                            start_vine(Iter i);
 
-	private:
-		VineListVector					vines;
-		Evaluator*						evaluator;
+    private:
+        VineListList                    vines;            // stores vine lists
+        VineListVector                  vines_vector;     // stores pointers (iterators) to vine lists
+        Evaluator*                      evaluator;
 };
 
 /**
- * Knee class stores the knee in R^3 as well as the cycle that is associated with the Simplex starting from the Knee.
+ * Knee class stores the knee in R^3.
+ *
+ * \ingroup topology
  */
-template<class S>
 class Knee
 {
-	public:
-		typedef					S												Simplex;
-		typedef					std::list<Simplex>								SimplexList;
-	
-		RealType				birth;
-		RealType				death;
-		RealType				time;
-		SimplexList				cycle;
-			
-								// Default parameters for serialization
-								Knee(RealType b = 0, RealType d = 0, RealType t = 0):
-									birth(b), death(d), time(t)
-								{}
-								Knee(const Knee& other): 
-									birth(other.birth), death(other.death), time(other.time)
-								{}
+    public:
+        RealType                birth;
+        RealType                death;
+        RealType                time;
+            
+                                // Default parameters for serialization
+                                Knee(RealType b = 0, RealType d = 0, RealType t = 0):
+                                    birth(b), death(d), time(t)
+                                {}
+                                Knee(const Knee& other): 
+                                    birth(other.birth), death(other.death), time(other.time)
+                                {}
 
-		bool 					is_diagonal() const								{ return birth == death; }
-		bool					is_infinite() const								{ return (death == Infinity) || (birth == Infinity); }
-		void 					set_cycle(const SimplexList& lst)				{ cycle = lst; }
+        bool                    is_diagonal() const                             { return birth == death; }
+        bool                    is_infinite() const                             { return (death == Infinity) || (birth == Infinity); }
 
-		std::ostream&			operator<<(std::ostream& out) const				{ return out << "(" << birth << ", " 
-																									<< death << ", " 
-																									<< time  << ")"; }
-	
-	private:
-		friend class boost::serialization::access;
+        std::ostream&           operator<<(std::ostream& out) const             { return out << "(" << birth << ", " 
+                                                                                                    << death << ", " 
+                                                                                                    << time  << ")"; }
+    
+    private:
+        friend class boost::serialization::access;
 
-		template<class Archive>
-		void 					serialize(Archive& ar, version_type );
+        template<class Archive>
+        void                    serialize(Archive& ar, version_type );
 };
 
-template<class S>
-std::ostream& operator<<(std::ostream& out, const Knee<S>& k) 					{ return k.operator<<(out); }
+std::ostream& operator<<(std::ostream& out, const Knee& k)                      { return k.operator<<(out); }
 
 /**
  * Vine is a list of Knees
  */
-template<class S>
-class Vine: public std::list<Knee<S> >
-{	
-	public:
-		typedef					S												Simplex;
-		typedef					Knee<Simplex>									Knee;
-		typedef					std::list<Knee>									VineRepresentation;
-		typedef					typename VineRepresentation::const_iterator		const_knee_iterator;
-		
-								Vine()											{}
-								Vine(const Knee& k)								{ add(k); }
-		
-		void 					add(RealType b, RealType d, RealType t)			{ push_back(Knee(b,d,t)); }
-		void 					add(const Knee& k)								{ push_back(k); }
+class Vine: public std::list<Knee>
+{   
+    public:
+        typedef                 std::list<Knee>                                 VineRepresentation;
+        typedef                 VineRepresentation::const_iterator              const_knee_iterator;
+        
+                                Vine()                                          {}
+                                Vine(const Vine& other): 
+                                    VineRepresentation(other)                   {}
+                                Vine(const VineRepresentation& other): 
+                                    VineRepresentation(other)                   {}
+                                Vine(const Knee& k)                             { add(k); }
+        
+        void                    add(RealType b, RealType d, RealType t)         { push_back(Knee(b,d,t)); }
+        void                    add(const Knee& k)                              { push_back(k); }
+
+        std::ostream&           operator<<(std::ostream& out) const             { std::copy(begin(), end(), std::ostream_iterator<Knee>(out, " ")); return out; }
 
-		using VineRepresentation::begin;
-		using VineRepresentation::end;
-		using VineRepresentation::front;
-		using VineRepresentation::back;
-		using VineRepresentation::size;
-		using VineRepresentation::empty;
+        using VineRepresentation::begin;
+        using VineRepresentation::end;
+        using VineRepresentation::front;
+        using VineRepresentation::back;
+        using VineRepresentation::size;
+        using VineRepresentation::empty;
+
+    protected:
+        using VineRepresentation::push_back;
+
+    private:
+        friend class boost::serialization::access;
 
-	protected:
-		using VineRepresentation::push_back;
+        template<class Archive>
+        void                    serialize(Archive& ar, version_type );
+};
+
+std::ostream& operator<<(std::ostream& out, const Vine& v)                      { return v.operator<<(out); }
+
 
-	private:
-		friend class boost::serialization::access;
+class VineData
+{
+    public:
+        void        set_vine(Vine* vine) const                                          { vine_ = vine; }
+        Vine*       vine() const                                                        { return vine_; }
 
-		template<class Archive>
-		void 					serialize(Archive& ar, version_type );
+    private:
+        mutable Vine*       vine_;      // cheap trick to work around MultiIndex's constness
 };
 
 
--- a/include/topology/vineyard.hpp	Fri Aug 24 16:58:25 2007 -0400
+++ b/include/topology/vineyard.hpp	Tue Jun 27 09:37:05 2017 -0700
@@ -3,155 +3,188 @@
 #include <fstream>
 #include <sstream>
 
-template<class FS>
+#include "utilities/log.h"
+
+#ifdef LOGGING
+static rlog::RLogChannel* rlVineyard =          DEF_CHANNEL("topology/vineyard", rlog::Log_Debug);
+#endif // LOGGING
+
+template<class I, class It, class E>
 void
-Vineyard<FS>::
-start_vines(Index bg, Index end)
+Vineyard<I,It,E>::
+start_vines(Iterator bg, Iterator end)
 {
-	AssertMsg(evaluator != 0, "Cannot start vines with a null evaluator");
-	for (Index cur = bg; cur != end; ++cur)
-	{
-		if (!cur->sign()) continue;
-		Dimension dim = cur->dimension();
-		
-		if (dim >= vines.size())
-		{
-			AssertMsg(dim == vines.size(), "New dimension has to be contiguous");
-			vines.push_back(std::list<Vine>());
-		}
+    AssertMsg(evaluator != 0, "Cannot start vines with a null evaluator");
+    for (Iterator cur = bg; cur != end; ++cur)
+    {
+        if (!cur->sign()) continue;
+        Dimension dim = evaluator->dimension(cur);
+        
+        if (dim >= vines.size())
+        {
+            AssertMsg(dim == vines.size(), "New dimension has to be contiguous");
+            vines.push_back(VineList());
+            vines_vector.push_back(boost::prior(vines.end()));
+        }
 
-		start_vine(cur);
-		record_knee(cur);
-	}
+        start_vine(cur);
+        record_knee(cur);
+    }
 }
 
-template<class FS>
+template<class I, class It, class E>
 void
-Vineyard<FS>::
+Vineyard<I,It,E>::
 switched(Index i, Index j)
 {
-	Vine* i_vine = i->vine();
-	Vine* j_vine = j->vine();
-	i->set_vine(j_vine);
-	j->set_vine(i_vine);
+    rLog(rlVineyard, "Switching vines");
+
+    Vine* i_vine = i->vine();
+    Vine* j_vine = j->vine();
+    i->set_vine(j_vine);
+    j->set_vine(i_vine);
+
+    // rLog(rlVineyard, "  %x %x %x %x", i->pair, i->pair->pair, j->pair, j->pair->pair);
+    // rLog(rlVineyard, "  %x %x %x %x", i_vine, i->pair->vine(), j_vine, j->pair->vine());
 
-	// Since the pairing has already been updated, the following assertions should be true
-	AssertMsg(i->vine() == i->pair()->vine(), "i's vine must match the vine of its pair");
-	AssertMsg(j->vine() == j->pair()->vine(), "j's vine must match the vine of its pair");
+    // Since the pairing has already been updated, the following assertions should be true
+    AssertMsg(i->vine() == i->pair->vine(), "i's vine must match the vine of its pair");
+    AssertMsg(j->vine() == j->pair->vine(), "j's vine must match the vine of its pair");
 
-	if (!i->sign()) i = i->pair();
-	if (!j->sign()) j = j->pair();
-	record_knee(i);
-	record_knee(j);
+    if (!i->sign()) i = i->pair;
+    if (!j->sign()) j = j->pair;
+
+    // std::cout << "i sign: " << i->sign() << std::endl;
+    // std::cout << "j sign: " << j->sign() << std::endl;
+
+    record_knee(i);
+    record_knee(j);
 }
 
-template<class FS>
+template<class I, class It, class E>
+template<class Iter>
 void
-Vineyard<FS>::
-start_vine(Index i)
+Vineyard<I,It,E>::
+start_vine(Iter i)
 {
-	Dout(dc::vineyard, "Starting new vine");
-	AssertMsg(i->sign(), "Can only start vines for positive simplices");
-		
-	Dimension dim = i->dimension();
-	vines[dim].push_back(Vine());
-	i->set_vine(&vines[dim].back());
-	i->pair()->set_vine(i->vine());
+    rLog(rlVineyard, "Starting new vine");
+    AssertMsg(i->sign(), "Can only start vines for positive simplices");
+        
+    Dimension dim = evaluator->dimension(i);
+    vines_vector[dim]->push_back(Vine());
+    i->set_vine(&vines_vector[dim]->back());
+    i->pair->set_vine(i->vine());
 }
-	
+    
 /// Records the current diagram in the vineyard
-template<class FS>
+template<class I, class It, class E>
 void 
-Vineyard<FS>::
-record_diagram(Index bg, Index end)
+Vineyard<I,It,E>::
+record_diagram(Iterator bg, Iterator end)
 {
-	Dout(dc::vineyard, "Entered: record_diagram()");
-	AssertMsg(evaluator != 0, "Cannot record diagram with a null evaluator");
-	
-	for (Index i = bg; i != end; ++i)
-	{
-		AssertMsg(i->vine() != 0, "Cannot process a null vine in record_diagram");
-		if (!i->sign())		continue;
-		record_knee(i);
-	}
+    rLog(rlVineyard, "Entered: record_diagram()");
+    AssertMsg(evaluator != 0, "Cannot record diagram with a null evaluator");
+    
+    for (Iterator i = bg; i != end; ++i)
+    {
+        AssertMsg(i->vine() != 0, "Cannot process a null vine in record_diagram");
+        if (!i->sign())     continue;
+        record_knee(i);
+    }
 }
 
 
-template<class FS>
-void			
-Vineyard<FS>::
-save_edges(const std::string& filename) const
+template<class I, class It, class E>
+void            
+Vineyard<I,It,E>::
+save_edges(const std::string& filename, bool skip_infinite) const
 {
-	for (unsigned int i = 0; i < vines.size(); ++i)
-	{
-		std::ostringstream os; os << i;
-		std::string fn = filename + os.str() + ".edg";
-		std::ofstream out(fn.c_str());
-		for (typename VineList::const_iterator vi = vines[i].begin(); vi != vines[i].end(); ++vi)
-			for (typename Vine::const_iterator ki = vi->begin(), kiprev = ki++; ki != vi->end(); kiprev = ki++)
-			{
-				if (kiprev->is_infinite() || ki->is_infinite()) continue;
-				out << kiprev->birth << ' ' << kiprev->death << ' ' << kiprev->time << std::endl;
-				out << ki->birth << ' ' << ki->death << ' ' << ki->time << std::endl;
-			}
-		out.close();
-	}
+    for (unsigned int i = 0; i < vines_vector.size(); ++i)
+    {
+        std::ostringstream os; os << i;
+        std::string fn = filename + os.str() + ".edg";
+        std::ofstream out(fn.c_str());
+        for (typename VineList::const_iterator vi = vines_vector[i]->begin(); vi != vines_vector[i]->end(); ++vi)
+            for (typename Vine::const_iterator ki = vi->begin(), kiprev = ki++; ki != vi->end(); kiprev = ki++)
+            {
+                if (skip_infinite && (kiprev->is_infinite() || ki->is_infinite()))
+                {
+                    std::cerr << "Warning: skipping an infinite knee in save_edges() in dimension " << i << std::endl;
+                    continue;
+                }
+                out << kiprev->birth << ' ' << kiprev->death << ' ' << kiprev->time << std::endl;
+                out << ki->birth << ' ' << ki->death << ' ' << ki->time << std::endl;
+            }
+        out.close();
+    }
+}
+
+template<class I, class It, class E>
+void            
+Vineyard<I,It,E>::
+save_vines(const std::string& filename, bool skip_infinite) const
+{
+    for (unsigned int i = 0; i < vines_vector.size(); ++i)
+    {
+        std::ostringstream os; os << i;
+        std::string fn = filename + os.str() + ".vin";
+        std::ofstream out(fn.c_str());
+        for (typename VineList::const_iterator vi = vines_vector[i]->begin(); vi != vines_vector[i]->end(); ++vi)
+        {
+            for (typename Vine::const_iterator ki = vi->begin(); ki != vi->end(); ki++)
+            {
+                if (skip_infinite && ki->is_infinite())
+                {
+                    std::cerr << "Warning: skipping an infinite knee in save_edges() in dimension " << i << std::endl;
+                    continue;
+                }
+                out << ki->birth << ' ' << ki->death << ' ' << ki->time << " ";
+            }
+            out << std::endl;
+        }
+        out.close();
+    }
 }
 
 /// Records a knee for the given simplex
-template<class FS>
+template<class I, class It, class E>
+template<class Iter>
 void
-Vineyard<FS>::
-record_knee(Index i)
+Vineyard<I,It,E>::
+record_knee(Iter i)
 {
-	Dout(dc::vineyard, "Entered record_knee()");
-	AssertMsg(evaluator != 0, "Cannot record knee with a null evaluator");
-	AssertMsg(i->vine() != 0, "Cannot add a knee to a null vine");
-	AssertMsg(i->sign(), "record_knee() must be called on a positive simplex");
-	
-	if (!i->is_paired())
-		i->vine()->add(evaluator->value(*i), Infinity, evaluator->time());
-	else
-	{
-		Dout(dc::vineyard, "Creating knee");
-		Knee k(evaluator->value(*i), evaluator->value(*(i->pair())), evaluator->time());
-		Dout(dc::vineyard, "Knee created: " << k);
+    rLog(rlVineyard, "Entered record_knee()");
+    AssertMsg(evaluator != 0, "Cannot record knee with a null evaluator");
+    AssertMsg(i->vine() != 0, "Cannot add a knee to a null vine");
+    AssertMsg(i->sign(), "record_knee() must be called on a positive simplex");
+    
+    if (i->unpaired())
+        i->vine()->add((*evaluator)(i), Infinity, evaluator->time());
+    else
+    {
+        rLog(rlVineyard, "Creating knee");
+        Knee k((*evaluator)(i), (*evaluator)((i->pair)), evaluator->time());
+        rLog(rlVineyard, "Knee created: %s", tostring(k).c_str());
+        rLog(rlVineyard, "Vine: %s", tostring(*(i->vine())).c_str());
 
-		if (!k.is_diagonal() || i->vine()->empty())			// non-diagonal k, or empty vine
-		{
-			Dout(dc::vineyard, "Extending a vine");
-			i->vine()->add(k);
-		}
-		else if (i->vine()->back().is_diagonal())			// last knee is diagonal
-		{
-			AssertMsg(i->vine()->size() == 1, "Only first knee may be diagonal for a live vine");
-			Dout(dc::vineyard, "Overwriting first diagonal knee");
-			i->vine()->back() = k;
-		} else												// finish this vine
-		{
-			Dout(dc::vineyard, "Finishing a vine");
-			i->vine()->add(k);
-			start_vine(i);
-			i->vine()->add(k);
-		}
-	}
-	
-	i->vine()->back().set_cycle(resolve_cycle(i));
-	Dout(dc::vineyard, "Leaving record_knee()");
+        if (!k.is_diagonal() || i->vine()->empty())         // non-diagonal k, or empty vine
+        {
+            rLog(rlVineyard, "Extending a vine");
+            i->vine()->add(k);
+        }
+        else if (i->vine()->back().is_diagonal())           // last knee is diagonal
+        {
+            AssertMsg(i->vine()->size() == 1, "Only first knee may be diagonal for a live vine");
+            rLog(rlVineyard, "Overwriting first diagonal knee");
+            i->vine()->back() = k;
+        } else                                              // finish this vine
+        {
+            rLog(rlVineyard, "Finishing a vine");
+            i->vine()->add(k);
+            start_vine(i);
+            i->vine()->add(k);
+        }
+    }
+    
+    rLog(rlVineyard, "Leaving record_knee()");
 }
-
-template<class FS>
-typename Vineyard<FS>::Knee::SimplexList  
-Vineyard<FS>::
-resolve_cycle(Index i) const
-{
-	Dout(dc::vineyard, "Entered resolve_cycle");
-	const Cycle& cycle = i->cycle();
-	
-	// Resolve simplices
-	typename Knee::SimplexList lst;
-	for (typename Cycle::const_iterator cur = cycle.begin(); cur != cycle.end(); ++cur)
-		lst.push_back(**cur);
-
-	return lst;
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/topology/weighted-rips.h	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,139 @@
+#ifndef __WEIGHTED_RIPS_H__
+#define __WEIGHTED_RIPS_H__
+
+#include <vector>
+#include <string>
+#include "simplex.h"
+#include "rips.h"
+#include <boost/iterator/counting_iterator.hpp>
+
+/**
+ * WeightedRipsSimplex class
+ * 
+ * This class sits as an invisible layer between the Simplex datatype passed
+ * to WeightedRips and the class itself. The need for this layer is the need
+ * to store the ``value'' (max inter-vertex distance) of each simplex in the
+ * Weighted Rips complex--something that the user of the class does not need
+ * to be aware of.
+ */
+
+template<class Simplex_, class DistanceType_>
+class WeightedRipsSimplex : public Simplex_
+{
+    public:
+        typedef          typename Simplex_::Vertex                 Vertex;
+        typedef          typename Simplex_::VertexContainer        VertexContainer;
+        typedef          DistanceType_                             DistanceType;
+
+        WeightedRipsSimplex(Simplex_ s) : Simplex_(s)  { }
+
+        void             setSimplexValue(const DistanceType &sv) { simplexValue = sv; }
+        DistanceType     getSimplexValue() const       { return    simplexValue;      }
+
+    protected:
+        DistanceType     simplexValue;
+};
+
+/**
+ * WeightedRips class
+ *
+ * Class providing basic operations to work with Rips complexes. It implements Bron-Kerbosch algorithm, 
+ * and provides simple wrappers for various functions.
+ *
+ * Distances_ is expected to define types IndexType and DistanceType as well as 
+ *               provide operator()(...) which given two IndexTypes should return 
+ *               the distance between them. There should be methods begin() and end() 
+ *               for iterating over IndexTypes as well as a method size().
+ */
+template<class Distances_, class Simplex_ = Simplex<typename Distances_::IndexType> >
+class WeightedRips : public Rips<Distances_, Simplex_>
+{
+    public:
+
+        /* redeclaring the typedefs because they cannot be inherited at compile-time */
+        typedef             Distances_                                      Distances; 
+        typedef             typename Distances::IndexType                   IndexType;
+        typedef             typename Distances::DistanceType                DistanceType;
+
+        typedef             WeightedRipsSimplex<Simplex_, DistanceType>     Simplex;
+        typedef             typename Simplex::Vertex                        Vertex;             // should be the same as IndexType
+        typedef             typename Simplex::VertexContainer               VertexContainer;
+
+        class               Evaluator;
+        class               Comparison;
+
+    public:
+                            WeightedRips(const Distances& distances):
+                                Rips<Distances_, Simplex_>(distances)                             {}
+
+                            template<class Functor>
+                            void generate(Dimension k, DistanceType max, const Functor& f) const;
+
+};
+
+/**
+ * DistanceDataStackingFunctor class
+ * 
+ * Class providing a functor that is to be called by WeightedRips::generate(). This functor
+ * takes as an argument (to its constructor) the original functor passed by the user to
+ * generate(), and a new ``double'' functor is created. Assuming that the functor acts on
+ * simplices, first the value of the simplex is computed (the radius at which the simplex
+ * appears in the weighted Rips complex), the data field of the simplex is populated with
+ * this value, and then the original functor is called (it has no idea that it was
+ * intercepted).
+ */
+
+template<class Rips_, class Functor_>
+class DistanceDataStackingFunctor
+{
+	public:
+		typedef     typename Rips_::Simplex         Simplex_;
+
+		DistanceDataStackingFunctor(const Rips_ &r, const Functor_ &f):
+			rips(r), original_functor(f) { }
+
+		void operator()(const Simplex_ &s) const
+		{
+			Simplex_         s_new(s);
+			s_new.setSimplexValue (rips.distance(s_new, s_new));
+			original_functor      (s_new);
+		}
+
+	private:
+		const Rips_       &rips;
+		const Functor_    &original_functor;
+};
+
+template<class Distances_, class Simplex_>
+template<class Functor>
+void WeightedRips<Distances_, Simplex_>::generate(Dimension k, DistanceType max, const Functor &f) const
+{
+	Rips<Distances_,Simplex_>::generate(k, max, DistanceDataStackingFunctor<WeightedRips<Distances_, Simplex_>,Functor>(*this, f));
+}
+
+template<class Distances_, class Simplex_>
+class WeightedRips<Distances_, Simplex_>::Evaluator: public Rips<Distances_,Simplex_>::Evaluator
+{
+    public:
+                            Evaluator(const Distances& distances): 
+                                Rips<Distances_, Simplex_>::Evaluator(distances)                       {}
+
+        DistanceType       operator()(const Simplex& s) const { return s.getSimplexValue(); }
+};
+
+template<class Distances_, class Simplex_>
+class WeightedRips<Distances_, Simplex_>::Comparison: public Rips<Distances_,Simplex_>::Comparison
+{
+    public:
+                            Comparison(const Distances& distances):
+                                Rips<Distances_, Simplex_>::Comparison(distances)                            {}
+
+        bool                operator()(const Simplex& s1, const Simplex& s2) const    
+        { 
+                            if (s1.dimension() != s2.dimension())
+                                return s1.dimension() < s2.dimension();
+                            return s1.getSimplexValue() < s2.getSimplexValue();
+        }
+};
+
+#endif // __WEIGHTED_RIPS_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/topology/zigzag-persistence.h	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,193 @@
+#ifndef __ZIGZAG_PERSISTENCE_H__
+#define __ZIGZAG_PERSISTENCE_H__
+
+#include "cycles.h"
+#include "utilities/types.h"
+#include <sstream>
+
+#if DEBUG_CONTAINERS
+    #include <debug/list>
+    using std::__debug::list;
+    #warning "Using debug/list in ZigzagPersistence"
+#else
+    #include <list>
+    using std::list;
+#endif
+
+
+/**
+ * Class: ZigzagPersistence
+ * TODO: this should probably be parametrized by Chain or Field
+ */
+template<class BirthID_ = Empty<>, class SimplexData_ = Empty<> >
+class ZigzagPersistence
+{
+    public:
+        typedef                         BirthID_                                BirthID;
+        typedef                         SimplexData_                            SimplexData;
+
+        struct ZNode;
+        struct BNode;
+        struct SimplexNode;
+
+        typedef                         list<ZNode>                                     ZList;
+        typedef                         typename ZList::iterator                        ZIndex;
+        typedef                         list<BNode>                                     BList;
+        typedef                         typename BList::iterator                        BIndex;
+        typedef                         list<SimplexNode>                               SimplexList;
+        typedef                         typename SimplexList::iterator                  SimplexIndex;
+
+        // TODO: should all chains be DequeChains? probably not
+        typedef                         typename DequeChains<ZIndex>::Chain             ZRow;
+        typedef                         typename DequeChains<ZIndex>::Chain             BColumn;
+        typedef                         typename VectorChains<BIndex>::Chain            BRow;
+        typedef                         typename VectorChains<BIndex>::Chain            CRow;
+        typedef                         typename VectorChains<SimplexIndex>::Chain      ZColumn;
+        typedef                         typename VectorChains<SimplexIndex>::Chain      CColumn;
+
+        typedef                         boost::optional<BirthID>                        Death;
+        typedef                         std::pair<SimplexIndex, Death>                  IndexDeathPair;
+
+        struct ZNode
+        {
+                                        ZNode(int o, BIndex l):
+                                            order(o), low(l)                            {}
+
+            int                         order;
+            ZColumn                     z_column;
+            BRow                        b_row;
+            BIndex                      low;            // which BColumn has this ZIndex as low
+
+            BirthID                     birth;          // TODO: do we need to do empty-member optimization?
+                                                        //       i.e., does it ever make sense for birth to be empty?
+        };
+
+        struct BNode
+        {
+                                        BNode(unsigned o): order(o)                     {}
+
+            unsigned                    order;
+            BColumn                     b_column;
+            CColumn                     c_column;
+        };
+
+        struct SimplexNode: public SimplexData
+        {
+                                        SimplexNode(unsigned o, ZIndex l):
+                                            order(o), low(l)                            {}
+
+            unsigned                    order;
+            ZRow                        z_row;
+            CRow                        c_row;
+            ZIndex                      low;            // which ZColumn has this SimplexNode as low
+#if ZIGZAG_CONSISTENCY
+            ZColumn                     boundary;       // NB: debug only
+#endif
+        };
+
+        // Constructor: ZigzagPersistence()
+                                        ZigzagPersistence()                             {}
+
+        // Function: add(bdry, birth)
+        IndexDeathPair                  add(ZColumn bdry, const BirthID& birth = BirthID())         { ZigzagVisitor zzv; return add<ZigzagVisitor>(bdry, birth, zzv); }
+
+        // Function: remove(s, birth)
+        Death                           remove(SimplexIndex s, const BirthID& birth = BirthID())    { ZigzagVisitor zzv; return remove<ZigzagVisitor>(s, birth, zzv); }
+
+
+        ZIndex                          begin()                                                     { return z_list.begin(); }
+        ZIndex                          end()                                                       { return z_list.end(); }
+
+        bool                            is_alive(ZIndex i) const                                    { return i->low == b_list.end(); }
+        bool                            is_alive(ZNode zn) const                                    { return zn.low == b_list.end(); }
+
+    protected:
+        // Function: add(s)
+        template<class Visitor>
+        IndexDeathPair                  add(ZColumn bdry, const BirthID& birth, Visitor& visitor);
+
+        // Function: remove(s)
+        template<class Visitor>
+        Death                           remove(SimplexIndex s, const BirthID& birth, Visitor& visitor);
+
+        // Struct: ZigzagVisitor
+        // Various methods of an instance of this class are called at different stages of addition and removal algorithm.
+        // NB: currently the places where it's called are catered for image zigzags, in the future this could be expanded
+        //     to provide simple support for other algorithms
+        // TODO: not obvious that the methods should be const (and therefore the reference passed to add() and remove())
+        //       revisit when working on ImageZigzag
+        struct ZigzagVisitor
+        {
+            SimplexIndex                new_simplex(ZigzagPersistence& zz);
+
+            // Function: new_z_in_add(zz, z, u)
+            // Called when a new cycle is born after adding a simplex. The method is expected to add an element to z_list, and return its ZIndex.
+            ZIndex                      new_z_in_add(ZigzagPersistence& zz, const ZColumn& z, const BRow& u);
+
+            BIndex                      select_j_in_remove(ZigzagPersistence& zz, const CRow& c_row);
+
+            ZIndex                      new_z_in_remove(ZigzagPersistence& zz);
+
+            void                        erasing_z(ZigzagPersistence&, ZIndex)           {}
+
+            Death                       death(ZigzagPersistence& zz, ZIndex dying_z);
+        };
+
+    public:
+        // Debug; non-const because Indices are iterators, and not const_iterators
+        void                            show_all();
+        bool                            check_consistency(SimplexIndex s_skip, ZIndex z_skip, BIndex b_skip);
+        bool                            check_consistency()                             { return check_consistency(s_list.end(), z_list.end(), b_list.end()); }
+
+    protected:
+        ZList                           z_list;
+        BList                           b_list;
+        SimplexList                     s_list;
+
+        /* Helper functors */
+        template<class Member, class Element>                                           struct Appender;
+        template<class Member, class Element>                                           struct Remover;
+        template<class Member, class Chain>                                             struct Adder;
+
+        template<class Member, class Element>
+        Appender<Member, Element>       make_appender(Member m, Element e) const        { return Appender<Member, Element>(m,e); }
+        template<class Member, class Element>
+        Remover<Member, Element>        make_remover(Member m, Element e) const         { return Remover<Member, Element>(m,e); }
+        template<class Member, class Chain>
+        Adder<Member, Chain>            make_adder(Member m, Chain& c) const            { return Adder<Member, Chain>(m, c); }
+
+        template<class Index, class IndexFrom, class PrimaryMember, class SecondaryMember>
+        void                            add_chains(Index bg, Index end, IndexFrom j, PrimaryMember pm, SecondaryMember sm);
+        template<class IndexTo, class IndexFrom, class PrimaryMemberTo, class SecondaryMemberTo, class PrimaryMemberFrom>
+        void                            add_chains(IndexTo bg, IndexTo end, IndexFrom j,
+                                                   PrimaryMemberTo   pmt, SecondaryMemberTo smt,
+                                                   PrimaryMemberFrom pmf);
+        template<class Index, class PrimaryMember, class SecondaryMember>
+        void                            add_chain(Index to, Index from,
+                                                  PrimaryMember   pmt, SecondaryMember smt);
+        template<class IndexTo, class IndexFrom, class PrimaryMemberTo, class SecondaryMemberTo, class PrimaryMemberFrom>
+        void                            add_chain(IndexTo to, IndexFrom from,
+                                                  PrimaryMemberTo   pmt, SecondaryMemberTo smt,
+                                                  PrimaryMemberFrom pmf);
+        template<class IndexTo, class IndexFrom, class PrimaryMember, class SecondaryMember, class DualPrimaryMember, class DualSecondaryMember>
+        void                            change_basis(IndexTo bg, IndexTo end, IndexFrom j,
+                                                     PrimaryMember pm, SecondaryMember sm,
+                                                     DualPrimaryMember dpm, DualSecondaryMember dsm);
+
+    public:
+        struct OrderComparison
+        {
+            template<class T>
+            bool                        operator()(T a, T b) const                      { return a->order < b->order; }
+        }                               cmp;
+
+        struct OrderOutput
+        {
+            template<class T>
+            std::string                 operator()(T a) const                           { std::stringstream s; s << a->order; return s.str(); }
+        }                               out;
+};
+
+#include "zigzag-persistence.hpp"
+
+#endif // __ZIGZAG_PERSISTENCE_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/topology/zigzag-persistence.hpp	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,724 @@
+#include <utilities/log.h>
+#include <boost/utility.hpp>
+#include <boost/iterator/filter_iterator.hpp>
+#include <algorithm>
+#include <utilities/indirect.h>
+#include <functional>
+
+#ifdef LOGGING
+static rlog::RLogChannel* rlZigzagAdd =                   DEF_CHANNEL("topology/persistence/zigzag/add",        rlog::Log_Debug);
+static rlog::RLogChannel* rlZigzagRemove =                DEF_CHANNEL("topology/persistence/zigzag/remove",     rlog::Log_Debug);
+static rlog::RLogChannel* rlZigzagAddChain =              DEF_CHANNEL("topology/persistence/zigzag/addchain",   rlog::Log_Debug);
+static rlog::RLogChannel* rlZigzagCheckConsistency=       DEF_CHANNEL("topology/persistence/zigzag/check",      rlog::Log_Debug);
+#endif // LOGGING
+
+#ifdef COUNTERS
+static Counter*  cZigzagAdd =                             GetCounter("zigzag/add");
+static Counter*  cZigzagRemove =                          GetCounter("zigzag/remove");
+static Counter*  cZigzagConsistency =                     GetCounter("zigzag/consistency");
+#endif // COUNTERS
+
+template<class BID, class SD>
+template<class Visitor>
+typename ZigzagPersistence<BID,SD>::IndexDeathPair
+ZigzagPersistence<BID,SD>::
+add(ZColumn bdry, const BirthID& birth, Visitor& visitor)
+{
+    Count(cZigzagAdd);
+
+    rLog(rlZigzagAdd,       "Entered ZigzagPersistence::add()");
+    rLog(rlZigzagAdd,       "  Boundary: %s", bdry.tostring(out).c_str());
+    rLog(rlZigzagAdd,       "  Boundary size: %d", bdry.size());
+    AssertMsg(check_consistency(), "Must be consistent before addition");
+
+    SimplexIndex last_s     = visitor.new_simplex(*this);
+    last_s->low             = z_list.end();
+#if ZIGZAG_CONSISTENCY
+    last_s->boundary        = bdry;     // NB: debug only
+#endif
+
+    rLog(rlZigzagAdd,   "  Reducing among cycles");
+    // Reduce bdry among the cycles
+    rLog(rlZigzagAdd,       "    Boundary: %s", bdry.tostring(out).c_str());
+    BColumn v;                // representation of the boundary in the cycle basis
+    while (!bdry.empty())
+    {
+        SimplexIndex l      = bdry.back();
+        ZIndex k            = l->low;
+        v.append(k, cmp);
+        bdry.add(k->z_column, cmp);
+        rLog(rlZigzagAdd,       "    Boundary: %s", bdry.tostring(out).c_str());
+    }
+    rLog(rlZigzagAdd,   "  Reduced among cycles");
+
+    // Reduce v among boundaries
+    BRow u;
+    while (!(v.empty()))
+    {
+        ZIndex l = v.back();
+        BIndex k = l->low;
+
+        if (k == b_list.end())
+            break;
+
+        u.append(k, cmp);
+        v.add(k->b_column, cmp);
+    }
+    rLog(rlZigzagAdd,   "  Reduced among boundaries");
+
+    if (v.empty())
+    {
+        rLog(rlZigzagAdd,       "  Birth case in add");
+
+        // Figure out the new cycle z
+        ZColumn z;
+        std::for_each(u.begin(), u.end(), make_adder(&BNode::c_column, z));
+        z.append(last_s, cmp);
+
+        // Birth
+        ZIndex new_z                = visitor.new_z_in_add(*this, z, u);
+        new_z->birth                = birth;
+
+        // Set s_row
+        std::for_each(z.begin(), z.end(), make_appender(&SimplexNode::z_row, new_z));
+
+        // Set z_column
+        new_z->z_column.swap(z);
+
+        // Set low
+        new_z->low                  = b_list.end();
+        last_s->low                 = new_z;
+
+        return std::make_pair(last_s, Death());
+    } else
+    {
+        rLog(rlZigzagAdd,       "  Death case in add");
+
+        // Death
+        unsigned order              = b_list.empty() ? 0 : boost::prior(b_list.end())->order + 1;
+        b_list.push_back(BNode(order));
+        BIndex last_b               = boost::prior(b_list.end());
+
+        // Set b_column and low
+        last_b->b_column.swap(v);
+        last_b->b_column.back()->low = last_b;
+
+        // Set b_row
+        std::for_each(last_b->b_column.begin(), last_b->b_column.end(), make_appender(&ZNode::b_row, last_b));
+
+        // Set c_column
+        CColumn& c                  = last_b->c_column;
+        std::for_each(u.begin(), u.end(), make_adder(&BNode::c_column, c));
+        c.append(last_s, cmp);
+
+        // Set c_row
+        std::for_each(c.begin(), c.end(), make_appender(&SimplexNode::c_row, last_b));
+
+        return std::make_pair(last_s, visitor.death(*this, last_b->b_column.back()));
+    }
+}
+
+
+template<class BID, class SD>
+template<class Visitor>
+typename ZigzagPersistence<BID,SD>::Death
+ZigzagPersistence<BID,SD>::
+remove(SimplexIndex s, const BirthID& birth, Visitor& visitor)
+{
+    Count(cZigzagRemove);
+
+    rLog(rlZigzagRemove,        "Entered ZigzagPersistence::remove(%d)", s->order);
+    AssertMsg(check_consistency(), "Must be consistent before removal");
+
+    if (s->z_row.empty())
+    {
+        AssertMsg(!(s->c_row.empty()),  "Birth after removal, row in C must be non-empty");
+
+        // Birth
+        //show_all();
+        rLog(rlZigzagRemove,        "Birth case in remove");
+
+        // Prepend DC[j] = ZB[j] to Z
+        rLog(rlZigzagRemove,        "Computing the column DC[j] = ZB[j] to prepend to Z");
+        BIndex j                    = visitor.select_j_in_remove(*this, s->c_row);
+        rLog(rlZigzagRemove,        "  j = %d", j->order);
+
+        ZColumn z;
+        std::for_each(j->b_column.begin(), j->b_column.end(), make_adder(&ZNode::z_column, z));
+
+        ZIndex first_z              = visitor.new_z_in_remove(*this);
+        first_z->birth              = birth;
+        std::for_each(z.begin(),           z.end(),           make_appender(&SimplexNode::z_row, first_z));
+        first_z->z_column.swap(z);
+        first_z->low                = b_list.end();
+
+        rLog(rlZigzagRemove,        "  Prepended %d [%s]", first_z->order, z.tostring(out).c_str());
+        //AssertMsg(check_consistency(),  "Must be consistent after prepending DC[j] = ZB[j] to Z");
+
+        // Prepend row of s in C to B
+        rLog(rlZigzagRemove,        "Prepending the row of s to B");
+        first_z->b_row = s->c_row;      // copying instead of swapping is inefficient,
+                                        // but it simplifies logic when subtracting chains later
+        std::for_each(first_z->b_row.begin(), first_z->b_row.end(), make_appender(&BNode::b_column, first_z));
+        //AssertMsg(check_consistency(),  "Must be consistent after prepending row of s to B");
+
+#if ZIGZAG_CONSISTENCY
+        {
+            ZColumn zz;
+            std::for_each(j->b_column.begin(), j->b_column.end(), make_adder(&ZNode::z_column, zz));
+            AssertMsg(zz.empty(),       "ZB[j] must be 0 after we prepended the row of s in C to B");
+        }
+#endif
+
+        typedef         std::not_equal_to<BIndex>       NotEqualBIndex;
+
+        // Subtract C[j] from every column of C that contains s
+        AssertMsg(s->c_row == first_z->b_row,   "s->c_row == first_z->b_row before subtracting C[j]");
+        rLog(rlZigzagRemove,        "Subtracting C[j]=[%s] from every column of C that contains s=%d with row [%s]",
+                                    j->c_column.tostring(out).c_str(),
+                                    s->order, s->c_row.tostring(out).c_str());
+        add_chains(boost::make_filter_iterator(std::bind2nd(NotEqualBIndex(), j), first_z->b_row.begin(), first_z->b_row.end()),
+                   boost::make_filter_iterator(std::bind2nd(NotEqualBIndex(), j), first_z->b_row.end(),   first_z->b_row.end()),
+                   j, &BNode::c_column, &SimplexNode::c_row);
+        add_chain(j, j, &BNode::c_column, &SimplexNode::c_row);
+        // TODO: that's how it was done before, now it can be removed
+        //       add_chains(first_z->b_row.rbegin(), first_z->b_row.rend(), j, &BNode::c_column, &SimplexNode::c_row);
+        //AssertMsg(check_consistency(s_list.end(), z_list.begin(), b_list.end()),  "Must be consistent after subtracting C[j] in remove::birth");
+
+        // Subtract B[j] from every other column of B that has l
+        ZIndex l                    = j->b_column.back();
+        BRow   l_row                = l->b_row;
+        rLog(rlZigzagRemove,    "Subtracting B[j], j is %d, l is %d, l_row: [%s]",
+                                j->order, l->order, l_row.tostring(out).c_str());
+        add_chains(boost::make_filter_iterator(std::bind2nd(NotEqualBIndex(), j), l_row.rbegin(), l_row.rend()),
+                   boost::make_filter_iterator(std::bind2nd(NotEqualBIndex(), j), l_row.rend(),   l_row.rend()),
+                   j, &BNode::b_column, &ZNode::b_row);
+        j->b_column.back()->low = b_list.end();     // redundant since l will be deleted (here for check_consistency only)
+        add_chain(j, j, &BNode::b_column, &ZNode::b_row);
+        // TODO: investigate why this works for ordinary zigzag, but fails for the image zigzag
+        //AssertMsg(check_consistency(s_list.end(), first_z, b_list.end()),  "Must be consistent after subtracting B[j] in remove::birth");
+
+
+        // Drop j, l, and s
+        //
+        // l->z_column is the only non-empty thing, but we drop it,
+        // the basis is preserved because we added first_z
+        l->z_column.back()->low     = z_list.end();
+        std::for_each(l->z_column.begin(), l->z_column.end(), make_remover(&SimplexNode::z_row, l));
+
+        //show_all();
+        rLog(rlZigzagRemove,        "l=%d has z_column: [%s]", l->order, l->z_column.tostring(out).c_str());
+
+        AssertMsg(l->b_row.empty(),     "b_row of l must be empty before erasing in remove::birth");
+        AssertMsg(s->z_row.empty(),     "z_row of s must be empty before erasing in remove::birth");
+        rLog(rlZigzagRemove,            "s->c_row: [%s]", s->c_row.tostring(out).c_str());
+        if (!s->c_row.empty())
+        {
+            rLog(rlZigzagRemove,        "s->c_row[0]: [%s]", s->c_row.front()->c_column.tostring(out).c_str());
+            rLog(rlZigzagRemove,        "   b_column: [%s]", s->c_row.front()->b_column.tostring(out).c_str());
+        }
+        AssertMsg(s->c_row.empty(),     "c_row of s must be empty before erasing in remove::birth");
+        visitor.erasing_z(*this, l);
+        b_list.erase(j);
+        z_list.erase(l);
+        s_list.erase(s);
+        AssertMsg(check_consistency(s_list.end(), first_z, b_list.end()),  "Must be consistent before reducing Z in remove::birth");
+
+        // Reduce Z
+        rLog(rlZigzagRemove,        "Reducing Z");
+        SimplexIndex ls = first_z->z_column.back();
+        while(ls->low != first_z)
+        {
+            if (ls->low == z_list.end())    { ls->low = first_z; break; }
+
+            // if ls->low precedes first_z, swap them
+            if (cmp(ls->low, first_z))      std::swap(ls->low, first_z);
+
+            add_chain(first_z, ls->low, &ZNode::b_row, &BNode::b_column);
+            add_chain(ls->low, first_z, &ZNode::z_column, &SimplexNode::z_row);
+            std::swap(ls->low, first_z);
+
+            ls = first_z->z_column.back();
+        }
+        AssertMsg(check_consistency(),  "Must be consistent at the end of birth case in remove");
+
+        return Death();
+    } else
+    {
+        // Death
+        rLog(rlZigzagRemove,        "Death case in remove");
+
+        ZIndex j                    = s->z_row.front();
+        CRow c_row                  = s->c_row;
+
+        rLog(rlZigzagRemove,        "j=%d, j->b_row=[%s]", j->order, j->b_row.tostring(out).c_str());
+        rLog(rlZigzagRemove,        "s=%d, s->c_row=[%s]", s->order, s->c_row.tostring(out).c_str());
+        rLog(rlZigzagRemove,        "s=%d, s->z_row=[%s]", s->order, s->z_row.tostring(out).c_str());
+
+        // Subtract Z[j] from every chain in C that contains s
+        // (it's Ok to go in the forward order since we are subtracting a column in Z from C)
+        add_chains(c_row.begin(), c_row.end(), j, &BNode::c_column, &SimplexNode::c_row, &ZNode::z_column);
+        AssertMsg(check_consistency(),  "Must be consistent after subtracting Z[j] from C");
+
+        // Change basis to remove s from Z
+        // Compute reducers --- columns that we will be adding to other columns
+        ZRow z_row                  = s->z_row;
+        typedef typename ZRow::reverse_iterator             ZRowReverseIterator;
+        typedef std::list<ZRowReverseIterator>              ReducersContainer;
+        ReducersContainer  reducers;                        // list of ZColumns that we will be adding to other columns
+        reducers.push_back(boost::prior(z_row.rend()));     // j is the first reducer
+        AssertMsg(*(reducers.back()) == j,  "The first element of reducers should be j");
+        SimplexIndex low            = j->z_column.back();
+        rLog(rlZigzagRemove,        "   Added reducer %d [%s] with low=%d",
+                                    j->order, j->z_column.tostring(out).c_str(),
+                                    low->order);
+        for (typename ZRow::iterator cur = z_row.begin(); cur != z_row.end(); ++cur)
+            if (cmp((*cur)->z_column.back(), low))
+            {
+                reducers.push_back(ZRowReverseIterator(boost::next(cur)));
+                low = (*(reducers.back()))->z_column.back();
+                rLog(rlZigzagRemove,        "   Added reducer %d [%s] with low=%d",
+                                            (*cur)->order, (*cur)->z_column.tostring(out).c_str(),
+                                            low->order);
+                rLog(rlZigzagRemove,        "   reducers.back(): %d [%s] with low=%d",
+                                            (*(reducers.back()))->order,
+                                            (*(reducers.back()))->z_column.tostring(out).c_str(),
+                                            (*(reducers.back()))->z_column.back()->order);
+            }
+        rLog(rlZigzagRemove,        " Reducers size: %d, s is %d",
+                                    reducers.size(), s->order);
+
+        //show_all();
+
+        // Add each reducer to the columns that follow them until the next reducer
+        // NB: processing reducers in the reverse order fixes a bug in the paper,
+        //     in step Remove.Death.1.4, where the matrix B is updated incorrectly.
+        //     I can't find a mention of this bug in my notes, but the fact
+        //     that it's fixed in the code suggests that I knew about it. (Or
+        //     most likely I didn't recognize that what the paper said is not
+        //     exactly what I meant.)
+        typename ReducersContainer::reverse_iterator    cur     = reducers.rbegin();
+        ZRowReverseIterator                             zcur    = z_row.rbegin();
+
+        while (cur != reducers.rend())
+        {
+            rLog(rlZigzagRemove,        " Cur reducer: %d [%s]", (**cur)->order,
+                                                                 (**cur)->z_column.tostring(out).c_str());
+            change_basis(zcur, *cur, **cur,
+                         &ZNode::z_column, &SimplexNode::z_row,
+                         &ZNode::b_row,    &BNode::b_column);
+            if (cur != reducers.rbegin())
+            {
+                AssertMsg((*zcur)->z_column.back() == (**cur)->z_column.back(),
+                          "The back of the z_columns must be the same.");
+                (*zcur)->z_column.back()->low = *zcur;
+            }
+            else
+                (**cur)->z_column.back()->low = z_list.end();
+
+            zcur = *cur++;
+            // This makes it inconsistent until the next iteration of this update loop
+        }
+
+        // Drop j and s
+        Death d                     = visitor.death(*this, j);
+
+        if (j->z_column.back()->low == j)
+            j->z_column.back()->low = z_list.end();
+        std::for_each(j->z_column.begin(), j->z_column.end(), make_remover(&SimplexNode::z_row, j));
+        rLog(rlZigzagRemove,            "j->b_row: [%s]", j->b_row.tostring(out).c_str());
+        if (!j->b_row.empty())
+        {
+            rLog(rlZigzagRemove,        "j->b_row[0]: [%s]", j->b_row.front()->b_column.tostring(out).c_str());
+            rLog(rlZigzagRemove,        "   c_column: [%s]", j->b_row.front()->c_column.tostring(out).c_str());
+        }
+        AssertMsg(j->b_row.empty(),     "b_row of j must be empty before erasing in remove(). Most likely you are trying to remove a simplex whose coface is still in the complex.");
+        AssertMsg(s->z_row.empty(),     "z_row of s must be empty before erasing in remove()");
+        AssertMsg(s->c_row.empty(),     "c_row of s must be empty before erasing in remove()");
+        visitor.erasing_z(*this, j);
+        z_list.erase(j);
+        s_list.erase(s);
+
+        //show_all();
+
+        AssertMsg(check_consistency(),  "Must be consistent when done in remove()");
+
+        return d;
+    }
+}
+
+template<class BID, class SD>
+void
+ZigzagPersistence<BID,SD>::
+show_all()
+{
+    std::cout << "s_list:" << std::endl;
+    for (SimplexIndex cur = s_list.begin(); cur != s_list.end(); ++cur)
+    {
+        std::cout << "  " << cur->order << ":" << std::endl;
+
+        std::cout << "    z_row: ";
+        for (typename ZRow::const_iterator zcur = cur->z_row.begin(); zcur != cur->z_row.end(); ++zcur)
+            std::cout << (*zcur)->order << " ";
+        std::cout << std::endl;
+
+        std::cout << "    c_row: ";
+        for (typename CRow::const_iterator ccur = cur->c_row.begin(); ccur != cur->c_row.end(); ++ccur)
+            std::cout << (*ccur)->order << " ";
+        std::cout << std::endl;
+
+        std::cout << "    low: ";
+        if (cur->low != z_list.end())
+            std::cout << cur->low->order;
+        else
+            std::cout << "none";
+        std::cout << std::endl;
+    }
+
+    std::cout << "z_list:" << std::endl;
+    for (ZIndex cur = z_list.begin(); cur != z_list.end(); ++cur)
+    {
+        std::cout << "  " << cur->order << ":" << std::endl;
+
+        std::cout << "    birth: " << cur->birth << std::endl;
+
+        std::cout << "    z_column: ";
+        for (typename ZColumn::const_iterator zcur = cur->z_column.begin(); zcur != cur->z_column.end(); ++zcur)
+            std::cout << (*zcur)->order << " ";
+        std::cout << std::endl;
+
+        std::cout << "    b_row: ";
+        for (typename BRow::const_iterator bcur = cur->b_row.begin(); bcur != cur->b_row.end(); ++bcur)
+            std::cout << (*bcur)->order << " ";
+        std::cout << std::endl;
+
+        std::cout << "    low: ";
+        if (cur->low != b_list.end())
+            std::cout << cur->low->order;
+        else
+            std::cout << "none";
+        std::cout << std::endl;
+    }
+
+    std::cout << "b_list:" << std::endl;
+    for (BIndex cur = b_list.begin(); cur != b_list.end(); ++cur)
+    {
+        std::cout << "  " << cur->order << ":" << std::endl;
+
+        std::cout << "    b_column: ";
+        for (typename BColumn::const_iterator bcur = cur->b_column.begin(); bcur != cur->b_column.end(); ++bcur)
+            std::cout << (*bcur)->order << " ";
+        std::cout << std::endl;
+
+        std::cout << "    c_column: ";
+        for (typename CColumn::const_iterator ccur = cur->c_column.begin(); ccur != cur->c_column.end(); ++ccur)
+            std::cout << (*ccur)->order << " ";
+        std::cout << std::endl;
+    }
+}
+
+template<class BID, class SD>
+bool
+ZigzagPersistence<BID,SD>::
+check_consistency(SimplexIndex, ZIndex, BIndex)
+{
+#ifdef ZIGZAG_CONSISTENCY
+    #warning "Checking consistency in ZigzagPersistence"
+
+    Count(cZigzagConsistency);
+    for (SimplexIndex cur = s_list.begin(); cur != s_list.end(); ++cur)
+    {
+        if (cur == s_skip) continue;
+        //rLog(rlZigzagCheckConsistency,      "SimplexIndex cur: %d", cur->order);
+        for (typename ZRow::const_iterator zcur = cur->z_row.begin(); zcur != cur->z_row.end(); ++zcur)
+            if (std::find((*zcur)->z_column.begin(), (*zcur)->z_column.end(), cur) == (*zcur)->z_column.end())
+            {
+                rError("In check_consistency(): SimplexNode %d not found in z_column of %d", cur->order, (*zcur)->order);
+                return false;
+            }
+        for (typename CRow::const_iterator ccur = cur->c_row.begin(); ccur != cur->c_row.end(); ++ccur)
+            if (std::find((*ccur)->c_column.begin(), (*ccur)->c_column.end(), cur) == (*ccur)->c_column.end())
+            {
+                rError("In check_consistency(): SimplexNode %d not found in c_column of %d", cur->order, (*ccur)->order);
+                return false;
+            }
+        if (cur->low != z_list.end())
+            AssertMsg(!(cur->low->z_column.empty()),        "z_column must not be empty");
+        if (cur->low != z_list.end() && cur->low->z_column.back() != cur)
+        {
+            rError("low of SimplexNode %d is incorrect", cur->order);
+            return false;
+        }
+    }
+
+    for (ZIndex cur = z_list.begin(); cur != z_list.end(); ++cur)
+    {
+        if (cur == z_skip) continue;
+
+        //rLog(rlZigzagCheckConsistency,      "ZIndex cur: %d", cur->order);
+        for (typename ZColumn::const_iterator scur = cur->z_column.begin(); scur != cur->z_column.end(); ++scur)
+            if (std::find((*scur)->z_row.begin(), (*scur)->z_row.end(), cur) == (*scur)->z_row.end())
+            {
+                rError("In check_consistency(): ZNode %d not found in z_row of %d", cur->order, (*scur)->order);
+                return false;
+            }
+        for (typename BRow::const_iterator bcur = cur->b_row.begin(); bcur != cur->b_row.end(); ++bcur)
+            if (std::find((*bcur)->b_column.begin(), (*bcur)->b_column.end(), cur) == (*bcur)->b_column.end())
+            {
+                rError("In check_consistency(): ZNode %d not found in b_column of %d", cur->order, (*bcur)->order);
+                return false;
+            }
+        if (cur->low != b_list.end() && cur->low->b_column.back() != cur)
+        {
+            rError("low of ZNode %d is incorrect", cur->order);
+            return false;
+        }
+        if (cur->z_column.back()->low != cur)
+        {
+            rError("The low of the back of the z_column must be set correctly");
+            rError("  %d [%s], its back %d with low=%d", cur->order,
+                                                         cur->z_column.tostring(out).c_str(),
+                                                         cur->z_column.back()->order,
+                                                         (cur->z_column.back()->low == z_list.end()) ? 0 : cur->z_column.back()->low->order);
+            return false;
+        }
+    }
+
+    for (BIndex cur = b_list.begin(); cur != b_list.end(); ++cur)
+    {
+        if (cur == b_skip) continue;
+
+        //rLog(rlZigzagCheckConsistency,      "BIndex cur: %d", cur->order);
+        for (typename BColumn::const_iterator zcur = cur->b_column.begin(); zcur != cur->b_column.end(); ++zcur)
+            if (std::find((*zcur)->b_row.begin(), (*zcur)->b_row.end(), cur) == (*zcur)->b_row.end())
+            {
+                rError("In check_consistency(): BNode %d not found in b_row of %d", cur->order, (*zcur)->order);
+                return false;
+            }
+        for (typename CColumn::const_iterator scur = cur->c_column.begin(); scur != cur->c_column.end(); ++scur)
+            if (std::find((*scur)->c_row.begin(), (*scur)->c_row.end(), cur) == (*scur)->c_row.end())
+            {
+                rError("In check_consistency(): BNode %d not found in c_row of %d", cur->order, (*scur)->order);
+                return false;
+            }
+        if (!(cur->b_column.empty() || cur->b_column.back()->low == cur))
+        {
+            rError("The low of the back of the b_column must be set correctly");
+            return false;
+        }
+
+        // ZB == DC
+        ZColumn zb, dc;
+        std::for_each(cur->b_column.begin(), cur->b_column.end(), make_adder(&ZNode::z_column, zb));
+        std::for_each(cur->c_column.begin(), cur->c_column.end(), make_adder(&SimplexNode::boundary, dc));
+        zb.add(dc, cmp);
+        if (!zb.empty())
+        {
+            rError("   b_column: [%s]",    cur->b_column.tostring(out).c_str());
+            rError("   c_column: [%s]",    cur->c_column.tostring(out).c_str());
+            rError("   zb - dc:  [%s]",    zb.tostring(out).c_str());
+            rError("ZB = DC");
+            return false;
+        }
+    }
+#endif
+
+    return true;
+}
+
+/* Private */
+
+// Class: Appender
+//
+// Functor that appends given element to the given member of whatever parameter it is invoked with
+template<class BID, class SD>
+template<class Member, class Element>
+struct ZigzagPersistence<BID,SD>::Appender
+{
+                Appender(Member mm, Element ee):
+                    m(mm), e(ee)                        {}
+
+    template<class T>
+    void        operator()(T& a)                        { ((*a).*m).append(e, cmp); }
+
+    Member          m;
+    Element         e;
+    OrderComparison cmp;
+};
+
+// Class: Remover
+//
+// Functor that removes given element from the given member of whatever parameter it is invoked with
+template<class BID, class SD>
+template<class Member, class Element>
+struct ZigzagPersistence<BID,SD>::Remover
+{
+                Remover(Member mm, Element ee):
+                    m(mm), e(ee)                        {}
+
+    template<class T>
+    void        operator()(T& a)                        { ((*a).*m).remove(e); }
+
+    Member  m;
+    Element e;
+};
+
+// Class: Adder
+//
+// Functor that adds the given member of whatever it is invoked with to the given chain
+template<class BID, class SD>
+template<class Member, class Chain>
+struct ZigzagPersistence<BID,SD>::Adder
+{
+                Adder(Member mm, Chain& cc):
+                    m(mm), c(cc)                        {}
+
+    template<class T>
+    void        operator()(T& a)                        { c.add((*a).*m, cmp); }
+
+    Member          m;
+    Chain&          c;
+    OrderComparison cmp;
+};
+
+
+// Function: add_chains()
+//
+// Special case of add_chains where all Indexes are the same, and
+// therefore PrimaryMemberFrom and PrimaryMemberTo are the same
+template<class BID, class SD>
+template<class Index, class IndexFrom, class PrimaryMember, class SecondaryMember>
+void
+ZigzagPersistence<BID,SD>::
+add_chains(Index bg, Index end, IndexFrom j, PrimaryMember pm, SecondaryMember sm)
+{
+    add_chains(bg, end, j, pm, sm, pm);
+}
+
+// Function: add_chains()
+//
+// Adds PrimaryMember pm of j to pm of every element in the range [bg,end)
+// Fixes SecondaryMembers by adding and removing the corresponding elements.
+// For example, if we add a column to a number of other columns, then PrimaryMember is that
+// column member, and SecondaryMember is the corresponding row member.
+template<class BID, class SD>
+template<class IndexTo, class IndexFrom, class PrimaryMemberTo, class SecondaryMemberTo, class PrimaryMemberFrom>
+void
+ZigzagPersistence<BID,SD>::
+add_chains(IndexTo bg, IndexTo end, IndexFrom j, PrimaryMemberTo pmt, SecondaryMemberTo smt, PrimaryMemberFrom pmf)
+{
+    for (IndexTo cur = bg; cur != end; ++cur)
+        add_chain(*cur, j, pmt, smt, pmf);
+}
+
+// Function: change_basis()
+//
+// Changes basis by adding PrimaryMember pm of j to pm of every element in range [bg, end).
+// In parallel it performs the reverse (complementary) update on the dual members, i.e.
+// column and row operations are performed in sync, so that the product of the two matrices doesn't change
+template<class BID, class SD>
+template<class IndexTo, class IndexFrom, class PrimaryMember, class SecondaryMember, class DualPrimaryMember, class DualSecondaryMember>
+void
+ZigzagPersistence<BID,SD>::
+change_basis(IndexTo bg, IndexTo end, IndexFrom j, PrimaryMember pm, SecondaryMember sm, DualPrimaryMember dpm, DualSecondaryMember dsm)
+{
+    for (IndexTo cur = bg; cur != end; ++cur)
+    {
+        add_chain(*cur, j,  pm,  sm,  pm);
+        add_chain(j, *cur, dpm, dsm, dpm);
+    }
+}
+
+template<class BID, class SD>
+template<class Index, class PrimaryMember, class SecondaryMember>
+void
+ZigzagPersistence<BID,SD>::
+add_chain(Index to, Index from, PrimaryMember pm, SecondaryMember sm)
+{
+    add_chain(to, from, pm, sm, pm);
+}
+
+// Function: add_chain()
+//
+// Adds PrimaryMemberFrom pmf of `from` to PrimaryMemberTo pmt of `to`.
+// Fixes SecondaryMemberTos. See add_chains().
+template<class BID, class SD>
+template<class IndexTo, class IndexFrom, class PrimaryMemberTo, class SecondaryMemberTo, class PrimaryMemberFrom>
+void
+ZigzagPersistence<BID,SD>::
+add_chain(IndexTo to, IndexFrom from, PrimaryMemberTo pmt, SecondaryMemberTo smt, PrimaryMemberFrom pmf)
+{
+    rLog(rlZigzagAddChain,  "Adding %d [%s] to %d [%s]",
+                            (*from).order,
+                            ((*from).*pmf).tostring(out).c_str(),
+                            (*to).order,
+                            ((*to).*pmt).tostring(out).c_str());
+
+    // Fix secondaries
+    std::for_each(make_intersection_iterator(((*from).*pmf).begin(),  ((*from).*pmf).end(),
+                                               ((*to).*pmt).begin(),    ((*to).*pmt).end(),
+                                             cmp),
+                  make_intersection_iterator(((*from).*pmf).end(),    ((*from).*pmf).end(),
+                                               ((*to).*pmt).end(),      ((*to).*pmt).end(),
+                                             cmp),
+                  make_remover(smt, to));
+    std::for_each(make_difference_iterator(((*from).*pmf).begin(),    ((*from).*pmf).end(),
+                                             ((*to).*pmt).begin(),      ((*to).*pmt).end(),
+                                           cmp),
+                  make_difference_iterator(((*from).*pmf).end(),      ((*from).*pmf).end(),
+                                             ((*to).*pmt).end(),        ((*to).*pmt).end(),
+                                           cmp),
+                  make_appender(smt, to));
+
+    // Add primaries
+    ((*to).*pmt).add((*from).*pmf, cmp);
+    rLog(rlZigzagAddChain,  "Got %s", ((*to).*pmt).tostring(out).c_str());
+}
+
+
+/* ZigzagVisitor */
+template<class BID, class SD>
+typename ZigzagPersistence<BID,SD>::SimplexIndex
+ZigzagPersistence<BID,SD>::ZigzagVisitor::
+new_simplex(ZigzagPersistence& zz)
+{
+    unsigned order      = zz.s_list.empty() ? 0 : boost::prior(zz.s_list.end())->order + 1;
+    zz.s_list.push_back(SimplexNode(order, zz.z_list.end()));
+    return boost::prior(zz.s_list.end());
+}
+
+template<class BID, class SD>
+typename ZigzagPersistence<BID,SD>::ZIndex
+ZigzagPersistence<BID,SD>::ZigzagVisitor::
+new_z_in_add(ZigzagPersistence& zz, const ZColumn&, const BRow&)
+{
+    int order                   = zz.z_list.empty() ? 0 : boost::prior(zz.z_list.end())->order + 1;
+    zz.z_list.push_back(ZNode(order, zz.b_list.end()));
+    return boost::prior(zz.z_list.end());
+}
+
+template<class BID, class SD>
+typename ZigzagPersistence<BID,SD>::BIndex
+ZigzagPersistence<BID,SD>::ZigzagVisitor::
+select_j_in_remove(ZigzagPersistence&, const CRow& c_row)
+{
+    return c_row.front();
+}
+
+template<class BID, class SD>
+typename ZigzagPersistence<BID,SD>::ZIndex
+ZigzagPersistence<BID,SD>::ZigzagVisitor::
+new_z_in_remove(ZigzagPersistence& zz)
+{
+    int order                   = zz.z_list.empty() ? 0 : zz.z_list.begin()->order - 1;
+    zz.z_list.push_front(ZNode(order, zz.b_list.end()));
+    return zz.z_list.begin();
+}
+
+template<class BID, class SD>
+typename ZigzagPersistence<BID,SD>::Death
+ZigzagPersistence<BID,SD>::ZigzagVisitor::
+death(ZigzagPersistence&, ZIndex dying_z)
+{
+    return Death(dying_z->birth);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/utilities/binaryheap.h	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,302 @@
+// Heap Plus implementation 1.01alpha
+// ChangeLog:
+//  2009.09.26  - Updated __down_heap, added _updatepos (Yanbin Lu)
+//  2009.08.10  - Added update_heap_pos functions so that we can adjust
+//                heap values outside of update_heap functions -- e.g., if
+//                we have external pointers into the heap entries -- then
+//                call update_heap on the position only, regardless of the value.
+//                (Danny Tarlow: dtarlow@cs.toronto.edu)
+//  2006.12.18  - Initially created (lihw)
+ 
+#ifndef HEAPPLUS_H_
+#define HEAPPLUS_H_
+ 
+#include <iterator>
+ 
+namespace std {
+  template<typename _RandomAccessIterator, typename _Distance, typename _Tp,
+	typename _Compare, typename _Updatepos>
+    void
+    __push_heap(_RandomAccessIterator __first, _Distance __holeIndex,
+				_Distance __topIndex, _Tp __value, _Compare __comp, _Updatepos __updatepos)
+    {
+      _Distance __parent = (__holeIndex - 1) / 2;
+      while (__holeIndex > __topIndex
+			 && __comp(*(__first + __parent), __value))
+		{
+		  *(__first + __holeIndex) = *(__first + __parent);
+		  __updatepos(*(__first + __holeIndex), __holeIndex); /* yanbin */
+		  __holeIndex = __parent;
+		  __parent = (__holeIndex - 1) / 2;
+		}
+      *(__first + __holeIndex) = __value;
+	  __updatepos(*(__first + __holeIndex), __holeIndex); /* yanbin */
+    }
+
+  template<typename _RandomAccessIterator, typename _Compare, typename _Updatepos>
+    inline void
+    push_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
+	      _Compare __comp, _Updatepos __updatepos)
+    {
+      typedef typename iterator_traits<_RandomAccessIterator>::value_type
+	  _ValueType;
+      typedef typename iterator_traits<_RandomAccessIterator>::difference_type
+	  _DistanceType;
+
+      // concept requirements
+      //__glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
+	  //  _RandomAccessIterator>)
+      //__glibcxx_requires_valid_range(__first, __last);
+      //__glibcxx_requires_heap_pred(__first, __last - 1, __comp);
+
+      std::__push_heap(__first, _DistanceType((__last - __first) - 1),
+		       _DistanceType(0), _ValueType(*(__last - 1)), __comp, __updatepos);
+    }
+
+  template<typename _RandomAccessIterator, typename _Distance,
+	typename _Tp, typename _Compare, typename _Updatepos>
+    void
+    __adjust_heap(_RandomAccessIterator __first, _Distance __holeIndex,
+				  _Distance __len, _Tp __value, _Compare __comp, _Updatepos __updatepos)
+  {
+	const _Distance __topIndex = __holeIndex;
+	_Distance __secondChild = 2 * __holeIndex + 2;
+	while (__secondChild < __len)
+	  {
+		if (__comp(*(__first + __secondChild),
+				   *(__first + (__secondChild - 1))))
+		  __secondChild--;
+		*(__first + __holeIndex) = *(__first + __secondChild);
+		__updatepos(*(__first + __holeIndex), __holeIndex); /* yanbin */
+		__holeIndex = __secondChild;
+		__secondChild = 2 * (__secondChild + 1);
+	  }
+	if (__secondChild == __len)
+	  {
+		*(__first + __holeIndex) = *(__first + (__secondChild - 1));
+		__updatepos(*(__first + __holeIndex), __holeIndex); /* yanbin */
+		__holeIndex = __secondChild - 1;
+	  }
+	std::__push_heap(__first, __holeIndex, __topIndex, __value, __comp, __updatepos);
+  }
+
+  template<typename _RandomAccessIterator, typename _Tp, typename _Compare, typename _Updatepos>
+    inline void
+    __pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
+	       _RandomAccessIterator __result, _Tp __value, _Compare __comp, _Updatepos __updatepos)
+    {
+      typedef typename iterator_traits<_RandomAccessIterator>::difference_type
+	_Distance;
+      *__result = *__first;
+      std::__adjust_heap(__first, _Distance(0), _Distance(__last - __first),
+			 __value, __comp, __updatepos);
+    }
+
+  template<typename _RandomAccessIterator, typename _Compare, typename _Updatepos>
+    inline void
+    pop_heap(_RandomAccessIterator __first,
+			 _RandomAccessIterator __last, _Compare __comp, _Updatepos __updatepos)
+    {
+      // concept requirements
+      //__glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
+	  //  _RandomAccessIterator>)
+      //__glibcxx_requires_valid_range(__first, __last);
+      //__glibcxx_requires_heap_pred(__first, __last, __comp);
+
+      typedef typename iterator_traits<_RandomAccessIterator>::value_type
+	_ValueType;
+      std::__pop_heap(__first, __last - 1, __last - 1,
+		      _ValueType(*(__last - 1)), __comp, __updatepos);
+    }
+
+  template<typename _RandomAccessIterator, typename _Compare, typename _Updatepos>
+    inline void
+    make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
+			  _Compare __comp, _Updatepos __updatepos)
+  {
+	typedef typename iterator_traits<_RandomAccessIterator>::value_type
+	  _ValueType;
+	typedef typename iterator_traits<_RandomAccessIterator>::difference_type
+	  _DistanceType;
+
+	// concept requirements
+	//__glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
+	//                            _RandomAccessIterator>)
+    //  __glibcxx_requires_valid_range(__first, __last);
+
+	if (__last - __first < 2)
+	  {
+		for (_DistanceType __len = 0; __len < __last - __first; __len ++)
+		  {
+			__updatepos(*(__first + __len), __len); /* yanbin */
+		  }
+
+		return;
+	  }
+	const _DistanceType __len = __last - __first;
+	_DistanceType __parent = (__len - 2) / 2;
+	while (true)
+	  {
+		std::__adjust_heap(__first, __parent, __len,
+						   _ValueType(*(__first + __parent)), __comp, __updatepos);
+		if (__parent == 0)
+		  {
+			for (_DistanceType __len = 0; __len < __last - __first; __len ++)
+			  {
+				__updatepos(*(__first + __len), __len); /* yanbin */
+			  }
+
+			return;
+		  }
+		__parent--;
+	  }
+
+  }
+
+
+  template<typename _RandomAccessIterator, typename _Distance, typename _Tp, typename _Compare, typename _Updatepos>
+inline void
+__up_heap(_RandomAccessIterator __first, _RandomAccessIterator __end, _RandomAccessIterator __pos,
+		  _Distance, _Tp __value,  _Compare __comp, _Updatepos __updatepos)
+{
+    _Distance __parent = (__pos - __first - 1) /  2;
+    _Distance __index = __pos - __first;
+    while (__index > 0 && __comp(*(__first + __parent), __value)) {
+        *(__first + __index) = *(__first + __parent);
+		__updatepos(*(__first + __index), __index); /* yanbin */
+
+        __index = __parent;
+        __parent = (__parent - 1) / 2;
+    }
+        
+    if (__pos != (__first + __index)) {
+        *(__first + __index) = __value;
+		__updatepos(*(__first + __index), __index); /* yanbin */
+	}
+}
+ 
+template<typename _RandomAccessIterator, typename _Distance, typename _Tp, typename _Compare, typename _Updatepos>
+inline void
+__down_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _RandomAccessIterator __pos,
+        _Distance, _Tp __value, _Compare __comp, _Updatepos __updatepos)
+{
+    _Distance __len = __last - __first;
+    _Distance __index = __pos - __first;
+    _Distance __left = __index * 2 + 1;
+    _Distance __right = __index * 2 + 2;
+    _Distance __largest;
+    while (__index < __len) 
+	  {
+		if (__right < __len)
+		  {
+			if (__comp(*(__first + __left), *(__first + __right)))
+			  {
+				__largest = __right;
+			  }
+			else
+			  {
+				__largest = __left;
+			  }
+		  }
+		else if (__left < __len)
+		  {
+			__largest = __left;
+		  }
+		else
+		  {
+			__largest = __index;
+		  }
+
+        if (__largest < __len && __comp(__value, *(__first + __largest))) 
+		  {
+            *(__first + __index) = *(__first + __largest);
+			__updatepos(*(__first + __index), __index); /* yanbin */
+            __index = __largest;
+            __left = __index * 2 + 1;
+            __right = __index * 2 + 2;
+		  } else
+		  break;
+	  }
+ 
+    if (__pos != (__first + __index)) {
+        *(__first + __index) = __value;
+		__updatepos(*(__first + __index), __index); /* yanbin */
+	}
+}
+ 
+template<typename _RandomAccessIterator, typename _Distance, typename _Tp,
+    typename _Compare, typename _Updatepos>
+inline void
+__update_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
+        _RandomAccessIterator __pos, _Distance, _Tp __value, _Compare __comp, _Updatepos __updatepos)
+{
+    *(__pos) = __value;
+     
+    _Distance __index = (__pos - __first);
+    _Distance __parent = (__index - 1) / 2;
+ 
+    if (__index > 0 && __comp(*(__first + __parent), __value))
+	  __up_heap(__first, __last, __pos, _Distance(), __value, __comp, __updatepos);
+    else
+	  __down_heap(__first, __last, __pos, _Distance(), __value, __comp, __updatepos);
+}
+ 
+template<typename _RandomAccessIterator, typename _Distance, typename _Compare, typename _Updatepos>
+inline void
+__update_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
+        _RandomAccessIterator __pos, _Distance, _Compare __comp, _Updatepos __updatepos)
+{
+    _Distance __index = (__pos - __first);
+    _Distance __parent = (__index - 1) / 2;
+    if (__index > 0 && __comp(*(__first + __parent), *(__pos)))
+      __up_heap(__first, __last, __pos, _Distance(), *(__pos), __comp, __updatepos);
+    else
+      __down_heap(__first, __last, __pos, _Distance(), *(__pos), __comp, __updatepos);
+}
+ 
+template<typename _RandomAccessIterator, typename _Tp, typename _Updatepos>
+inline void
+update_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
+        _RandomAccessIterator __pos, _Tp __value, _Updatepos __updatepos)
+{
+      typedef typename iterator_traits<_RandomAccessIterator>::value_type _ValueType;
+      typedef typename iterator_traits<_RandomAccessIterator>::difference_type _DistanceType;
+ 
+      __update_heap(__first, __last, __pos, _DistanceType(), __value, less<_ValueType>(), __updatepos);
+}
+ 
+template<typename _RandomAccessIterator, typename _Tp, typename _Compare, typename _Updatepos>
+inline void
+update_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
+        _RandomAccessIterator __pos, _Tp __value, _Compare __comp, _Updatepos __updatepos)
+{
+  __update_heap(__first, __last, __pos, __value, __comp, __updatepos);
+}
+ 
+ 
+ template<typename _RandomAccessIterator, typename _Updatepos>
+inline void
+update_heap_pos(_RandomAccessIterator __first, _RandomAccessIterator __last,
+  _RandomAccessIterator __pos, _Updatepos __updatepos) {
+      typedef typename iterator_traits<_RandomAccessIterator>::value_type _ValueType;
+      typedef typename iterator_traits<_RandomAccessIterator>::difference_type _DistanceType;
+ 
+      __update_heap(__first, __last, __pos, _DistanceType(), less<_ValueType>(), __updatepos);
+}
+ 
+ 
+template<typename _RandomAccessIterator, typename _Compare, typename _Updatepos>
+inline void
+update_heap_pos(_RandomAccessIterator __first, _RandomAccessIterator __last,
+  _RandomAccessIterator __pos, _Compare __comp, _Updatepos __updatepos) {
+      typedef typename iterator_traits<_RandomAccessIterator>::value_type _ValueType;
+      typedef typename iterator_traits<_RandomAccessIterator>::difference_type _DistanceType;
+
+      __update_heap(__first, __last, __pos, _DistanceType(), __comp, __updatepos);
+}
+ 
+ 
+ 
+}; // namespace std
+ 
+#endif // !HEAPPLUS_H_
--- a/include/utilities/consistencylist.h	Fri Aug 24 16:58:25 2007 -0400
+++ b/include/utilities/consistencylist.h	Tue Jun 27 09:37:05 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Author: Dmitriy Morozov 
+ * Author: Dmitriy Morozov
  * Department of Computer Science, Duke University, 2006
  */
 
@@ -31,7 +31,7 @@
 class ConsistencyList: public OrderList<ConsistencyListNode<T> >
 {
 	public:
-		class 			OrderComparison;				
+		class 			OrderComparison;
 		class 			LessThanComparison;
 		class 			GreaterThanComparison;
 		class 			ConsistencyComparison;
@@ -43,20 +43,20 @@
 		typedef			GreaterThanComparison						GreaterThanComparison;
 		typedef			ConsistencyComparison						ConsistencyComparison;
 		/// @}
-	
+
 		typedef			ConsistencyListNode<T>						NodeType;
 		typedef			ConsistencyList<T>							Self;
 		typedef			OrderList<NodeType >						Parent;
-		
+
 		typedef			T											value_type;
 		typedef			T&											reference;
 		typedef			const T&									const_reference;
 		typedef			ConsistencyListIterator<T>					iterator;
 		typedef			const_ConsistencyListIterator<T>			const_iterator;
-	
+
 						ConsistencyList(): sz(0)					{}
 						~ConsistencyList() 							{ clear(); }
-	
+
 		/// \name Order operations
 		void			swap(iterator i, iterator j);				///< Exchanges the order of simplices pointed to by i and j
 		template<class BinaryPredicate>
@@ -69,7 +69,7 @@
 		iterator		insert(iterator predecessor, const_reference x);	///< Inserts x immediately after predecessor (has to be a valid iterator)
 		void			erase(iterator x)							{ Parent::erase(x.get_base()); --sz; }
 
-		void			clear()										{ return Parent::clear(); }	
+		void			clear()										{ return Parent::clear(); }
 		bool			empty() const								{ return Parent::empty(); }
 		SizeType		size()	const								{ return sz; }
 		iterator		begin()										{ return iterator(Parent::begin()); }
@@ -79,11 +79,11 @@
 		reference		back()										{ return Parent::back(); }
 		const_reference	back() const								{ return Parent::back(); }
 		void			pop_back()									{ return Parent::pop_back(); }
-		                                                			
+
 		iterator		last()										{ return iterator(boost::prior(end())); }
 		const_iterator	last() const								{ return const_iterator(boost::prior(end())); }
 		/// @}
-	
+
 	private:
 		unsigned int	sz;
 };
@@ -93,31 +93,31 @@
 class ConsistencyList<T>::OrderComparison
 {
 	public:
-		typedef			typename ConsistencyList<T>::const_iterator		ComparableType;				
+		typedef			typename ConsistencyList<T>::const_iterator		ComparableType;
 
-		int 			compare(ComparableType a, ComparableType b) const;				/// (-1,0,1) = a (precedes, ==, succeeds) b 
+		int 			compare(ComparableType a, ComparableType b) const;				/// (-1,0,1) = a (precedes, ==, succeeds) b
 };
 
 /// Determines if the first element is less than the second one
 template<class T>
-class ConsistencyList<T>::LessThanComparison: public OrderComparison 
+class ConsistencyList<T>::LessThanComparison: public OrderComparison
 {
 	public:
 		typedef			OrderComparison								Parent;
-		typedef			typename Parent::ComparableType				ComparableType;				
-		
-		int 			compare(ComparableType a, ComparableType b) const;	
+		typedef			typename Parent::ComparableType				ComparableType;
+
+		int 			compare(ComparableType a, ComparableType b) const;
 		bool 			operator()(ComparableType a, ComparableType b) const;
 };
 
 /// Determines if the first element is greater than the second one
 template<class T>
-class ConsistencyList<T>::GreaterThanComparison: public OrderComparison 
+class ConsistencyList<T>::GreaterThanComparison: public OrderComparison
 {
 	public:
 		typedef			OrderComparison								Parent;
-		typedef			typename Parent::ComparableType				ComparableType;				
-		
+		typedef			typename Parent::ComparableType				ComparableType;
+
 		int 			compare(ComparableType a, ComparableType b) const;
 		bool 			operator()(ComparableType a, ComparableType b) const;
 };
@@ -127,10 +127,10 @@
 class ConsistencyList<T>::ConsistencyComparison
 {
 	public:
-		typedef			typename ConsistencyList<T>::const_iterator		ComparableType;				
-		
-		int 			compare(ComparableType a, ComparableType b) const;				///< (-1,0,1) = a (precedes, ==, succeeds) b 
-		bool 			operator()(ComparableType a, ComparableType b) const;		
+		typedef			typename ConsistencyList<T>::const_iterator		ComparableType;
+
+		int 			compare(ComparableType a, ComparableType b) const;				///< (-1,0,1) = a (precedes, ==, succeeds) b
+		bool 			operator()(ComparableType a, ComparableType b) const;
 };
 
 /// Structure storing auxilliary information requred for each node of ConsistencyList
@@ -140,11 +140,11 @@
 	ConsistencyListNode(const T& d, unsigned int c):
 		data(d), consistency(c)
 	{}
-	
+
 	T 				data;
 	OrderType		consistency;
 
-	std::ostream& 		operator<<(std::ostream& out) const					{ return out << data << ": " << consistency; }
+	std::ostream& 		operator<<(std::ostream& out) const					{ return out << consistency << ": " << data; }
 };
 
 template<class T>
@@ -157,7 +157,7 @@
 {
 	private:
 		struct			enabler										{};
-		
+
 	public:
 		typedef			typename ConsistencyList<T>::Parent			ConsistencyListParent;
 		typedef 		boost::iterator_adaptor<ConsistencyListIterator<T>,
@@ -168,10 +168,10 @@
 
 						ConsistencyListIterator()					{}
 						ConsistencyListIterator(const typename ConsistencyListParent::iterator& iter):
-    						ConsistencyListIterator::iterator_adaptor_(iter)	
+    						ConsistencyListIterator::iterator_adaptor_(iter)
 						{}
 						ConsistencyListIterator(const ConsistencyListIterator<T>& other):
-							ConsistencyListIterator::iterator_adaptor_(other.base())			
+							ConsistencyListIterator::iterator_adaptor_(other.base())
 						{}
 
 	private:
@@ -189,7 +189,7 @@
 {
 	private:
 		struct			enabler										{};
-		
+
 	public:
 		typedef			typename ConsistencyList<T>::Parent				ConsistencyListParent;
 		typedef 		boost::iterator_adaptor<const_ConsistencyListIterator<T>,
@@ -200,13 +200,13 @@
 
 						const_ConsistencyListIterator()					{}
 						const_ConsistencyListIterator(const typename ConsistencyListParent::const_iterator& iter):
-    						const_ConsistencyListIterator::iterator_adaptor_(iter)	
+    						const_ConsistencyListIterator::iterator_adaptor_(iter)
 						{}
 						const_ConsistencyListIterator(const const_ConsistencyListIterator<T>& other):
-							const_ConsistencyListIterator::iterator_adaptor_(other.base())			
+							const_ConsistencyListIterator::iterator_adaptor_(other.base())
 						{}
 						const_ConsistencyListIterator(const ConsistencyListIterator<T>& other):
-							const_ConsistencyListIterator::iterator_adaptor_(other.base())			
+							const_ConsistencyListIterator::iterator_adaptor_(other.base())
 						{}
 
 	private:
@@ -216,7 +216,6 @@
 						get_base()									{ return Parent::base_reference(); }
 
 		friend class 	ConsistencyList<T>::OrderComparison;
-		friend class 	ConsistencyList<T>::ConsistencyComparison;
 };
 
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/utilities/containers.h	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,228 @@
+#ifndef __CONTAINERS_H__
+#define __CONTAINERS_H__
+
+#include "circular_list.h"
+
+#if DEBUG_CONTAINERS
+    #include <debug/vector>
+    #include <debug/deque>
+    using std::__debug::vector;
+    using std::__debug::deque;
+#else
+    #include <vector>
+    #include <deque>
+    using std::vector;
+    using std::deque;
+#endif
+
+// TODO: write documentation
+
+template<class Container_, class Comparison_ = std::less<typename Container_::value_type> >
+struct ContainerTraits
+{
+    typedef     Container_                                                                  Container;
+    typedef     typename Container::value_type                                              Item;
+    typedef     typename Container::const_reference                                         const_reference;
+    typedef     Comparison_                                                                 Comparison;
+
+    static void reserve(Container& c, size_t sz)                                            {}
+    static void sort(Container& c, const Comparison& cmp = Comparison())                    { c.sort(cmp); }
+    static void push_front(Container& c, const_reference x)                                 { c.push_front(x); }
+};
+
+/**
+ * Class: SizeStorage
+ *
+ * This class expresses how size should be stored for various containers to be able 
+ * to deduce it in constant time. By default it is stored explicitly, so that if the 
+ * Container is std::list everything works. However, specialization is available for 
+ * std::vector which uses its builtin size() function.
+ */
+template<class Container_>
+class SizeStorage
+{
+    public:
+        typedef         Container_                                                          Container;
+        typedef         SizeStorage<Container>                                              Self;
+
+                        SizeStorage(size_t size = 0): size_(size)                           {}
+
+        Self&           operator+=(size_t inc)                                              { size_ += inc; return *this; }
+        Self&           operator-=(size_t dec)                                              { size_ -= dec; return *this; }
+        Self&           operator++()                                                        { ++size_; return *this; }
+        Self            operator++(int)                                                     { Self tmp = *this; size_++; return tmp; }
+        Self&           operator--()                                                        { --size_; return *this; }
+        Self            operator--(int)                                                     { Self tmp = *this; size_--; return tmp; }
+        size_t          size(const Container& c) const                                      { return size_; }
+        void            swap(SizeStorage& other)                                            { std::swap(size_, other.size_); }
+
+        void            clear()                                                             { size_ = 0; }
+
+    private:
+        size_t          size_;
+};
+
+/**
+ * Class: CountingBackInserter<C>
+ *
+ * Derives from std::back_insert_iterator<C> and SizeStorage<C>, 
+ * and keeps track of the number of inserted elements.
+ */
+template<class C>
+struct CountingBackInserter: public std::back_insert_iterator<C>, 
+                             public SizeStorage<C>
+{
+    typedef                     CountingBackInserter                            Self;
+    typedef                     std::back_insert_iterator<C>                    ParentIterator;
+    typedef                     SizeStorage<C>                                  ParentSize;
+
+                                CountingBackInserter(C& c):
+                                    ParentIterator(c)                           {}
+
+    Self&                       operator++()                                    { ParentSize::operator++(); ParentIterator::operator++(); return *this; }
+    Self                        operator++(int i)                               { Self tmp = *this; ParentSize::operator++(i); ParentIterator::operator++(i); return tmp; }
+};
+
+/**
+ * Class: PushBackFunctor<Container>
+ *
+ * Performs the same task as std::back_insert_iterator<Container>, but as a functor.
+ */
+template<class Container_>
+class PushBackFunctor
+{
+    public:
+        typedef                 Container_                                      Container;
+        typedef                 typename Container::value_type                  value_type;
+
+                                PushBackFunctor(Container& container):
+                                    container_(container)                       {}
+
+        void                    operator()(const value_type& v) const           { container_.push_back(v); }
+
+    private:
+        Container&              container_;
+};
+
+template<class Container>
+PushBackFunctor<Container>
+make_push_back_functor(Container& container)                                    { return PushBackFunctor<Container>(container); }
+
+/**
+ * Class: InsertFunctor<Container>
+ *
+ * Performs insertions of its arguments into the given container.
+ */
+template<class Container_>
+class InsertFunctor
+{
+    public:
+        typedef                 Container_                                      Container;
+        typedef                 typename Container::value_type                  value_type;
+
+                                InsertFunctor(Container& container):
+                                    container_(container)                       {}
+
+        void                    operator()(const value_type& v) const           { container_.insert(v); }
+
+    private:
+        Container&              container_;
+};
+
+template<class Container>
+InsertFunctor<Container>
+make_insert_functor(Container& container)                                       { return InsertFunctor<Container>(container); }
+
+/* Specializations */
+
+template<class T, class Comparison_>
+struct ContainerTraits<vector<T>, Comparison_>
+{
+    typedef     T                                                                           Item;
+    typedef     vector<T>                                                                   Container;
+    typedef     typename Container::const_reference                                         const_reference;
+    typedef     Comparison_                                                                 Comparison;
+
+    static void reserve(Container& c, size_t sz)                                            { c.reserve(sz); }
+    static void sort(Container& c, const Comparison& cmp = Comparison())                    { std::sort(c.begin(), c.end(), cmp); }
+    static void push_front(Container& c, const_reference x)                                 { c.insert(c.begin(), x); }
+};
+
+template<class T, class Comparison_>
+struct ContainerTraits<deque<T>, Comparison_>
+{
+    typedef     T                                                                           Item;
+    typedef     deque<T>                                                                    Container;
+    typedef     typename Container::const_reference                                         const_reference;
+    typedef     Comparison_                                                                 Comparison;
+
+    static void reserve(Container& c, size_t sz)                                            { }
+    static void sort(Container& c, const Comparison& cmp = Comparison())                    { std::sort(c.begin(), c.end(), cmp); }
+    static void push_front(Container& c, const_reference x)                                 { c.push_front(x); }
+};
+
+template<class T, class Comparison_>
+struct ContainerTraits<List<T>, Comparison_>
+{
+    typedef     T                                                                           Item;
+    typedef     List<T>                                                                     Container;
+    typedef     typename Container::const_reference                                         const_reference;
+    typedef     Comparison_                                                                 Comparison;
+
+    static void reserve(Container& c, size_t sz)                                            { }
+    static void sort(Container& c, const Comparison& cmp = Comparison())                    
+    { 
+        vector<Item> tmp(c.begin(), c.end());
+        std::sort(tmp.begin(), tmp.end(), cmp);
+        std::copy(tmp.begin(), tmp.end(), c.begin());
+    }
+    static void push_front(Container& c, const_reference x)                                 { c.push_front(x); }
+};
+
+// TODO: specialize for List (singly-linked list)
+
+template<class T>
+class SizeStorage<vector<T> >
+{
+    public:
+        typedef         vector<T>                                                           Container;
+        typedef         SizeStorage<Container>                                              Self;
+
+                        SizeStorage()                                                       {}
+                        SizeStorage(size_t)                                                 {}
+
+        Self&           operator+=(size_t)                                                  { return *this; }
+        Self&           operator-=(size_t)                                                  { return *this; }
+        Self&           operator++()                                                        { return *this; }
+        Self            operator++(int)                                                     { return *this; }
+        Self&           operator--()                                                        { return *this; }
+        Self            operator--(int)                                                     { return *this; }
+        size_t          size(const Container& c) const                                      { return c.size(); }
+        void            swap(SizeStorage&)                                                  {}
+
+        void            clear()                                                             {}
+};
+
+template<class T>
+class SizeStorage<deque<T> >
+{
+    public:
+        typedef         deque<T>                                                            Container;
+        typedef         SizeStorage<Container>                                              Self;
+
+                        SizeStorage()                                                       {}
+                        SizeStorage(size_t)                                                 {}
+
+        Self&           operator+=(size_t)                                                  { return *this; }
+        Self&           operator-=(size_t)                                                  { return *this; }
+        Self&           operator++()                                                        { return *this; }
+        Self            operator++(int)                                                     { return *this; }
+        Self&           operator--()                                                        { return *this; }
+        Self            operator--(int)                                                     { return *this; }
+        size_t          size(const Container& c) const                                      { return c.size(); }
+        void            swap(SizeStorage&)                                                  {}
+
+        void            clear()                                                             {}
+};
+
+#endif // __CONTAINERS_H__
--- a/include/utilities/counter.h	Fri Aug 24 16:58:25 2007 -0400
+++ b/include/utilities/counter.h	Tue Jun 27 09:37:05 2017 -0700
@@ -1,68 +1,85 @@
 /*
  * Author: Dmitriy Morozov
- * Department of Computer Science, Duke University, 2005 -- 2006
+ * Department of Computer Science, Duke University, 2005 -- 2007
  */
 
 #ifndef __COUNTER_H__
 #define __COUNTER_H__
 
-/* This should be integrated with the logging facilities. Written in the same framework. */
+
+#ifndef COUNTERS
+    #define     GetCounter(path)        0
+    #define     Count(x)
+    #define     CountNum(x,y)
+    #define     CountBy(x,y)
+    #define     CountNumBy(x,y,z)
+    #define     SetFrequency(x, freq)
+    #define     SetTrigger(x, y)
+    #define     Print(x)
+#else // COUNTERS
+    #define     GetCounter(path)            get_counter(path)
+    #define     Count(x)                    do { x->count++; if ((x->count % x->frequency == 0)) x->trigger->print(); } while (0)
+    #define     CountNum(x,y)               do { x->subcount[y]++; } while (0)
+    #define     CountBy(x,y)                do { x->count += y; } while (0)
+    #define     CountNumBy(x,y,z)           do { x->subcount[y] += z; } while (0)
+    #define     SetFrequency(x, freq)       do { x->frequency = freq; } while (0)
+    #define     SetTrigger(x, y)            do { x->trigger = y; } while(0)
+    #define     Print(x)                    do { x->trigger->print(); } while(0)
+
 
 #include <map>
 #include <string>
 #include <iostream>
+#include <limits>
+#include <unistd.h>
 
-#ifndef COUNTERS
-#define Count(x)
-#define CountNum(x,y)
-#else // COUNTERS
-#define Count(x) counters.inc(x)
-#define CountNum(x,y) counters.inc(x,y)
-#endif
-
-typedef 		unsigned long 		CounterType;
-typedef			std::string			KeyType;
-
-class CounterFactory
+class Counter
 {
-	private:
-		typedef				std::map<int, CounterType> 			CountersMap;
-		typedef				std::map<KeyType, CountersMap>		KeyMap;
-		KeyMap				ctrs;
-		
-	public:
-		~CounterFactory()
-		{
-#ifdef COUNTERS
-			std::cout << "Counters:" << std::endl;
-			for (KeyMap::const_iterator cur = ctrs.begin(); cur != ctrs.end(); ++cur)
-			{
-				std::cout << cur->first << ": ";
-				if (cur->second.size() == 1)
-				{
-					std::cout << cur->second.begin()->second << std::endl;
-					continue;
-				}
-				std::cout << std::endl;
-				for (CountersMap::const_iterator ccur = cur->second.begin();
-														  ccur != cur->second.end();
-														  ++ccur)
-					std::cout << "  " << ccur->first << ": " << ccur->second << std::endl;
-			}
+    public:
+        typedef                 unsigned long                           CounterType;
+        typedef                 std::map<std::string, Counter*>         SubCounterMap;
+        typedef                 std::map<int, CounterType>              SubCountMap;
+
+    public:
+        CounterType             count;
+        CounterType             frequency;
+        SubCountMap             subcount;
+        Counter*                trigger;
+
+    public:
+                                Counter(const std::string& full_name = "",
+                                        CounterType freq = std::numeric_limits<CounterType>::max());
+                                ~Counter();
+
+        Counter*                get_child(const std::string& path, std::string::size_type pos);
+        void                    print();
+
+    private:    
+        SubCounterMap           subcounters_;
+        std::string             full_name_;
+        
+        static const char*      start_color;
+        static const char*      finish_color;
+        static const char       green_color[];
+        static const char       normal_color[];
+        static const char       empty_string[];
+};
+const char Counter::green_color[]       = "\033[32m";
+const char Counter::normal_color[]      = "\033[0m";
+const char Counter::empty_string[]      = "";
+const char* Counter::start_color        = 0;
+const char* Counter::finish_color       = 0;
+
+static      Counter             rootCounter;
+
+Counter*    get_counter(const char* path)
+{
+    return rootCounter.get_child(path, 0);
+}
+
+#include "counter.hpp"
+
 #endif // COUNTERS
-		}
 
-		void inc(const KeyType& key, int num = 0)
-		{
-			ctrs[key][num]++;
-		}
-
-		CounterType lookup(const KeyType& key, int num = 0) const
-		{
-			return const_cast<KeyMap&>(ctrs)[key][num];
-		}
-};
-
-static CounterFactory counters;
 
 #endif // __COUNTER_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/utilities/counter.hpp	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,69 @@
+#include <ctime>
+#include <cstdio>
+
+Counter::
+Counter(const std::string& full_name,
+		CounterType freq):
+		count(0), frequency(freq), trigger(this), full_name_(full_name)
+{ 
+	if (isatty(STDOUT_FILENO)) 
+	{
+		start_color = green_color; 
+		finish_color = normal_color;
+	} 
+	else
+	{	start_color = finish_color = empty_string;	}
+}
+
+
+Counter*
+Counter::
+get_child(const std::string& path, std::string::size_type pos)
+{
+	if (pos >= path.size())
+		return this;
+
+	std::string::size_type slash_pos = path.find('/', pos);
+	if (slash_pos == std::string::npos)
+		slash_pos = path.size();
+
+	std::string child_name = path.substr(pos, slash_pos - pos);
+	SubCounterMap::iterator child = subcounters_.find(child_name);
+
+	if (child != subcounters_.end())
+		return child->second->get_child(path, slash_pos + 1);
+	else	
+		return (subcounters_[child_name] = new Counter(path.substr(0, slash_pos)))->get_child(path, slash_pos + 1);
+}
+
+Counter::
+~Counter()
+{ 
+	if (full_name_ == "" && (!subcounters_.empty() || count))
+		print(); 
+
+	for (SubCounterMap::iterator cur = subcounters_.begin(); cur != subcounters_.end(); ++cur)
+		delete cur->second;
+}
+
+inline
+void
+Counter::
+print()
+{
+	time_t rawtime; time(&rawtime);
+	struct tm* timeinfo = localtime(&rawtime);
+
+	printf("%s(%02i:%02i:%02i)%s ",
+		    start_color,	
+			timeinfo->tm_hour,
+			timeinfo->tm_min,
+			timeinfo->tm_sec,
+			finish_color);
+	std::cout << "Counter [" << full_name_ << "]: " << count << std::endl;
+	for (SubCountMap::const_iterator cur = subcount.begin(); cur != subcount.end(); ++cur)
+		std::cout << "    " << cur->first << ": " << cur->second << std::endl;
+	for (SubCounterMap::iterator cur = subcounters_.begin(); cur != subcounters_.end(); ++cur)
+		cur->second->print();
+}	
+
--- a/include/utilities/debug.h	Fri Aug 24 16:58:25 2007 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,90 +0,0 @@
-#ifndef DEBUG_H
-#define DEBUG_H
-
-#ifndef CWDEBUG
-
-#include <iostream>     // std::cerr
-#include <cstdlib>      // std::exit, EXIT_FAILURE
-#include <cassert>
-
-#define AllocTag1(p)
-#define AllocTag2(p, desc)
-#define AllocTag_dynamic_description(p, data)
-#define AllocTag(p, data)
-#define Debug(STATEMENT...)
-#define Dout(cntrl, data)
-#define DoutFatal(cntrl, data) LibcwDoutFatal(, , cntrl, data)
-#define ForAllDebugChannels(STATEMENT...)
-#define ForAllDebugObjects(STATEMENT...)
-#define LibcwDebug(dc_namespace, STATEMENT...)
-#define LibcwDout(dc_namespace, d, cntrl, data)
-#define LibcwDoutFatal(dc_namespace, d, cntrl, data) do { ::std::cerr << data << ::std::endl; ::std::exit(EXIT_FAILURE); } while(1)
-#define LibcwdForAllDebugChannels(dc_namespace, STATEMENT...)
-#define LibcwdForAllDebugObjects(dc_namespace, STATEMENT...)
-#define NEW(x) new x
-#define CWDEBUG_ALLOC 0
-#define CWDEBUG_MAGIC 0
-#define CWDEBUG_LOCATION 0
-#define CWDEBUG_LIBBFD 0
-#define CWDEBUG_DEBUG 0
-#define CWDEBUG_DEBUGOUTPUT 0
-#define CWDEBUG_DEBUGM 0
-#define CWDEBUG_DEBUGT 0
-#define CWDEBUG_MARKER 0
-#define AssertMsg(TEST,MSG)
-//#define AssertMsg(TEST,STRM,MSG)
-
-
-#else // CWDEBUG
-
-// This must be defined before <libcwd/debug.h> is included and must be the
-// name of the namespace containing your `dc' (Debug Channels) namespace
-// (see below).  You can use any namespace(s) you like, except existing
-// namespaces (like ::, ::std and ::libcwd).
-#define DEBUGCHANNELS ::dionysus::debug::channels
-#include <libcwd/debug.h>
-
-namespace dionysus
-{
-	namespace debug 
-	{
-		void init(void);		// Initialize debugging code from main().
-		void init_thread(void);	// Initialize debugging code from new threads.
-
-		namespace channels 	// This is the DEBUGCHANNELS namespace, see above.
-		{
-			namespace dc 		// 'dc' is defined inside DEBUGCHANNELS.
-			{
-				using namespace libcwd::channels::dc;
-				using libcwd::channel_ct;
-
-				// Add the declaration of new debug channels here
-				// and add their definition in a custom debug.cc file.
-				extern channel_ct filtration;
-				extern channel_ct transpositions;
-				extern channel_ct vineyard;
-				extern channel_ct cycle;
-				extern channel_ct lsfiltration;
-				extern channel_ct orderlist;
-			} // namespace dc
-		} // namespace DEBUGCHANNELS
-	}
-}
-
-
-#define AssertMsg(TEST,MSG)                                           \
-				 ( (TEST) ? (void)0                                   \
-						  : (std::cerr << __FILE__ ":" << __LINE__    \
-								  << ": Assertion failed " #TEST      \
-								  << " - " << MSG << std::endl,abort()))
-/*
-#define AssertMsg(TEST,STRM,MSG)                                      \
-				 ( (TEST) ? (void)0                                   \
-						  : (DoutFatal(STRM, __FILE__ "(" << __LINE__ \
-								  << "): Assertion failed " #TEST     \
-								  << MSG << std::endl)))
-*/
-								  
-#endif // CWDEBUG
-
-#endif // DEBUG_H
--- a/include/utilities/eventqueue.h	Fri Aug 24 16:58:25 2007 -0400
+++ b/include/utilities/eventqueue.h	Tue Jun 27 09:37:05 2017 -0700
@@ -2,60 +2,223 @@
 #define __EVENTQUEUE_H__
 
 #include <list>
+#include <vector>
 #include <functional>
+
 #include <boost/utility.hpp>
+#include <boost/iterator/iterator_adaptor.hpp>
+namespace b = boost;
+
+
+#include <utilities/log.h>
+#ifdef LOGGING
+static rlog::RLogChannel* rlEventQueue =             DEF_CHANNEL("utilities/eventqueue", rlog::Log_Debug);
+#endif // LOGGING
+
+#include <utilities/binaryheap.h>
 
 #include <iostream>
-#include <cassert>					// TODO: switch to internal debugging system
 #include <string>
-
-// TODO: change inefficient list-based implementation to something heap-based
-// Need a queue that supports deleting arbitrary items (given by iterator), 
-// and maintaining correctness of iterators when different operations (notably 
-// remove and update are performed)
+#include <algorithm>
 
 template<class Event_, class EventComparison_>
 class EventQueue
 {
+    public:
+        typedef                 Event_                                          Event;
+        typedef                 EventComparison_                                EventComparison;
 
-	public:
-		typedef					Event_											Event;
-		typedef					EventComparison_								EventComparison;
+        struct                  HeapNode;
+        struct                  CompareNodes;
+        struct                  MarkedCompareNodes;
+        struct                  UpdateNode;
+        class                   iterator;
+        class                   const_iterator;
+
+        typedef                 std::list<HeapNode>                             QueueRepresentation;
+        typedef                 std::vector<iterator>                           EventListHeap;
+
+                                EventQueue()                {}
+
+        const_iterator          top() const                 { AssertMsg(!empty(), "Queue must not be empty"); return heap_.front(); }
+        iterator                top()                       { AssertMsg(!empty(), "Queue must not be empty"); return heap_.front(); }
+        iterator                push(Event e);
+        void                    pop();
+        void                    remove(iterator i);
+        void                    replace(iterator i, Event e);
+        void                    promoted(iterator i);
+        void                    demoted(iterator i);
+
+        iterator                begin()                     { return queue_.begin(); }
+        const_iterator          begin() const               { return queue_.begin(); }
+        iterator                end()                       { return queue_.end(); }
+        const_iterator          end() const                 { return queue_.end(); }
+        bool                    empty() const               { return queue_.empty(); }
+        size_t                  size() const                { return heap_.size(); }
+
+        std::ostream&           print(std::ostream& out, const std::string& prefix) const;
+
+    private:
+        QueueRepresentation     queue_;
+        EventListHeap           heap_;
+};
+
+template<class Event_, class EventComparison_>
+struct EventQueue<Event_, EventComparison_>::HeapNode
+{
+                        HeapNode(const Event& e): e_(e)     {}
+
+    size_t              heap_position_;
+    Event               e_;
+};
+
+template<class Event_, class EventComparison_>
+class EventQueue<Event_, EventComparison_>::iterator:
+    public boost::iterator_adaptor<iterator,
+                                   typename QueueRepresentation::iterator,
+                                   Event>
+{
+    public:
+        iterator():
+            iterator::iterator_adaptor_(0)                              {}
 
-		typedef					std::list<Event>								QueueRepresentation;
-		typedef					typename QueueRepresentation::iterator			iterator;
-		typedef					typename QueueRepresentation::const_iterator	const_iterator;
-		
-		EventQueue()			{}
-		
-		const_iterator 			top() const					{ assert(!empty()); return queue_.begin(); }
-		iterator 				top()						{ assert(!empty()); return queue_.begin(); }
-		iterator 				push(Event e)				{ queue_.push_front(e); iterator i = top(); update(i); return i; }
-		void 					pop()						{ assert(!empty()); queue_.erase(queue_.begin()); }
-		void					remove(iterator i)			{ queue_.erase(i); }
-		void					update(iterator i);
+        iterator(typename QueueRepresentation::iterator i):
+            iterator::iterator_adaptor_(i)                              {}
+
+        using iterator::iterator_adaptor_::base;
+
+        typename iterator::iterator_adaptor_::reference
+                        dereference() const                             { return base()->e_; }
+};
+
+template<class Event_, class EventComparison_>
+class EventQueue<Event_, EventComparison_>::const_iterator:
+    public boost::iterator_adaptor<const_iterator,
+                                   typename QueueRepresentation::const_iterator,
+                                   Event,
+                                   b::use_default,
+                                   const Event&>
+{
+    public:
+        const_iterator():
+            const_iterator::iterator_adaptor_(0)                        {}
+
+        const_iterator(iterator i):
+            const_iterator::iterator_adaptor_(i.base())                 {}
+
+        const_iterator(typename QueueRepresentation::const_iterator i):
+            const_iterator::iterator_adaptor_(i)                        {}
+
+        using const_iterator::iterator_adaptor_::base;
 
-		iterator 				end()						{ return queue_.end(); }
-		const_iterator 			end() const					{ return queue_.end(); }
-		bool					empty() const				{ return queue_.empty(); }
-		size_t					size() const				{ return queue_.size(); }
+        typename const_iterator::iterator_adaptor_::reference
+                        dereference() const                             { return base()->e_; }
+};
+
+template<class Event_, class EventComparison_>
+struct EventQueue<Event_, EventComparison_>::UpdateNode
+{
+    void operator()(iterator i, size_t pos) const                       { i.base()->heap_position_ = pos; }
+};
 
-		std::ostream&			print(std::ostream& out, const std::string& prefix) const;
+template<class Event_, class EventComparison_>
+struct EventQueue<Event_, EventComparison_>::CompareNodes
+{
+    bool operator()(iterator i, iterator j) const                       { return EventComparison()(*j, *i); }
+};
 
-	private:
-		QueueRepresentation		queue_;
+template<class Event_, class EventComparison_>
+struct EventQueue<Event_, EventComparison_>::MarkedCompareNodes
+{
+         MarkedCompareNodes(iterator i): i_(i)                          {}
+    bool operator()(iterator i, iterator j) const
+    {
+        // i_ is less than everything else
+        if (i == i_)
+            return false;
+        if (j == i_)
+            return true;
+        return EventComparison()(*j, *i);
+    }
+    iterator i_;
 };
 
 
 template<class Event_, class EventComparison_>
+typename EventQueue<Event_, EventComparison_>::iterator
+EventQueue<Event_, EventComparison_>::
+push(Event e)
+{
+    queue_.push_back(e);
+    iterator i = b::prior(queue_.end());
+    heap_.push_back(i);
+    std::push_heap(heap_.begin(), heap_.end(), CompareNodes(), UpdateNode());
+
+    return i;
+}
+
+template<class Event_, class EventComparison_>
+void
+EventQueue<Event_, EventComparison_>::
+pop()
+{
+    AssertMsg(!empty(), "Queue must not be empty");
+    std::pop_heap(heap_.begin(), heap_.end(), CompareNodes(), UpdateNode());
+    queue_.erase(heap_.back().base()); heap_.pop_back();
+}
+
+template<class Event_, class EventComparison_>
 void
 EventQueue<Event_, EventComparison_>::
-update(iterator i)
+remove(iterator i)
+{
+    MarkedCompareNodes mcmp(i);
+    std::update_heap_pos(heap_.begin(), heap_.end(), heap_.begin() + i.base()->heap_position_, mcmp, UpdateNode());
+    std::pop_heap(heap_.begin(), heap_.end(), mcmp, UpdateNode());
+    AssertMsg(heap_.back() == i, "i should be in the back");
+    queue_.erase(heap_.back().base());
+    heap_.pop_back();
+}
+
+template<class Event_, class EventComparison_>
+void
+EventQueue<Event_, EventComparison_>::
+replace(iterator i, Event e)
 {
-	QueueRepresentation tmp;
-	tmp.splice(tmp.end(), queue_, i);
-	iterator pos = std::find_if(queue_.begin(), queue_.end(), std::not1(std::bind2nd(EventComparison(), *i)));
-	queue_.splice(pos, tmp);
+
+    if (EventComparison()(*i, e))
+    {
+        *i = e;
+        promoted(i);
+    } else
+    {
+        *i = e;
+        demoted(i);
+    }
+}
+
+template<class Event_, class EventComparison_>
+void
+EventQueue<Event_, EventComparison_>::
+promoted(iterator i)
+{
+    std::update_heap_pos(heap_.begin(), heap_.end(), heap_.begin() + i.base()->heap_position_, CompareNodes(), UpdateNode());
+}
+
+template<class Event_, class EventComparison_>
+void
+EventQueue<Event_, EventComparison_>::
+demoted(iterator i)
+{
+    // Bring to front
+    MarkedCompareNodes mcmp(i);
+    std::update_heap_pos(heap_.begin(), heap_.end(), heap_.begin() + i.base()->heap_position_, mcmp, UpdateNode());
+
+    // Bring to back
+    std::pop_heap(heap_.begin(), heap_.end(), mcmp, UpdateNode());
+
+    // Find new place
+    std::update_heap_pos(heap_.begin(), heap_.end(), heap_.begin() + i.base()->heap_position_, CompareNodes(), UpdateNode());
 }
 
 template<class Event_, class EventComparison_>
@@ -63,9 +226,9 @@
 EventQueue<Event_, EventComparison_>::
 print(std::ostream& out, const std::string& prefix) const
 {
-	for (typename QueueRepresentation::const_iterator cur = queue_.begin(); cur != queue_.end(); ++cur)
-		(*cur)->print(out << prefix) << std::endl;
-	return out;
+    for (typename EventListHeap::const_iterator cur = heap_.begin(); cur != heap_.end(); ++cur)
+        out << prefix << **cur << std::endl;
+    return out;
 }
 
 #endif // __EVENTQUEUE_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/utilities/indirect.h	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,185 @@
+#ifndef __INDIRECT_H__
+#define __INDIRECT_H__
+
+#include <boost/iterator/iterator_adaptor.hpp>
+#include <boost/iterator/iterator_facade.hpp>
+#include <iterator>
+
+// TODO: write documentation
+
+/**************
+ * Comparison *
+ **************/
+
+template<class Comparison_>
+struct IndirectComparison
+{
+    typedef         Comparison_                             Comparison;
+
+                    IndirectComparison(const Comparison& cmp):
+                        cmp_(cmp)
+                    {}
+
+    template<class Iterator>
+    bool            operator()(Iterator a, Iterator b) const
+    { return cmp_(*a, *b); }
+
+    const Comparison&               cmp_;
+};
+template<class Comparison>
+IndirectComparison<Comparison> make_indirect_comparison(const Comparison& cmp)
+{ return IndirectComparison<Comparison>(cmp); }
+
+
+template<class Comparison_>
+class FirstComparison
+{
+    public:
+        typedef     Comparison_                             Comparison;
+
+                    FirstComparison(Comparison cmp): 
+                        cmp_(cmp)                           {}
+
+        template<class Pair>
+        bool        operator()(const Pair& a, const Pair& b) const
+        { return cmp_(a.first, b.first); }
+
+    private:
+        Comparison  cmp_;
+};
+template<class Comparison>
+FirstComparison<Comparison> make_first_comparison(const Comparison& cmp)
+{ return FirstComparison<Comparison>(cmp); }
+
+
+template<class Comparison>
+struct ThreeOutcomeCompare: public Comparison
+{
+    typedef         typename Comparison::first_argument_type                            first_argument_type;
+    typedef         typename Comparison::second_argument_type                           second_argument_type;
+
+                    ThreeOutcomeCompare(const Comparison& cmp = Comparison()): Comparison(cmp)              {}
+
+    int             compare(first_argument_type a, second_argument_type b) const
+    {   if (this->operator()(a,b))          return -1;
+        else if (this->operator()(b,a))     return 1;
+        else                                return 0;
+    }
+};
+
+template<class Evaluator_>
+class ThroughEvaluatorComparison
+{
+    public:
+        typedef                 Evaluator_                                                  Evaluator;
+
+                                ThroughEvaluatorComparison(const Evaluator& eval): 
+                                    eval_(eval)                                             {}
+
+        template<class T>                            
+        bool                    operator()(T a, T b) const                                  { return (eval_(a) < eval_(b)); }
+
+    private:
+        const Evaluator&        eval_;
+};
+
+
+/*************
+ * Iterators *
+ *************/
+
+// Iterates over the difference of the two sorted sequences, dereferencing into the first sequence
+template<class Iterator1, class Iterator2, class StrictWeakOrdering>
+class difference_iterator: public boost::iterator_facade<difference_iterator<Iterator1, Iterator2, StrictWeakOrdering>,
+                                                         typename std::iterator_traits<Iterator1>::value_type,
+                                                         boost::forward_traversal_tag>
+{
+    public:
+        typedef     typename std::iterator_traits<Iterator1>::reference                 reference;
+
+                    difference_iterator(Iterator1 cur1, Iterator1 end1,
+                                        Iterator2 cur2, Iterator2 end2,
+                                        const StrictWeakOrdering& cmp = StrictWeakOrdering()):
+                        cur1_(cur1), end1_(end1), cur2_(cur2), end2_(end2), cmp_(cmp)   { catchup(); }
+
+    private:
+        friend class boost::iterator_core_access;
+
+        void        increment()                                                         { ++cur1_; catchup(); }
+        bool        equal(const difference_iterator& other) const                       { return (cur1_ == other.cur1_) && (cur2_ == other.cur2_); }
+        reference   dereference() const                                                 { return *cur1_; }
+
+    private:
+        Iterator1   cur1_, end1_;
+        Iterator2   cur2_, end2_;
+        const StrictWeakOrdering&   cmp_;
+
+    private:
+        void        catchup()
+        {
+            while ((cur1_ != end1_) && (cur2_ != end2_))
+            {
+                if      (cmp_(*cur1_, *cur2_))      break;
+                else if (cmp_(*cur2_, *cur1_))      ++cur2_;
+                else                                { ++cur1_; ++cur2_; }
+            }
+
+            if (cur1_ == end1_)                     cur2_ = end2_;
+        }
+};
+
+template<class Iterator1, class Iterator2, class StrictWeakOrdering>
+difference_iterator<Iterator1, Iterator2, StrictWeakOrdering>
+make_difference_iterator(Iterator1 cur1, Iterator1 end1, Iterator2 cur2, Iterator2 end2, const StrictWeakOrdering& cmp)
+{ return difference_iterator<Iterator1, Iterator2, StrictWeakOrdering>(cur1, end1, cur2, end2, cmp); }
+
+// Iterates over the intersection of the two sorted sequences, dereferencing into the first sequence
+template<class Iterator1, class Iterator2, class StrictWeakOrdering>
+class intersection_iterator: public boost::iterator_facade<intersection_iterator<Iterator1, Iterator2, StrictWeakOrdering>,
+                                                           typename std::iterator_traits<Iterator1>::value_type,
+                                                           boost::forward_traversal_tag>
+{
+    public:
+        typedef     typename std::iterator_traits<Iterator1>::reference                 reference;
+
+                    intersection_iterator(Iterator1 cur1, Iterator1 end1,
+                                          Iterator2 cur2, Iterator2 end2,
+                                          const StrictWeakOrdering& cmp = StrictWeakOrdering()):
+                        cur1_(cur1), end1_(end1), cur2_(cur2), end2_(end2), cmp_(cmp)   { catchup(); }
+
+    private:
+        friend class boost::iterator_core_access;
+
+        void        increment()                                                         { ++cur1_; ++cur2_; catchup(); }
+        bool        equal(const intersection_iterator& other) const                     { return (cur1_ == other.cur1_) && (cur2_ == other.cur2_); }
+        reference   dereference() const                                                 { return *cur1_; }
+
+    private:
+        Iterator1   cur1_, end1_;
+        Iterator2   cur2_, end2_;
+        const StrictWeakOrdering&   cmp_;
+
+    private:
+        void        catchup()
+        {
+            while ((cur1_ != end1_) && (cur2_ != end2_))
+            {
+                if      (cmp_(*cur1_, *cur2_))      ++cur1_;
+                else if (cmp_(*cur2_, *cur1_))      ++cur2_;
+                else                                break;
+            }
+
+            if ((cur1_ == end1_) || (cur2_ == end2_))
+            {
+                cur1_ = end1_;
+                cur2_ = end2_;
+            }
+        }
+};
+
+template<class Iterator1, class Iterator2, class StrictWeakOrdering>
+intersection_iterator<Iterator1, Iterator2, StrictWeakOrdering>
+make_intersection_iterator(Iterator1 cur1, Iterator1 end1, Iterator2 cur2, Iterator2 end2, const StrictWeakOrdering& cmp)
+{ return intersection_iterator<Iterator1, Iterator2, StrictWeakOrdering>(cur1, end1, cur2, end2, cmp); }
+
+#endif // __INDIRECT_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/utilities/log.h	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,68 @@
+#ifndef __LOG_H__
+#define __LOG_H__
+
+#include <unistd.h>		// for STDOUT_FILENO and STDERR_FILENO
+
+#if LOGGING
+
+#define RLOG_COMPONENT dionysus
+
+#include <rlog/rlog.h>
+#include <rlog/RLogChannel.h>
+#include <rlog/StdioNode.h>
+#include <sstream>
+
+#undef RLOG_SECTION
+#define RLOG_SECTION
+
+template<class T>
+std::string tostring(const T& t) { std::ostringstream out; out << t; return out.str(); }
+template<class T>
+std::string intostring(const T& t) { std::ostringstream out; t.operator<<(out); return out.str(); }
+
+#define AssertMsg(cond, message, ...)		do { if (!(cond)) { rError(message, ##__VA_ARGS__); rAssertSilent(cond); } } while (0)
+	
+#else // LOGGING
+
+#define rDebug(...)
+#define rInfo(...)
+#define rWarning(...)
+#define rError(...)
+#define rLog(...)
+
+#define rAssert(...)
+#define rAssertSilent(...)
+
+#define DEF_CHANNEL(...) 0
+#define RLOG_CHANNEL(...) 0
+
+#define AssertMsg(cond, ...)
+
+// To avoid undefined errors for RLogChannel, we create a dummy namespace
+namespace rlog
+{
+	typedef		void			RLogChannel;
+
+	class StdioNode
+	{
+		public:
+								StdioNode(int,int)					{}
+			void				subscribeTo(RLogChannel*)			{}
+
+			static const int 	OutputColor = 0;
+			static const int	OutputChannel = 0;
+	};
+}
+
+#endif // LOGGING
+
+static rlog::StdioNode stdoutLog(STDOUT_FILENO,
+								 rlog::StdioNode::OutputColor + 
+								 rlog::StdioNode::OutputChannel);
+
+static rlog::StdioNode stderrLog(STDERR_FILENO,
+								 rlog::StdioNode::OutputColor + 
+								 rlog::StdioNode::OutputChannel);
+
+
+#endif //__LOG_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/utilities/memory.h	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,43 @@
+#ifndef __MEMORY_H__
+#define __MEMORY_H__
+
+#if LOGGING     // TODO: add check for Linux (and preferably the right version of Linux)
+
+#include "log.h"
+#include <fstream>
+#include <sstream>
+#include <string>
+#include <unistd.h>
+
+static rlog::RLogChannel* rlMemory =                   DEF_CHANNEL("memory",    rlog::Log_Debug);
+
+unsigned    report_memory()
+{
+    pid_t pid = getpid();
+    std::stringstream smaps_name;
+    smaps_name << "/proc/" << pid << "/smaps";
+    std::ifstream in(smaps_name.str().c_str());
+
+    std::string str;
+    unsigned memory = 0, value;
+    while (in)
+    {
+        in >> str;
+        if (std::string(str, 0, 7) == "Private")
+        {
+            in >> value;
+            memory += value;
+        }
+    }
+    rLog(rlMemory, "Private memory usage: %d kB", memory);
+    
+    return memory;
+}
+
+#else
+
+unsigned report_memory() { return 0; }
+
+#endif // LOGGING
+
+#endif // __MEMORY_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/utilities/munkres/matrix.h	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,56 @@
+/*
+ *   Copyright (c) 2007 John Weaver
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+
+#if !defined(_MATRIX_H_)
+#define _MATRIX_H_
+
+template <class T>
+class Matrix {
+public:
+	Matrix();
+	Matrix(int rows, int columns);
+	Matrix(const Matrix<T> &other);
+	Matrix<T> & operator= (const Matrix<T> &other);
+	~Matrix();
+	// all operations except product modify the matrix in-place.
+	void resize(int rows, int columns);
+	void identity(void);
+	void clear(void);
+	T& operator () (int x, int y);
+	T trace(void);
+	Matrix<T>& transpose(void);
+	Matrix<T> product(Matrix<T> &other);
+	int minsize(void) {
+		return ((m_rows < m_columns) ? m_rows : m_columns);
+	}
+	int columns(void) {
+		return m_columns;
+	}
+	int rows(void) {
+		return m_rows;
+	}
+private:
+	T **m_matrix;
+	int m_rows;
+	int m_columns;
+};
+
+#include "matrix.hpp"
+
+#endif /* !defined(_MATRIX_H_) */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/utilities/munkres/matrix.hpp	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,231 @@
+/*
+ *   Copyright (c) 2007 John Weaver
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+
+#include "matrix.h"
+
+#include <cassert>
+#include <cstdlib>
+#include <algorithm>
+
+/*export*/ template <class T>
+Matrix<T>::Matrix() {
+	m_rows = 0;
+	m_columns = 0;
+	m_matrix = NULL;
+}
+
+/*export*/ template <class T>
+Matrix<T>::Matrix(const Matrix<T> &other) {
+	if ( other.m_matrix != NULL ) {
+		// copy arrays
+		m_matrix = NULL;
+		resize(other.m_rows, other.m_columns);
+		for ( int i = 0 ; i < m_rows ; i++ )
+			for ( int j = 0 ; j < m_columns ; j++ )
+				m_matrix[i][j] = other.m_matrix[i][j];
+	} else {
+		m_matrix = NULL;
+		m_rows = 0;
+		m_columns = 0;
+	}
+}
+
+/*export*/ template <class T>
+Matrix<T>::Matrix(int rows, int columns) {
+	m_matrix = NULL;
+	resize(rows, columns);
+}
+
+/*export*/ template <class T>
+Matrix<T> &
+Matrix<T>::operator= (const Matrix<T> &other) {
+	if ( other.m_matrix != NULL ) {
+		// copy arrays
+		resize(other.m_rows, other.m_columns);
+		for ( int i = 0 ; i < m_rows ; i++ )
+			for ( int j = 0 ; j < m_columns ; j++ )
+				m_matrix[i][j] = other.m_matrix[i][j];
+	} else {
+		// free arrays
+		for ( int i = 0 ; i < m_columns ; i++ )
+			delete [] m_matrix[i];
+
+		delete [] m_matrix;
+
+		m_matrix = NULL;
+		m_rows = 0;
+		m_columns = 0;
+	}
+	
+	return *this;
+}
+
+/*export*/ template <class T>
+Matrix<T>::~Matrix() {
+	if ( m_matrix != NULL ) {
+		// free arrays
+		for ( int i = 0 ; i < m_rows ; i++ )
+			delete [] m_matrix[i];
+
+		delete [] m_matrix;
+	}
+	m_matrix = NULL;
+}
+
+/*export*/ template <class T>
+void
+Matrix<T>::resize(int rows, int columns) {
+	if ( m_matrix == NULL ) {
+		// alloc arrays
+		m_matrix = new T*[rows]; // rows
+		for ( int i = 0 ; i < rows ; i++ )
+			m_matrix[i] = new T[columns]; // columns
+
+		m_rows = rows;
+		m_columns = columns;
+		clear();
+	} else {
+		// save array pointer
+		T **new_matrix;
+		// alloc new arrays
+		new_matrix = new T*[rows]; // rows
+		for ( int i = 0 ; i < rows ; i++ ) {
+			new_matrix[i] = new T[columns]; // columns
+			for ( int j = 0 ; j < columns ; j++ )
+				new_matrix[i][j] = 0;
+		}
+
+		// copy data from saved pointer to new arrays
+		int minrows = std::min<int>(rows, m_rows);
+		int mincols = std::min<int>(columns, m_columns);
+		for ( int x = 0 ; x < minrows ; x++ )
+			for ( int y = 0 ; y < mincols ; y++ )
+				new_matrix[x][y] = m_matrix[x][y];
+
+		// delete old arrays
+		if ( m_matrix != NULL ) {
+			for ( int i = 0 ; i < m_rows ; i++ )
+				delete [] m_matrix[i];
+
+			delete [] m_matrix;
+		}
+
+		m_matrix = new_matrix;
+	}
+
+	m_rows = rows;
+	m_columns = columns;
+}
+
+/*export*/ template <class T>
+void
+Matrix<T>::identity() {
+	assert( m_matrix != NULL );
+
+	clear();
+
+	int x = std::min<int>(m_rows, m_columns);
+	for ( int i = 0 ; i < x ; i++ )
+		m_matrix[i][i] = 1;
+}
+
+/*export*/ template <class T>
+void
+Matrix<T>::clear() {
+	assert( m_matrix != NULL );
+
+	for ( int i = 0 ; i < m_rows ; i++ )
+		for ( int j = 0 ; j < m_columns ; j++ )
+			m_matrix[i][j] = 0;
+}
+
+/*export*/ template <class T>
+T 
+Matrix<T>::trace() {
+	assert( m_matrix != NULL );
+
+	T value = 0;
+
+	int x = std::min<int>(m_rows, m_columns);
+	for ( int i = 0 ; i < x ; i++ )
+		value += m_matrix[i][i];
+
+	return value;
+}
+
+/*export*/ template <class T>
+Matrix<T>& 
+Matrix<T>::transpose() {
+	assert( m_rows > 0 );
+	assert( m_columns > 0 );
+
+	int new_rows = m_columns;
+	int new_columns = m_rows;
+
+	if ( m_rows != m_columns ) {
+		// expand matrix
+		int m = std::max<int>(m_rows, m_columns);
+		resize(m,m);
+	}
+
+	for ( int i = 0 ; i < m_rows ; i++ ) {
+		for ( int j = i+1 ; j < m_columns ; j++ ) {
+			T tmp = m_matrix[i][j];
+			m_matrix[i][j] = m_matrix[j][i];
+			m_matrix[j][i] = tmp;
+		}
+	}
+
+	if ( new_columns != new_rows ) {
+		// trim off excess.
+		resize(new_rows, new_columns);
+	}
+
+	return *this;
+}
+
+/*export*/ template <class T>
+Matrix<T> 
+Matrix<T>::product(Matrix<T> &other) {
+	assert( m_matrix != NULL );
+	assert( other.m_matrix != NULL );
+	assert ( m_columns == other.m_rows );
+
+	Matrix<T> out(m_rows, other.m_columns);
+
+	for ( int i = 0 ; i < out.m_rows ; i++ ) {
+		for ( int j = 0 ; j < out.m_columns ; j++ ) {
+			for ( int x = 0 ; x < m_columns ; x++ ) {
+				out(i,j) += m_matrix[i][x] * other.m_matrix[x][j];
+			}
+		}
+	}
+
+	return out;
+}
+
+/*export*/ template <class T>
+T&
+Matrix<T>::operator ()(int x, int y) {
+	assert ( x >= 0 );
+	assert ( y >= 0 );
+	assert ( x < m_rows );
+	assert ( y < m_columns );
+	assert ( m_matrix != NULL );
+	return m_matrix[x][y];
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/utilities/munkres/munkres.cpp	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,359 @@
+/*
+ *   Copyright (c) 2007 John Weaver
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+
+#include "munkres.h"
+
+#include <iostream>
+#include <cmath>
+
+bool 
+Munkres::find_uncovered_in_matrix(double item, int &row, int &col) {
+  for ( row = 0 ; row < matrix.rows() ; row++ )
+    if ( !row_mask[row] )
+      for ( col = 0 ; col < matrix.columns() ; col++ )
+        if ( !col_mask[col] )
+          if ( matrix(row,col) == item )
+            return true;
+
+  return false;
+}
+
+bool 
+Munkres::pair_in_list(const std::pair<int,int> &needle, const std::list<std::pair<int,int> > &haystack) {
+  for ( std::list<std::pair<int,int> >::const_iterator i = haystack.begin() ; i != haystack.end() ; i++ ) {
+    if ( needle == *i )
+      return true;
+  }
+  
+  return false;
+}
+
+int 
+Munkres::step1(void) {
+  for ( int row = 0 ; row < matrix.rows() ; row++ )
+    for ( int col = 0 ; col < matrix.columns() ; col++ )
+      if ( matrix(row,col) == 0 ) {
+        bool isstarred = false;
+        for ( int nrow = 0 ; nrow < matrix.rows() ; nrow++ )
+          if ( mask_matrix(nrow,col) == STAR ) {
+            isstarred = true;
+            break;
+          }
+
+        if ( !isstarred ) {
+          for ( int ncol = 0 ; ncol < matrix.columns() ; ncol++ )
+            if ( mask_matrix(row,ncol) == STAR ) {
+              isstarred = true;
+              break;
+            }
+        }
+              
+        if ( !isstarred ) {
+          mask_matrix(row,col) = STAR;
+        }
+      }
+
+  return 2;
+}
+
+int 
+Munkres::step2(void) {
+  int rows = matrix.rows();
+  int cols = matrix.columns();
+  int covercount = 0;
+  for ( int row = 0 ; row < rows ; row++ )
+    for ( int col = 0 ; col < cols ; col++ )
+      if ( mask_matrix(row,col) == STAR ) {
+        col_mask[col] = true;
+        covercount++;
+      }
+      
+  int k = matrix.minsize();
+
+  if ( covercount >= k ) {
+#ifdef DEBUG
+    std::cout << "Final cover count: " << covercount << std::endl;
+#endif
+    return 0;
+  }
+
+#ifdef DEBUG
+  std::cout << "Munkres matrix has " << covercount << " of " << k << " Columns covered:" << std::endl;
+  for ( int row = 0 ; row < rows ; row++ ) {
+    for ( int col = 0 ; col < cols ; col++ ) {
+      std::cout.width(8);
+      std::cout << matrix(row,col) << ",";
+    }
+    std::cout << std::endl;
+  }
+  std::cout << std::endl;
+#endif
+
+
+  return 3;
+}
+
+int 
+Munkres::step3(void) {
+  /*
+  Main Zero Search
+
+   1. Find an uncovered Z in the distance matrix and prime it. If no such zero exists, go to Step 5
+   2. If No Z* exists in the row of the Z', go to Step 4.
+   3. If a Z* exists, cover this row and uncover the column of the Z*. Return to Step 3.1 to find a new Z
+  */
+  if ( find_uncovered_in_matrix(0, saverow, savecol) ) {
+    mask_matrix(saverow,savecol) = PRIME; // prime it.
+  } else {
+    return 5;
+  }
+
+  for ( int ncol = 0 ; ncol < matrix.columns() ; ncol++ )
+    if ( mask_matrix(saverow,ncol) == STAR ) {
+      row_mask[saverow] = true; //cover this row and
+      col_mask[ncol] = false; // uncover the column containing the starred zero
+      return 3; // repeat
+    }
+
+  return 4; // no starred zero in the row containing this primed zero
+}
+
+int 
+Munkres::step4(void) {
+  int rows = matrix.rows();
+  int cols = matrix.columns();
+
+  std::list<std::pair<int,int> > seq;
+  // use saverow, savecol from step 3.
+  std::pair<int,int> z0(saverow, savecol);
+  std::pair<int,int> z1(-1,-1);
+  std::pair<int,int> z2n(-1,-1);
+  seq.insert(seq.end(), z0);
+  int row, col = savecol;
+  /*
+  Increment Set of Starred Zeros
+
+   1. Construct the ``alternating sequence'' of primed and starred zeros:
+
+         Z0 : Unpaired Z' from Step 4.2 
+         Z1 : The Z* in the column of Z0
+         Z[2N] : The Z' in the row of Z[2N-1], if such a zero exists 
+         Z[2N+1] : The Z* in the column of Z[2N]
+
+      The sequence eventually terminates with an unpaired Z' = Z[2N] for some N.
+  */
+  bool madepair;
+  do {
+    madepair = false;
+    for ( row = 0 ; row < rows ; row++ )
+      if ( mask_matrix(row,col) == STAR ) {
+        z1.first = row;
+        z1.second = col;
+        if ( pair_in_list(z1, seq) )
+          continue;
+        
+        madepair = true;
+        seq.insert(seq.end(), z1);
+        break;
+      }
+
+    if ( !madepair )
+      break;
+
+    madepair = false;
+
+    for ( col = 0 ; col < cols ; col++ )
+      if ( mask_matrix(row,col) == PRIME ) {
+        z2n.first = row;
+        z2n.second = col;
+        if ( pair_in_list(z2n, seq) )
+          continue;
+        madepair = true;
+        seq.insert(seq.end(), z2n);
+        break;
+      }
+  } while ( madepair );
+
+  for ( std::list<std::pair<int,int> >::iterator i = seq.begin() ;
+      i != seq.end() ;
+      i++ ) {
+    // 2. Unstar each starred zero of the sequence.
+    if ( mask_matrix(i->first,i->second) == STAR )
+      mask_matrix(i->first,i->second) = NORMAL;
+
+    // 3. Star each primed zero of the sequence,
+    // thus increasing the number of starred zeros by one.
+    if ( mask_matrix(i->first,i->second) == PRIME )
+      mask_matrix(i->first,i->second) = STAR;
+  }
+
+  // 4. Erase all primes, uncover all columns and rows, 
+  for ( int row = 0 ; row < mask_matrix.rows() ; row++ )
+    for ( int col = 0 ; col < mask_matrix.columns() ; col++ )
+      if ( mask_matrix(row,col) == PRIME )
+        mask_matrix(row,col) = NORMAL;
+  
+  for ( int i = 0 ; i < rows ; i++ ) {
+    row_mask[i] = false;
+  }
+
+  for ( int i = 0 ; i < cols ; i++ ) {
+    col_mask[i] = false;
+  }
+
+  // and return to Step 2. 
+  return 2;
+}
+
+int 
+Munkres::step5(void) {
+  int rows = matrix.rows();
+  int cols = matrix.columns();
+  /*
+  New Zero Manufactures
+
+   1. Let h be the smallest uncovered entry in the (modified) distance matrix.
+   2. Add h to all covered rows.
+   3. Subtract h from all uncovered columns
+   4. Return to Step 3, without altering stars, primes, or covers. 
+  */
+  double h = 0;
+  for ( int row = 0 ; row < rows ; row++ ) {
+    if ( !row_mask[row] ) {
+      for ( int col = 0 ; col < cols ; col++ ) {
+        if ( !col_mask[col] ) {
+          if ( (h > matrix(row,col) && matrix(row,col) != 0) || h == 0 ) {
+            h = matrix(row,col);
+          }
+        }
+      }
+    }
+  }
+
+  for ( int row = 0 ; row < rows ; row++ )
+    if ( row_mask[row] )
+      for ( int col = 0 ; col < cols ; col++ )
+        matrix(row,col) += h;
+  
+  for ( int col = 0 ; col < cols ; col++ )
+    if ( !col_mask[col] )
+      for ( int row = 0 ; row < rows ; row++ )
+        matrix(row,col) -= h;
+
+  return 3;
+}
+
+void 
+Munkres::solve(Matrix<double> &m) {
+  // Linear assignment problem solution
+  // [modifies matrix in-place.]
+  // matrix(row,col): row major format assumed.
+
+  // Assignments are remaining 0 values
+  // (extra 0 values are replaced with -1)
+#ifdef DEBUG
+  std::cout << "Munkres input matrix:" << std::endl;
+  for ( int row = 0 ; row < m.rows() ; row++ ) {
+    for ( int col = 0 ; col < m.columns() ; col++ ) {
+      std::cout.width(8);
+      std::cout << m(row,col) << ",";
+    }
+    std::cout << std::endl;
+  }
+  std::cout << std::endl;
+#endif
+
+  double highValue = 0;
+  for ( int row = 0 ; row < m.rows() ; row++ ) {
+    for ( int col = 0 ; col < m.columns() ; col++ ) {
+      if ( m(row,col) != INFINITY && m(row,col) > highValue )
+        highValue = m(row,col);
+    }
+  }
+  highValue++;
+  
+  for ( int row = 0 ; row < m.rows() ; row++ )
+    for ( int col = 0 ; col < m.columns() ; col++ )
+      if ( m(row,col) == INFINITY )
+        m(row,col) = highValue;
+
+  bool notdone = true;
+  int step = 1;
+
+  this->matrix = m;
+  // STAR == 1 == starred, PRIME == 2 == primed
+  mask_matrix.resize(matrix.rows(), matrix.columns());
+
+  row_mask = new bool[matrix.rows()];
+  col_mask = new bool[matrix.columns()];
+  for ( int i = 0 ; i < matrix.rows() ; i++ ) {
+    row_mask[i] = false;
+  }
+
+  for ( int i = 0 ; i < matrix.columns() ; i++ ) {
+    col_mask[i] = false;
+  }
+
+  while ( notdone ) {
+    switch ( step ) {
+      case 0:
+        notdone = false;
+        break;
+      case 1:
+        step = step1();
+        break;
+      case 2:
+        step = step2();
+        break;
+      case 3:
+        step = step3();
+        break;
+      case 4:
+        step = step4();
+        break;
+      case 5:
+        step = step5();
+        break;
+    }
+  }
+
+  // Store results
+  for ( int row = 0 ; row < matrix.rows() ; row++ )
+    for ( int col = 0 ; col < matrix.columns() ; col++ )
+      if ( mask_matrix(row,col) == STAR )
+        matrix(row,col) = 0;
+      else
+        matrix(row,col) = -1;
+
+#ifdef DEBUG
+  std::cout << "Munkres output matrix:" << std::endl;
+  for ( int row = 0 ; row < matrix.rows() ; row++ ) {
+    for ( int col = 0 ; col < matrix.columns() ; col++ ) {
+      std::cout.width(1);
+      std::cout << matrix(row,col) << ",";
+    }
+    std::cout << std::endl;
+  }
+  std::cout << std::endl;
+#endif
+
+  m = matrix;
+
+  delete [] row_mask;
+  delete [] col_mask;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/utilities/munkres/munkres.h	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,52 @@
+/*
+ *   Copyright (c) 2007 John Weaver
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+
+#if !defined(_MUNKRES_H_)
+#define _MUNKRES_H_
+
+#include "matrix.h"
+
+#include <list>
+#include <utility>
+
+class Munkres {
+public:
+	void solve(Matrix<double> &m);
+private:
+  static const int NORMAL = 0;
+  static const int STAR = 1;
+  static const int PRIME = 2; 
+	inline bool find_uncovered_in_matrix(double,int&,int&);
+	inline bool pair_in_list(const std::pair<int,int> &, const std::list<std::pair<int,int> > &);
+	int step1(void);
+	int step2(void);
+	int step3(void);
+	int step4(void);
+	int step5(void);
+	int step6(void);
+	Matrix<int> mask_matrix;
+	Matrix<double> matrix;
+	bool *row_mask;
+	bool *col_mask;
+	int saverow, savecol;
+};
+
+// DM: This is dangerous, but will do for now
+#include "munkres.cpp"
+
+#endif /* !defined(_MUNKRES_H_) */
--- a/include/utilities/orderlist.h	Fri Aug 24 16:58:25 2007 -0400
+++ b/include/utilities/orderlist.h	Tue Jun 27 09:37:05 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Author: Dmitriy Morozov 
+ * Author: Dmitriy Morozov
  * Department of Computer Science, Duke University, 2006
  *
  * Implements the simplified order list data strcutre given in ``Two Simplified
@@ -12,15 +12,13 @@
 #ifndef __ORDERLIST_H__
 #define __ORDERLIST_H__
 
-#include "sys.h"
-#include "debug.h"
+#include "log.h"
 
 #include <iterator>
 #include <iostream>
 #include <list>
 
 #include "types.h"
-//#include "counter.h"
 
 #include <boost/utility.hpp>
 #include <boost/iterator/iterator_adaptor.hpp>
@@ -44,21 +42,21 @@
 class OrderList: public std::list<OrderListNode<T> >
 {
 	public:
-		class 			OrderComparison;				
+		class 			OrderComparison;
 
 		/// OrderComparison type
 		typedef			OrderComparison								OrderComparison;
-	
+
 		typedef			OrderListNode<T>							NodeType;
 		typedef			OrderList<T>								Self;
 		typedef			std::list<NodeType >						Parent;
-		
+
 		typedef			T											value_type;
 		typedef			T&											reference;
 		typedef			const T&									const_reference;
 		typedef			OrderListIterator<T>						iterator;
 		typedef			const_OrderListIterator<T>					const_iterator;
-	
+
 						OrderList()									{}
 						~OrderList() 								{ clear(); }
 
@@ -73,8 +71,8 @@
 		iterator		push_back(const_reference x);
 		iterator		insert(iterator predecessor, const_reference x);	///< Inserts x immediately after predecessor (has to be a valid iterator)
 		void			erase(iterator x)							{ Parent::erase(x.get_base()); }
-		
-		void			clear()										{ return Parent::clear(); }	
+
+		void			clear()										{ return Parent::clear(); }
 		bool			empty() const								{ return Parent::empty(); }
 		SizeType		size()	const								{ return Parent::size(); }
 		iterator		begin()										{ return iterator(Parent::begin()); }
@@ -84,18 +82,18 @@
 		reference		back()										{ return Parent::back(); }
 		const_reference	back() const								{ return Parent::back(); }
 		void			pop_back()									{ return Parent::pop_back(); }
-		                                                			
+
 		iterator		last()										{ return iterator(boost::prior(end())); }
 		const_iterator	last() const								{ return const_iterator(boost::prior(end())); }
 		/// @}
-		
+
 		/// \name Debugging operations
 		/// @{
 		void			show_elements() const;
 		/// @}
 
 	private:
-		static const float density_threshold = 1.2;
+		static const float density_threshold;
 };
 
 /// Basic comparison that LessThan and GreaterThan derive from
@@ -103,8 +101,8 @@
 class OrderList<T>::OrderComparison
 {
 	public:
-		typedef			typename OrderList<T>::const_iterator		ComparableType;				
-		int 			compare(ComparableType a, ComparableType b) const;				/// (-1,0,1) = a (precedes, ==, succeeds) b 
+		typedef			typename OrderList<T>::const_iterator		ComparableType;
+		int 			compare(ComparableType a, ComparableType b) const;				/// (-1,0,1) = a (precedes, ==, succeeds) b
 		bool			operator()(ComparableType a, ComparableType b) const;
 };
 
@@ -115,10 +113,10 @@
 	OrderListNode(const T& d, unsigned int t):
 		data(d), tag(t)
 	{}
-	
+
 	T 				data;
 	OrderType		tag;
-	
+
 	std::ostream& 	operator<<(std::ostream& out) const				{ return out << data << ": " << tag; }
 };
 
@@ -144,7 +142,7 @@
 {
 	private:
 		struct			enabler										{};
-		
+
 	public:
 		typedef			typename OrderList<T>::Parent				OrderListParent;
 		typedef 		boost::iterator_adaptor<OrderListIterator<T>,
@@ -155,12 +153,12 @@
 
 						OrderListIterator()							{}
 						OrderListIterator(const typename OrderListParent::iterator& iter):
-    						OrderListIterator::iterator_adaptor_(iter)	
+    						OrderListIterator::iterator_adaptor_(iter)
 						{}
 						OrderListIterator(const OrderListIterator<T>& other):
-							OrderListIterator::iterator_adaptor_(other.base())			
+							OrderListIterator::iterator_adaptor_(other.base())
 						{}
-	
+
 	private:
 		friend class	boost::iterator_core_access;
 		reference		dereference() const							{ return Parent::base_reference()->data; }
@@ -176,7 +174,7 @@
 {
 	private:
 		struct			enabler										{};
-		
+
 	public:
 		typedef			typename OrderList<T>::Parent				OrderListParent;
 		typedef 		boost::iterator_adaptor<const_OrderListIterator<T>,
@@ -187,13 +185,13 @@
 
 						const_OrderListIterator()					{}
 						const_OrderListIterator(const typename OrderListParent::const_iterator& iter):
-    						const_OrderListIterator::iterator_adaptor_(iter)	
+    						const_OrderListIterator::iterator_adaptor_(iter)
 						{}
 						const_OrderListIterator(const const_OrderListIterator<T>& other):
-							const_OrderListIterator::iterator_adaptor_(other.base())			
+							const_OrderListIterator::iterator_adaptor_(other.base())
 						{}
 						const_OrderListIterator(const OrderListIterator<T>& other):
-							const_OrderListIterator::iterator_adaptor_(other.base())			
+							const_OrderListIterator::iterator_adaptor_(other.base())
 						{}
 
 	private:
@@ -203,7 +201,6 @@
 						get_base()									{ return Parent::base_reference(); }
 
 		friend class 	OrderList<T>;
-		friend class 	OrderList<T>::OrderComparison;
 };
 
 
--- a/include/utilities/orderlist.hpp	Fri Aug 24 16:58:25 2007 -0400
+++ b/include/utilities/orderlist.hpp	Tue Jun 27 09:37:05 2017 -0700
@@ -1,5 +1,13 @@
 /* Implementations */
 
+#ifdef LOGGING
+static rlog::RLogChannel* rlOrderList = 					DEF_CHANNEL("utilities/orderlist", rlog::Log_Debug);
+#endif // LOGGING
+
+// This cannot be in the header file to conform to the C++ standard
+template<class T>
+const float OrderList<T>::density_threshold = 1.2;
+
 template<class T>
 void 
 OrderList<T>::
@@ -70,16 +78,16 @@
 	} while (inv_density * num_elements >= maximum);
 	++num_elements;			// for the extra element inserted
 
-	Dout(dc::orderlist, num_elements << ", " << lower << ", " << upper);
-	Dout(dc::orderlist, "prev is at the end: " << (prev == Parent::end()));
-	Dout(dc::orderlist, "next is at the end: " << (next == Parent::end()));
+	rLog(rlOrderList, "%i, %i, %i", num_elements, lower, upper);
+	rLog(rlOrderList, "prev is at the end: %i", (prev == Parent::end()));
+	rLog(rlOrderList, "next is at the end: %i", (next == Parent::end()));
 	
 	// Reorder
 	AssertMsg((upper - lower + 1)/num_elements > 0, "Spacing between new tags must be non-zero");
 	for (unsigned int i = 0; i < num_elements; ++i)
 	{
 		(++prev)->tag = lower + i*((upper - lower + 1)/num_elements);
-		Dout(dc::orderlist, prev->tag);
+		rLog(rlOrderList, "%i", prev->tag);
 		AssertMsg(prev->tag != 0 || prev == Parent::begin(), "Cannot assign 0 tag except at the beginning of OrderList");
 	}
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/utilities/property-maps.h	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,183 @@
+#ifndef __PROPERTY_MAPS_H__
+#define __PROPERTY_MAPS_H__
+
+#include <boost/version.hpp>
+#if BOOST_VERSION >= 104000
+#include <boost/property_map/property_map.hpp>
+#else
+#include <boost/property_map.hpp>
+#endif
+
+#include <boost/iterator/iterator_traits.hpp>
+#include <algorithm>
+#include "utilities/log.h"
+
+
+/* Associative Map */           // FIXME: this needs to have more thought put into it
+template<class UniquePairAssociativeContainer_>
+class AssociativeMap: public boost::associative_property_map<UniquePairAssociativeContainer_>
+{
+    public:
+        typedef         boost::associative_property_map<UniquePairAssociativeContainer_>        Parent;
+        
+    public:
+        // FIXME: takes begin, end, and initializes with the reverse
+        AssociativeMap():
+            container(), Parent(container)                                                      {}
+
+    private:
+        UniquePairAssociativeContainer_                                                         container;
+};
+
+
+/* Dereference Map */
+template<class Iterator_>
+class DereferenceMap
+{
+    public:
+        typedef         Iterator_                                                               Iterator;
+        typedef         Iterator                                                                key_type;
+        typedef         typename boost::iterator_value<Iterator>::type                          value_type;
+        typedef         boost::readable_property_map_tag                                        category;
+
+    public:
+        value_type      operator[](const key_type& k) const                                     { return *k; }
+};
+
+
+/* Binary Search Map */
+template<class Query_, class Index_, class Comparison_ = std::less<Query_> >
+class BinarySearchMap
+{
+    public:
+        typedef         Query_                                                                  Query;
+        typedef         Index_                                                                  Index;
+        typedef         Comparison_                                                             Comparison;
+
+        typedef         Query                                                                   key_type;
+        typedef         Index                                                                   value_type;
+        typedef         boost::readable_property_map_tag                                        category;
+
+   public:
+                        BinarySearchMap(Index bg, Index end, 
+                                        Comparison cmp = Comparison()): 
+                            bg_(bg), end_(end), cmp_(cmp)                                       {}
+
+        value_type      operator[](const key_type& k) const                                     
+        { 
+            value_type res = std::lower_bound(bg_, end_, k, cmp_);
+            AssertMsg(!cmp_(*res, k) && !cmp_(k, *res), "Query must always be found");
+            return res;
+        }
+
+   private:
+        Index           bg_;
+        Index           end_;
+        Comparison      cmp_;
+
+};
+
+/* Offset Map */
+template<class From_, class To_>
+struct OffsetMap
+{
+    typedef             From_                                                   From;
+    typedef             To_                                                     To;
+    typedef             From                                                    key_type;
+    typedef             To                                                      value_type;
+
+                        OffsetMap(From bg_from, To bg_to):
+                            bg_from_(bg_from), bg_to_(bg_to)                    {}
+                        
+    To                  operator[](From i) const                                { return bg_to_ + (i - bg_from_); }
+
+    From                from() const                                            { return bg_from_; }
+    To                  to() const                                              { return bg_to_; }
+    
+    
+    template<class NewFrom_> struct rebind_from
+    { typedef           OffsetMap<NewFrom_, To_>                                other; };
+    template<class NewTo_> struct rebind_to
+    { typedef           OffsetMap<From_, NewTo_>                                other; };
+
+
+    private:
+                        From                                                    bg_from_;
+                        To                                                      bg_to_;
+};
+
+template<class From_, class To_>
+OffsetMap<From_, To_>
+make_offset_map(From_ bg_from, To_ bg_to)
+{ return OffsetMap<From_, To_>(bg_from, bg_to); }
+
+
+template<class From_, class To_, class FromIndex_, class ToIndex_>
+struct OffsetBeginMap
+{
+    typedef             From_                                                   From;
+    typedef             To_                                                     To;
+    typedef             FromIndex_                                              key_type;
+    typedef             ToIndex_                                                value_type;
+
+                        OffsetBeginMap(const From& from, const To& to):
+                            from_(from), to_(to)                                {}
+                        
+    value_type          operator[](key_type i) const                            { return to_.begin() + (i - from_.begin()); }
+
+    const From&         from() const                                            { return from_; }
+    const To&           to() const                                              { return to_; }
+    
+    private:
+                  const From&                                                   from_;
+                  const To&                                                     to_;
+};
+
+
+/* ChainMap */
+template<class Map1, class Map2>
+class ChainMap
+{
+    public:
+        typedef         typename Map1::key_type                                 key_type;
+        typedef         typename Map2::value_type                               value_type;
+
+
+                        ChainMap(const Map1& m1, const Map2& m2): 
+                            m1_(m1), m2_(m2)                                    {}
+        value_type      operator[](const key_type& k) const                     { return m2_[m1_[k]]; }
+
+    private:
+        const Map1&     m1_;
+        const Map2&     m2_;
+};
+
+/* ThroughMap */
+template<class Functor_, class Map_>
+class ThroughMap
+{
+    public:
+        typedef                 Map_                                            Map;
+        typedef                 Functor_                                        Functor;
+
+        typedef                 typename Functor::result_type                   result_type;
+        typedef                 typename Map_::key_type                         first_argument_type;
+
+                                ThroughMap(const Map&       map,
+                                           const Functor&   functor):
+                                    map_(map),
+                                    functor_(functor)                           {}
+
+        result_type             operator()(first_argument_type a) const         { return functor_(map_[a]); }
+
+    private:
+        const Map&              map_;
+        const Functor&          functor_;
+};
+
+template<class Map, class Functor>
+ThroughMap<Functor, Map>
+evaluate_through_map(const Map& map, const Functor& functor)
+{ return ThroughMap<Functor, Map>(map, functor); }
+
+#endif // __PROPERTY_MAPS_H__
--- a/include/utilities/sys.h	Fri Aug 24 16:58:25 2007 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,26 +0,0 @@
-// sys.h
-//
-// This header file is included at the top of every source file,
-// before any other header file.
-// It is intended to add defines that are needed globally and
-// to work around Operating System dependend incompatibilities.
-
-// EXAMPLE: If you use autoconf you can add the following here.
-// #ifdef HAVE_CONFIG_H
-// #include "config.h"
-// #endif
-
-// EXAMPLE: You could add stuff like this here too
-// (Otherwise add -DCWDEBUG to your CFLAGS).
-// #if defined(WANTSDEBUGGING) && defined(HAVE_LIBCWD_BLAHBLAH)
-// #define CWDEBUG
-// #endif
-
-// The following is the libcwd related mandatory part.
-// It must be included before any system header file is included!
-#ifdef CWDEBUG
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE
-#endif
-#include <libcwd/sys.h>
-#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/utilities/timer.h	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,69 @@
+#ifndef __TIMER_H__
+#define __TIMER_H__
+
+// Adapted with minor changes from http://oldmill.uchicago.edu/~wilder/Code/timer/
+
+#include <ctime>
+#include <iostream>
+#include <iomanip>
+
+class Timer
+{
+    public:
+                    Timer(): start_time(0), acc_time(0)                     {}
+
+        void        start();
+        void        stop();
+        void        check(const char* msg = 0) const;
+
+    private:
+        clock_t     start_clock;
+        time_t      start_time;
+        double      acc_time;
+
+        double      elapsed_time() const;
+};
+
+// Return the total time that the timer has been in the "running" state since
+// it was last "started".  For "short" time periods (less than an hour), the
+// actual cpu time used is reported instead of the elapsed time.
+inline double 
+Timer::
+elapsed_time() const
+{
+    time_t acc_sec = time(0) - start_time;
+    if (acc_sec < 3600)
+        return (clock() - start_clock) / (1.0 * CLOCKS_PER_SEC);
+    else
+        return (1.0 * acc_sec);
+}
+
+inline void 
+Timer::
+start()
+{
+    start_clock = clock();
+    start_time = time(0);
+}
+
+inline void 
+Timer::
+stop()
+{
+    acc_time += elapsed_time();
+}
+
+// Print out an optional message followed by the current timer timing.
+inline void 
+Timer::
+check(const char* msg) const
+{
+    // Print an optional message, something like "Checking timer t";
+    if (msg) std::cout << msg << " : ";
+
+    std::cout << "Elapsed time [" << std::setiosflags(std::ios::fixed)
+              << std::setprecision(2) << acc_time << "] seconds\n";
+}
+
+#endif // __TIMER_H__
+
--- a/include/utilities/types.h	Fri Aug 24 16:58:25 2007 -0400
+++ b/include/utilities/types.h	Tue Jun 27 09:37:05 2017 -0700
@@ -2,10 +2,11 @@
 #define __TYPES_H__
 
 #include <limits>
+#include <iostream>
 
 /* Types */
 typedef 	bool					Sign;
-typedef		short int				Dimension;
+typedef		short int		        Dimension;
 const 		Sign	 				POS = true;
 const 		Sign					NEG = false;
 typedef		double					RealType;
@@ -15,4 +16,48 @@
 
 typedef 	const unsigned int&		version_type;
 
+// Empty is made a template so that we don't have to compile and deal with a library
+// solely for its operator<<(out, e) function
+template<typename T = void>
+struct      Empty                   {};
+
+
+struct      use_default             {};
+
+template<class T, class Default>
+struct      if_default
+{ typedef   T           type; };
+
+template<class Default>
+struct      if_default<use_default, Default>
+{ typedef   Default     type; };
+
+
+template<typename T>
+std::ostream& operator<<(std::ostream& out, Empty<T> e) { return out; }
+
+enum        SwitchType
+{
+            DiffDim     = 0,
+            Case1       = 0x4,
+            Case12      = 0x5,
+            Case112     = 0x6,
+            Case2       = 0x8,
+            Case212     = 0x9,
+            Case3       = 0x10,
+            Case31      = 0x11,
+            Case4       = 0x20,
+};
+
+// Nothing to do for serializing Empty, but still need to provide this function
+namespace boost {
+namespace serialization {
+
+template<class Archive, class T>
+void serialize(Archive & ar, Empty<T>&, const unsigned int )
+{}
+
+} // namespace serialization
+} // namespace boost
+
 #endif // __TYPES_H__
--- a/src/debug.cpp	Fri Aug 24 16:58:25 2007 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,81 +0,0 @@
-#include "sys.h"
-#include "debug.h"
-
-#ifdef CWDEBUG
-
-namespace dionysus
-{
-	namespace debug 
-	{
-		namespace channels 		// DEBUGCHANNELS is set to this in debug.h
-		{
-			namespace dc 
-			{
-		        // Add new debug channels here.
-				channel_ct filtration("FILTRATION");
-				channel_ct transpositions("TRANSPOS");
-				channel_ct vineyard("VINEYARD");
-				channel_ct cycle("CYCLE");
-				channel_ct lsfiltration("LSFILTRATION");
-				channel_ct orderlist("ORDERLIST");
-			}
-    	} // namespace DEBUGCHANNELS
-
-		// Initialize debugging code from new threads.
-		void init_thread(void)
-		{
-			// Everything below needs to be repeated at the start of every
-			// thread function, because every thread starts in a completely
-			// reset state with all debug channels off etc.
-		
-			#if LIBCWD_THREAD_SAFE		// For the non-threaded case this is set by the rcfile.
-			// Turn on all debug channels by default.
-			ForAllDebugChannels(while(!debugChannel.is_on()) debugChannel.on());
-			// Turn off specific debug channels.
-			Debug(dc::bfd.off());
-			Debug(dc::malloc.off());
-			#endif
-		
-			// Turn on debug output.
-			// Only turn on debug output when the environment variable SUPPRESS_DEBUG_OUTPUT is not set.
-			Debug(if (getenv("SUPPRESS_DEBUG_OUTPUT") == NULL) libcw_do.on());
-			#if LIBCWD_THREAD_SAFE
-			Debug(libcw_do.set_ostream(&std::cout, &cout_mutex));
-		
-			// Set the thread id in the margin.
-			char margin[12];
-			sprintf(margin, "%-10lu ", pthread_self());
-			Debug(libcw_do.margin().assign(margin, 11));
-			#else
-			Debug(libcw_do.set_ostream(&std::cout));
-			#endif
-		
-			// Write a list of all existing debug channels to the default debug device.
-			Debug(list_channels_on(libcw_do));
-		}
-		
-		// Initialize debugging code from main().
-		void init(void)
-		{
-			// You want this, unless you mix streams output with C output.
-			// Read  http://gcc.gnu.org/onlinedocs/libstdc++/27_io/howto.html#8 for an explanation.
-			// We can't use it, because other code uses printf to write to the console.
-			//std::ios::sync_with_stdio(false);
-
-			// This will warn you when you are using header files that do not belong to the
-			// shared libcwd object that you linked with.
-			Debug(check_configuration());
-		
-			#if CWDEBUG_ALLOC
-			// Remove all current (pre- main) allocations from the Allocated Memory Overview.
-			libcwd::make_all_allocations_invisible_except(NULL);
-			#endif
-			
-			//Debug(read_rcfile());
-			
-			init_thread();
-		}
-	} // namespace debug
-} // namespace dionysus
-
-#endif // CWDEBUG
--- a/tests/geometry/CMakeLists.txt	Fri Aug 24 16:58:25 2007 -0400
+++ b/tests/geometry/CMakeLists.txt	Tue Jun 27 09:37:05 2017 -0700
@@ -1,12 +1,17 @@
 set							(targets
 							 euclidean
-							 polynomial
-							 test-eventqueue
-							 test-kinetic-sort
-							 test-linalg)
+                             test-ksort-linear
+							 test-eventqueue)
+
+if                          (use_synaps)
+    set                     (targets                    ${targets}
+                                                        polynomial
+                                                        test-kinetic-sort
+							                            test-linalg)
+endif                       (use_synaps)
 
 foreach 					(t ${targets})
 	add_executable			(${t} ${t}.cpp)
-	target_link_libraries	(${t} ${synaps_libraries})
+	target_link_libraries	(${t} ${synaps_libraries} ${libraries})
 endforeach 					(t ${targets})
 
--- a/tests/geometry/polynomial.cpp	Fri Aug 24 16:58:25 2007 -0400
+++ b/tests/geometry/polynomial.cpp	Tue Jun 27 09:37:05 2017 -0700
@@ -7,7 +7,7 @@
 
 typedef UPolynomial<ZZ>						PolynomialKernel;
 typedef PolynomialKernel::Polynomial		Polynomial;
-typedef PolynomialKernel::RationalFunction	RationalF;
+typedef PolynomialKernel::Function	        RationalF;
 
 typedef Kernel<RationalF>					K;
 typedef K::Point							Point;
@@ -75,8 +75,6 @@
 		while (!roots.empty()) { std::cout << roots.top() << std::endl; roots.pop(); }
 	}
 
-	return 0;
-
 	// Edges
 	{
 		PointContainer vertices(2);
--- a/tests/geometry/test-eventqueue.cpp	Fri Aug 24 16:58:25 2007 -0400
+++ b/tests/geometry/test-eventqueue.cpp	Tue Jun 27 09:37:05 2017 -0700
@@ -4,20 +4,30 @@
 
 int main()
 {
-	typedef EventQueue<int, std::less<int> >			EQ;
+	typedef EventQueue<int, std::less<int> >            EQ;
 	typedef EQ::iterator								iterator;
 	 
 	EQ queue;
 
-	iterator i = queue.push(4);
-	queue.push(2);
-	queue.push(7);
-	iterator j = queue.push(6);
-	queue.push(5);
+    std::cout << "Queue initialized" << std::endl;
+
+	iterator i1 = queue.push(4);
+	iterator i2 = queue.push(2);
+	iterator i3 = queue.push(9);
+	iterator i4 = queue.push(6);
+	iterator i5 = queue.push(5);
 
-	*i = 8;
-	queue.update(i);
-	queue.remove(j);
+    std::cout << "Values inserted" << std::endl;
+    queue.print(std::cout, "  ");
+
+    queue.replace(i1,1);
+    queue.remove(i4);
+    queue.replace(i5,10);
+
+    *i3 = 14;
+    queue.demoted(i3);
+    
+    std::cout << "Replaced and removed" << std::endl;
 
 	while (!queue.empty())
 	{
--- a/tests/geometry/test-kinetic-sort.cpp	Fri Aug 24 16:58:25 2007 -0400
+++ b/tests/geometry/test-kinetic-sort.cpp	Tue Jun 27 09:37:05 2017 -0700
@@ -6,6 +6,8 @@
 #include <boost/utility.hpp>
 #include <boost/bind.hpp>
 
+#include <utilities/log.h>
+
 typedef		double							FieldType;
 //typedef		ZZ								FieldType;
 //typedef		QQ								FieldType;
@@ -37,14 +39,23 @@
 	s->splice(i, *s, boost::next(i));
 }
 
-int main()
+int main(int argc, char** argv)
 {
+#ifdef LOGGING
+    rlog::RLogInit(argc, argv);
+
+    stderrLog.subscribeTo( RLOG_CHANNEL("error") );
+    stdoutLog.subscribeTo( RLOG_CHANNEL("geometry/simulator") );
+    stdoutLog.subscribeTo( RLOG_CHANNEL("geometry/kinetic-sort") );
+#endif
+
 	SimulatorFT		simulator;
 	SortDS 			list;
 
 	// Insert polynomials and sort the list for current time
 	list.push_back(Polynomial("x^3 - 3"));
 	list.push_back(Polynomial("x^2 - 2*x - 2"));
+	list.push_back(Polynomial("x^2 - 2*x - 2"));
 	list.push_back(Polynomial("2*x - 4"));
 	list.push_back(Polynomial("x"));
 	list.push_back(Polynomial("-x + 4"));
@@ -59,12 +70,21 @@
 	// Setup kinetic sort
 	KineticSortDS	ks(list.begin(), list.end(), boost::bind(swap, &list, _1, _2), &simulator);
 
-	while(!simulator.reached_infinity() && simulator.current_time() < 4)
+    std::cout << "Examining " << simulator;
+
+	while(!simulator.reached_infinity())
 	{
 		std::cout << "Current time before: " << simulator.current_time() << std::endl;
 		//if (!ks.audit(&simulator)) return 1;
-		//simulator.print(std::cout << "Auditing ");
+		ks.audit(&simulator);
+        std::cout << "Examining " << simulator;
 		simulator.process();
 		std::cout << "Current time after: " << simulator.current_time() << std::endl;
 	}
+	ks.audit(&simulator);
+    std::cout << "Examining " << simulator;
+
+    std::cout << "Done at " << simulator.current_time() << std::endl;
+    for (SortDS::const_iterator cur = list.begin(); cur != list.end(); ++cur)
+        std::cout << "  " << *cur << std::endl;    
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/geometry/test-ksort-linear.cpp	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,88 @@
+#include <geometry/simulator.h>
+#include <geometry/kinetic-sort.h>
+#include <geometry/linear-kernel.h>
+#include <iostream>
+
+#include <boost/utility.hpp>
+#include <boost/bind.hpp>
+
+#include <utilities/log.h>
+
+typedef     double                          FieldType;
+//typedef       ZZ                              FieldType;
+//typedef       QQ                              FieldType;
+typedef     LinearKernel<FieldType>         LKernel;
+typedef     LKernel::Function               Function;
+typedef     std::list<Function>             SortDS;
+typedef     SortDS::iterator                SortDSIterator;
+typedef     Simulator<LKernel>              SimulatorFT;
+
+class TrajectoryExtractor
+{
+    public:
+        Function                operator()(SortDSIterator i) const          { return *i; }
+};
+
+typedef     KineticSort<SortDSIterator, TrajectoryExtractor, SimulatorFT>       KineticSortDS;
+
+struct EvaluatedComparison: public std::binary_function<const Function&, const Function&, bool>
+{
+                                EvaluatedComparison(FieldType v): vv(v) {}
+    bool                        operator()(const Function& p1, const Function& p2)              
+                                { return p1(vv) < p2(vv); }
+    FieldType                   vv;
+};
+
+void swap(SortDS* s, SortDSIterator i, SimulatorFT* simulator)
+{
+    std::cout << "Swapping " << *i << " " << *boost::next(i) << std::endl;
+    s->splice(i, *s, boost::next(i));
+}
+
+int main(int argc, char** argv)
+{
+#ifdef LOGGING
+    rlog::RLogInit(argc, argv);
+
+    stderrLog.subscribeTo( RLOG_CHANNEL("error") );
+    stdoutLog.subscribeTo( RLOG_CHANNEL("geometry/simulator") );
+    stdoutLog.subscribeTo( RLOG_CHANNEL("geometry/kinetic-sort") );
+#endif
+
+    SimulatorFT     simulator;
+    SortDS          list;
+
+    // Insert polynomials and sort the list for current time
+    list.push_back(Function(2, -2));
+    list.push_back(Function(1, 3));
+    list.push_back(Function(-1, 6));
+    list.push_back(Function(2));
+    list.push_back(Function(2, 2));
+    //list.sort(EvaluatedComparison(simulator.current_time()));
+    list.sort(EvaluatedComparison(0));
+
+    // Print out the list
+    for (SortDS::const_iterator cur = list.begin(); cur != list.end(); ++cur)
+        std::cout << *cur << std::endl;
+
+    // Setup kinetic sort
+    KineticSortDS   ks(list.begin(), list.end(), boost::bind(swap, &list, _1, _2), &simulator);
+
+    std::cout << "Examining " << simulator;
+
+    while(!simulator.reached_infinity())
+    {
+        std::cout << "Current time before: " << simulator.current_time() << std::endl;
+        //if (!ks.audit(&simulator)) return 1;
+        ks.audit(&simulator);
+        std::cout << "Examining " << simulator;
+        simulator.process();
+        std::cout << "Current time after: " << simulator.current_time() << std::endl;
+    }
+    ks.audit(&simulator);
+    std::cout << "Examining " << simulator;
+
+    std::cout << "Done at " << simulator.current_time() << std::endl;
+    for (SortDS::const_iterator cur = list.begin(); cur != list.end(); ++cur)
+        std::cout << "  " << *cur << std::endl;    
+}
--- a/tests/utilities/CMakeLists.txt	Fri Aug 24 16:58:25 2007 -0400
+++ b/tests/utilities/CMakeLists.txt	Tue Jun 27 09:37:05 2017 -0700
@@ -1,8 +1,13 @@
 set							(targets						
+							 test-set-iterators
 							 test-consistencylist
 							 test-orderlist)
 
+if                          (counters)
+    set                     (targets    ${targets} test-counters)
+endif                       (counters)
+
 foreach 					(t ${targets})
-	add_executable			(${t} ${t}.cpp ${external_sources})
+	add_executable			(${t} ${t}.cpp)
 	target_link_libraries	(${t} ${libraries})
 endforeach 					(t ${targets})
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/utilities/test-counters.cpp	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,33 @@
+#include <utilities/counter.h>
+
+static Counter* cTestElaborate = GetCounter("test/elaborate");
+static Counter* cTestBasic = GetCounter("test/basic");
+static Counter* cTestBasicSub = GetCounter("test/basic/sub");
+
+int main()
+{
+	SetFrequency(cTestBasic, 2);
+
+	Count(cTestBasic);
+	Count(cTestBasicSub);
+	Count(cTestBasicSub);
+	Count(cTestBasicSub);
+	Count(cTestElaborate);
+	Count(cTestBasic);
+	Count(cTestElaborate);
+	Count(cTestBasic);
+	Count(cTestBasic);
+	CountNum(cTestBasic, 25);
+	CountNum(cTestBasic, 132);
+	CountNum(cTestBasic, 25);
+	CountNum(cTestBasic, 121);
+	CountNum(cTestBasic, 132);
+	CountNum(cTestBasic, 25);
+	
+	SetTrigger(cTestBasic, &rootCounter);
+	Count(cTestBasic);
+	Count(cTestBasic);
+	
+	SetFrequency(cTestElaborate, 3);
+	Count(cTestElaborate);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/utilities/test-set-iterators.cpp	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,59 @@
+#include <vector>
+#include <list>
+#include <algorithm>
+#include <iostream>
+
+#include <utilities/indirect.h>
+
+#include <boost/lambda/lambda.hpp>
+using    boost::lambda::_1;
+
+int main()
+{
+    std::vector<int>    v;
+    v.push_back(1);
+    v.push_back(3);
+    v.push_back(5);
+    v.push_back(7);
+    v.push_back(9);
+    std::cout << "v: ";
+    std::for_each(v.begin(), v.end(), std::cout << _1 << ' ');
+    std::cout << std::endl;
+
+    std::list<int>      l;
+    l.push_back(2);
+    l.push_back(3);
+    l.push_back(4);
+    l.push_back(5);
+    l.push_back(6);
+    l.push_back(8);
+    std::cout << "l: ";
+    std::for_each(l.begin(), l.end(), std::cout << _1 << ' ');
+    std::cout << std::endl;
+    std::cout << std::endl;
+
+    std::cout << "v \\cap l: ";
+    std::for_each(make_intersection_iterator(v.begin(), v.end(), l.begin(), l.end(), std::less<int>()),
+                  make_intersection_iterator(v.end(),   v.end(), l.end(),   l.end(), std::less<int>()),
+                  std::cout << _1 << ' ');
+    std::cout << std::endl;
+    
+    std::cout << "v - l: ";
+    std::for_each(make_difference_iterator(v.begin(),   v.end(), l.begin(), l.end(), std::less<int>()),
+                  make_difference_iterator(v.end(),     v.end(), l.end(),   l.end(), std::less<int>()),
+                  std::cout << _1 << ' ');
+    std::cout << std::endl;
+    std::cout << std::endl;
+    
+    std::cout << "l \\cap v: ";
+    std::for_each(make_intersection_iterator(l.begin(), l.end(), v.begin(), v.end(), std::less<int>()),
+                  make_intersection_iterator(l.end(),   l.end(), v.end(),   v.end(), std::less<int>()),
+                  std::cout << _1 << ' ');
+    std::cout << std::endl;
+    
+    std::cout << "l - v: ";
+    std::for_each(make_difference_iterator(l.begin(),   l.end(), v.begin(), v.end(), std::less<int>()),
+                  make_difference_iterator(l.end(),     l.end(), v.end(),   v.end(), std::less<int>()),
+                  std::cout << _1 << ' ');
+    std::cout << std::endl;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/CMakeLists.txt	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,19 @@
+#find_package                (Qt4)
+
+#if                          (QT4_FOUND)
+#    set                     (QT_USE_QTOPENGL TRUE)
+#    set                     (QT_USE_QTXML TRUE)
+#    include                 (${QT_USE_FILE})
+
+#    add_subdirectory        (diagram-viewer)
+##find_library                (gle_LIBRARY                NAMES gle)
+##find_library                (QGLViewer_LIBRARY          NAMES QGLViewer)
+##find_path                   (QGLViewer_INCLUDE_DIR      QGLViewer/qglviewer.h)
+##include_directories         (${QGLViewer_INCLUDE_DIR})
+#endif                       (QT4_FOUND)
+
+
+add_executable              (extract-diagram                extract-diagram.cpp)
+target_link_libraries       (extract-diagram                ${libraries} ${Boost_SERIALIZATION_LIBRARY})
+
+add_subdirectory            (matching)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/diagram-viewer/CMakeLists.txt	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,18 @@
+set                         (diagram-viewerSources
+                             diagram.cpp 
+                             diagram-viewer-main.cpp)
+
+set                         (diagram-viewerHeaders
+                             diagram.h)
+
+qt4_wrap_cpp                (diagram-viewerMocSources       ${diagram-viewerHeaders})
+
+set                         (libraries                      ${libraries} 
+                                                            ${Boost_SERIALIZATION_LIBRARY}
+                                                            ${Boost_PROGRAM_OPTIONS_LIBRARY}
+                                                            ${QT_LIBRARIES})
+
+add_executable              (diagram-viewer                 ${diagram-viewerSources} 
+                                                            ${diagram-viewerMocSources})
+
+target_link_libraries       (diagram-viewer                 ${libraries})
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/diagram-viewer/diagram-viewer-main.cpp	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,59 @@
+#include <qapplication.h>
+#include <QtGui>
+
+#include "diagram.h"
+
+#include <fstream>
+#include <map>
+#include <boost/archive/binary_iarchive.hpp>
+#include <boost/serialization/map.hpp>
+
+#include <boost/program_options.hpp>
+namespace po = boost::program_options;
+
+
+int main (int argc, char *argv[])
+{
+    std::string     diagrams_filename;
+    int dimension;
+
+    po::options_description hidden("Hidden options");
+    hidden.add_options()
+        ("diagrams-file",  po::value<std::string>(&diagrams_filename),  "The collection of persistence diagrams")
+        ("dimension",      po::value<int>(&dimension),                  "Dimension of the diagram to show");
+
+    po::positional_options_description p;
+    p.add("diagrams-file", 1);
+    p.add("dimension", 2);
+    
+    po::options_description all; all.add(hidden);
+
+    po::variables_map vm;
+    po::store(po::command_line_parser(argc, argv).
+                  options(all).positional(p).run(), vm);
+    po::notify(vm);
+
+    if (!vm.count("diagrams-file") || !vm.count("dimension"))
+    { 
+        std::cout << "Usage: " << argv[0] << " diagrams-file dimension" << std::endl;
+        std::cout << hidden << std::endl; 
+        return 1; 
+    }
+
+    std::map<Dimension, PDiagram>       dgms;
+    std::ifstream ifs(diagrams_filename.c_str());
+    boost::archive::binary_iarchive ia(ifs);
+    ia >> dgms;
+    
+    
+    QApplication application(argc, argv);
+
+    std::cout << dimension << std::endl;
+    std::cout << dgms[dimension] << std::endl;
+
+    DgmViewer pd(dgms[dimension]);
+    pd.show();
+
+    // Run main loop.
+    return application.exec();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/diagram-viewer/diagram.cpp	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,95 @@
+#include <iostream>
+
+#include <QtGui>
+#include <QRectF>
+
+#include "diagram.h"
+#include <cmath>
+
+//static const double ellipse_size        = 0.035;
+static const double ellipse_size        = 3;
+
+/* DgmViewer Implementation */
+DgmViewer::DgmViewer(const PDiagram& dgm):
+    min_x(0), min_y(0), max_x(0), max_y(0)
+{
+    points.reserve(dgm.size());
+    
+    for (PDiagram::const_iterator cur = dgm.begin(); cur != dgm.end(); ++cur)
+    {
+        min_x = std::min(min_x, cur->x());
+        min_y = std::min(min_y, cur->y());
+        max_x = std::max(max_x, cur->x());
+        max_y = std::max(max_y, cur->y());
+
+        points.push_back(new DgmPoint(*cur, ellipse_size));
+    }
+        
+    addDgmPoints();
+    setWindowTitle(QString("Persistence Diagram"));
+}
+DgmViewer::~DgmViewer()
+{
+    for (PointsVector::iterator cur = points.begin(); cur != points.end(); ++cur)
+        delete *cur;
+}
+
+
+void DgmViewer::addDgmPoints()
+{    
+    RealType min = std::min(min_x, min_y);
+    RealType max = std::max(max_x, max_y);
+
+    QGraphicsLineItem* diagonal = new QGraphicsLineItem(QLineF(min, -min, max, -max));
+    QGraphicsLineItem* y_axis = new QGraphicsLineItem(QLineF(0, -min_y, 0, -max_y));
+    QGraphicsLineItem* x_axis = new QGraphicsLineItem(QLineF(min_x, 0, max_x, 0));
+
+    scene.addItem(diagonal);
+    scene.addItem(y_axis);
+    scene.addItem(x_axis);
+
+    for (PointsVector::const_iterator cur = points.begin(); cur != points.end(); ++cur)
+        scene.addItem(*cur);
+
+    //scale(100,100);
+    setScene(&scene);
+    setRenderHint(QPainter::Antialiasing);
+    ensureVisible(scene.itemsBoundingRect());
+    //setMinimumSize( (int)(maxX - minX)*100 + 100, (int) (maxY - minY)*100 + 100);
+}
+
+
+DgmPoint::DgmPoint(QGraphicsItem* parent): 
+    QGraphicsItem(parent) 
+{
+}
+
+DgmPoint::DgmPoint(const Parent& pt, qreal size, QGraphicsItem *parent):
+    Parent(pt), ellipse_size(size), QGraphicsItem(parent)
+{
+    setToolTip(QString("(%1, %2)").arg(getX()).arg(getY()));
+}
+
+DgmPoint::DgmPoint(RealType b, RealType d, qreal size, QGraphicsItem *parent): 
+    Parent(b, d), ellipse_size(size), QGraphicsItem(parent)
+{
+    setToolTip(QString("(%1, %2)").arg(getX()).arg(getY()));
+}
+
+void DgmPoint::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+{
+    Q_UNUSED(option);
+    Q_UNUSED(widget);
+
+    //QBrush solidFill(unselectColor);
+    //QBRush selectSolidFill(selectColor);
+    painter->setBrush(Qt::SolidPattern);
+    //painter->setPen(selectColor);
+    painter->drawEllipse(QRectF(getX() - ellipse_size, -getY() - ellipse_size, 2*ellipse_size, 2*ellipse_size));
+}
+
+
+QRectF DgmPoint::boundingRect() const
+{
+    return QRectF(getX() - ellipse_size, -getY() - ellipse_size, 2*ellipse_size, 2*ellipse_size);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/diagram-viewer/diagram.h	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,60 @@
+#ifndef __DIAGRAM_H__
+#define __DIAGRAM_H__
+
+#include <QtGui>
+#include <QObject>
+#include <QColor>
+
+#include <map>
+
+#include <utilities/types.h>
+#include <topology/persistence-diagram.h>
+
+typedef         PersistenceDiagram<>                PDiagram;
+typedef         std::map<Dimension, PDiagram>       Diagrams;
+
+class DgmPoint;
+
+class DgmViewer: public QGraphicsView
+{
+    Q_OBJECT
+
+    public:
+        typedef             std::vector<DgmPoint*>          PointsVector;
+
+                            DgmViewer(const PDiagram& dgm);
+                            ~DgmViewer();
+
+        void                addDgmPoints();
+
+    private:
+        PointsVector        points;
+        QGraphicsScene      scene;
+        RealType            min_x, min_y, max_x, max_y;
+};
+
+
+class DgmPoint: public PDPoint<>, public QGraphicsItem
+{
+    public:
+        typedef             PDPoint<>                                       Parent;
+
+                            DgmPoint(QGraphicsItem* parent = 0);
+                            DgmPoint(const Parent& pt, qreal size, QGraphicsItem *parent = 0); 
+                            DgmPoint(RealType b, RealType d, qreal size, QGraphicsItem *parent = 0); 
+        
+        void                paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
+        QRectF                 boundingRect() const;
+        
+        qreal               getX() const                    { return Parent::x(); }
+        qreal               getY() const                    { return Parent::y(); }
+
+        int                 type() const                                    { return QGraphicsItem::UserType + 1; }
+
+    private:
+        // size of rectangle containing ellipses
+        qreal                 ellipse_size;
+};
+
+
+#endif // __DIAGRAM_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/draw-diagram/draw.py	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,25 @@
+#!/usr/bin/env python2
+
+import  pd
+from    sys         import argv, exit
+
+if len(argv) < 2:
+    print "Usage: %s FILENAME [MULTIPLIER=1] [NOISE=0] [RADIUS=.15] [DIMENSIONS=XMIN,YMIN,XMAX,YMAX]" % argv[0]
+    print "  MULTIPLIER -   multiply coordinates of each point by this quantity"
+    print "  NOISE -        filter out points below this persistence"
+    print "  RADIUS -       radius of a point in the persistence diagram"
+    print "  DIMENSIONS -   dimensions of the persistence diagram"
+    print 
+    print "  Example: %s torus.dgm 1 0 .05 -1,-1,10,10" % argv[0]
+    exit()
+
+multiplier =    float(argv[2])                  if len(argv) > 2    else 1
+noise =         float(argv[3])                  if len(argv) > 3    else 0
+R =             float(argv[4])                  if len(argv) > 4    else .15
+dimensions =    map(float, argv[5].split(','))  if len(argv) > 5    else None
+
+noise_filter =   pd.noise_filter(noise)
+amplify_filter = pd.amplify_filter(multiplier)
+
+dgm = pd.PersistenceDiagram(argv[1], lambda x,y: noise_filter(x,y) and amplify_filter(x,y))
+dgm.savePDF(argv[1] + '.', radius = R, dimensions = dimensions)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/draw-diagram/pd.py	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,113 @@
+#!/usr/bin/env python2
+
+# Author: Dmitriy Morozov <morozov@cs.duke.edu>
+# (2004-2008) Department of Computer Science, Duke University
+
+import pyx, string, sys, math
+
+class PersistenceDiagram:
+    def drawAxes(self,c,radius,spacing = 1, dimensions = None):
+        if not dimensions:
+            xmax = math.ceil(max(self.xmax,1) + radius + 1)
+            xmin = math.floor(min(self.xmin,-1) - radius - 1)
+            ymax = math.ceil(max(self.ymax,1) + radius + 1)
+            ymin = math.floor(min(self.ymin,-1) - radius - 1)
+        else:
+            xmin,ymin,xmax,ymax = dimensions
+
+        minmax = min([xmax, ymax])
+        maxmin = max([xmin, ymin])
+        for i in xrange(int(math.floor(xmin)),int(math.ceil(xmax)), spacing):
+            c.stroke(pyx.path.line(i,ymin,i,ymax), [pyx.style.linestyle.dashed, pyx.color.gray(0.5)])
+        for j in xrange(int(math.floor(ymin)),int(math.ceil(ymax)), spacing):
+            c.stroke(pyx.path.line(xmin,j,xmax,j), [pyx.style.linestyle.dashed, pyx.color.gray(0.5)])
+        c.stroke(pyx.path.line(xmin,0,xmax,0), [pyx.deco.earrow.normal])
+        c.stroke(pyx.path.line(0,ymin,0,ymax), [pyx.deco.earrow.normal])
+        c.stroke(pyx.path.line(maxmin,maxmin,minmax,minmax))
+
+
+    def drawCanvas(self, c, points, color = 'red', filled = 1, radius = 0.15):
+        for p in points:
+            self.drawPoint(c,p,color,filled,radius)
+
+    def drawPoint(self,c,p, color = 'red', filled = 1, radius = 0.15):
+        if color == 'red':
+            options = [pyx.color.rgb.red]
+        elif color == 'blue':
+            options = [pyx.color.rgb.blue]
+        elif color == 'green':
+            options = [pyx.color.rgb.green]
+        else:
+            options = []
+
+        if filled:
+            draw = c.fill
+        else:
+            draw = c.stroke
+
+        xmax = max(self.xmax,1)
+        xmin = min(self.xmin,-1)
+        ymax = max(self.ymax,1)
+        ymin = min(self.ymin,-1)
+
+        x,y = p
+        if abs(x) == float('inf') or abs(y) == float('inf'): radius = radius * 2
+        if x == float('inf'): x = xmax + 1
+        if x == float('-inf'): x = xmin - 1
+        if y == float('inf'): y = ymax + 1
+        if y == float('-inf'): y = ymin -1
+
+        draw(pyx.path.circle(x,y,radius), options)
+
+    def savePDF(self, filename, color = 'red', filled = 1, radius = 0.15, axes = 1, dimensions = None):
+        for d in self.points.keys():
+            c = pyx.canvas.canvas()
+            self.drawAxes(c, radius, axes, dimensions)
+            self.drawCanvas(c, self.points[d], color, filled, radius)
+            c.writePDFfile(filename + str(d))
+
+    def add(self, d, p, filter):
+        x,y = p
+        p = filter(x,y)
+        if not p: return
+        x,y = p
+
+        if d not in self.points.keys():
+            self.points[d] = []
+        self.points[d] += [(x,y)]
+
+        if abs(x) != float('inf'):
+            self.xmax = max(x,self.xmax)
+            self.xmin = min(x,self.xmin)
+        if abs(y) != float('inf'):
+            self.ymax = max(y,self.ymax)
+            self.ymin = min(y,self.ymin)
+
+    def load(self,filename, filter):
+        self.xmax = self.ymax = 0
+        self.xmin = self.ymin = 0
+        f = file(filename, 'r')
+        for line in f:
+            if line.strip().startswith('#'): continue
+            dim,xstr,ystr = string.split(line)[:3]
+            self.add(dim, (float(xstr),float(ystr)), filter)
+
+    def __init__(self, filename, filter = lambda x,y: (x,y)):
+        self.points = {}
+        self.load(filename, filter)
+
+
+def noise_filter(epsilon):
+    def noise(x,y):
+        if y - x <= epsilon: return None
+        return (x,y)
+
+    return noise
+
+def amplify_filter(x_mult, y_mult = None):
+    if not y_mult: y_mult = x_mult
+
+    def amplify(x,y):
+        return (x_mult*x, y_mult*y)
+
+    return amplify
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/extract-diagram.cpp	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,30 @@
+#include <topology/persistence-diagram.h>
+
+#include <string>
+#include <map>
+#include <iostream>
+
+#include <fstream>
+#include <boost/archive/binary_iarchive.hpp>
+#include <boost/serialization/map.hpp>
+
+typedef PersistenceDiagram<>                    PDgm;
+
+int main(int argc, char** argv)
+{
+    if (argc < 2)
+    {
+        std::cout << "Usage: " << argv[0] << " FILENAME" << std::endl;
+        return 0;
+    }
+    std::string infilename = argv[1];
+    
+    std::ifstream ifs(infilename.c_str());
+    boost::archive::binary_iarchive ia(ifs);
+    
+    std::map<Dimension, PDgm> dgms;
+    ia >> dgms;
+    for (std::map<Dimension, PDgm>::const_iterator cur = dgms.begin(); cur != dgms.end(); ++cur)
+        for (PDgm::const_iterator pcur = cur->second.begin(); pcur != cur->second.end(); ++pcur)
+            std::cout << cur->first << " " << pcur->x() << " " << pcur->y() << std::endl;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/matching/CMakeLists.txt	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,9 @@
+set                             (libraries                      ${libraries} 
+                                                                ${Boost_PROGRAM_OPTIONS_LIBRARY})
+
+# Build compare-diagrams
+add_executable                  (bottleneck                     bottleneck.cpp)
+target_link_libraries           (bottleneck                     ${libraries})
+
+add_executable                  (wasserstein                     wasserstein.cpp)
+target_link_libraries           (wasserstein                     ${libraries})
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/matching/bottleneck.cpp	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,66 @@
+#include <iostream>
+#include <fstream>
+
+#include <topology/persistence-diagram.h>
+
+#include <boost/program_options.hpp>
+namespace po = boost::program_options;
+
+typedef PersistenceDiagram<>                    PDgm;
+typedef PDgm::Point                             Point;
+
+
+void    read_diagram(const std::string& filename, PDgm& dgm);
+void    process_program_options(int argc, char* argv[], std::string& filename1, std::string& filename2);
+
+
+int main(int argc, char* argv[])
+{
+    std::string     filename1, filename2;
+    process_program_options(argc, argv, filename1, filename2);
+
+    PDgm dgm1, dgm2;
+    read_diagram(filename1, dgm1);
+    read_diagram(filename2, dgm2);
+
+    std::cout << bottleneck_distance(dgm1, dgm2) << std::endl;
+}
+
+
+void    read_diagram(const std::string& filename, PDgm& dgm)
+{
+    std::ifstream in(filename.c_str());
+    double birth, death;
+    while(in)
+    {
+        in >> birth >> death;
+        //std::cout << "birth: " << birth << ", death: " << death << std::endl;
+        if (in)
+            dgm.push_back(Point(birth, death));
+    }
+}
+
+void    process_program_options(int     argc, char* argv[], std::string& filename1, std::string& filename2)
+{
+    po::options_description hidden("Hidden options");
+    hidden.add_options()
+        ("input-file1",  po::value<std::string>(&filename1), "The first collection of persistence diagrams")
+        ("input-file2",  po::value<std::string>(&filename2), "The second collection of persistence diagrams");
+
+    po::positional_options_description p;
+    p.add("input-file1", 1);
+    p.add("input-file2", 2);
+    
+    po::options_description all; all.add(hidden);
+
+    po::variables_map vm;
+    po::store(po::command_line_parser(argc, argv).
+                  options(all).positional(p).run(), vm);
+    po::notify(vm);
+
+    if (!vm.count("input-file1") || !vm.count("input-file2"))
+    { 
+        std::cout << "Usage: " << argv[0] << " input-file1 input-file2" << std::endl;
+        std::abort();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/matching/wasserstein.cpp	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,74 @@
+#include <iostream>
+#include <fstream>
+
+#include <topology/persistence-diagram.h>
+
+#include <boost/program_options.hpp>
+namespace po = boost::program_options;
+
+typedef PersistenceDiagram<>                    PDgm;
+typedef PDgm::Point                             Point;
+
+
+void    read_diagram(const std::string& filename, PDgm& dgm);
+void    process_program_options(int argc, char* argv[], std::string& filename1, std::string& filename2, double& wasserPower);
+
+
+int main(int argc, char* argv[])
+{
+    std::string     filename1, filename2;
+    double wasserPower;
+    process_program_options(argc, argv, filename1, filename2, wasserPower);
+
+    PDgm dgm1, dgm2;
+    read_diagram(filename1, dgm1);
+    read_diagram(filename2, dgm2);
+
+    std::cout << pow(wasserstein_distance(dgm1, dgm2, wasserPower), 1.0 / wasserPower) << std::endl;
+}
+
+
+void    read_diagram(const std::string& filename, PDgm& dgm)
+{
+    std::ifstream in(filename.c_str());
+    double birth, death;
+    while(in)
+    {
+        in >> birth >> death;
+        //std::cout << "birth: " << birth << ", death: " << death << std::endl;
+        if (in)
+            dgm.push_back(Point(birth, death));
+    }
+}
+
+void    process_program_options(int     argc, char* argv[], std::string& filename1, std::string& filename2, double& wasserPower)
+{
+    po::options_description hidden("Hidden options");
+    hidden.add_options()
+        ("input-file1",  po::value<std::string>(&filename1), "The first collection of persistence diagrams")
+        ("input-file2",  po::value<std::string>(&filename2), "The second collection of persistence diagrams")
+        ("wasser-power",  po::value<double>(&wasserPower), "The power of Wasserstein distance");
+
+    po::positional_options_description p;
+    p.add("input-file1", 1);
+    p.add("input-file2", 1);
+    p.add("wasser-power", 1);
+    
+    po::options_description all; all.add(hidden);
+
+    po::variables_map vm;
+    po::store(po::command_line_parser(argc, argv).
+                  options(all).positional(p).run(), vm);
+    po::notify(vm);
+
+    if (!vm.count("input-file1") || !vm.count("input-file2"))
+    { 
+        std::cout << "Usage: " << argv[0] << " input-file1 input-file2" << std::endl;
+        std::abort();
+    }
+    if (!vm.count("wasser-power")) 
+    {
+        // use L2 by default
+        wasserPower = 2;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/plot-values/plot.py	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,52 @@
+#!/usr/bin/env python
+
+from    pylab           import scatter, show, cm, colorbar, savefig, axis, \
+                               figure, xlim, axes, hsv, subplots_adjust as adjust
+from    itertools       import izip
+from    sys             import argv, exit
+import  os.path         as     osp
+
+
+def plot(val_fn, pts_fn, output_fn):
+    points = []
+    with open(pts_fn) as fp:
+        for line in fp.xreadlines():
+            points.append(map(float, line.split()))
+    
+    values = []
+    with open(val_fn) as fp:
+        for line in fp.xreadlines():
+            values.append(float(line.split()[1]))
+
+    xx = [pt[0] for pt in points]
+    yy = [pt[1] for pt in points]
+    print "X:", min(xx), max(xx)
+    print "Y:", min(yy), max(yy)
+
+    m = min(values)
+    values = [(v-m) % 1. for v in values]
+    print "V:", min(values), max(values)
+
+    # hsv()
+    fig = figure()
+    scatter(xx,yy,s=10,c=values)
+    colorbar()
+    
+    # ax = fig.add_axes([-.05,-.1,1.1,1.1])
+    ax = axes()
+    ax.set_axis_off()
+    ax.set_aspect('equal', 'box')
+    # adjust(0,0,1,1,0,0)
+
+    fig.savefig(output_fn)
+
+if __name__ == '__main__':
+    if len(argv) < 3:
+        print "Usage: %s VALUES POINTS" % argv[0]
+        exit()
+
+    val_fn = argv[1]
+    pts_fn  = argv[2]
+    output_fn, ext = osp.splitext(val_fn)
+    output_fn += '.pdf'
+    plot(val_fn, pts_fn, output_fn)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/plot-values/scatter.py	Tue Jun 27 09:37:05 2017 -0700
@@ -0,0 +1,43 @@
+#!/usr/bin/env python
+
+from    pylab           import scatter, show, cm, colorbar, axes, savefig
+from    itertools       import izip
+from    sys             import argv, exit
+import  os.path         as     osp
+
+
+def plot(val1_fn, val2_fn, outfn = None):
+    values1 = []
+    with open(val1_fn) as fp:
+        for line in fp.xreadlines():
+            values1.append(float(line.split()[1]))
+    
+    values2 = []
+    with open(val2_fn) as fp:
+        for line in fp.xreadlines():
+            values2.append(float(line.split()[1]))
+    
+    values1 = [v % 1. for v in values1]
+    values2 = [v % 1. for v in values2]
+    print min(values1), max(values2), min(values1), min(values2)
+
+    scatter(values1, values2, s=10)
+    axes().set_aspect('equal')
+    if not outfn:
+        show()
+    else:
+        savefig(outfn)
+
+if __name__ == '__main__':
+    if len(argv) < 3:
+        print "Usage: %s VALUES1 VALUES2 [OUTPUT]" % argv[0]
+        exit()
+
+    val1_fn = argv[1]
+    val2_fn  = argv[2]
+    
+    outfn = None
+    if len(argv) > 3: 
+        outfn = argv[3]
+
+    plot(val1_fn, val2_fn, outfn)