alexmat.sa


Generated by gen_html_sa_files from ICSI. Contact gomes@icsi.berkeley.edu for details
 
-- Copyright (C) in the sense of GPL.
-- 2003/12 twisted Novikov(extended Alexander)ideal. kdm
-- 2002/12 twisted Alexander based on ALEXMAT class. kdm
-- 2002/11 Novikov (extended Alexander) ideal. kdm
-- 2001/12 Grobner bases for Elementary ideals. kdm
-- 2001/02 Sather version. kdm
-- 1998/1 LongInt kdm
-- 1997/1 Theta curve, un-oriented surface in S^4 kdm
-- 1996/10 LINUX version, bug fix for 2-knot kdm
-- 1992/6  Alexander matrix and Alexander polynomial.  kdm
-- 1992/6/20:  10para99(parallel of k10c99. 40 crossing) 10sec. kdm
-- 1983 Alexander poly. 1st version Kouji kdm KODAMA 
--K. Kodama


class ALEXMAT

class ALEXMAT is include ALEXMAT_ALG{MAT_POLYS_INTI,POLYS_INTI,INTI}; include ALEXMAT_IDEAL_ALG{MAT_POLYS_INTI,POLYS_INTI,INTI}; include ALEXMAT_IDEAL_INTI_ALG{MAT_POLYS_INTI,POLYS_INTI,INTI}; include C2A_ALG{POLYS_INTI}; APolyOut(p0:CARD, testSym:BOOL,use_conway:BOOL) is pa:POLYS_INTI; AlexPoly(p0,out pa); if use_conway then pc:POLYS_INTI; apoly2conway(pa, out pc); printConway(pc); else printApoly(pa,"Alexander Polynomial"); end; if testSym then -- Test symmetry using Murasugi's condition. SYMMET::TestSym(pa); end; end; AlexMat(TCode:TCODE, testSym:BOOL, testGb:BOOL) is AlexMat(TCode,testSym,testGb,false); end; MatReduction:CARD is -- reduce relation matrix and get ideals. rDeg:CARD; MAT_POLYS_INTI_REDUCTION::reduce(inout AMat,out jPivot,out rDeg); return rDeg; end; AlexMat(TCode:TCODE, testSym:BOOL, testGb:BOOL, use_conway:BOOL) is if testSym then if TCode.has_band then #OUT+"[test cyclic] not support knotting surface.\n"; return; elsif TCode.number_compo/=1.int then #OUT+"[test cyclic] not support links.\n"; return; end; end; -- num_gen:=TCode.number_gen; if (num_gen<=1)or(num_gen=TCode.number_compo.card) then #LOGOUT+"The "; if TCode[TCode.length].compo=1.int then #LOGOUT+"knot"; else #LOGOUT+"link"; end; if num_gen=0 then #LOGOUT+" is empty."; else #LOGOUT+" is Trivial."; end; LOGOUT::flush; return; end; POLYS_INTI::init; MakeMatrix(TCode); LOGOUT::LogTime; WriteMatrix(0); LOGOUT::flush; trimMat1(TCode); rDeg::=MatReduction; WriteMatrix(rDeg); LOGOUT::flush; if testGb then AlexanderIdeals(rDeg); end; LOGOUT::flush; if ~TCode.has_band then APolyOut(rDeg,testSym,use_conway); end; #LOGOUT+"\n"; LOGOUT::flush; AMat:=#(0,0); end; end;

class ALEXMAT_TWIST

class ALEXMAT_TWIST is -- CT: INTI -- ET: POLYS_INTI -- 2002/12 twisted Alexander based on ALEXMAT class. include ALEXMAT_ALG{MAT_POLYS_INTI,POLYS_INTI,INTI}; include ALEXMAT_IDEAL_ALG{MAT_POLYS_INTI,POLYS_INTI,INTI}; include ALEXMAT_IDEAL_INTI_ALG{MAT_POLYS_INTI,POLYS_INTI,INTI}; include ALEXMAT_TWIST_ALG{MAT_POLYS_INTI,POLYS_INTI,INTI}; MatReduction:CARD is rDeg:CARD; MAT_POLYS_INTI_REDUCTION::reduce(inout AMat,out jPivot,out rDeg); return rDeg; end; end;

