{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"##This code computes various d invariants of large surgery, as well as the invariants Y_c\n",
"##There are two classes, CF and CFKinfty\n",
"##The class CF is a class which represents a free f.g. chain complex over F[U]\n",
"## The class CFKinfty represents a knot-like chain complex resembing CFK-infty\n",
"##The most important methods are\n",
"##CFKinfty()### (to initialize)\n",
"##Tensor([C_1,C_2,C_3,...,C_n])### (to tensor CFKinfty complexes together)\n",
"##PrintYGrid(C)### computes and prints all the Y_{c,g} invariants\n",
"##C.dual() computes the dual knot complex of a CFKinfty complex C\n",
"\n",
"\n",
"\n",
"\n",
"class CF(object):\n",
" #gen should be a list of Maslov gradings (of the generators over F[U])\n",
" #diff is a list of lists, of the same length as gen.\n",
" #e.g. [[],[1,2],[3],[]]. in diff[i] we put all of the indices of the intersection points such that there is \n",
" # a nonzero differential from i to j (the U-powers are filled in later).\n",
" # We assume that the complex inputted has HF^infty equal to one tower,\n",
" # supported in even gradings\n",
" def __init__(self,gen,diff):\n",
" self.gen=gen\n",
" self.diff=diff\n",
" self.rank=len(gen)\n",
" \n",
" \n",
" \n",
"class CFKinfty(object):\n",
" #gen should be a list of 3 element lists of the form [gr,i,j] represent the generators of CFK^infty.\n",
" #An element [gr,i,j] represents x u^i v^j (so i and j are opposite from Ozsvath and Szabo's convention)\n",
" #these are generators of the Alexander grading 0 version, so we assume that A(x)+j-i=0.\n",
" #Here, gr is the Maslov (or homological) grading.\n",
" #They can be any generators, so, e.g., incrementing i and j both by 1 is ok and has no effect.\n",
" #diff is a list of lists, of the same length as gen.\n",
" #diff[i] is a list of integers, and j is in diff[i] if and only if there is an arrow from i to j (with some weighting)\n",
" #(The weighting need not be entered, since it is determined by the grading)\n",
" #length of diff and gen should be equal.\n",
" def __init__(self, gen, diff):\n",
" self.gen=gen\n",
" self.diff=diff\n",
" self.rank=len(gen)\n",
" #the following returns the generators and differential for CF of the large surgeries complex\n",
" def AComplex(self,indexn):\n",
" NewGens=[]\n",
" for oldg in self.gen:\n",
" oldgrading=oldg[0]\n",
" indexi=oldg[1]\n",
" indexj=oldg[2]\n",
" newgrading=oldgrading+2*min(indexi,indexj+indexn)\n",
" NewGens.append(newgrading)\n",
" diffcopy=deepcopy(self.diff)\n",
" Complex=CF(NewGens,diffcopy)\n",
" return Complex\n",
" def dual(self):\n",
" NewGens=[[-x[0],-x[1],-x[2]] for x in self.gen]\n",
" NewDiff=[[] for i in range(self.rank)]\n",
" for i in range(self.rank):\n",
" for j in self.diff[i]:\n",
" NewDiff[j].append(i)\n",
" return CFKinfty(NewGens,NewDiff)\n",
" \n",
"#input CFK^infty-cx\n",
"#output is a CF-minus cx\n",
"#n>=0 assumed\n",
"#could instead just tensor C with S_{-n} (negative staircase with n length 1 steps)\n",
"def StairCaseCx(C, n):\n",
" if n==0:\n",
" return C.AComplex(0)\n",
" #henceforth we assume n>0\n",
" OldGens=C.gen\n",
" OldDiff=C.diff\n",
" NewGens=[]\n",
" rank=C.rank\n",
" NewDiff=[[] for x in range((2*n+1)*rank)]\n",
" #i enumerates all of the summands of S-n\n",
" for i in range(2*n+1):\n",
" #i in this range corresponds to the summand A_{-n+i}, so we set s=-n+i\n",
" s=n-i\n",
" for x in OldGens:\n",
" #we now add generators, with shifts in grading as in AComplex, as well as with the formal shifts\n",
" grnew=x[0]+2*min(x[1],x[2]+s)-s+n\n",
" NewGens.append(grnew)\n",
" for j in range(rank):\n",
" for y in C.diff[j]:\n",
" #add the internal differentials\n",
" NewDiff[i*rank+j].append(i*rank+y)\n",
" #we now add the cone arrows to A_n (left most)\n",
" for i in range(rank):\n",
" NewDiff[i].append(i+rank)\n",
" # now add the cone arrows for the right most arrow A_{-n}\n",
" for i in range(rank):\n",
" NewDiff[(2*n)*rank+i].append((2*n-1)*rank+i)\n",
" for i in range(1,n):\n",
" #we now add the remaining cone arrows\n",
" for j in range(rank):\n",
" NewDiff[2*i*rank+j].append((2*i-1)*rank+j)\n",
" NewDiff[2*i*rank+j].append((2*i+1)*rank+j)\n",
" return CF(NewGens,NewDiff)\n",
"\n",
"# Input is a CFK-infty complex and an integer n. Output is the CF complex A_n\n",
"def AComplex(C,n):\n",
" return C.AComplex(n)\n",
" \n",
" \n",
"#input is two CFKinfty complexes\n",
"#Output is their knot-tensor product.\n",
"#NOTE: There is a function which tensors a list of CFK complexes together (As many as one likes)\n",
"#See the function Tensor, below\n",
"def Tensor2(C1,C2):\n",
" gen1=C1.gen\n",
" gen2=C2.gen\n",
" diff1=C1.diff\n",
" diff2=C2.diff\n",
" rank1=C1.rank\n",
" rank2=C2.rank\n",
" newGens=[]\n",
" newDiffs=[[] for x in range(rank1*rank2)]\n",
" for i in range(rank1):\n",
" gi=gen1[i]\n",
" for j in range(rank2):\n",
" gj=gen2[j]\n",
" gigj=[sum(x) for x in zip(gi, gj)]\n",
" newGens.append(gigj)\n",
" for k in diff1[i]:\n",
" newDiffs[i*rank2+j].append(k*rank2+j)\n",
" for m in diff2[j]:\n",
" newDiffs[i*rank2+j].append(i*rank2+m)\n",
" return CFKinfty(newGens,newDiffs)\n",
"\n",
"#input is a knot complex, output is V_0,V_1,V_2,...\n",
"def Vlist(C):\n",
" VInvariants=[]\n",
" Index=0\n",
" VInvariants.append(-d(C.AComplex(0))/2)\n",
" while(not VInvariants[-1]== 0):\n",
" Index=Index+1\n",
" VInvariants.append(-d(C.AComplex(Index))/2)\n",
" return VInvariants\n",
"\n",
"# Outputs a list of the Y, similar to Vlist.\n",
"def Ylist(C):\n",
" YInvariants=[]\n",
" Index=0\n",
" YInvariants.append(-d(StairCaseCx(C,0))/2)\n",
" while(not YInvariants[-1]== 0):\n",
" Index=Index+1\n",
" YInvariants.append(-d(StairCaseCx(C,Index))/2)\n",
" return YInvariants\n",
" \n",
"\n",
"#input is a list of CFKinfty complexes, e.g. Tensor([C_1,C_2,C_3,...,C_n])\n",
"def Tensor(Complexes):\n",
" if len(Complexes)==1:\n",
" return Complexes[0]\n",
" C=Complexes[0]\n",
" for j in range(1, len(Complexes)):\n",
" C=Tensor2(C,Complexes[j])\n",
" return C\n",
" \n",
"\n",
"#The following is a helper function:\n",
"#takes a list and deletes elements that appear twice (and leaves one if they appear an odd number of times)\n",
"def mod2(L):\n",
" K=deepcopy(L)\n",
" for x in K:\n",
" if L.count(x)>1:\n",
" L.remove(x)\n",
" L.remove(x)\n",
" return L\n",
" \n",
"\n",
"#The following is a helper function:\n",
"#Input is old differential\n",
"#outputs new differential\n",
"#note, this changes the old differential\n",
"#We assume that x_i and x_j have the same parity\n",
"#We assume g(x_j)>g(x_i)\n",
"#The change of basis is that x_i is replaced by x_i+U^k x_j\n",
"#x_j is left the same\n",
"def BasisChange(diff,i,j):\n",
" #first changes differentials going to i an j\n",
" for x in diff:\n",
" if i in x:\n",
" x.append(j)\n",
" mod2(x)\n",
" for y in diff[j]:\n",
" diff[i].append(y)\n",
" mod2(diff[i])\n",
" return diff\n",
"\n",
"#The following is a helper function:\n",
"#The following deletes all arrows with a power of U^i, where i=power\n",
"# It does this via a change of basis, and then deleting 2 step complexes\n",
"#Note, the program assumes that there are no arrows weighted by U^n for n1:\n",
" BasisChange(Diff, ySpecial,Diff[x][0])\n",
" for xOther in range(rank):\n",
" if ySpecial in Diff[xOther] and not xOther==x:\n",
" BasisChange(Diff, xOther,x)\n",
" toDelete.append(ySpecial)\n",
" toDelete.append(x)\n",
" toDelete.sort(reverse=True)\n",
" # deletes all the entries of toDelete, and shifts Diff correctly each time\n",
" for i in toDelete:\n",
" del Diff[i]\n",
" del Gen[i]\n",
" for Dxs in Diff:\n",
" for j in range(len(Dxs)):\n",
" if Dxs[j]>i:\n",
" Dxs[j]=Dxs[j]-1\n",
" \n",
"#input is a CF complex\n",
"def d(C):\n",
" Diff=deepcopy(C.diff)\n",
" Gen=deepcopy(C.gen)\n",
" power=0\n",
" while(len(Diff)>1):\n",
" DeleteArrows(Diff,Gen,power)\n",
" power=power+1\n",
" return Gen[0]\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"T23Gens=[[-2,0,1],[-2,1,0],[-1,0,0]]\n",
"T23Diff=[[],[],[0,1]]\n",
"T23=CFKinfty(T23Gens,T23Diff)\n",
"\n",
"Fig8Gens=[[0,0,0],[-1,0,1],[-1,1,0],[0,0,0],[0,0,0]]\n",
"Fig8Diff=[[1,2],[3],[3],[],[]]\n",
"Fig8=CFKinfty(Fig8Gens,Fig8Diff)\n",
"\n",
"T38Gens=[[-14,7,0],[-13,6,0],[-14,6,2],[-13,5,2],[-14,5,4],[-13,4,4],[-14,4,5],[-13,2,5],[-14,2,6],[-13,0,6],[-14,0,7]]\n",
"T38Diff=[[],[0,2],[],[2,4],[],[4,6],[],[6,8],[],[8,10],[]]\n",
"T38=CFKinfty(T38Gens,T38Diff)\n",
"\n",
"T213Gens=[[-12,6,0],[-11,5,0],[-12,5,1],[-11,4,1],[-12,4,2],[-11,3,2],[-12,3,3],[-11,2,3],[-12,2,4],[-11,1,4],[-12,1,5],[-11,0,5],[-12,0,6]]\n",
"T213Diff=[[],[0,2],[],[2,4],[],[4,6],[],[6,8],[],[8,10],[],[10,12],[]]\n",
"T213=CFKinfty(T213Gens,T213Diff)\n",
"\n",
"T45Gens=[[-12,0,6],[-11,0,5],[-12,3,5],[-11,3,3],[-12,5,3],[-11,5,0],[-12,6,0]]\n",
"T45Diff=[[],[0,2],[],[2,4],[],[4,6],[]]\n",
"T45=CFKinfty(T45Gens,T45Diff)\n",
"\n",
"T56Gens=[[-20, 0, 10],[-19, 0, 9],[-20, 4, 9],[-19, 4, 7],[-20, 7, 7],[-19, 7, 4],[-20, 9, 4],[-19, 9, 0],[-20, 10, 0]]\n",
"T56Diff=[[], [0, 2], [], [2, 4], [], [4, 6], [], [6, 8], []]\n",
"T56=CFKinfty(T56Gens,T56Diff)\n"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[3, 3, 2, 2, 2, 1, 1, 1, 0]"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"Vlist(Tensor([T23,T38]))"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "SageMath 9.1",
"language": "sage",
"name": "sagemath"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.3"
}
},
"nbformat": 4,
"nbformat_minor": 2
}