Esempio n. 1
0
 def run_homology_selftest(output=sys.stdout):
     ok = True
     # second, try known cases and inspect results
     for (g, n, ok) in [ (0,3, [1,0,0]),
                         (0,4, [1,2,0,0,0,0]),
                         (0,5, [1,5,6,0,0,0,0,0,0]),
                         (1,1, [1,0,0]),
                         (1,2, [1,0,0,0,0,0]),
                         (2,1, [1,0,1,0,0,0,0,0,0]),
                         ]:
         output.write("  Computation of M_{%d,%d} homology: " % (g,n))
         # compute homology of M_{g,n}
         timing.start("homology M%d,%d" % (g,n))
         hs = compute_homology(g,n)
         timing.stop("homology M%d,%d" % (g,n))
         # check result
         if hs == ok:
             output.write("OK (elapsed: %0.3fs)\n"
                          % timing.get("homology M%d,%d" % (g,n)))
         else:
             logging.error("Computation of M_{%d,%d} homology: FAILED, got %s expected %s"
                           % (g,n,hs,ok))
             output.write("FAILED, got %s expected %s\n" % (hs,ok))
             ok = False
     return ok
Esempio n. 2
0
 def compute_boundary_operators(self):
     #: Matrix form of boundary operators; the `i`-th differential
     #: `D[i]` is `dim C[i-1]` rows (range) by `dim C[i]` columns
     #: (domain).
     m = self.module  # micro-optimization
     D = DifferentialComplex()
     D.append(NullMatrix, 0, len(m[0]))
     for i in xrange(1, len(self)):
         timing.start("D[%d]" % i)
         p = len(m[i - 1])  # == dim C[i-1]
         q = len(m[i])  # == dim C[i]
         try:
             checkpoint = os.path.join(runtime.options.checkpoint_dir,
                                       ('M%d,%d-D%d.sms' %
                                        (runtime.g, runtime.n, i)))
         except AttributeError:
             checkpoint = None
         # maybe load `D[i]` from persistent storage
         if checkpoint and p > 0 and q > 0 and runtime.options.restart:
             d = SimpleMatrix(p, q)
             if d.load(checkpoint):
                 D.append(d, p, q)
                 logging.info("  Loaded %dx%d matrix D[%d] from file '%s'",
                              p, q, i, checkpoint)
                 continue  # with next `i`
         # compute `D[i]`
         d = SimpleMatrix(p, q)
         j0 = 0
         for pool1 in m[i].iterblocks():
             k0 = 0
             for pool2 in m[i - 1].iterblocks():
                 for edgeno in xrange(pool1.graph.num_edges):
                     if pool1.graph.is_loop(edgeno):
                         continue  # with next `edgeno`
                     for (j, k, s) in NumberedFatgraphPool.facets(
                             pool1, edgeno, pool2):
                         assert k < len(pool2)
                         assert j < len(pool1)
                         assert k + k0 < p
                         assert j + j0 < q
                         d.addToEntry(k + k0, j + j0, s)
                 k0 += len(pool2)
                 # # `pool2` will never be used again, so clear it from the cache.
                 # # XXX: using implementation detail!
                 # pool2.graph._cache_isomorphisms.clear()
             j0 += len(pool1)
             # `pool1` will never be used again, so clear it from the cache.
             # XXX: using implementation detail!
             pool1.graph._cache_isomorphisms.clear()
         timing.stop("D[%d]" % i)
         if checkpoint:
             d.save(checkpoint)
         D.append(d, p, q)
         logging.info("  Computed %dx%d matrix D[%d] (elapsed: %.3fs)", p,
                      q, i, timing.get("D[%d]" % i))
     return D