class ALEXMAT_TWIST_FP

class ALEXMAT_TWIST_FP is -- CT: Finite Field -- ET: polynomial is principal ideal domain (with GCD algorithm) -- 2002/12 twisted Alexander based on ALEXMAT class. include ALEXMAT_ALG{MAT_POLYS_FP,POLYS_FP,FINITE_FIELD}; include ALEXMAT_IDEAL_ALG{MAT_POLYS_FP,POLYS_FP,FINITE_FIELD}; include ALEXMAT_IDEAL_FP_ALG{MAT_POLYS_FP,POLYS_FP,FINITE_FIELD}; include ALEXMAT_TWIST_ALG{MAT_POLYS_FP,POLYS_FP,FINITE_FIELD}; MatReduction:CARD is rDeg:CARD; AMat.reduce(out jPivot,out rDeg); return rDeg; end; end;

partial class ALEXMAT_IDEAL_ALG{MT,ET,CT}

partial class ALEXMAT_IDEAL_ALG{MT,ET,CT} is splitMatrix(p0:CARD, out diagonal_part:ARRAY{ET}, out SAMat:MT) is -- split Alexander matrix AMat to diagoanl part and other part. zFlg:BOOL; zFlg:=true; degR::=AMat.nr; degG::=AMat.nc; if (degR=degG)and(p0=degR-1) then p0:=degR; end; -- Get diagonal part. d0::=(p0).min(degR).min(degG);-- length of diagonel part diagonal_part:=#; -- Number of 0-part is trimN. loop i::=0.upto!(d0-1); j::=jPivot[i]; if (AMat[i][j].is_one)or(AMat[i][j].negate.is_one) then ;--remove trivial elsif (AMat[i][j].is_zero) then trimN:=trimN+1; else diagonal_part:=diagonal_part.append(AMat[i][j]); end; end; -- Get other part SAMat:=#(degR-p0,degG-p0); if (p0<degR)or(p0<degG) then loop i::=(p0).upto!(degR-1); si::=0.up!; loop SAMat[si][0.up!]:=AMat[i][jPivot[(p0).upto!(degG-1)]]; end; end; end; end; AlexanderIdeals(p0:CARD) is diagonal_part:ARRAY{ET}; SAMat:MT; splitMatrix(p0,out diagonal_part,out SAMat); -- #OUT+"diagonal-0: "; loop trimN.times!; #OUT+"0,"; end; #OUT+"\n"; -- #OUT+"diagonal: "+diagonal_part+"\n"; -- #OUT+"matrix : "+SAMat.str+"\n"; -- diagonal is: trimN times 0 and diagonal_part loop ideg::=trimN.upto!(trimN+diagonal_part.size+SAMat.nc-1); --upto #_of_generator-1 if AlexIdeal(trimN.int,diagonal_part,SAMat,ideg.int) then break!; end; -- "true" if ideal is trivial, so higher ideals are all trivial. end end; end;

partial class ALEXMAT_IDEAL_FP_ALG{MT,ET,CT}

