Skip to content

Commit

Permalink
sagemathgh-36166: Additions to the bigraded Betti number methods
Browse files Browse the repository at this point in the history
    
This pull request expands the functionality of
``bigraded_betti_number()`` methods of a ``SimplicialComplex`` by adding
an additional parameter ``verbose``. The ``verbose`` option increases
verbosity while computing the invariant by printing the subcomplexes
along with their non-trivial homology groups.

This PR is a part of sagemath#35640 (GSoC 2023).

### 📝 Checklist

- [x] The title is concise, informative, and self-explanatory.
- [x] The description explains in detail what this PR is about.
- [x] I have linked a relevant issue or discussion.
- [x] I have created tests covering the changes.
- [x] I have updated the documentation accordingly.
    
URL: sagemath#36166
Reported by: Ognjen Petrov
Reviewer(s): Ognjen Petrov, Travis Scrimshaw
  • Loading branch information
Release Manager committed Sep 27, 2023
2 parents 05d7d1d + 037b616 commit ce855de
Showing 1 changed file with 91 additions and 9 deletions.
100 changes: 91 additions & 9 deletions src/sage/topology/simplicial_complex.py
Original file line number Diff line number Diff line change
Expand Up @@ -4845,11 +4845,23 @@ def intersection(self, other):
F = F + [s for s in self.faces()[k] if s in other.faces()[k]]
return SimplicialComplex(F)

