User:Ben/KRhomology: Difference between revisions

From Knot Atlas
Jump to navigationJump to search
(added revised program, deleted table of computations)
Line 1: Line 1:
==Calculations==
==Actual calculations==
Since calculations have now been incorporated into the normal KAtlas data structure, I don't feel like there's much point in having a table of them here.
Note: these polynomials are missing fudge factors. These will be fixed when I get back to Berkeley on Wednesday.

Here is a table of known KR homologies. We let <math>KR_K(q,s,t)</math> be the Hilbert series of KR homology. Note that a factor of the Hilbert series of the unknot appears in all of them. This will not be true of links, I believe.

Unfortunately, computation seems to bog down very fast. [[6_1]] has been giving me a lot of trouble, probably because it has braid index 4. If someone with a faster machine would run it, I would be very appreciative.

'''Warning''' the polynomial for [[5_2]] here is incorrect. The correct value appears on the main Knot Atlas page for [[5_2]]. --[[User:Scott|Scott]] 12:48, 3 Dec 2005 (EST)

{|align=center border=1
|-
| [[0_1]]
| <math>\frac{{q} {t}+1}{1-t}</math>
|-
| [[3_1]]
| <math>\left(\frac{{q} {t}+1}{1-t}\right)(s^{2} t^{2}+{q} t^{2}+1)</math>
|-
| [[4_1]]
| <math>\left(\frac{{q} {t}+1}{1-t}\right)(t^{{-1}}+{q} {t}+{q} s^{{-1}}+{q} s^{{-{2}}} t^{{-1}}+q^{2} s^{{-{2}}} {t})</math>
|-
| [[5_1]]
| <math>\left(\frac{{q} {t}+1}{1-t}\right)(1+s^{2} t^{2}+s^{4} t^{4}+{q} s^{2} t^{4}+{q} t^{2})</math>
|-
| [[5_2]]
| <math>\left(\frac{{q} {t}+1}{1-t}\right)({q}+q^{2} s^{{-{2}}}+t^{{-{2}}}+q^{2} s^{{-{3}}} t^{{-1}}+{q} s^{{-{2}}} t^{{-{2}}})</math>
|-
| [[6_2]]
| <math>\left(\frac{{q} {t}+1}{1-t}\right)({q} {t}+q^{2} s^{{-{2}}} {t}+{q} s^{{-1}}+t^{{-1}}+2 {q} s^{{-{2}}} t^{{-1}}+s^{{-1}} t^{{-{2}}}+q^{2} s^{{-{4}}} t^{{-1}}+{q}s^{{-{3}}} t^{{-{2}}}+s^{{-{2}}} t^{{-{3}}}+{q} s^{{-{4}}} t^{{-{3}}})</math>
|-
| [[6_3]]
| <math>{\left(\frac{{q} {t}+1}{1-t}\right)(q} {s} t^{2}+q^{2} s^{{-1}} t^{2}+{q} {t}+{s}+q^{2} s^{{-{2}}} {t}+3 {q} s^{{-1}}+t^{{-1}}+q^{2} s^{{-{3}}}+{q} s^{{-{2}}} t^{{-1}}+s^{{-1}} t^{{-{2}}}+{q} s^{{-{3}}} t^{{-{2}}})</math>
|}

I've been running more calculations on panda and neuron, two of the fast computers in the math department. I've got panda working through all the braid index 3 knots, and it's started giving some results. [[7_3]] took about half an hour, and consumed about a gig of memory. --[[User:Scott|Scott]] 02:16, 30 Nov 2005 (EST)
{|align=center border=1
|-
| [[7_3]]
| <math>\left(\frac{{q} {t}+1}{1-t}\right)({q} s^{3} t^{5}+s^{4} t^{4}+q^{2} {s} t^{5}+{q} s^{2} t^{4}+s^{3} t^{3}+2 {q} {s} t^{3}+s^{2} t^{2}+q^{2} s^{{-1}} t^{3}+{q} t^{2}+{s} {t}+{q} s^{{-1}} {t}+1)</math>
|-
| [[7_5]]
| <math> \left(\frac{{q} {t}+1}{1-t}\right) (q^{2} s^{{-{2}}}+{q} s^{{-1}} t^{{-1}}+q^{2} s^{{-{3}}} t^{{-1}}+2 {q} s^{{-{2}}} t^{{-{2}}}+s^{{-1}} t^{{-{3}}}+2 q^{2} s^{{-{4}}} t^{{-{2}}}+2 {q} s^{{-{3}}} t^{{-{3}}}+s^{{-{2}}} t^{{-{4}}}+q^{2} s^{{-{5}}} t^{{-{3}}}+2 {q} s^{{-{4}}} t^{{-{4}}}+s^{{-{3}}} t^{{-{5}}}+q^{2} s^{{-{6}}} t^{{-{4}}}+{q} s^{{-{5}}} t^{{-{5}}})</math>
|}

neuron is working on braid index 4 knots, starting with [[6_1]], and seems to be working fine. [[6_1]] took over an hour, and about 1.2 gigs of memory. --[[User:Scott|Scott]] 02:59, 30 Nov 2005 (EST)
{|align=center border=1
|-
| [[6_1]]
| <math>\left(\frac{{q} {t}+1}{1-t}\right)(q^{2} s^{{-1}} t^{2}+{q} {t}+q^{3} s^{{-{3}}} t^{2}+q^{2} s^{{-{2}}} {t}+2 {q} s^{{-1}}+t^{{-1}}+q^{2} s^{{-{3}}}+{q} s^{{-{2}}} t^{{-1}})</math>
|}

==Theoretical stuff==
I have some ideas which I hope will be of interest to ya'll, but I'd like to mull them a bit longer. Maybe when I get back on Wednesday.

For those who are curious, the polynomials above should follow the skein relation <math>q(-)+q^{-1}(+)=(t^{-1}-t)(| |)</math> after subsituting ''s=-1.''


==Macaulay2 program==
==Macaulay2 program==
Line 58: Line 6:
<code>KRpoly</code> is probabby the command you want (but it only works for knots at the moment). It outputs <math>\frac{1-t}{qt+1}KR_K(q,s,t)</math>.
<code>KRpoly</code> is probabby the command you want (but it only works for knots at the moment). It outputs <math>\frac{1-t}{qt+1}KR_K(q,s,t)</math>.
Using <code>texMath</code> puts things in format for LaTeX.
Using <code>texMath</code> puts things in format for LaTeX.

Changes from the previous version: the important change is in the construction of the Rouquier complex. Now it works by breaking up the braid into (at the moment, very simple) patterns it recognizes, and uses simplified Rouquier complexes for those chunks. This seems to be make a big difference in computational time, indicating that a program that could simplify large Rouquier complexes could lead to very large computational savings. I've made some progress in this direction, but am still struggling to produce something truly robust.


Line 70: Line 20:
--loaded KR.m2
--loaded KR.m2


i2 : texMath KRpoly K01
i2 : texMath KRpoly (K01,true)


o2 = 1
o2 = 1


i3 : texMath KRpoly K31
i3 : texMath KRpoly (K31,true)


o3 = s^{2} t^{2}+{q} t^{2}+1
o3 = s^{2} t^{2}+{q} t^{2}+1
Line 82: Line 32:
Here's the code for the program.
Here's the code for the program.
<pre>
<pre>
--KR.m2
--This file defines a new object for Macaulay2, called a "Link."
--This file defines a new object for Macaulay2, called a "Link."
--Like all objects in Macaulay2, a Link is just a hash table.
--Like all objects in Macaulay2, a Link is just a hash table.
Line 97: Line 46:
--(Remember to use {}, not () or [])
--(Remember to use {}, not () or [])
braidClosure = L ->(
braidClosure = L ->(
K=new Link;
K:=new Link;
K#braid=L;
K#braid=L;
K)
K)
Line 106: Line 55:
K41=braidClosure {1,-2,1,-2};
K41=braidClosure {1,-2,1,-2};
K51=braidClosure {1,1,1,1,1};
K51=braidClosure {1,1,1,1,1};
K52=braidClosure {-1,-1,-2,1,-2};
--Warning: early versions of this program included the wrong braid representation for 5_2 (missing the first -1). Scott.
K52=braidClosure {-1,-1,-1,-2,1,-2};
K61=braidClosure {1,1,2,-1,-3,2,-3};
K61=braidClosure {1,1,2,-1,-3,2,-3};
K62=braidClosure {-1,-1,-1,2,-1,2};
K62=braidClosure {-1,-1,-1,2,-1,2};
Line 119: Line 67:
K77=braidClosure {1,-2,1,-2,3,-2,3}
K77=braidClosure {1,-2,1,-2,3,-2,3}