partial class ALEXMAT_IDEAL_FP_ALG{MT,ET,CT} is -- CT: field. So ET is PID(euclidean domain). AlexIdeal(trimN:INT,diagonal_part:ARRAY{ET},SAMat:MT,ideg:INT):BOOL is -- When free differential method, we must delete __one__ free meridian generator. ideg:=ideg-trimN; if ideg.is_neg then return false; end; -- [ 0 ] #LOGOUT+"Elementary_ideal_E( "+ideg.str+" ):\n"; ddeg::=diagonal_part.size.int; degr::=ddeg+SAMat.nr.int; -- number of relator degc::=ddeg+SAMat.nc.int; -- number of generator mdeg:INT:=degc-ideg; -- degree of minor. ap:ET; -- generator of the alexander ideal if mdeg.is_non_pos then #LOGOUT+"[\n"+"1\n"+"]\n\n"; return true; elsif degr<mdeg then #LOGOUT+"[\n"+"0\n"+"]\n\n"; return false; end; -- separate "mdeg" to diagonal part "mdegd" and other part mdeg-mdegd. -- (1) 0<=mdegd<=ddeg , (2) 0<=mdeg-mdegd<= min(degr,degc)-ddeg -- (2) means mdegd<=mdeg and mdeg+ddeg-min(degr,degc)<=mdegd. ap:=ET::zero; loop mdegd::=0.int.max(mdeg+ddeg-(degr.min(degc))).upto!(ddeg.min(mdeg)); combi3::=#COMBI_NR_STREAM(ddeg.card,mdegd.card); c3:ARRAY{CARD}; loop while!(combi3.get(out c3)); f3::=ET::one; loop f3:=f3*diagonal_part[c3.elt!(1)-1]; end; if (mdeg=mdegd) then ap:=ap.gcd(f3); else combi1::=#COMBI_NR_STREAM((degr-ddeg).card,(mdeg-mdegd).card); c1:ARRAY{CARD}; loop while!(combi1.get(out c1)); sub1::=c1.create(c1.size-1); loop sub1[0.up!]:=c1.elt!(1)-1; end; combi2::=#COMBI_NR_STREAM((degc-ddeg).card,(mdeg-mdegd).card); c2:ARRAY{CARD}; loop while!(combi2.get(out c2)); sub2::=c2.create(c2.size-1); loop sub2[0.up!]:=c2.elt!(1)-1; end; ap:=ap.gcd(SAMat.sub_matrix(sub1,sub2).det*f3); end; end; end; end; end; ap:=ap.shift0; #LOGOUT+"[\n"; #LOGOUT+ap.str("tex","t",false)+"\n"; #LOGOUT+"]\n"; LOGOUT::flush; if ap.degree.is_one then return true; end; return false; end; end;

partial class ALEXMAT_IDEAL_INTI_ALG{MT,ET,CT}

partial class ALEXMAT_IDEAL_INTI_ALG{MT,ET,CT} is -- ET:POLYS_INTI, CT:INTI ExtendedAlexanderPoly(ap:ET, ideg:INT) is -- Base in Z[[t]][1/t]. -- Note that it is PID, and monic is invertible. ap:=ap.reverseDeg; -- The lowest term is strong. c.f. GBASES_INTI_L if ap.is_zero then ; elsif (ap.lc.abs)=(1.inti) then ap:=ET::one; else loop f::=ap.factorize.elt!; if (f.lc.abs)=(1.inti) then ap:=ap/f; end; end; end; ap:=ap.reverseDeg; #LOGOUT+"Novikov(Extended_Alexander)Ideal:"+"A( "+ideg.str+" )= "+ap.str("tex","t",false)+"\n"; LOGOUT::flush; end; printAp(ap:ET) is -- ET: POLYS_INTI x::=ET::x; b1:ET:=ap/x; low_c:CT:=b1.low_coeff; b0::=(ap-b1*x)*x; #LOGOUT+b0.str("tex","(1/t)",true); -- lowest term if low_c.is_neg then #LOGOUT+b1.str("tex","t",false); elsif low_c.is_pos then #LOGOUT+"+"+b1.str("tex","t",false); else -- is_zero end; #LOGOUT+"\n"; end; AlexIdeal(trimN:INT,diagonal_part:ARRAY{ET},SAMat:MT,ideg:INT):BOOL is -- Assume that ET: POLYS_INTI, CT: INTI -- When free differential method, we must delete __one__ free meridian generator. ideg:=ideg-trimN; if ideg.is_neg then return false; end; -- [ 0 ] #LOGOUT+"Elementary_ideal_E( "+ideg.str+" ):\n"; ddeg::=diagonal_part.size.int; degr::=ddeg+SAMat.nr.int; -- number of relator degc::=ddeg+SAMat.nc.int; -- number of generator mdeg:INT:=degc-ideg; -- degree of minor. ap:ET; if mdeg.is_non_pos then #LOGOUT+"[\n"+"1\n"+"]\n"; ap:=ET::one; ExtendedAlexanderPoly(ap, ideg); return true; elsif degr<mdeg then #LOGOUT+"[\n"+"0\n"+"]\n"; ap:=ET::zero; ExtendedAlexanderPoly(ap, ideg); return false; end; -- separate "mdeg" to diagonal part "mdegd" and other part mdeg-mdegd. -- (1) 0<=mdegd<=ddeg , (2) 0<=mdeg-mdegd<= min(degr,degc)-ddeg -- (2) means mdegd<=mdeg and mdeg+ddeg-min(degr,degc)<=mdegd. gBases:ARRAY{ET}:=#; loop mdegd::=0.int.max(mdeg+ddeg-(degr.min(degc))).upto!(ddeg.min(mdeg)); combi3::=#COMBI_NR_STREAM(ddeg.card,mdegd.card); c3:ARRAY{CARD}; loop while!(combi3.get(out c3)); f3::=POLYS_INTI::one; loop f3:=f3*diagonal_part[c3.elt!(1)-1]; end; if (mdeg=mdegd) then gBases:=gBases.append(f3); else combi1::=#COMBI_NR_STREAM((degr-ddeg).card,(mdeg-mdegd).card); c1:ARRAY{CARD}; loop while!(combi1.get(out c1)); sub1::=c1.create(c1.size-1); loop sub1[0.up!]:=c1.elt!(1)-1; end; combi2::=#COMBI_NR_STREAM((degc-ddeg).card,(mdeg-mdegd).card); c2:ARRAY{CARD}; loop while!(combi2.get(out c2)); sub2::=c2.create(c2.size-1); loop sub2[0.up!]:=c2.elt!(1)-1; end; gBases:=gBases.append(SAMat.sub_matrix(sub1,sub2).det*f3); end; end; end; end; end; --#OUT+"grobner bases:\n"+gBases.str+"\n\n"; gBases:=GBASES_INTI_L::getGBaseIL(gBases,out ap); -- get Grobner bases --#LOGOUT+gBases.str+"\n\n"; #LOGOUT+"[\n"; if gBases.size=0 then #LOGOUT+"0\n"; else printAp(ap); loop b::=gBases.elt!; #LOGOUT+b.str("tex","t",false)+"\n"; end; end; #LOGOUT+"]\n"; LOGOUT::flush; ExtendedAlexanderPoly(ap, ideg); if ap.is_one then return true; end; return false; end; end;

