bfh_python

A bordered Heegaard Floer computation package

Further Tutorials

Relative gradings and spinc structures

bfh_python computes the decomposition of HF-hat into spinc-structures and the relative Maslov grading in each spinc-structure. It also computes the relative, rational Maslov grading between torsion spinc-structures, and the ambiguity of the Maslov grading in non-torsion spinc-structures (the divisibility of the first Chern class).

A lens space

As a first example, consider our computation of the Floer homology of L(5,2):

from dstructure import infTypeD, zeroTypeD
from pmc import splitPMC
from arcslide import Arcslide
from arcslideda import ArcslideDA

Z = splitPMC(1)
solid_torus = infTypeD(1)
tau_m = ArcslideDA(Arcslide(Z,1,2))
tau_l = ArcslideDA(Arcslide(Z,2,1))
slides = [tau_m, tau_m, tau_l, tau_l]
for s in slides:
    solid_torus = s.tensorD(solid_torus)
oth_side = zeroTypeD(1)
cf = oth_side.morToD(solid_torus)
cf.simplify()
print(len(cf))

To get the relative gradings:

gens = cf.generators #The list of generators
grads = [cf.grading[x] for x in gens] #The list of their gradings
gr_set = cf.gr_set #The grading set for the complex. This is a Z-set.
rel_grs = [gr_set.eltDiffShortForm(x,grads[0]) for x in grads] 
print(rel_grs)
#List of gradings relative to (arbitrarily chosen) first generator.

The first entry is the relative Maslov grading, the second is the ambiguity, and the third is the relative spinc-grading. Since the generators represent different spinc structures, the first entry is essentially meaningless here. The second is always zero, because all generators represent torsion spinc-structures. The third is the interesting one: we get five different numbers, so the generators represent five different spinc-structures.

We can get the relative rational Maslov gradings instead:

rel_Q_grs = [gr_set.eltDiffShortForm(x,grads[0],use_rational=True) for x in grads] 
print(rel_Q_grs)
#List of gradings relative to (arbitrarily chosen) first generator.

We've lost the decomposition into spinc-structures, but now the first entry gives us the relative rational grading between the first generator and the given one. I get 0/1, 4/5, 0/1, 2/5, and 4/5, which is correct for the relative rational gradings on L(5,2). In particular, the fourth generator represents the unique spin structure.

Σ(2,3,7)

Here is the branched double cover of the (2,-3,-7) pretzel knot:

import braid
from braid import BridgePresentation
name = 'P(2,-3,-7)'
left_closure = (6,3,2,5,4,1)
braid = 2*[1]+3*[-3]+7*[-5]
right_closure = (6,3,2,5,4,1)
pretzel = BridgePresentation(name, left_closure, braid, right_closure)
hf = pretzel.getHFByLocalDA()

We get the relative gradings of generators as above:

grads = [hf.grading[x] for x in hf.generators]
rel_grs = [hf.gr_set.eltDiffShortForm(x,grads[0]) for x in grads]
print(rel_grs)

There are two generators in the same grading and one in grading 1 smaller, which is correct for Σ(2,3,7).

A non-torsion spinc-structure

Here is the branched double cover of L10n59, a two-component, determinant zero link.

import braid
from braid import BridgePresentation
name = 'L10n59'
left_closure = (2,1,4,3,6,5,8,7)
right_closure = left_closure
braid = [-2,4,4,6,3,-5,-2,-4,-4,6]
L10n59 = BridgePresentation(name, left_closure, braid, right_closure)
hf = L10n59.getHFByLocalDA()
print(len(hf))

grads = [hf.grading[x] for x in hf.generators]
rel_grs = [hf.gr_set.eltDiffShortForm(x,grads[0]) for x in grads]
print(rel_grs)

The output I get is:

(0,2,[0,0]), (1,2,[0,0]), (3/2,2,[0,1]), (7/2,0,[-1,-1]), (9/2,2,[0,1]), (5/2,0,[-1,-1])

