alexmat.sa
Generated by gen_html_sa_files from ICSI. Contact gomes@icsi.berkeley.edu for details
-- Copyright (C) 1983 1992 1996 Kouji KODAMA
-- 2001/12 Grobner bases for Elementary ideals.
-- 2001/02 Sather version
--
-- 1998/1 LongInt
--
--1997/1
--Theta curve
--un-oriented surface in S^4
--
--1996/10
--LINUX version
--
--bug fix for 2-knot
--
--92/09/30 03:14:42
--1992/6 Alexander matrix and Alexander polynomial.
--1992/6/20: 10para99(parallel of k10c99. 40 crossing) 10sec.
--K. Kodama
class ALEXMAT
class ALEXMAT is
-- ALEXMATmaxC=maxC;
--matV=array[1..ALEXMATmaxC] OF PolyInt;
--pmatV=POINTER TO matV;
--amatV=array[1..ALEXMATmaxC] OF pmatV;
apoly2conway(apoly:POLYS_INTI, out cpoly:POLYS_INTI) is
a2c(apoly,out cpoly);
a1:POLYS_INTI; 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:POLYS_INTI, out apoly:POLYS_INTI) is
c2a(cpoly, out apoly);
c1:POLYS_INTI; 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:POLYS_INTI, out cpoly:POLYS_INTI) is
deg::=apoly.degree;
CN:ARRAY{POLYS_INTI}:=POLY_COEFF::AllocCN(deg);
cpoly:=#; x::=POLYS_INTI::x;
loop z::=deg.downto!((deg+1)/2);
cpoly:=cpoly+x^(z*2-deg)*apoly[z];
apoly:=apoly-CN[z*2-deg]*x^(deg-z)*apoly[z];
end;
end;
private c2a(cpoly:POLYS_INTI, out apoly:POLYS_INTI) is
-- a=c.substitute(x-1/x)
a:POLYS_INTI:=#; x::=POLYS_INTI::x;
cn::=POLYS_INTI::one;
cn1::=x^2-1;
loop z::=0.upto!(cpoly.degree);
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:POLYS_INTI) is
LOGOUT::Title("Conway","Polynomial");
#LOGOUT+cpoly.str("tex","z",true)+"\n";
LOGOUT::flush;
end;
printApoly(apoly:POLYS_INTI) is
LOGOUT::Title("Alexander","Polynomial");
loop i::=0.upto!(apoly.degree);
if (i>0) and (apoly[i]>=0.inti) then #LOGOUT+"+"; end;
#LOGOUT+apoly[i];
end;
#LOGOUT+"\n"; LOGOUT::flush;
end;
shared AMat:MAT_POLYS_INTI;
shared jPivot:ARRAY{INT};
shared trimN:INT; -- number of free generator
shared trimC:INT; -- component of over bridge of deleted relation
shared Relator:ARRAY{WORD};
shared g2c:ARRAY{INT};
shared compoN:INT; -- #of component
WriteMatrix(p0:INT) 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:INT:=(p0).min(degR).min(degG);-- length of diagonel part
loop i::=1.upto!(trimN);
zFlg:=false; #LOGOUT+"diagonal part: 0\n";
end;
loop i::=0.upto!(d0-1); j::=jPivot[i];
if (~AMat[i][j].is_one)and(~AMat[i][j].negate.is_one) then
zFlg:=false; #LOGOUT+"diagonal part: "+AMat[i][j].str("tex","t",true)+"\n";
end;
end;
-- Write other part
if (p0<degR)or(p0<degG) then
sub1:ARRAY{INT}:=#(degR-p0); loop sub1[0.up!]:=p0.upto!(degR-1); end;
sub2:ARRAY{INT}:=#(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;
splitMatrix(p0:INT, out diagonal_part:ARRAY{POLYS_INTI}, out SAMat:MAT_POLYS_INTI) 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:INT:=(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;
MakeMatrix(TCode:TCODE) is
-- RLength
KNOT_GROUP::get_Relator(TCode, out Relator, out g2c);
#OUT+"Rel:\n";
loop i::=Relator.ind!; #OUT+Relator[i].str+"\n"; end;
trimN:=0; trimC:=0; compoN:=TCode[TCode.length].compo;
g:INT:=g2c.size-1;
r:INT:=Relator.size;
jPivot:=#(g); loop i::=jPivot.ind!; jPivot[i]:=i; end;
AMat:=#(r,g); AMat.clear;
if (r=0)or(g=0) then return; end;
loop i::=0.upto!(r-1);
-- Make relation with Fox's free differential
AMat[i][Relator[i][0]-1]:=
AMat[i][Relator[i][0]-1]+(POLYS_INTI::one);
AMat[i][Relator[i][1]-1]:=
AMat[i][Relator[i][1]-1]+(#POLYS_INTI(1.inti,1));
if Relator[i].w.has_ind(2) then
AMat[i][-Relator[i][2]-1]:=
AMat[i][-Relator[i][2]-1]-(#POLYS_INTI(1.inti,1));
end;
if Relator[i].w.has_ind(3) then
AMat[i][-Relator[i][3]-1]:=
AMat[i][-Relator[i][3]-1]-(POLYS_INTI::one)
end;
--#OUT+"AMat "+i.int+"-th relation:"
-- +AMat[i][Relator[i][0]-1].str+", "
-- +AMat[i][Relator[i][1]-1].str+", "
-- +AMat[i][-Relator[i][2]-1].str+", "
-- +AMat[i][-Relator[i][3]-1].str+"\n";
end;
end;
trimMat1(TCode:TCODE) is
trimN:=0; -- Set # of "0" element.
delR,delG:INT;
pt:INT:=0; 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:=1;
delR:=1; delG:=word[1];
trimC:=g2c[delG];
AMat:=AMat.minor_matrix(delR-1,delG-1);
jPivot:=#(AMat.nc); loop i::=jPivot.ind!; jPivot[i]:=i; end;
end;
end;
end;
AlexIdeal(trimN:INT,diagonal_part:ARRAY{POLYS_INTI},SAMat:MAT_POLYS_INTI,ideg:INT) is
#LOGOUT+"Elementary_ideal_E( "+(ideg-1).str+" ):\n";
-- When free differential method, we must delete __one__ free meridian generator.
ap:POLYS_INTI;
if ideg<trimN then #LOGOUT+"[\n"+"0\n"+"]\n\n"; return; end;
ideg:=ideg-trimN;
ddeg::=diagonal_part.size;
degr::=ddeg+SAMat.nr; -- number of relator
degc::=ddeg+SAMat.nc; -- number of generator
mdeg:INT:=degc-ideg; -- degree of minor.
if mdeg<=0 then #LOGOUT+"[\n"+"1\n"+"]\n\n"; return;
elsif degr<mdeg then #LOGOUT+"[\n"+"0\n"+"]\n\n"; return;
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{POLYS_INTI}:=#;
loop mdegd::=0.max(mdeg+ddeg-(degr.min(degc))).upto!(ddeg.min(mdeg));
combi3::=#COMBI_NR_STREAM(ddeg,mdegd); c3:ARRAY{INT};
loop while!(combi3.get(out c3));
f3::=POLYS_INTI::one; loop f3:=f3*diagonal_part[c3.elt!(1)-1]; end;
if (mdeg-mdegd=0) then gBases:=gBases.append(|f3|);
else
combi1::=#COMBI_NR_STREAM(degr-ddeg,mdeg-mdegd); c1:ARRAY{INT};
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,mdeg-mdegd); c2:ARRAY{INT};
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
loop b::=gBases.elt!; #LOGOUT+b.str("tex","t",true)+"\n"; end;
end;
#LOGOUT+"]\n";
#LOGOUT+"Extended Alexnader Polynomial: "+"A"+ideg.str+" = "+ap.str("tex","t",true)+"\n";
LOGOUT::flush;
end;
AlexanderIdeals(p0:INT) is
diagonal_part:ARRAY{POLYS_INTI};
SAMat:MAT_POLYS_INTI;
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::=1.upto!(trimN+diagonal_part.size+SAMat.nc-1); --upto #_of_generator-1
AlexIdeal(trimN,diagonal_part,SAMat,ideg);
end
end;
AlexPoly(p0:INT, out apoly:POLYS_INTI) is
apoly:=POLYS_INTI::one; --- alex.poly
if AMat.nr/=AMat.nc then
#OUT+"Alexander matrix is not square.\n";
apoly:=POLYS_INTI::zero;
return;
end;
pw:POLYS_INTI; -- 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<=1 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:=POLYS_INTI::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(1.inti)<0.inti then apoly:=-apoly; end;
end;
end;
APolyOut(p0:INT, 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);
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;
AlexMat(TCode:TCODE, testSym:BOOL, testGb:BOOL, use_conway:BOOL) is
rDeg:INT;
if testSym then
if TCode.has_band then
#OUT+"[test cyclic] not support knotting surface.\n";
return;
elsif TCode.number_compo/=1 then
#OUT+"[test cyclic] not support links.\n";
return;
end;
end;
POLYS_INTI::init;
MakeMatrix(TCode);
#LOGOUT+"\n";
if AMat.nr<1 or AMat.nc<1 then
#LOGOUT+"The ";
if TCode[TCode.length].compo=1 then
#LOGOUT+"knot";
else
#LOGOUT+"link";
end;
if AMat.nc<1 then #LOGOUT+" is empty.";
else #LOGOUT+" is Trivial.";
end;
return;
else
LOGOUT::LogTime;
WriteMatrix(0);
trimMat1(TCode);
MAT_POLYS_INTI_REDUCTION::reduce(inout AMat,out jPivot,out rDeg);
-- WriteMatrix(0);
WriteMatrix(rDeg);
if testGb then AlexanderIdeals(rDeg); end;
if ~TCode.has_band then APolyOut(rDeg,testSym,use_conway); end;
end;
#LOGOUT+"\n"; LOGOUT::flush;
end;
end;