class ALEXMAT_TWIST_ALG{MT,ET,CT}

class ALEXMAT_TWIST_ALG{MT,ET,CT} is -- matrix MT -- element polynomial ET -- coeffifient of polynomial CT APolyOut(p0:CARD) is pa:ET; AlexPoly(p0,out pa); printApoly(pa,"Twisted Alexander Polynomial"); end; AlexMat(TCode:TCODE, Rep:ARRAY{MT},RepR:ARRAY{MT}) is -- Rep/RepR: Representation / reverse -- Rep[i] : image of generator x_i. -- Rep[0] : not used. #LOGOUT+"\n"; num_gen:=TCode.number_gen; if (num_gen<=1)or(num_gen=TCode.number_compo.card) then #LOGOUT+"The "; if TCode[TCode.length].compo=1.int then #LOGOUT+"knot"; else #LOGOUT+"link"; end; if num_gen=0 then #LOGOUT+" is empty."; else #LOGOUT+" is Trivial."; end; LOGOUT::flush; return; end; POLYS_INTI::init; MakeMatrix(TCode,Rep,RepR); LOGOUT::LogTime; WriteMatrix(0); LOGOUT::flush; trimMat1(TCode); rDeg::=MatReduction; WriteMatrix(rDeg); LOGOUT::flush; AlexanderIdeals(rDeg); if ~TCode.has_band then APolyOut(rDeg); end; #LOGOUT+"\n"; LOGOUT::flush; AMat:=#(0,0); end; end;

class C2A_ALG{ET}

