         for s in done {
             let a1 = g(f(s)) - C(s)
             let a2 = h(C(s).boundary()) + h(s).boundary()
-            assert(a1 == a2, "(gf - 1)(\(s)) = \(a1),\n(h∂ + ∂h)(\(s)) = \(a2)\n\nf:\(fTable),\n\nh:\(hTable)\n\n")
+            assert(a1 == a2, "(gf - 1)(\(s)) = \(a1),\n(h∂ + ∂h)(\(s)) = \(a2)\n")
         }
         
         for s in generators {
             let b1 = f(g(s))
-            assert(b1 == C(s), "fg(\(s)) = \(b1)\n\nf:\(fTable),\nh:\(hTable)\n\n")
+            assert(b1 == C(s), "fg(\(s)) = \(b1)\n")
         }
         
         for s in generators.filter({ diff[$0] == nil}) {
             let b = g(s).boundary()
-            assert(b == C.zero, "∂s = \(b), should be 0.")
+            assert(b == C.zero, "∂s = \(b), should be 0.\n")
         }
     }
 }

            } else {
                log("\tadd: \(s) with diff: \(f_bs)")
                
                generators.append(s)
                fTable[s] = C(s)
                
                relations.append(f_bs)
                diff[s] = f_bs
            }
            
            fTable = fTable.filter{ $0.1 != C.zero }
            hTable = hTable.filter{ $0.1 != C.zero }
            relations = relations.filter{ $0 != C.zero }
        }
        
        done.insert(s)
        
        log("\tgenerators: \(generators)")
        log("")
        
//        assertChainContraction()

        return c.sum{ (s, a) in a * g(s) }
    }
    
    internal func h(_ s: S, path: Bool = false) -> C {
        return hTable[s]!.sum { (t, a) in
            if t.dim == s.dim + 1 || (path && t == s) {
                return a * C(t)
            } else if s != t {
                return a * h(t, path: path)
            } else {
                return C.zero
            }
        }
    }
    
    internal func h(_ c: C, path: Bool = false) -> C {
        return c.sum{ (s, a) in a * h(s, path: path) }
    }
    
    internal func isZero(_ c: C) -> Bool {