Esempio n. 3
0
 def compute_boundary_operators(self):
     #: Matrix form of boundary operators; the `i`-th differential
     #: `D[i]` is `dim C[i-1]` rows (range) by `dim C[i]` columns
     #: (domain).
     m = self.module # micro-optimization
     D = DifferentialComplex()
     D.append(NullMatrix, 0, len(m[0]))
     for i in xrange(1, len(self)):
         timing.start("D[%d]" % i)
         p = len(m[i-1]) # == dim C[i-1]
         q = len(m[i])   # == dim C[i]
         try:
             checkpoint = os.path.join(runtime.options.checkpoint_dir,
                                       ('M%d,%d-D%d.sms' % (runtime.g, runtime.n, i)))
         except AttributeError:
             checkpoint = None
         # maybe load `D[i]` from persistent storage
         if checkpoint and p>0 and q>0 and runtime.options.restart:
             d = SimpleMatrix(p, q)
             if d.load(checkpoint):
                 D.append(d, p, q)
                 logging.info("  Loaded %dx%d matrix D[%d] from file '%s'",
                              p, q, i, checkpoint)
                 continue # with next `i`
         # compute `D[i]`
         d = SimpleMatrix(p, q)
         j0 = 0
         for pool1 in m[i].iterblocks():
             k0 = 0
             for pool2 in m[i-1].iterblocks():
                 for edgeno in xrange(pool1.graph.num_edges):
                     if pool1.graph.is_loop(edgeno):
                         continue # with next `edgeno`
                     for (j, k, s) in NumberedFatgraphPool.facets(pool1, edgeno, pool2):
                         assert k < len(pool2)
                         assert j < len(pool1)
                         assert k+k0 < p
                         assert j+j0 < q
                         d.addToEntry(k+k0, j+j0, s)
                 k0 += len(pool2)
                 # # `pool2` will never be used again, so clear it from the cache.
                 # # XXX: using implementation detail!
                 # pool2.graph._cache_isomorphisms.clear()
             j0 += len(pool1)
             # `pool1` will never be used again, so clear it from the cache.
             # XXX: using implementation detail!
             pool1.graph._cache_isomorphisms.clear()
         timing.stop("D[%d]" % i)
         if checkpoint:
             d.save(checkpoint)
         D.append(d, p, q)
         logging.info("  Computed %dx%d matrix D[%d] (elapsed: %.3fs)", 
                      p, q, i, timing.get("D[%d]" % i))
     return D
Esempio n. 4
0
    def compute_homology_ranks(self):
        """Compute and return (list of) homology group ranks.

        Returns a list of integers: item at index `n` is the rank of
        the `n`-th homology group of this differential complex.  Since
        the differential complex has finite length, homology group
        indices can only run from 0 to the length of the complex (all
        other groups being, trivially, null).
        """
        # check that the differentials form a complex
        # if __debug__:
        #     for i in xrange(1, len(self)-1):
        #         assert is_null_product(self[i-1][0], self[i][0]), \
        #                "DifferentialComplex.compute_homology_ranks:" \
        #                " Product of boundary operator matrices D[%d] and D[%d]" \
        #                " is not null!" \
        #                % (i-1, i)

        #: ranks of `D[n]` matrices, for 0 <= n < len(self); the differential
        #: `D[0]` is the null map.
        ranks = list()
        # only compute those ranks that were not saved
        for (i, (A, ddim, cdim)) in enumerate(self):
            try:
                checkpoint = (os.path.join(
                    runtime.options.checkpoint_dir,
                    "M%d,%d-rkD%d.txt" % (runtime.g, runtime.n, i)))
            except AttributeError:
                # running tests, so no `runtime.options`
                checkpoint = None
            # XXX: LinBox segfaults if asked to compute the rank of a 0xL matrix
            if A.num_rows > 0 and A.num_columns > 0:
                rs = None
                if checkpoint is not None and runtime.options.restart:
                    rs = load(checkpoint)
                    if rs:
                        r = rs[0]
                        logging.info("  rank D[%d]=%d (loaded from file '%s')",
                                     i, r, checkpoint)
                if rs is None:  # `rs` was not loaded from checkpoint file
                    timing.start("rank D[%d]" % i)
                    r = A.rank()
                    timing.stop("rank D[%d]" % i)
                    # checkpoint the computation so far
                    if checkpoint is not None:
                        save([r], checkpoint)
                    logging.info("  rank D[%d]=%d (computed in %.3fs)", i, r,
                                 timing.get("rank D[%d]" % i))
            else:  # A is a 0xL matrix
                r = 0
                logging.info("  rank D[%d]=%d (immediate)", i, r)
            ranks.append(r)

        ## compute homology group ranks from rank and nullity
        ## of boundary operators.
        ##
        ## By the rank-nullity theorem, if A:V-->W is a linear map,
        ## then null(A) =  dim(V) - rk(A), hence:
        ##   dim(Z_i) = null(D_i) = dim(C_i) - rk(D_i)
        ##   dim(B_i) = rk(D_{i+1})
        ## Therefore:
        ##   h_i = dim(H_i) = dim(Z_i / B_i) = dim(Z_i) - dim(B_i)
        ##       = (dim(C_i) - rk(D_i)) - rk(D_{i+1})
        ##       = dim(C_i) - (rk(D_i) + rk(D_{i+1}))
        ## where D_i:C_i-->C_{i+1}
        ##
        domain_dim = [ddim for (A, ddim, cdim) in self]
        domain_dim.append(self[-1][2])  # add dimension of last vector space
        ranks.append(0)  # augment complex with the null map.
        # note: `domain_dim` indices are offset by 1 w.r.t. to `ranks` indices
        return [(domain_dim[i + 1] - ranks[i] - ranks[i + 1])
                for i in xrange(len(self))]