Looking at the second components, HF-hat is supported in spinc-structures with first Chern classes -2, 0, and 2. For computing the gradings, we've (arbitrarily) chosen a base generator with first Chern class ±2. The third component tells us that we have three different spinc-structures represented. In each there are two generators (sensible). In each of them, the Maslov grading difference of those generators is one: in the spinc-structure labeled [0,1] it looks like the Maslov grading difference is 9/2-3/2=3, but the Maslov grading is only well-defined mod 2.

Involutive Heegaard Floer homology

To compute HFI-hat of a manifold Y, you need to split Y=Y1∪Y2, compute P=CFD(Y1) and Q=CFD(Y2), and then invoke involutiveCx(P,Q). This can take a long time to run; you can add verbose=True as an argument to have it print its progress along the way. What the function involutiveCx is doing is documented in comments inside the function.

For example, here's the HFI-hat of the lens space L(5,2), borrowing from the computation of its HF-hat on the main page:

from dstructure import infTypeD, zeroTypeD
from pmc import splitPMC
from arcslide import Arcslide
from arcslideda import ArcslideDA
from involutive import involutiveCx

Z = splitPMC(1)
solid_torus = infTypeD(1)
tau_m = ArcslideDA(Arcslide(Z,1,2))
tau_l = ArcslideDA(Arcslide(Z,2,1))
slides = [tau_m, tau_m, tau_l, tau_l]
for s in slides:
    solid_torus = s.tensorD(solid_torus)
oth_side = zeroTypeD(1)
cfi = involutiveCx(solid_torus,oth_side)
len(cfi)

(You should get 6: the conjugation-invariant spin structure contributes 2 and the other spin^c-structures contribute 1 each.)

To compute HFI-hat of branched covers, there are convenience functions invOfDCov and invOfDCovSplit. The input to invOfDCov has the same format as the input to readBridgePresentation in braid.py; the docstring to readBridgePresentation is fairly thorough. So, the following computes HFI-hat of the branched double cover of the figure 8 knot. (Here, 4_1 is a name for the knot. The next 3 means this is a closure of a 6-strand braid. The top closure is (1,0,5,4,3,2), which means the bottom two strands (0 and 1) are connected, strand 2 is connected to strand 5, and strand 3 is connected to strand 4. The braid has 4 crossings, which are strand 1 over strand 2, strand 3 over strand 2, strand 1 over strand 2, and strand 1 over strand 0. The bottom closure is (5,4,3,2,1,0), which is the braid closure.)

from involutive import invOfDCov
C = invOfDCov("4_1 3 1 0 5 4 3 2 4 1 2 3 2 1 2 1 0 5 4 3 2 1 0")
len(C)

the figure-8 knot

The function invOfDCovSplit takes an integer in addition to a bridge presentation: where to split the bridge presentation when computing HFI-hat (i.e., after which crossing, from 0 to n=the number of crossings). (Sometimes, splitting in one place is much faster than splitting in another.) So, these also compute HFI-hat of the branched double cover of 41:

from involutive import invOfDCovSplit
len(invOfDCovSplit("4_1 3 1 0 5 4 3 2 4 1 2 3 2 1 2 1 0 5 4 3 2 1 0",0))
len(invOfDCovSplit("4_1 3 1 0 5 4 3 2 4 1 2 3 2 1 2 1 0 5 4 3 2 1 0",1))
len(invOfDCovSplit("4_1 3 1 0 5 4 3 2 4 1 2 3 2 1 2 1 0 5 4 3 2 1 0",2))
len(invOfDCovSplit("4_1 3 1 0 5 4 3 2 4 1 2 3 2 1 2 1 0 5 4 3 2 1 0",3))
len(invOfDCovSplit("4_1 3 1 0 5 4 3 2 4 1 2 3 2 1 2 1 0 5 4 3 2 1 0",4))