class C2A_ALG{ET} is -- polynomial ET (assumed that POLYS_INTI) apoly2conway(apoly:ET, out cpoly:ET) is a2c(apoly,out cpoly); a1:ET; c2a(cpoly,out a1); if (apoly/=a1)and(apoly/=-a1) then raise "Failed to convert between a.poly. and c.poly.\n"; end; end; conway2apoly(cpoly:ET, out apoly:ET) is c2a(cpoly, out apoly); c1:ET; a2c(apoly,out c1); if (cpoly/=c1)and(cpoly/=-c1) then raise "Failed to convert between a.poly. and c.poly.\n"; end; end; private a2c(apoly:ET, out cpoly:ET) is deg::=apoly.degree; CN:ARRAY{ET}:=POLY_COEFF::AllocCN(deg.card); cpoly:=#; x::=ET::x; loop z::=deg.downto!((deg+1)/2.int); cpoly:=cpoly+x^(z*2-deg)*apoly[z.card]; apoly:=apoly-CN[(z*2-deg).card]*x^(deg-z)*apoly[z.card]; end; end; private c2a(cpoly:ET, out apoly:ET) is -- a=c.substitute(x-1/x) a:ET:=#; x::=ET::x; cn::=ET::one; cn1::=x^2-1; loop z::=0.upto!(cpoly.degree.card); a:=a*x+cn*cpoly[z]; cn:=cn*cn1; end; -- apoly=a.substitute(sqrt("t")) apoly:=#; loop i::=a.arr.ind!; j::=i/2; apoly[j]:=apoly[j]+a[i]; end; end; printConway(cpoly:ET) is LOGOUT::Title("Conway","Polynomial"); #LOGOUT+cpoly.str("tex","z",true)+"\n"; LOGOUT::flush; end; end;

class ALEXMAT_ALG{MT,ET,CT}