Esempio n. 5
0
    def compute_homology_ranks(self):
        """Compute and return (list of) homology group ranks.

        Returns a list of integers: item at index `n` is the rank of
        the `n`-th homology group of this differential complex.  Since
        the differential complex has finite length, homology group
        indices can only run from 0 to the length of the complex (all
        other groups being, trivially, null).
        """
        # check that the differentials form a complex
        # if __debug__:
        #     for i in xrange(1, len(self)-1):
        #         assert is_null_product(self[i-1][0], self[i][0]), \
        #                "DifferentialComplex.compute_homology_ranks:" \
        #                " Product of boundary operator matrices D[%d] and D[%d]" \
        #                " is not null!" \
        #                % (i-1, i)

        #: ranks of `D[n]` matrices, for 0 <= n < len(self); the differential
        #: `D[0]` is the null map.
        ranks = list()
        # only compute those ranks that were not saved
        for (i, (A, ddim, cdim)) in enumerate(self):
            try:
                checkpoint = (os.path.join(runtime.options.checkpoint_dir,
                                           "M%d,%d-rkD%d.txt" % (runtime.g, runtime.n, i)))
            except AttributeError:
                # running tests, so no `runtime.options`
                checkpoint = None
            # XXX: LinBox segfaults if asked to compute the rank of a 0xL matrix
            if A.num_rows > 0 and A.num_columns > 0:
                rs = None
                if checkpoint is not None and runtime.options.restart:
                    rs = load(checkpoint)
                    if rs:
                        r = rs[0]
                        logging.info("  rank D[%d]=%d (loaded from file '%s')",
                                     i, r, checkpoint)
                if rs is None: # `rs` was not loaded from checkpoint file
                    timing.start("rank D[%d]" % i)
                    r = A.rank()
                    timing.stop("rank D[%d]" % i)
                    # checkpoint the computation so far
                    if checkpoint is not None:
                        save([r], checkpoint)
                    logging.info("  rank D[%d]=%d (computed in %.3fs)",
                                 i, r, timing.get("rank D[%d]" % i))
            else: # A is a 0xL matrix
                r = 0
                logging.info("  rank D[%d]=%d (immediate)", i, r)
            ranks.append(r)

        ## compute homology group ranks from rank and nullity
        ## of boundary operators.
        ##
        ## By the rank-nullity theorem, if A:V-->W is a linear map,
        ## then null(A) =  dim(V) - rk(A), hence:
        ##   dim(Z_i) = null(D_i) = dim(C_i) - rk(D_i)
        ##   dim(B_i) = rk(D_{i+1})
        ## Therefore:
        ##   h_i = dim(H_i) = dim(Z_i / B_i) = dim(Z_i) - dim(B_i)
        ##       = (dim(C_i) - rk(D_i)) - rk(D_{i+1})
        ##       = dim(C_i) - (rk(D_i) + rk(D_{i+1}))
        ## where D_i:C_i-->C_{i+1}
        ##
        domain_dim = [ ddim for (A, ddim, cdim) in self ]
        domain_dim.append(self[-1][2]) # add dimension of last vector space
        ranks.append(0) # augment complex with the null map.
        # note: `domain_dim` indices are offset by 1 w.r.t. to `ranks` indices
        return [ (domain_dim[i+1] - ranks[i] - ranks[i+1])
                 for i in xrange(len(self)) ]
Esempio n. 6
0
    # valences -- show vertex valences for given g,n
    elif 'valences' == cmdline.action:
        logging.debug("Computing vertex valences occurring in g=%d,n=%d fatgraphs ...", g, n)
        vvs = compute_valences(g,n)
        for vv in vvs:
            outfile.write("%s\n" % str(vv))


    # graphs -- create graphs from given g,n but do not compute homology
    elif "graphs" == cmdline.action:
        logging.info("Will save graph list files into directory '%s'.",
                     runtime.options.checkpoint_dir)
        graphs, D = compute_graphs(g,n)
        logging.info("Graph family computation took %.3fs.",
                     timing.get("compute_graphs(%d,%d)" % (g,n)))


    # homology -- compute homology ranks
    elif 'homology' == cmdline.action:
        # compute graph complex and its homology ranks
        hs = compute_homology(g, n)
        logging.info("Homology computation took %.3fs.",
                     timing.get("compute_homology(%d,%d)" % (g,n)))

        # print results
        for (i, h) in enumerate(hs):
            outfile.write("h_%d(M_{%d,%d}) = %d\n" % (i, g, n, h))
        if cmdline.outfile is not None:
            logging.info("Results written to file '%s'" % cmdline.outfile)