def bigraded_betti_numbers(self, base_ring=ZZ):
def bigraded_betti_numbers(self, base_ring=ZZ, verbose=False):
r"""
Return a dictionary of the bigraded Betti numbers of ``self``,
with keys `(-a, 2b)`.
INPUT:
- ``base_ring`` -- (default: ``ZZ``) the base ring used
when computing homology
- ``verbose`` -- (default: ``False``) if ``True``, print
messages during the computation, which indicate in which
subcomplexes non-trivial homologies appear
.. NOTE::
If ``verbose`` is ``True``, then caching is avoided.
.. SEEALSO::
See :meth:`bigraded_betti_number` for more information.
Expand All @@ -4858,12 +4870,56 @@ def bigraded_betti_numbers(self, base_ring=ZZ):
sage: X = SimplicialComplex([[0,1],[1,2],[1,3],[2,3]])
sage: Y = SimplicialComplex([[1,2,3],[1,2,4],[3,5],[4,5]])
sage: sorted(X.bigraded_betti_numbers().items(), reverse=True) # needs sage.modules
sage: sorted(X.bigraded_betti_numbers(base_ring=QQ).items(), reverse=True)
[((0, 0), 1), ((-1, 6), 1), ((-1, 4), 2), ((-2, 8), 1), ((-2, 6), 1)]
sage: sorted(Y.bigraded_betti_numbers(base_ring=QQ).items(), reverse=True) # needs sage.modules
sage: sorted(Y.bigraded_betti_numbers(verbose=True).items(), reverse=True)
(-1, 4): Non-trivial homology Z in dimension 0 of the full
subcomplex generated by a set of vertices (1, 5)
(-1, 4): Non-trivial homology Z in dimension 0 of the full
subcomplex generated by a set of vertices (2, 5)
(-1, 4): Non-trivial homology Z in dimension 0 of the full
subcomplex generated by a set of vertices (3, 4)
(-2, 6): Non-trivial homology Z in dimension 0 of the full
subcomplex generated by a set of vertices (1, 2, 5)
(-2, 8): Non-trivial homology Z in dimension 1 of the full
subcomplex generated by a set of vertices (1, 3, 4, 5)
(-2, 8): Non-trivial homology Z in dimension 1 of the full
subcomplex generated by a set of vertices (2, 3, 4, 5)
(-3, 10): Non-trivial homology Z in dimension 1 of the full
subcomplex generated by a set of vertices (1, 2, 3, 4, 5)
[((0, 0), 1), ((-1, 4), 3), ((-2, 8), 2), ((-2, 6), 1), ((-3, 10), 1)]
"""
if base_ring in self._bbn_all_computed:
If we wish to view them in a form of a table, it is
simple enough to create a function as such::
sage: def print_table(bbns):
....: max_a = max(-p[0] for p in bbns)
....: max_b = max(p[1] for p in bbns)
....: bbn_table = [[bbns.get((-a,b), 0) for a in range(max_a+1)]
....: for b in range(max_b+1)]
....: width = len(str(max(bbns.values()))) + 1
....: print(' '*width, end=' ')
....: for i in range(max_a+1):
....: print(f'{-i:{width}}', end=' ')
....: print()
....: for j in range(len(bbn_table)):
....: print(f'{j:{width}}', end=' ')
....: for r in bbn_table[j]:
....: print(f'{r:{width}}', end=' ')
....: print()
sage: print_table(X.bigraded_betti_numbers())
0 -1 -2
0 1 0 0
1 0 0 0
2 0 0 0
3 0 0 0
4 0 2 0
5 0 0 0
6 0 1 1
7 0 0 0
8 0 0 1
"""
if base_ring in self._bbn_all_computed and not verbose:
return self._bbn[base_ring]

from sage.homology.homology_group import HomologyGroup
Expand All @@ -4884,18 +4940,33 @@ def bigraded_betti_numbers(self, base_ring=ZZ):
if ind not in B:
B[ind] = ZZ.zero()
B[ind] += len(H[j-k-1].gens())
if verbose:
print("{}: Non-trivial homology {} in dimension {} of the full subcomplex generated by a set of vertices {}".format(ind, H[j-k-1], j-k-1, x))

self._bbn[base_ring] = B
self._bbn_all_computed.add(base_ring)

return B

def bigraded_betti_number(self, a, b, base_ring=ZZ):
def bigraded_betti_number(self, a, b, base_ring=ZZ, verbose=False):
r"""
Return the bigraded Betti number indexed in the form `(-a, 2b)`.
Bigraded Betti number with indices `(-a, 2b)` is defined as a sum of ranks
of `(b-a-1)`-th (co)homologies of full subcomplexes with exactly `b` vertices.
Bigraded Betti number with indices `(-a, 2b)` is defined as a
sum of ranks of `(b-a-1)`-th (co)homologies of full subcomplexes
with exactly `b` vertices.
INPUT:
- ``base_ring`` -- (default: ``ZZ``) the base ring used
when computing homology
- ``verbose`` -- (default: ``False``) if ``True``, print
messages during the computation, which indicate in which
subcomplexes non-trivial homologies appear
.. NOTE::
If ``verbose`` is ``True``, then caching is avoided.
EXAMPLES::
Expand All @@ -4915,12 +4986,21 @@ def bigraded_betti_number(self, a, b, base_ring=ZZ):
2
sage: X.bigraded_betti_number(-1, 8)
0
sage: Y = SimplicialComplex([[1,2,3],[1,2,4],[3,5],[4,5]])
sage: Y.bigraded_betti_number(-1, 4, verbose=True)
Non-trivial homology Z in dimension 0 of the full subcomplex
generated by a set of vertices (1, 5)
Non-trivial homology Z in dimension 0 of the full subcomplex
generated by a set of vertices (2, 5)
Non-trivial homology Z in dimension 0 of the full subcomplex
generated by a set of vertices (3, 4)
3
"""
if b % 2:
return ZZ.zero()
if a == 0 and b == 0:
return ZZ.one()
if base_ring in self._bbn:
if base_ring in self._bbn and not verbose:
if base_ring in self._bbn_all_computed:
return self._bbn[base_ring].get((a, b), ZZ.zero())
elif (a, b) in self._bbn[base_ring]:
Expand All @@ -4939,6 +5019,8 @@ def bigraded_betti_number(self, a, b, base_ring=ZZ):
H = S.homology(base_ring=base_ring)
if b+a-1 in H and H[b+a-1] != H0:
B += len(H[b+a-1].gens())
if verbose:
print("Non-trivial homology {} in dimension {} of the full subcomplex generated by a set of vertices {}".format(H[b+a-1], b+a-1, x))

B = ZZ(B)

Expand Down

0 comments on commit ce855de

Please sign in to comment.