--Now all programs using the Rouqier complex (KR, KRHom, KRpoly) take an extra argument, which should be a truth value.
--This outputs a List of complexes, one in each Hochschild degree.
--If this is "true," then the program will simplify chunks of the Rouquier complex using prescribed homotopies.
--The homology of these complexes is actual KR homology. Mostly this function
--If it is "false," it will use the old brute force method.
--just feeds into others.
--Preliminary results indicate that the program will run MUCH faster if you use the "true" option,
KR = K -> (
--but it is not 100% vetted yet. there might well be mistakes hiding in there. Let the user beware.
if K#?KR then return K#KR else (

--this program now produces a complex homotopic to the Rouquier complex of the input braid,
--as well as a presentation for the module that corresponds to closing the braid (in matrix form).
KR = (K,v) -> (
if not K#?braid then error "no braid representation" else (
if not K#?braid then error "no braid representation" else (
Kb=K#braid;
Kb:=K#braid;
P=K#nbcross=#Kb;
P:=K#nbcross=#Kb;
Ka=apply(Kb,abs);
Ka:=apply(Kb,abs);
Kt=apply(Kb,i->(i>0));
Kt:=apply(Kb,i->(i>0));
Ks=sort Ka;
Ks:=sort Ka;
--error Ks;
bind:=K#bindex=last(Ks)+1;
bind=K#bindex=last(Ks)+1;
Cvars:=new MutableList from toList (-bind..-1);
R=QQ[vars(1 .. 2*P+bind)];
I:=0;
J:=0;
Kmod = chainComplex( gradedModule(R^1));
Kp:={};
Cvars=new MutableList from toList (0..bind);
--error Cvars#3;
newv:=0;
for I from 0 to P-1 do (
while I<P do (
print I;
Kmod=Kmod**KhMods(Cvars#(Ka_I)-1,Cvars#(Ka_I+1)-1,bind+2*I,R,Kt_I);
M:=1;
Cvars#(Ka_I)=bind+2*I+1;
Cvars#(Ka_I+1)=bind+2*I+2;
while (Kb#?(I+M) and Kb#(I+M)==Kb#I) do M=M+1;
if (M>1 and v) then (
print ("used IImod " | toString(M));
Kp=append(Kp, (("II",M),(Cvars#(Ka_I-1),Cvars#(Ka_I+1-1),newv,Kt_I)));
newvp=newv+2;
J=I+M)
else if ((Kb#?(I+2) and Ka_I==Ka_(I+2)) and v) then (
if Ka_I==Ka_(I+1)+1 then (
if (Kb_(I+1)==Kb_(I+3) and Kb_I==Kb_(I+2)) then (
print "used babamod";
Kp=append(Kp,("baba",(Cvars#(Ka_I),Cvars#(Ka_I-1),Cvars#(Ka_I-2),newv+1,newv,newv+2,Kt_I,Kt_(I+1),Kt_(I+2),Kt_(I+3))));
J=I+4;
)
else (
print "used abamod";
Kp=append(Kp,("aba",(Cvars#(Ka_I),Cvars#(Ka_I-1),Cvars#(Ka_I-2),newv+1,newv,newv+2,Kt_I,Kt_(I+1),Kt_(I+2))));
J=I+3;
);
Cvars#(Ka_I-2)=newv+2;
newvp=newv+3)
else if Ka_I==Ka_(I+1)-1 then (
if (Kb_(I+1)==Kb_(I+3) and Kb_I==Kb_(I+2)) then (
print "used babamod";
Kp=append(Kp,("baba",(Cvars#(Ka_I-1),Cvars#(Ka_I),Cvars#(Ka_I+1),newv,newv+1,newv+2,Kt_I,Kt_(I+1),Kt_(I+2),Kt_(I+3))));
J=I+4;
)
else(
print "used abamod";
Kp=append(Kp,("aba",(Cvars#(Ka_I-1),Cvars#(Ka_I),Cvars#(Ka_I+1),newv,newv+1,newv+2,Kt_I,Kt_(I+1),Kt_(I+2))));
J=I+3;
);
Cvars#(Ka_I+1)=newv+2;
newvp=newv+3
)
else (
print "used stmod";
Kp=append(Kp,("st",(Cvars#(Ka_I-1),Cvars#(Ka_I),newv,Kt_I)));
newvp=newv+2;
J=I+1)
)
else (
print "used stmod";
Kp=append(Kp,("st",(Cvars#(Ka_I-1),Cvars#(Ka_I),newv,Kt_I)));
newvp=newv+2;
J=I+1);
Cvars#(Ka_I-1)=newv;
Cvars#(Ka_I)=newv+1;
I=J;
newv=newvp;
);
);
Ml=toList (1..bind);
print Kp;
elim=newv-bind;
M=matrix {apply(Ml, I-> R_(Cvars#I-1)-R_(I-1))};
R:=QQ[vars(1 .. newv+bind),MonomialOrder=>Eliminate elim];
KKR=Torify(Kmod,M);
Kp=apply(Kp,(S1,S2) -> (S1,apply(S2,i-> (if (class i===ZZ and i<0) then x=i+newv+bind else x=i; x))));
return KKR)
Kmod:= chainComplex( gradedModule(R^1));
)
for J from 0 to #Kp-1 do (
if ((Kp_J)_0)_0=="II" then Kmod=Kmod**IImod join((Kp_J)_1, (((Kp_J)_0)_1,R))
else if (Kp_J)_0=="aba" then Kmod=Kmod**abamod append((Kp_J)_1,R)
else if (Kp_J)_0=="baba" then Kmod=Kmod**babamod append((Kp_J)_1,R)
else if (Kp_J)_0=="st" then Kmod=Kmod**stmod append((Kp_J)_1,R)
else error "oops, missed a case"
);
-- scan(spots Kmod, i -> if Kmod#dd#?i then print (isWellDefined Kmod.dd_i));
M:=matrix {apply(bind, I-> R_(Cvars#I)-R_(newv+I))};
return (Kmod,M);
);
)
)


--this produces a simpler complex for an arbitrary number of twists of two adjacent strands.
--this function just makes the modules used in the complex above.
KhMods = (H,I,J,S,W) -> (
IImod = (H,I,J,W,n,S) -> (
Mp=S^1/ideal(S_H+S_I-S_J-S_(J+1),S_H*S_I-S_J*S_(J+1));
i:=ideal(S_H+S_I-S_J-S_(J+1),S_H*S_I-S_J*S_(J+1));
Np=S^{-1}/ideal(S_H-S_J,S_I-S_(J+1));
Dp:=chainComplex map(S^{0}/i,S^{-1}/i,S_I-S_J);
Mn=S^{1}/ideal(S_H+S_I-S_J-S_(J+1),S_H*S_I-S_J*S_(J+1));
Dn:=chainComplex map(S^{2}/i,S^{1}/i,S_I-S_J)[1];
Nn=S^{1}/ideal(S_H-S_J,S_I-S_(J+1));
if mod(n,2)==0 then C=ftmod(H,I,J,W,S);
if mod(n,2)==1 then C=stmod(H,I,J,W,S);
if W then C=chainComplex(map(Mp,Np,(S_J-S_I))) else C=chainComplex(map(Nn,Mn))[1];
while n>2 do (
if W then C=C[-2]**S^{-2}++Dp
else C=C[2]**S^{2}++Dn;
n=n-2;
);
C)

--this produces a simpler complex for a full twist of two strands. Now just feeds into "IImod."
ftmod = (H,I,J,W,S) -> (
i:=ideal(S_H+S_I-S_J-S_(J+1),S_H*S_I-S_J*S_(J+1));
j:=ideal(S_H-S_J,S_I-S_(J+1));
if W then (
M0=S^1/i;
M1=S^{-1}/i;
M2=S^{-2}/j;
f1=map(M0,M1,S_H-S_I-S_J+S_(J+1));
f2=map(M1,M2,S_J-S_I);
C=chainComplex(f1,f2));
if not W then (
M0=S^{2}/j;
M1=S^{2}/i;
M2=S^{1}/i;
f1=map(M0,M1);
f2=map(M1,M2,S_H-S_J-S_I+S_(J+1));
C=chainComplex(f1,f2)[2]);
C)

--this produces the standard Rouquier complex for a single crossing
stmod = (H,I,J,W,S) -> (
if W then (
Mp=S^1/ideal(S_H+S_I-S_J-S_(J+1),S_H*S_I-S_J*S_(J+1));
Np=S^{-1}/ideal(S_H-S_J,S_I-S_(J+1));
C=chainComplex(map(Mp,Np,(S_J-S_I))))
else (
Mn=S^{1}/ideal(S_H+S_I-S_J-S_(J+1),S_H*S_I-S_J*S_(J+1));
Nn=S^{1}/ideal(S_H-S_J,S_I-S_(J+1));
C=chainComplex(map(Nn,Mn))[1]);
C)
C)
--this produces a simplified Rouquier for braids of length 3 lifting the longest element of S_3.
abamod = (G,H,I,J,K,L,W,V,X,S) -> (
i:=ideal(S_G-S_J,S_H-S_K,S_I-S_L);
j1:=ideal(S_H+S_G-S_J-S_K,S_H*S_G-S_J*S_K,S_I-S_L);
j2:=ideal(S_H+S_I-S_L-S_K,S_H*S_I-S_L*S_K,S_G-S_J);
k1:=ideal(S_H+S_G+S_I-S_J-S_K-S_L, (S_I-S_K)*(S_I-S_L),(S_J-S_G)*(S_J-S_H));
k2:=ideal(S_H+S_G+S_I-S_J-S_K-S_L, (S_L-S_H)*(S_I-S_L),(S_J-S_G)*(S_G-S_K));
l:=ideal(S_H+S_G+S_I-S_J-S_K-S_L, S_H*S_G+S_I*S_G+S_I*S_H-S_J*S_K-S_L*S_J-S_K*S_L, S_H*S_G*S_I-S_J*S_K*S_L);
if ((not W) and (not V) and (not X)) then (
M0=S^{3}/i;
M1=S^{3}/j1++S^{3}/j2;
M2=S^{3}/k1++S^{3}/k2;
M3=S^{3}/l;
f1=map(M0,M1,matrix{{1_S,-1}});
f2=map(M1,M2,matrix{{1_S,-1},{1,-1}});
f3=map(M2,M3,matrix{{1_S},{1}});
C=chainComplex(f1,f2,f3)[3]
)
else if (W and V and X) then (
M0=S^1/l;
M1=S^{-1}/k1++S^{-1}/k2;
M2=S^{-2}/j1++S^{-2}/j2;
M3=S^{-3}/i;
f1=map(M0,M1,matrix{{S_I-S_J,-S_G+S_L}});
f2=map(M1,M2,matrix{{S_I-S_K,-S_H+S_J},{S_H-S_L,-S_G+S_K}});
f3=map(M2,M3,matrix{{-S_K+S_G},{-S_L+S_H}});
C=chainComplex(f1,f2,f3)
)
else if ((not W) and (not V) and X) then (
M0=S^{2}/k2++S^{1}/i;
M1=S^{2}/l++S^{1}/j1++S^{1}/j2;
M2=S^{1}/k1;
f1=map(M0,M1,matrix{{1,S_H-S_L,S_G-S_K},{0,-1,1}});
f2=map(M1,M2,matrix{{S_I-S_J},{1},{1}});
C=chainComplex(f1,f2)[1]
)
else if (W and (not V) and (not X)) then (
M0=S^{2}/k1++S^{1}/i;
M1=S^{2}/l++S^{1}/j1++S^{1}/j2;
M2=S^{1}/k2;
f1=map(M0,M1,matrix{{1,S_I-S_K,S_H-S_J},{0,-1,1}});
f2=map(M1,M2,matrix{{S_G-S_L},{1},{1}});
C=chainComplex(f1,f2)[1]
)
else if (W and V and (not X)) then (
M2=S^{0}/k2++S^{-1}/i;
M1=S^{1}/l++S^{0}/j1++S^{0}/j2;
M0=S^{1}/k1;
f1=map(M0,M1,matrix {{-1,-S_I+S_K,S_J-S_H}});
f2=map(M1,M2,matrix {{S_G-S_L,0},{1,S_H-S_J},{1,-S_I+S_K}});
C=chainComplex(f1,f2)[1])
else if ((not W) and V and X) then (
M2=S^{0}/k1++S^{-1}/i;
M1=S^{1}/l++S^{0}/j1++S^{0}/j2;
M0=S^{1}/k2;
f1=map(M0,M1,matrix {{-1,-S_L+S_H,S_G-S_K}});
f2=map(M1,M2,matrix {{S_J-S_I,0},{1,S_K-S_G},{1,-S_L+S_H}});
C=chainComplex(f1,f2)[1]
)
else if ((not W) and V and (not X)) then (
C=new ChainComplex;
C.ring=S;
C#0 = cokernel map(S^{{1}, {1}, {2}}, S^{{1}, {0}, {0}, {0}, {0}, {0}, {-1}, {-1}, {-1}}, {{0, S_H+S_G-S_K-S_J, 0, 0, 0, S_I-S_L, S_G^2-S_G*S_K-S_G*S_J+S_K*S_J, 0, 0}, {0, 0, S_I+S_H+S_G-S_K-S_J-S_L, S_H+S_G-S_K-S_J, -S_H-S_G+S_K+S_J, 0, 0, -S_H*S_G+S_K*S_J, S_H^2+S_H*S_G+S_G^2-S_H*S_K-S_G*S_K-S_H*S_J-S_G*S_J+S_K*S_J-S_H*S_L-S_G*S_L+S_K*S_L+S_J*S_L}, {S_I+S_H+S_G-S_K-S_J-S_L, 0, 0, S_H*S_G-S_H*S_K-S_G*S_K+S_K^2-S_H*S_J-S_G*S_J+S_K*S_J+S_J^2, S_H^2+S_G^2-S_K^2-S_J^2-S_H*S_L-S_G*S_L+S_K*S_L+S_J*S_L, 0, 0, S_H*S_K*S_J+S_G*S_K*S_J-S_K^2*S_J-S_K*S_J^2, 0}});
C#1 = cokernel map(S^{{0}}, S^{{-1}, {-1}, {-2}}, {{S_H+S_G-S_K-S_J, S_I-S_L, S_G^2-S_G*S_K-S_G*S_J+S_K*S_J}});
C#-2 = cokernel map(S^{{2}}, S^{{1}, {1}, {0}}, {{S_G-S_J, S_I+S_H-S_K-S_L, S_H^2-S_H*S_K-S_H*S_L+S_K*S_L}});
C#-1 = cokernel map(S^{{1}, {2}, {2}}, S^{{1}, {1}, {0}, {0}, {0}, {0}, {0}, {0}, {0}}, {{0, 0, S_G-S_J, S_H-S_K, S_I-S_L, 0, 0, 0, 0}, {S_I+S_H+S_G-S_K-S_J-S_L, 0, 0, 0, 0, 0, S_H*S_G-S_H*S_J-S_G*S_J+S_J^2, S_H^2+S_G^2-S_H*S_K-S_G*S_K+S_K*S_J-S_J^2-S_H*S_L-S_G*S_L+S_K*S_L+S_J*S_L, 0}, {0, S_I+S_H+S_G-S_K-S_J-S_L, 0, 0, 0, S_G^2-S_G*S_K-S_G*S_J+S_K*S_J, 0, 0, S_H^2+S_H*S_G-S_H*S_K-S_H*S_J-S_H*S_L-S_G*S_L+S_K*S_L+S_J*S_L}});
C#dd#0 = map(cokernel map(S^{{1}, {2}, {2}}, S^{{1}, {1}, {0}, {0}, {0}, {0}, {0}, {0}, {0}}, {{0, 0, S_G-S_J, S_H-S_K, S_I-S_L, 0, 0, 0, 0}, {S_I+S_H+S_G-S_K-S_J-S_L, 0, 0, 0, 0, 0, S_H*S_G-S_H*S_J-S_G*S_J+S_J^2, S_H^2+S_G^2-S_H*S_K-S_G*S_K+S_K*S_J-S_J^2-S_H*S_L-S_G*S_L+S_K*S_L+S_J*S_L, 0}, {0, S_I+S_H+S_G-S_K-S_J-S_L, 0, 0, 0, S_G^2-S_G*S_K-S_G*S_J+S_K*S_J, 0, 0, S_H^2+S_H*S_G-S_H*S_K-S_H*S_J-S_H*S_L-S_G*S_L+S_K*S_L+S_J*S_L}}), cokernel map(S^{{1}, {1}, {2}}, S^{{1}, {0}, {0}, {0}, {0}, {0}, {-1}, {-1}, {-1}}, {{0, S_H+S_G-S_K-S_J, 0, 0, 0, S_I-S_L, S_G^2-S_G*S_K-S_G*S_J+S_K*S_J, 0, 0}, {0, 0, S_I+S_H+S_G-S_K-S_J-S_L, S_H+S_G-S_K-S_J, -S_H-S_G+S_K+S_J, 0, 0, -S_H*S_G+S_K*S_J, S_H^2+S_H*S_G+S_G^2-S_H*S_K-S_G*S_K-S_H*S_J-S_G*S_J+S_K*S_J-S_H*S_L-S_G*S_L+S_K*S_L+S_J*S_L}, {S_I+S_H+S_G-S_K-S_J-S_L, 0, 0, S_H*S_G-S_H*S_K-S_G*S_K+S_K^2-S_H*S_J-S_G*S_J+S_K*S_J+S_J^2, S_H^2+S_G^2-S_K^2-S_J^2-S_H*S_L-S_G*S_L+S_K*S_L+S_J*S_L, 0, 0, S_H*S_K*S_J+S_G*S_K*S_J-S_K^2*S_J-S_K*S_J^2, 0}}), {{-1, 0, 0}, {S_H+S_G-S_J-S_L, -S_K, -1}, {0, S_G-S_K-S_J, -1}});
C#dd#1 = map(cokernel map(S^{{1}, {1}, {2}}, S^{{1}, {0}, {0}, {0}, {0}, {0}, {-1}, {-1}, {-1}}, {{0, S_H+S_G-S_K-S_J, 0, 0, 0, S_I-S_L, S_G^2-S_G*S_K-S_G*S_J+S_K*S_J, 0, 0}, {0, 0, S_I+S_H+S_G-S_K-S_J-S_L, S_H+S_G-S_K-S_J, -S_H-S_G+S_K+S_J, 0, 0, -S_H*S_G+S_K*S_J, S_H^2+S_H*S_G+S_G^2-S_H*S_K-S_G*S_K-S_H*S_J-S_G*S_J+S_K*S_J-S_H*S_L-S_G*S_L+S_K*S_L+S_J*S_L}, {S_I+S_H+S_G-S_K-S_J-S_L, 0, 0, S_H*S_G-S_H*S_K-S_G*S_K+S_K^2-S_H*S_J-S_G*S_J+S_K*S_J+S_J^2, S_H^2+S_G^2-S_K^2-S_J^2-S_H*S_L-S_G*S_L+S_K*S_L+S_J*S_L, 0, 0, S_H*S_K*S_J+S_G*S_K*S_J-S_K^2*S_J-S_K*S_J^2, 0}}), cokernel map(S^{{0}}, S^{{-1}, {-1}, {-2}}, {{S_H+S_G-S_K-S_J, S_I-S_L, S_G^2-S_G*S_K-S_G*S_J+S_K*S_J}}), {{S_G-S_J}, {S_G-S_L}, {S_G^2-S_G*S_K-S_G*S_J-S_G*S_L+S_K*S_L+S_J*S_L}});
C#dd#-1 = map(cokernel map(S^{{2}}, S^{{1}, {1}, {0}}, {{S_G-S_J, S_I+S_H-S_K-S_L, S_H^2-S_H*S_K-S_H*S_L+S_K*S_L}}), cokernel map(S^{{1}, {2}, {2}}, S^{{1}, {1}, {0}, {0}, {0}, {0}, {0}, {0}, {0}}, {{0, 0, S_G-S_J, S_H-S_K, S_I-S_L, 0, 0, 0, 0}, {S_I+S_H+S_G-S_K-S_J-S_L, 0, 0, 0, 0, 0, S_H*S_G-S_H*S_J-S_G*S_J+S_J^2, S_H^2+S_G^2-S_H*S_K-S_G*S_K+S_K*S_J-S_J^2-S_H*S_L-S_G*S_L+S_K*S_L+S_J*S_L, 0}, {0, S_I+S_H+S_G-S_K-S_J-S_L, 0, 0, 0, S_G^2-S_G*S_K-S_G*S_J+S_K*S_J, 0, 0, S_H^2+S_H*S_G-S_H*S_K-S_H*S_J-S_H*S_L-S_G*S_L+S_K*S_L+S_J*S_L}}), {{-S_H+S_L, -1, 1}});)
else if (W and (not V) and X) then (
C=new ChainComplex;
C.ring=S;
C#0 = cokernel map(S^{{0}, {0}, {1}}, S^{{0}, {-1}, {-1}, {-1}, {-1}, {-1}, {-2}, {-2}, {-2}}, {{0, S_H+S_G-S_K-S_J, 0, S_I-S_L, 0, 0, S_G^2-S_G*S_K-S_G*S_J+S_K*S_J, 0, 0}, {0, 0, S_I+S_H+S_G-S_K-S_J-S_L, 0, S_H+S_G-S_K-S_J, -S_H-S_G+S_K+S_J, 0, S_H^2+S_H*S_G+S_G^2-S_H*S_K-S_G*S_K-S_H*S_J-S_G*S_J+S_K*S_J-S_H*S_L-S_G*S_L+S_K*S_L+S_J*S_L, -S_H*S_G+S_K*S_J}, {S_I+S_H+S_G-S_K-S_J-S_L, 0, 0, 0, S_H*S_G-S_H*S_K-S_G*S_K+S_K^2-S_H*S_J-S_G*S_J+S_K*S_J+S_J^2, S_H^2+S_G^2-S_K^2-S_J^2-S_H*S_L-S_G*S_L+S_K*S_L+S_J*S_L, 0, 0, S_H*S_K*S_J+S_G*S_K*S_J-S_K^2*S_J-S_K*S_J^2}});
C#1 = cokernel map(S^{{-1}, {0}, {0}}, S^{{-1}, {-1}, {-2}, {-2}, {-2}, {-2}, {-2}, {-2}, {-2}}, {{0, 0, S_G-S_J, S_H-S_K, S_I-S_L, 0, 0, 0, 0}, {S_I+S_H+S_G-S_K-S_J-S_L, 0, 0, 0, 0, S_G^2-S_G*S_K-S_G*S_J+S_K*S_J, 0, 0, S_H^2+S_H*S_G-S_H*S_K-S_H*S_J-S_H*S_L-S_G*S_L+S_K*S_L+S_J*S_L}, {0, S_I+S_H+S_G-S_K-S_J-S_L, 0, 0, 0, 0, S_H*S_G-S_H*S_J-S_G*S_J+S_J^2, S_H^2+S_G^2-S_H*S_K-S_G*S_K+S_K*S_J-S_J^2-S_H*S_L-S_G*S_L+S_K*S_L+S_J*S_L, 0}});
C#2 = cokernel map(S^{{-1}}, S^{{-2}, {-2}, {-3}}, {{S_G-S_J, S_I+S_H-S_K-S_L, S_H^2-S_H*S_K-S_H*S_L+S_K*S_L}});
C#-1 = cokernel map(S^{{1}}, S^{{0}, {0}, {-1}}, {{S_H+S_G-S_K-S_J, S_I-S_L, S_G^2-S_G*S_K-S_G*S_J+S_K*S_J}});
C#dd#0 = map(cokernel map(S^{{1}}, S^{{0}, {0}, {-1}}, {{S_H+S_G-S_K-S_J, S_I-S_L, S_G^2-S_G*S_K-S_G*S_J+S_K*S_J}}), cokernel map(S^{{0}, {0}, {1}}, S^{{0}, {-1}, {-1}, {-1}, {-1}, {-1}, {-2}, {-2}, {-2}}, {{0, S_H+S_G-S_K-S_J, 0, S_I-S_L, 0, 0, S_G^2-S_G*S_K-S_G*S_J+S_K*S_J, 0, 0}, {0, 0, S_I+S_H+S_G-S_K-S_J-S_L, 0, S_H+S_G-S_K-S_J, -S_H-S_G+S_K+S_J, 0, S_H^2+S_H*S_G+S_G^2-S_H*S_K-S_G*S_K-S_H*S_J-S_G*S_J+S_K*S_J-S_H*S_L-S_G*S_L+S_K*S_L+S_J*S_L, -S_H*S_G+S_K*S_J}, {S_I+S_H+S_G-S_K-S_J-S_L, 0, 0, 0, S_H*S_G-S_H*S_K-S_G*S_K+S_K^2-S_H*S_J-S_G*S_J+S_K*S_J+S_J^2, S_H^2+S_G^2-S_K^2-S_J^2-S_H*S_L-S_G*S_L+S_K*S_L+S_J*S_L, 0, 0, S_H*S_K*S_J+S_G*S_K*S_J-S_K^2*S_J-S_K*S_J^2}}), {{S_G-S_J, -S_J, -1}});
C#dd#1 = map(cokernel map(S^{{0}, {0}, {1}}, S^{{0}, {-1}, {-1}, {-1}, {-1}, {-1}, {-2}, {-2}, {-2}}, {{0, S_H+S_G-S_K-S_J, 0, S_I-S_L, 0, 0, S_G^2-S_G*S_K-S_G*S_J+S_K*S_J, 0, 0}, {0, 0, S_I+S_H+S_G-S_K-S_J-S_L, 0, S_H+S_G-S_K-S_J, -S_H-S_G+S_K+S_J, 0, S_H^2+S_H*S_G+S_G^2-S_H*S_K-S_G*S_K-S_H*S_J-S_G*S_J+S_K*S_J-S_H*S_L-S_G*S_L+S_K*S_L+S_J*S_L, -S_H*S_G+S_K*S_J}, {S_I+S_H+S_G-S_K-S_J-S_L, 0, 0, 0, S_H*S_G-S_H*S_K-S_G*S_K+S_K^2-S_H*S_J-S_G*S_J+S_K*S_J+S_J^2, S_H^2+S_G^2-S_K^2-S_J^2-S_H*S_L-S_G*S_L+S_K*S_L+S_J*S_L, 0, 0, S_H*S_K*S_J+S_G*S_K*S_J-S_K^2*S_J-S_K*S_J^2}}), cokernel map(S^{{-1}, {0}, {0}}, S^{{-1}, {-1}, {-2}, {-2}, {-2}, {-2}, {-2}, {-2}, {-2}}, {{0, 0, S_G-S_J, S_H-S_K, S_I-S_L, 0, 0, 0, 0}, {S_I+S_H+S_G-S_K-S_J-S_L, 0, 0, 0, 0, S_G^2-S_G*S_K-S_G*S_J+S_K*S_J, 0, 0, S_H^2+S_H*S_G-S_H*S_K-S_H*S_J-S_H*S_L-S_G*S_L+S_K*S_L+S_J*S_L}, {0, S_I+S_H+S_G-S_K-S_J-S_L, 0, 0, 0, 0, S_H*S_G-S_H*S_J-S_G*S_J+S_J^2, S_H^2+S_G^2-S_H*S_K-S_G*S_K+S_K*S_J-S_J^2-S_H*S_L-S_G*S_L+S_K*S_L+S_J*S_L, 0}}), {{S_G-S_K, 1, 0}, {0, -1, -1}, {0, -S_H+S_K+S_J, S_J}});
C#dd#2 = map(cokernel map(S^{{-1}, {0}, {0}}, S^{{-1}, {-1}, {-2}, {-2}, {-2}, {-2}, {-2}, {-2}, {-2}}, {{0, 0, S_G-S_J, S_H-S_K, S_I-S_L, 0, 0, 0, 0}, {S_I+S_H+S_G-S_K-S_J-S_L, 0, 0, 0, 0, S_G^2-S_G*S_K-S_G*S_J+S_K*S_J, 0, 0, S_H^2+S_H*S_G-S_H*S_K-S_H*S_J-S_H*S_L-S_G*S_L+S_K*S_L+S_J*S_L}, {0, S_I+S_H+S_G-S_K-S_J-S_L, 0, 0, 0, 0, S_H*S_G-S_H*S_J-S_G*S_J+S_J^2, S_H^2+S_G^2-S_H*S_K-S_G*S_K+S_K*S_J-S_J^2-S_H*S_L-S_G*S_L+S_K*S_L+S_J*S_L, 0}}), cokernel map(S^{{-1}}, S^{{-2}, {-2}, {-3}}, {{S_G-S_J, S_I+S_H-S_K-S_L, S_H^2-S_H*S_K-S_H*S_L+S_K*S_L}}), {{1}, {-S_G+S_K}, {-S_H+S_J}});
)
else error "looks like I forgot a case";
C)


--these extend Macaulay2's ability to take tensor products and induced maps.
--these extend Macaulay2's ability to take tensor products and induced maps.
Line 167: Line 298:
D)
D)


inducedchainMap = (C,D,f) -> (
inducedchainMap = (C,D) -> (
map(
map(
C,D,i->inducedMap(C_i,D_i)
C,D,i->( inducedMap(C_i,D_i)) --print "found another induced map";
)
)
)
)


chainhomology = (FB,GB) -> (
--This has input a chain complex C and output a list of the complexes
CB:=source FB;
--Tor^i(C,coker M), provided M is a regular sequence.
H:=inducedchainMap(ker FB,image GB,id_CB);
E:=coker H;
E)

--this has input a chain complex C and a sequence M.
--The output is the complexes Tor^i(C,coker M) if M is a regular sequence.
Torify = (C,M) -> (
Torify = (C,M) -> (
J:=rank source M;
J:=rank source M;
KD:=apply(J+2,I->(print ("took tensor product " | toString I); C**koszul(I,M)));
L:=(0..J);
Lt=apply(L,I->(
Lt=apply(J+1,I->(
F:=koszul(I,M);
F:=KD_I;
G:=koszul(I+1,M);
G:=KD_(I+1);
FB=C**F;
E:=inducedchainMap(ker F,image G);
GB=C**G;
print ("found E " | toString I);
CB=source FB;
H:=coker E;
print ("found K-homology " | toString I);
H=inducedchainMap(ker FB,image GB,id_CB);
H));
E=coker H;
E));
Lt)
Lt)


--input, a link. output, KR homology (as modules). this is less useful than you think, just because of the difficulty of reading the output.
--This has input a braid, output the K-homology of KR double complex (i.e. the complexes of Tor's)
KRHom = K -> (
KRHom = (K,v) -> (
L:=KR(K);
L:=Torify(KR(K,v));
M:=apply(L,homology);
M:=apply(L,homology);
N:=apply(M,prune);
N:=apply(M,prune);
K#KRHom=N;
N)
N)


--This sends a chain complex to the list of degrees for which Macaulay2 remembers a module in it.
spots = C -> select(keys C, i -> class i === ZZ)
spots = C -> select(keys C, i -> class i === ZZ)


Line 204: Line 340:
--input, a knot K. output ((1-t)/(1+q*t))*(the graded Hilbert
--input, a knot K. output ((1-t)/(1+q*t))*(the graded Hilbert
--polynomial of K). THIS CURRENTLY ONLY WORKS FOR KNOTS, NOT LINKS.
--polynomial of K). THIS CURRENTLY ONLY WORKS FOR KNOTS, NOT LINKS.
KRpoly = K -> (
KRpoly = (K,v) -> (
L:=KRHom(K,v);
if K#?KRpoly then return K#KRpoly;
L:=KRHom K;
R:=ring L_0;
R:=ring L_0;
print "hello";
Rn:=#generators R;
Rn:=#generators R;
S:=QQ[t];
S:=QQ[t];
Line 217: Line 353:
spoM:=sort (spots M_0);
spoM:=sort (spots M_0);
P:=sum(apply(toList (0..#M-1), i-> (
P:=sum(apply(toList (0..#M-1), i-> (
q^i*sum(apply(spoM, j-> (
q^i*sum(apply(spoM, j-> (
s^j*sum(apply(flatten N_i j, k->t^k))
s^j*sum(apply(flatten N_i j, k->t^k))
)
)
))
))
)
)
));
));
K#KRpoly=P//(q*t+1);
K#KRpoly=P;
K#KRpoly)
P//(q*t+1))

--Basically the same as KRHom with more readable output.
KRdisp =(K,v) -> (
L:=KRHom (K,v);
N:=stack(between(" ", apply(#L,i->net i | " " | net L_i)));
N)
</pre>
</pre>

Revision as of 18:34, 15 January 2006

Calculations

Since calculations have now been incorporated into the normal KAtlas data structure, I don't feel like there's much point in having a table of them here.

Macaulay2 program

Save this as a file (called KR.m2), open Macaulay2 (in command line or emacs), and type load "KR.m2". KRpoly is probabby the command you want (but it only works for knots at the moment). It outputs . Using texMath puts things in format for LaTeX.

Changes from the previous version: the important change is in the construction of the Rouquier complex. Now it works by breaking up the braid into (at the moment, very simple) patterns it recognizes, and uses simplified Rouquier complexes for those chunks. This seems to be make a big difference in computational time, indicating that a program that could simplify large Rouquier complexes could lead to very large computational savings. I've made some progress in this direction, but am still struggling to produce something truly robust.


Here's a sample session:

Macaulay 2, version 0.9
--Copyright 1993-2001, D. R. Grayson and M. E. Stillman
--Singular-Factory 1.3b, copyright 1993-2001, G.-M. Greuel, et al.
--Singular-Libfac 0.3.2, copyright 1996-2001, M. Messollen

i1 : load "KR.m2"
KR.m2:113:11: warning: local declaration of N shields variable with same name
--loaded KR.m2

i2 : texMath KRpoly (K01,true)

o2 = 1

i3 : texMath KRpoly (K31,true)

o3 = s^{2} t^{2}+{q} t^{2}+1

i4 : 

Here's the code for the program.

--This file defines a new object for Macaulay2, called a "Link."
--Like all objects in Macaulay2, a Link is just a hash table.
--Defining a link lets you store information about it for later use.  

Link = new Type of MutableHashTable 
Link.synonym = "link"
new Link := Link => (cl) -> (
     C:=newClass(Link,new MutableHashTable);
     C)

--braidClosure is currently the only useful way of defining a link.  
--I think it should be clear from the examples below how to use it.
--(Remember to use {}, not () or [])
braidClosure = L ->(
     K:=new Link;
     K#braid=L;
     K)

--This defines all links of 7 or fewer crossings by a braid closure.
K01=braidClosure {1};
K31=braidClosure {1,1,1};
K41=braidClosure {1,-2,1,-2};
K51=braidClosure {1,1,1,1,1};
K52=braidClosure {-1,-1,-2,1,-2};
K61=braidClosure {1,1,2,-1,-3,2,-3};
K62=braidClosure {-1,-1,-1,2,-1,2};
K63=braidClosure {-1,-1,2,-1,2,2};
K71=braidClosure {-1,-1,-1,-1,-1,-1,-1}
K72=braidClosure {-1,-1,-1,-2,1,-2,-3,2,-3}
K73=braidClosure {1,1,1,1,1,2,-1,2}
K74=braidClosure {1,1,2,-1,2,2,3,-2,3}
K75=braidClosure {-1,-1,-1,-1,-2,1,-2,-2}
K76=braidClosure {-1,-1,2,-1,-3,2,-3}
K77=braidClosure {1,-2,1,-2,3,-2,3}

--Now all programs using the Rouqier complex (KR, KRHom, KRpoly) take an extra argument, which should be a truth value.  
--If this is "true," then the program will simplify chunks of the Rouquier complex using prescribed homotopies.  
--If it is "false," it will use the old brute force method.  
--Preliminary results indicate that the program will run MUCH faster if you use the "true" option, 
--but it is not 100% vetted yet.  there might well be mistakes hiding in there.  Let the user beware.

--this program now produces a complex homotopic to the Rouquier complex of the input braid, 
--as well as a presentation for the module that corresponds to closing the braid (in matrix form).
KR = (K,v) -> (
          if not K#?braid then error "no braid representation" else (
               Kb:=K#braid;
               P:=K#nbcross=#Kb;
               Ka:=apply(Kb,abs);
               Kt:=apply(Kb,i->(i>0));
               Ks:=sort Ka;
               bind:=K#bindex=last(Ks)+1;
               Cvars:=new MutableList from toList (-bind..-1);
	       I:=0;
	       J:=0;
	       Kp:={};
	       newv:=0;
               while I<P do (
		    print I;
		    M:=1;
		    while (Kb#?(I+M) and Kb#(I+M)==Kb#I) do M=M+1;
		    if (M>1 and v) then (
			 print ("used IImod " | toString(M));
			 Kp=append(Kp, (("II",M),(Cvars#(Ka_I-1),Cvars#(Ka_I+1-1),newv,Kt_I)));
			 newvp=newv+2;
			 J=I+M)
		    else if ((Kb#?(I+2) and Ka_I==Ka_(I+2)) and v) then (
			 if Ka_I==Ka_(I+1)+1 then (
			      if (Kb_(I+1)==Kb_(I+3) and Kb_I==Kb_(I+2)) then (
				   print "used babamod";
				   Kp=append(Kp,("baba",(Cvars#(Ka_I),Cvars#(Ka_I-1),Cvars#(Ka_I-2),newv+1,newv,newv+2,Kt_I,Kt_(I+1),Kt_(I+2),Kt_(I+3))));
				   J=I+4;
				   )
			      else (
			      	   print "used abamod";
			      	   Kp=append(Kp,("aba",(Cvars#(Ka_I),Cvars#(Ka_I-1),Cvars#(Ka_I-2),newv+1,newv,newv+2,Kt_I,Kt_(I+1),Kt_(I+2))));
				   J=I+3;
				   );
			      Cvars#(Ka_I-2)=newv+2;
			      newvp=newv+3)
			 else if Ka_I==Ka_(I+1)-1  then (
			      if (Kb_(I+1)==Kb_(I+3) and Kb_I==Kb_(I+2)) then ( 
	     		      	   print "used babamod";
			      	   Kp=append(Kp,("baba",(Cvars#(Ka_I-1),Cvars#(Ka_I),Cvars#(Ka_I+1),newv,newv+1,newv+2,Kt_I,Kt_(I+1),Kt_(I+2),Kt_(I+3))));
				   J=I+4;
				   )
			      else(
				   print "used abamod";
			      	   Kp=append(Kp,("aba",(Cvars#(Ka_I-1),Cvars#(Ka_I),Cvars#(Ka_I+1),newv,newv+1,newv+2,Kt_I,Kt_(I+1),Kt_(I+2))));
				   J=I+3;
				   );
			      Cvars#(Ka_I+1)=newv+2;
			      newvp=newv+3
			      )
			 else (
			      print "used stmod"; 
			      Kp=append(Kp,("st",(Cvars#(Ka_I-1),Cvars#(Ka_I),newv,Kt_I)));
			      newvp=newv+2;
			      J=I+1)
			 )
		    else (
			 print "used stmod"; 
			 Kp=append(Kp,("st",(Cvars#(Ka_I-1),Cvars#(Ka_I),newv,Kt_I)));
			 newvp=newv+2;
			 J=I+1);
                    Cvars#(Ka_I-1)=newv;
                    Cvars#(Ka_I)=newv+1;
		    I=J;
		    newv=newvp;
                    );
	       print Kp;
	       elim=newv-bind;
	       R:=QQ[vars(1 .. newv+bind),MonomialOrder=>Eliminate elim];
	       Kp=apply(Kp,(S1,S2) -> (S1,apply(S2,i-> (if (class i===ZZ and i<0) then x=i+newv+bind else x=i; x))));
               Kmod:= chainComplex( gradedModule(R^1));
	       for J from 0 to #Kp-1 do (
	       	    if ((Kp_J)_0)_0=="II" then  Kmod=Kmod**IImod join((Kp_J)_1,  (((Kp_J)_0)_1,R))
		    else if (Kp_J)_0=="aba" then Kmod=Kmod**abamod append((Kp_J)_1,R)
		    else if (Kp_J)_0=="baba" then Kmod=Kmod**babamod append((Kp_J)_1,R)
		    else if (Kp_J)_0=="st" then Kmod=Kmod**stmod append((Kp_J)_1,R)
		    else error "oops, missed a case"	     
          	    );
--	       scan(spots Kmod, i -> if Kmod#dd#?i then print (isWellDefined Kmod.dd_i));
     	       M:=matrix {apply(bind, I-> R_(Cvars#I)-R_(newv+I))};
               return (Kmod,M);
          );
     )

--this produces a simpler complex for an arbitrary number of twists of two adjacent strands.
IImod = (H,I,J,W,n,S) -> (
     i:=ideal(S_H+S_I-S_J-S_(J+1),S_H*S_I-S_J*S_(J+1));
     Dp:=chainComplex map(S^{0}/i,S^{-1}/i,S_I-S_J);
     Dn:=chainComplex map(S^{2}/i,S^{1}/i,S_I-S_J)[1];
     if mod(n,2)==0 then C=ftmod(H,I,J,W,S);
     if mod(n,2)==1 then C=stmod(H,I,J,W,S);
     while n>2 do (
	  if W then C=C[-2]**S^{-2}++Dp
	  else C=C[2]**S^{2}++Dn;
	  n=n-2;
	  );
     C)

--this produces a simpler complex for a full twist of two strands.  Now just feeds into "IImod."
ftmod = (H,I,J,W,S) -> (
     i:=ideal(S_H+S_I-S_J-S_(J+1),S_H*S_I-S_J*S_(J+1));
     j:=ideal(S_H-S_J,S_I-S_(J+1));
     if W then (
	  M0=S^1/i;
	  M1=S^{-1}/i;
	  M2=S^{-2}/j;
	  f1=map(M0,M1,S_H-S_I-S_J+S_(J+1));
	  f2=map(M1,M2,S_J-S_I);
	  C=chainComplex(f1,f2));
     if not W then (
	  M0=S^{2}/j;
	  M1=S^{2}/i;
	  M2=S^{1}/i;
	  f1=map(M0,M1);
	  f2=map(M1,M2,S_H-S_J-S_I+S_(J+1));
	  C=chainComplex(f1,f2)[2]);
     C)

--this produces the standard Rouquier complex for a single crossing
stmod = (H,I,J,W,S) -> (
          if W then (
	       Mp=S^1/ideal(S_H+S_I-S_J-S_(J+1),S_H*S_I-S_J*S_(J+1));
               Np=S^{-1}/ideal(S_H-S_J,S_I-S_(J+1));
	       C=chainComplex(map(Mp,Np,(S_J-S_I))))
          else (
	       Mn=S^{1}/ideal(S_H+S_I-S_J-S_(J+1),S_H*S_I-S_J*S_(J+1));
               Nn=S^{1}/ideal(S_H-S_J,S_I-S_(J+1));
               C=chainComplex(map(Nn,Mn))[1]);
          C)
     
--this produces a simplified Rouquier for braids of length 3 lifting the longest element of S_3.
abamod = (G,H,I,J,K,L,W,V,X,S) -> (
     i:=ideal(S_G-S_J,S_H-S_K,S_I-S_L);
     j1:=ideal(S_H+S_G-S_J-S_K,S_H*S_G-S_J*S_K,S_I-S_L);
     j2:=ideal(S_H+S_I-S_L-S_K,S_H*S_I-S_L*S_K,S_G-S_J);
     k1:=ideal(S_H+S_G+S_I-S_J-S_K-S_L, (S_I-S_K)*(S_I-S_L),(S_J-S_G)*(S_J-S_H));
     k2:=ideal(S_H+S_G+S_I-S_J-S_K-S_L, (S_L-S_H)*(S_I-S_L),(S_J-S_G)*(S_G-S_K));
     l:=ideal(S_H+S_G+S_I-S_J-S_K-S_L, S_H*S_G+S_I*S_G+S_I*S_H-S_J*S_K-S_L*S_J-S_K*S_L, S_H*S_G*S_I-S_J*S_K*S_L);
     if ((not W) and (not V) and (not X)) then (
	  M0=S^{3}/i;
	  M1=S^{3}/j1++S^{3}/j2;
	  M2=S^{3}/k1++S^{3}/k2;	  
	  M3=S^{3}/l;
	  f1=map(M0,M1,matrix{{1_S,-1}});
	  f2=map(M1,M2,matrix{{1_S,-1},{1,-1}});
	  f3=map(M2,M3,matrix{{1_S},{1}});
	  C=chainComplex(f1,f2,f3)[3]
	  )
     else if (W and V and X) then (
	  M0=S^1/l;
	  M1=S^{-1}/k1++S^{-1}/k2;
	  M2=S^{-2}/j1++S^{-2}/j2;
	  M3=S^{-3}/i;
	  f1=map(M0,M1,matrix{{S_I-S_J,-S_G+S_L}});
	  f2=map(M1,M2,matrix{{S_I-S_K,-S_H+S_J},{S_H-S_L,-S_G+S_K}});
	  f3=map(M2,M3,matrix{{-S_K+S_G},{-S_L+S_H}});
	  C=chainComplex(f1,f2,f3)
	  )      
     else if ((not W) and (not V) and X) then (
	  M0=S^{2}/k2++S^{1}/i;
	  M1=S^{2}/l++S^{1}/j1++S^{1}/j2;
	  M2=S^{1}/k1;
	  f1=map(M0,M1,matrix{{1,S_H-S_L,S_G-S_K},{0,-1,1}});
	  f2=map(M1,M2,matrix{{S_I-S_J},{1},{1}});
	  C=chainComplex(f1,f2)[1]
	  )
     else if (W and (not V) and (not X)) then (
	  M0=S^{2}/k1++S^{1}/i;
	  M1=S^{2}/l++S^{1}/j1++S^{1}/j2;
	  M2=S^{1}/k2;
	  f1=map(M0,M1,matrix{{1,S_I-S_K,S_H-S_J},{0,-1,1}});
	  f2=map(M1,M2,matrix{{S_G-S_L},{1},{1}});
	  C=chainComplex(f1,f2)[1]
	  )
     else if (W and V and (not X)) then (
     	  M2=S^{0}/k2++S^{-1}/i;
	  M1=S^{1}/l++S^{0}/j1++S^{0}/j2;
	  M0=S^{1}/k1;
	  f1=map(M0,M1,matrix {{-1,-S_I+S_K,S_J-S_H}});
	  f2=map(M1,M2,matrix {{S_G-S_L,0},{1,S_H-S_J},{1,-S_I+S_K}});
	  C=chainComplex(f1,f2)[1])
     else if ((not W) and V and X) then (
     	  M2=S^{0}/k1++S^{-1}/i;
	  M1=S^{1}/l++S^{0}/j1++S^{0}/j2;
	  M0=S^{1}/k2;
	  f1=map(M0,M1,matrix {{-1,-S_L+S_H,S_G-S_K}});
	  f2=map(M1,M2,matrix {{S_J-S_I,0},{1,S_K-S_G},{1,-S_L+S_H}});
	  C=chainComplex(f1,f2)[1]
	  )
     else if ((not W) and V and (not X)) then (
	  C=new ChainComplex;
	  C.ring=S;
C#0 = cokernel map(S^{{1}, {1}, {2}}, S^{{1}, {0}, {0}, {0}, {0}, {0}, {-1}, {-1}, {-1}}, {{0, S_H+S_G-S_K-S_J, 0, 0, 0, S_I-S_L, S_G^2-S_G*S_K-S_G*S_J+S_K*S_J, 0, 0}, {0, 0, S_I+S_H+S_G-S_K-S_J-S_L, S_H+S_G-S_K-S_J, -S_H-S_G+S_K+S_J, 0, 0, -S_H*S_G+S_K*S_J, S_H^2+S_H*S_G+S_G^2-S_H*S_K-S_G*S_K-S_H*S_J-S_G*S_J+S_K*S_J-S_H*S_L-S_G*S_L+S_K*S_L+S_J*S_L}, {S_I+S_H+S_G-S_K-S_J-S_L, 0, 0, S_H*S_G-S_H*S_K-S_G*S_K+S_K^2-S_H*S_J-S_G*S_J+S_K*S_J+S_J^2, S_H^2+S_G^2-S_K^2-S_J^2-S_H*S_L-S_G*S_L+S_K*S_L+S_J*S_L, 0, 0, S_H*S_K*S_J+S_G*S_K*S_J-S_K^2*S_J-S_K*S_J^2, 0}});
      C#1 = cokernel map(S^{{0}}, S^{{-1}, {-1}, {-2}}, {{S_H+S_G-S_K-S_J, S_I-S_L, S_G^2-S_G*S_K-S_G*S_J+S_K*S_J}});
      C#-2 = cokernel map(S^{{2}}, S^{{1}, {1}, {0}}, {{S_G-S_J, S_I+S_H-S_K-S_L, S_H^2-S_H*S_K-S_H*S_L+S_K*S_L}});
      C#-1 = cokernel map(S^{{1}, {2}, {2}}, S^{{1}, {1}, {0}, {0}, {0}, {0}, {0}, {0}, {0}}, {{0, 0, S_G-S_J, S_H-S_K, S_I-S_L, 0, 0, 0, 0}, {S_I+S_H+S_G-S_K-S_J-S_L, 0, 0, 0, 0, 0, S_H*S_G-S_H*S_J-S_G*S_J+S_J^2, S_H^2+S_G^2-S_H*S_K-S_G*S_K+S_K*S_J-S_J^2-S_H*S_L-S_G*S_L+S_K*S_L+S_J*S_L, 0}, {0, S_I+S_H+S_G-S_K-S_J-S_L, 0, 0, 0, S_G^2-S_G*S_K-S_G*S_J+S_K*S_J, 0, 0, S_H^2+S_H*S_G-S_H*S_K-S_H*S_J-S_H*S_L-S_G*S_L+S_K*S_L+S_J*S_L}});
      C#dd#0 = map(cokernel map(S^{{1}, {2}, {2}}, S^{{1}, {1}, {0}, {0}, {0}, {0}, {0}, {0}, {0}}, {{0, 0, S_G-S_J, S_H-S_K, S_I-S_L, 0, 0, 0, 0}, {S_I+S_H+S_G-S_K-S_J-S_L, 0, 0, 0, 0, 0, S_H*S_G-S_H*S_J-S_G*S_J+S_J^2, S_H^2+S_G^2-S_H*S_K-S_G*S_K+S_K*S_J-S_J^2-S_H*S_L-S_G*S_L+S_K*S_L+S_J*S_L, 0}, {0, S_I+S_H+S_G-S_K-S_J-S_L, 0, 0, 0, S_G^2-S_G*S_K-S_G*S_J+S_K*S_J, 0, 0, S_H^2+S_H*S_G-S_H*S_K-S_H*S_J-S_H*S_L-S_G*S_L+S_K*S_L+S_J*S_L}}), cokernel map(S^{{1}, {1}, {2}}, S^{{1}, {0}, {0}, {0}, {0}, {0}, {-1}, {-1}, {-1}}, {{0, S_H+S_G-S_K-S_J, 0, 0, 0, S_I-S_L, S_G^2-S_G*S_K-S_G*S_J+S_K*S_J, 0, 0}, {0, 0, S_I+S_H+S_G-S_K-S_J-S_L, S_H+S_G-S_K-S_J, -S_H-S_G+S_K+S_J, 0, 0, -S_H*S_G+S_K*S_J, S_H^2+S_H*S_G+S_G^2-S_H*S_K-S_G*S_K-S_H*S_J-S_G*S_J+S_K*S_J-S_H*S_L-S_G*S_L+S_K*S_L+S_J*S_L}, {S_I+S_H+S_G-S_K-S_J-S_L, 0, 0, S_H*S_G-S_H*S_K-S_G*S_K+S_K^2-S_H*S_J-S_G*S_J+S_K*S_J+S_J^2, S_H^2+S_G^2-S_K^2-S_J^2-S_H*S_L-S_G*S_L+S_K*S_L+S_J*S_L, 0, 0, S_H*S_K*S_J+S_G*S_K*S_J-S_K^2*S_J-S_K*S_J^2, 0}}), {{-1, 0, 0}, {S_H+S_G-S_J-S_L, -S_K, -1}, {0, S_G-S_K-S_J, -1}});
      C#dd#1 = map(cokernel map(S^{{1}, {1}, {2}}, S^{{1}, {0}, {0}, {0}, {0}, {0}, {-1}, {-1}, {-1}}, {{0, S_H+S_G-S_K-S_J, 0, 0, 0, S_I-S_L, S_G^2-S_G*S_K-S_G*S_J+S_K*S_J, 0, 0}, {0, 0, S_I+S_H+S_G-S_K-S_J-S_L, S_H+S_G-S_K-S_J, -S_H-S_G+S_K+S_J, 0, 0, -S_H*S_G+S_K*S_J, S_H^2+S_H*S_G+S_G^2-S_H*S_K-S_G*S_K-S_H*S_J-S_G*S_J+S_K*S_J-S_H*S_L-S_G*S_L+S_K*S_L+S_J*S_L}, {S_I+S_H+S_G-S_K-S_J-S_L, 0, 0, S_H*S_G-S_H*S_K-S_G*S_K+S_K^2-S_H*S_J-S_G*S_J+S_K*S_J+S_J^2, S_H^2+S_G^2-S_K^2-S_J^2-S_H*S_L-S_G*S_L+S_K*S_L+S_J*S_L, 0, 0, S_H*S_K*S_J+S_G*S_K*S_J-S_K^2*S_J-S_K*S_J^2, 0}}), cokernel map(S^{{0}}, S^{{-1}, {-1}, {-2}}, {{S_H+S_G-S_K-S_J, S_I-S_L, S_G^2-S_G*S_K-S_G*S_J+S_K*S_J}}), {{S_G-S_J}, {S_G-S_L}, {S_G^2-S_G*S_K-S_G*S_J-S_G*S_L+S_K*S_L+S_J*S_L}});
      C#dd#-1 = map(cokernel map(S^{{2}}, S^{{1}, {1}, {0}}, {{S_G-S_J, S_I+S_H-S_K-S_L, S_H^2-S_H*S_K-S_H*S_L+S_K*S_L}}), cokernel map(S^{{1}, {2}, {2}}, S^{{1}, {1}, {0}, {0}, {0}, {0}, {0}, {0}, {0}}, {{0, 0, S_G-S_J, S_H-S_K, S_I-S_L, 0, 0, 0, 0}, {S_I+S_H+S_G-S_K-S_J-S_L, 0, 0, 0, 0, 0, S_H*S_G-S_H*S_J-S_G*S_J+S_J^2, S_H^2+S_G^2-S_H*S_K-S_G*S_K+S_K*S_J-S_J^2-S_H*S_L-S_G*S_L+S_K*S_L+S_J*S_L, 0}, {0, S_I+S_H+S_G-S_K-S_J-S_L, 0, 0, 0, S_G^2-S_G*S_K-S_G*S_J+S_K*S_J, 0, 0, S_H^2+S_H*S_G-S_H*S_K-S_H*S_J-S_H*S_L-S_G*S_L+S_K*S_L+S_J*S_L}}), {{-S_H+S_L, -1, 1}});)
     else if (W and (not V) and X) then ( 
	  C=new ChainComplex;
	  C.ring=S;
	  C#0 = cokernel map(S^{{0}, {0}, {1}}, S^{{0}, {-1}, {-1}, {-1}, {-1}, {-1}, {-2}, {-2}, {-2}}, {{0, S_H+S_G-S_K-S_J, 0, S_I-S_L, 0, 0, S_G^2-S_G*S_K-S_G*S_J+S_K*S_J, 0, 0}, {0, 0, S_I+S_H+S_G-S_K-S_J-S_L, 0, S_H+S_G-S_K-S_J, -S_H-S_G+S_K+S_J, 0, S_H^2+S_H*S_G+S_G^2-S_H*S_K-S_G*S_K-S_H*S_J-S_G*S_J+S_K*S_J-S_H*S_L-S_G*S_L+S_K*S_L+S_J*S_L, -S_H*S_G+S_K*S_J}, {S_I+S_H+S_G-S_K-S_J-S_L, 0, 0, 0, S_H*S_G-S_H*S_K-S_G*S_K+S_K^2-S_H*S_J-S_G*S_J+S_K*S_J+S_J^2, S_H^2+S_G^2-S_K^2-S_J^2-S_H*S_L-S_G*S_L+S_K*S_L+S_J*S_L, 0, 0, S_H*S_K*S_J+S_G*S_K*S_J-S_K^2*S_J-S_K*S_J^2}});
       	  C#1 = cokernel map(S^{{-1}, {0}, {0}}, S^{{-1}, {-1}, {-2}, {-2}, {-2}, {-2}, {-2}, {-2}, {-2}}, {{0, 0, S_G-S_J, S_H-S_K, S_I-S_L, 0, 0, 0, 0}, {S_I+S_H+S_G-S_K-S_J-S_L, 0, 0, 0, 0, S_G^2-S_G*S_K-S_G*S_J+S_K*S_J, 0, 0, S_H^2+S_H*S_G-S_H*S_K-S_H*S_J-S_H*S_L-S_G*S_L+S_K*S_L+S_J*S_L}, {0, S_I+S_H+S_G-S_K-S_J-S_L, 0, 0, 0, 0, S_H*S_G-S_H*S_J-S_G*S_J+S_J^2, S_H^2+S_G^2-S_H*S_K-S_G*S_K+S_K*S_J-S_J^2-S_H*S_L-S_G*S_L+S_K*S_L+S_J*S_L, 0}});
       	  C#2 = cokernel map(S^{{-1}}, S^{{-2}, {-2}, {-3}}, {{S_G-S_J, S_I+S_H-S_K-S_L, S_H^2-S_H*S_K-S_H*S_L+S_K*S_L}});
       	  C#-1 = cokernel map(S^{{1}}, S^{{0}, {0}, {-1}}, {{S_H+S_G-S_K-S_J, S_I-S_L, S_G^2-S_G*S_K-S_G*S_J+S_K*S_J}});
       	  C#dd#0 = map(cokernel map(S^{{1}}, S^{{0}, {0}, {-1}}, {{S_H+S_G-S_K-S_J, S_I-S_L, S_G^2-S_G*S_K-S_G*S_J+S_K*S_J}}), cokernel map(S^{{0}, {0}, {1}}, S^{{0}, {-1}, {-1}, {-1}, {-1}, {-1}, {-2}, {-2}, {-2}}, {{0, S_H+S_G-S_K-S_J, 0, S_I-S_L, 0, 0, S_G^2-S_G*S_K-S_G*S_J+S_K*S_J, 0, 0}, {0, 0, S_I+S_H+S_G-S_K-S_J-S_L, 0, S_H+S_G-S_K-S_J, -S_H-S_G+S_K+S_J, 0, S_H^2+S_H*S_G+S_G^2-S_H*S_K-S_G*S_K-S_H*S_J-S_G*S_J+S_K*S_J-S_H*S_L-S_G*S_L+S_K*S_L+S_J*S_L, -S_H*S_G+S_K*S_J}, {S_I+S_H+S_G-S_K-S_J-S_L, 0, 0, 0, S_H*S_G-S_H*S_K-S_G*S_K+S_K^2-S_H*S_J-S_G*S_J+S_K*S_J+S_J^2, S_H^2+S_G^2-S_K^2-S_J^2-S_H*S_L-S_G*S_L+S_K*S_L+S_J*S_L, 0, 0, S_H*S_K*S_J+S_G*S_K*S_J-S_K^2*S_J-S_K*S_J^2}}), {{S_G-S_J, -S_J, -1}});
       	  C#dd#1 = map(cokernel map(S^{{0}, {0}, {1}}, S^{{0}, {-1}, {-1}, {-1}, {-1}, {-1}, {-2}, {-2}, {-2}}, {{0, S_H+S_G-S_K-S_J, 0, S_I-S_L, 0, 0, S_G^2-S_G*S_K-S_G*S_J+S_K*S_J, 0, 0}, {0, 0, S_I+S_H+S_G-S_K-S_J-S_L, 0, S_H+S_G-S_K-S_J, -S_H-S_G+S_K+S_J, 0, S_H^2+S_H*S_G+S_G^2-S_H*S_K-S_G*S_K-S_H*S_J-S_G*S_J+S_K*S_J-S_H*S_L-S_G*S_L+S_K*S_L+S_J*S_L, -S_H*S_G+S_K*S_J}, {S_I+S_H+S_G-S_K-S_J-S_L, 0, 0, 0, S_H*S_G-S_H*S_K-S_G*S_K+S_K^2-S_H*S_J-S_G*S_J+S_K*S_J+S_J^2, S_H^2+S_G^2-S_K^2-S_J^2-S_H*S_L-S_G*S_L+S_K*S_L+S_J*S_L, 0, 0, S_H*S_K*S_J+S_G*S_K*S_J-S_K^2*S_J-S_K*S_J^2}}), cokernel map(S^{{-1}, {0}, {0}}, S^{{-1}, {-1}, {-2}, {-2}, {-2}, {-2}, {-2}, {-2}, {-2}}, {{0, 0, S_G-S_J, S_H-S_K, S_I-S_L, 0, 0, 0, 0}, {S_I+S_H+S_G-S_K-S_J-S_L, 0, 0, 0, 0, S_G^2-S_G*S_K-S_G*S_J+S_K*S_J, 0, 0, S_H^2+S_H*S_G-S_H*S_K-S_H*S_J-S_H*S_L-S_G*S_L+S_K*S_L+S_J*S_L}, {0, S_I+S_H+S_G-S_K-S_J-S_L, 0, 0, 0, 0, S_H*S_G-S_H*S_J-S_G*S_J+S_J^2, S_H^2+S_G^2-S_H*S_K-S_G*S_K+S_K*S_J-S_J^2-S_H*S_L-S_G*S_L+S_K*S_L+S_J*S_L, 0}}), {{S_G-S_K, 1, 0}, {0, -1, -1}, {0, -S_H+S_K+S_J, S_J}});
       	  C#dd#2 = map(cokernel map(S^{{-1}, {0}, {0}}, S^{{-1}, {-1}, {-2}, {-2}, {-2}, {-2}, {-2}, {-2}, {-2}}, {{0, 0, S_G-S_J, S_H-S_K, S_I-S_L, 0, 0, 0, 0}, {S_I+S_H+S_G-S_K-S_J-S_L, 0, 0, 0, 0, S_G^2-S_G*S_K-S_G*S_J+S_K*S_J, 0, 0, S_H^2+S_H*S_G-S_H*S_K-S_H*S_J-S_H*S_L-S_G*S_L+S_K*S_L+S_J*S_L}, {0, S_I+S_H+S_G-S_K-S_J-S_L, 0, 0, 0, 0, S_H*S_G-S_H*S_J-S_G*S_J+S_J^2, S_H^2+S_G^2-S_H*S_K-S_G*S_K+S_K*S_J-S_J^2-S_H*S_L-S_G*S_L+S_K*S_L+S_J*S_L, 0}}), cokernel map(S^{{-1}}, S^{{-2}, {-2}, {-3}}, {{S_G-S_J, S_I+S_H-S_K-S_L, S_H^2-S_H*S_K-S_H*S_L+S_K*S_L}}), {{1}, {-S_G+S_K}, {-S_H+S_J}});
      	  )
     else error "looks like I forgot a case";
     C)

--these extend Macaulay2's ability to take tensor products and induced maps.
ChainComplex ** Matrix := ChainComplexMap => (C,f) ->(
     map(C ** target f,C** source f,i -> id_(C_i)**f))

RingMap ** GradedModule := GradedModule => (f,C) -> (
     D := new GradedModule;
     D#ring= target f;
     scan(spots C, i->D#i=f**C#i);
     D) 

inducedchainMap = (C,D) -> (
     map(
          C,D,i->( inducedMap(C_i,D_i)) --print "found another induced map";
          )
     )

chainhomology = (FB,GB) -> (
          CB:=source FB;
          H:=inducedchainMap(ker FB,image GB,id_CB);
          E:=coker H;
	  E)

--this has input a chain complex C and a sequence M.  
--The output is the complexes Tor^i(C,coker M) if M is a regular sequence.
Torify = (C,M) -> (
     J:=rank source M;
     KD:=apply(J+2,I->(print ("took tensor product " | toString I); C**koszul(I,M)));
     Lt=apply(J+1,I->(
          F:=KD_I;
          G:=KD_(I+1);
          E:=inducedchainMap(ker F,image G);
	  print ("found E " | toString I);
	  H:=coker E;
	  print ("found K-homology " | toString I);
	  H));
      Lt)

--This has input a braid, output the K-homology of KR double complex (i.e. the complexes of Tor's)
KRHom = (K,v) -> (
          L:=Torify(KR(K,v));
          M:=apply(L,homology);
          N:=apply(M,prune);
	  K#KRHom=N;
          N)

spots = C -> select(keys C, i -> class i === ZZ)

degrees(GradedModule) := Function => C -> (
     i -> degrees C_i)

--input, a knot K. output ((1-t)/(1+q*t))*(the graded Hilbert 
--polynomial of K).  THIS CURRENTLY ONLY WORKS FOR KNOTS, NOT LINKS.
KRpoly = (K,v) -> (
     L:=KRHom(K,v);
     R:=ring L_0;
     print "hello";
     Rn:=#generators R;
     S:=QQ[t];
     f=map(S,R,apply(toList (1..Rn),i->t));
     M:=apply(L, C -> f**C);
     N:=apply(M,degrees);
     K#KRdeg=N;
     Pring=QQ[q,s,t,Inverses=>true];
     spoM:=sort (spots M_0);
     P:=sum(apply(toList (0..#M-1), i-> (
		    q^i*sum(apply(spoM, j-> (
				   s^j*sum(apply(flatten N_i j, k->t^k))
				   )
			 ))
	       )
	)); 
     K#KRpoly=P;
     P//(q*t+1))

--Basically the same as KRHom with more readable output.
KRdisp =(K,v) -> (
     L:=KRHom (K,v);
     N:=stack(between(" ", apply(#L,i->net i | "  " | net L_i)));
     N)