class ALEXMAT_ALG{MT,ET,CT} is -- matrix MT -- element polynomial ET -- coeffifient of polynomial CT shared AMat:MT; shared jPivot:ARRAY{CARD}; shared trimN:CARD; -- number of free generator shared trimC:CARD; -- component of over bridge of deleted relation shared Relator:ARRAY{WORD}; shared g2c:ARRAY{CARD}; -- map: generator to comploent shared compoN:CARD; -- #of component shared rep_deg:CARD; -- degree of representation matrix shared num_gen:CARD; -- number of generatrs printApoly(apoly:ET, title:STR) is LOGOUT::Title(title,""); ps:STR:=""; -- to be "+". loop --i::=apoly.degree.card.downto!(0); i::=0.upto!(apoly.degree.card); if (apoly[i].inti>=0.inti) then #LOGOUT+ps; end; #LOGOUT+apoly[i].str; ps:="+"; end; #LOGOUT+"\n"; LOGOUT::flush; end; WriteMatrix(p0:CARD) is LOGOUT::Title("Alexander matrix",""); zFlg:BOOL; zFlg:=true; degR::=AMat.nr; degG::=AMat.nc; --if p0>degR then p0:=degR; end; --if p0>degG then p0:=degG; end; -- Alexander matrix is the form of -- \pmatrix{ -- diagonal & 0 \cr -- 0 & matrix \cr -- } if (degR=degG)and(p0=degR-1) then p0:=degR; end; -- Write diagonal part. d0::=(p0).min(degR).min(degG);-- length of diagonel part loop trimN.times!; zFlg:=false; #LOGOUT+"diagonal part: 0\n"; end; if d0>0 then loop i::=0.int.upto!(d0.int-1); j::=jPivot[i]; if (AMat[i][j].is_one.not)and(AMat[i][j].negate.is_one.not) then zFlg:=false; #LOGOUT+"diagonal part: "+AMat[i][j].str("tex","t",true)+"\n"; end; end; end; -- Write other part if (p0<degR)or(p0<degG) then sub1:ARRAY{CARD}:=#(degR-p0); loop sub1[0.up!]:=p0.upto!(degR-1); end; sub2:ARRAY{CARD}:=#(degG-p0); loop sub2[0.up!]:=jPivot[p0.upto!(degG-1)]; end; #LOGOUT+AMat.sub_matrix(sub1,sub2).str_pmatrix("t"); if (p0<degR)and(p0<degG) then zFlg:=false; end; end; if zFlg then #LOGOUT+"0\n"; end; LOGOUT::flush; end; MakeMatrix(TCode:TCODE,Rep:ARRAY{MT},RepR:ARRAY{MT}) is rep_deg:=Rep[1].nc; KNOT_GROUP::get_Relator(TCode, out Relator, out g2c); -- #OUT+"Relations:\n"; loop i::=Relator.ind!; #OUT+Relator[i].str+"\n"; end; -- trimN:=0; trimC:=0; compoN:=(TCode[TCode.length].compo).card; g:CARD:=g2c.size-1; -- # of generators num_gen:=g; r:CARD:=Relator.size; -- # of relators jPivot:=#(g*rep_deg); loop i::=jPivot.ind!; jPivot[i]:=i; end; AMat:=#(r*rep_deg,g*rep_deg); AMat.clear; if (r=0)or(g=0) then return; end; warr:MT:=#(rep_deg,rep_deg); warr.to_unit; p_one::=ET::one; p_x::=ET::x; loop i:CARD:=0.upto!(r-1); -- Make relation matrix with Fox's free differential -- w=(a b a~ c~) or (a b c~ b~) AMat.plus(warr,i*rep_deg,((Relator[i][0]-1)*rep_deg).card); warr:=warr*Rep[(Relator[i][0]).card]; AMat.plus(warr*p_x,i*rep_deg,((Relator[i][1]-1)*rep_deg).card); if Relator[i].w.has_ind(2) then warr:=warr*Rep[(Relator[i][1]).card]*RepR[(-Relator[i][2]).card]; AMat.minus(warr*p_x, i*rep_deg, ((-Relator[i][2]-1)*rep_deg).card); end; if Relator[i].w.has_ind(3) then warr:=warr*RepR[(-Relator[i][3]).card]; AMat.minus(warr, i*rep_deg, ((-Relator[i][3]-1)*rep_deg).card); end; --#OUT+"AMat "+i.int+"-th relation:"+"\n"; end; end; MakeMatrix(TCode:TCODE) is -- non-twisted case is concluded to trivial representation. rep_deg:=1; num_gen:=TCode.number_gen; Rep:ARRAY{MT}:=#(num_gen+1); RepR:ARRAY{MT}:=#(num_gen+1); loop i::=1.upto!(num_gen); Rep[i]:=MT::unit(1,1); end; loop i::=1.upto!(num_gen); RepR[i]:=MT::unit(1,1); end; MakeMatrix(TCode,Rep,RepR); end; trimMat1(TCode:TCODE) is trimN:=0; -- Set # of "0" element. delR,delG:CARD; pt:INT:=0.int; word:WORD; if TCode.has_band then -- 2-dim knot/link res::=KNOT_GROUP::getCrossR(TCode, inout pt, out word); if res and (pt<TCode.bandStart) then ; end; else -- 1-dim knot/link -- delete a crossing relation res::=KNOT_GROUP::getCrossR(TCode, inout pt, out word); if res and (pt<TCode.bandStart) then trimN:=rep_deg; delR:=1; delG:=word[1].card; trimC:=g2c[delG].card; loop i::=(delR*rep_deg-1).downto!((delR-1)*rep_deg); AMat:=AMat.minor_matrix_row(i); end; loop i::=(delG*rep_deg-1).downto!((delG-1)*rep_deg); AMat:=AMat.minor_matrix_column(i); end; jPivot:=#(AMat.nc); loop i::=jPivot.ind!; jPivot[i]:=i; end; end; end; end; AlexPoly(p0:CARD, out apoly:ET) is apoly:=ET::one; if AMat.nr/=AMat.nc then #OUT+"Alexander matrix is not square.\n"; apoly:=ET::zero; return; end; pw:ET; -- work -- diagonal part countz::=0; -- count "0" loop i::=0.upto!(p0-1); pw:=AMat[i,jPivot[i]]; if pw.is_zero then countz:=countz+1; else apoly:=apoly*pw; end; end; -- non-diagonal part if countz+trimN<=rep_deg then if p0<AMat.nr then mat::=AMat.copy; jPivotm::=jPivot.copy; loop i::=0.upto!(p0-1); mat:=mat.minor_matrix(0,jPivotm[i]); loop j::=i.upto!(jPivotm.size-1); if jPivotm[j]>jPivotm[i] then jPivotm[j]:=jPivotm[j]-1; end; end; end; apoly:=apoly*mat.det; end; else apoly:=ET::zero; end; if apoly.is_zero.not then apoly:=apoly.shift_deg(-(apoly.low_deg)); --if (trimN=1)and(compoN>1) then -- apoly:=apoly/(#POLYS_INTI(1.inti,1)-1.inti); --end; -- if apoly.substitute(#CT(1.int)).inti.is_neg then apoly:=-apoly; end; end; end; end;