braidcnv.sa
Generated by gen_html_sa_files from ICSI. Contact gomes@icsi.berkeley.edu for details
-- memo: dia -- braid --str
-- This code is "GPL"ed.
------------- braid ---------------
-- 1999/2 K.Kodama
-- use ArtinFormM.
-- 1998/7 K.Kodama
-- Module of primitive functions BraidPrim
--1998/4 K.Kodama
-- History
-- 1996/10 K.Kodama
--LINUX version
--
--1992/4 Kodama
--MS-DOS version
-- Knot diagram --> braid word
-- braid word --> knot diagram
class BRAID2KNOT
class BRAID2KNOT is
-- word[] --> Knot[]
shared height, width:INT;
shared d, ds:INT; -- frame of crossings
shared v0,vlu,vll,vru,vrl:VERTEXK;
shared dx,dy,dxy,vc:VERTEXK;
shared dlu,dll,dru,drl: VERTEXK;
setString(inout Knot:KNOT,tbl:BRAID_TABLE) is
v1,v2:VERTEXK;
Knot:=#; ch:CARD:=tbl.index; cw:CARD:=tbl.length;
if cw=0 then -- trivial braid
v1:=v0;
loop j::=1.upto!(ch);
ki::=Knot.bandStart.card;
Knot.CodeIn(VERTEXC::knot_s, ki); ki:=ki+1;
Knot.CodeIn(v1,ki); ki:=ki+1;
Knot.CodeIn(v1+dx,ki); ki:=ki+1;
Knot.CodeIn(VERTEXC::knot_e, ki); ki:=ki+1;
v1:=v1+dy;
end;
return;
end;
-- Assume that cw>0.
v1:=v0;
loop i::=0.upto!(cw-1);
v2:=v1;
loop j::=1.upto!(ch);
ki::=Knot.bandStart.card;
Knot.CodeIn(VERTEXC::knot_s, ki); ki:=ki+1;
Knot.CodeIn(v2,ki); ki:=ki+1;
if j>1 and tbl.crossTbl[i][j-1]=1.int then
Knot.CodeIn(v2-dy+vc,ki); Knot[ki].sep:=VERTEXC::cross_over; ki:=ki+1;
Knot.CodeIn(v2-dy+dx,ki); ki:=ki+1;
elsif j>1 and tbl.crossTbl[i][j-1]=-1 then
Knot.CodeIn(v2-dy+vc,ki); Knot[ki].sep:=VERTEXC::cross_under; ki:=ki+1;
Knot.CodeIn(v2-dy+dx,ki); ki:=ki+1;
elsif j<ch and tbl.crossTbl[i][j]=1.int then
Knot.CodeIn(v2+vc,ki); Knot[ki].sep:=VERTEXC::cross_under; ki:=ki+1;
Knot.CodeIn(v2+dxy,ki); ki:=ki+1;
elsif j<ch and tbl.crossTbl[i][j]=-1 then
Knot.CodeIn(v2+vc,ki); Knot[ki].sep:=VERTEXC::cross_over; ki:=ki+1;
Knot.CodeIn(v2+dxy,ki); ki:=ki+1;
else
Knot.CodeIn(v2+dx,ki); ki:=ki+1;
end;
Knot.CodeIn(VERTEXC::knot_e, ki); ki:=ki+1;
v2:=v2+dy;
end;
v1:=v1+dx;
end;
end;
setClosing(inout Knot:KNOT,cw,ch:CARD,close:BOOL) is
v1,v2,v3,v4,v5,v6: VERTEXK;
if cw=0 then cw:=1; end;
ki:CARD;
if close then
---- closed braid
v4:=vlu; v3:=vru;
v5:=vll; v6:=v0; v1:=vrl.minus(d*ch,0.int); v2:=vrl;
ki:=0;
loop i::=1.upto!(ch);
Knot.CodeIn(VERTEXC::knot_s, ki); ki:=ki+1;
Knot.CodeIn(v5,ki); ki:=ki+1; v5:=v5+dll;
Knot.CodeIn(v6,ki); ki:=ki+1; v6:=v6+dy;
Knot.CodeIn(VERTEXC::knot_e, ki); ki:=ki+1;
end;
v4:=vlu; v3:=vru;
v5:=vll; v6:=v0; v1:=vrl.minus(d*ch,0.int); v2:=vrl;
ki:=Knot.bandStart.card;
loop i::=1.upto!(ch);
Knot.CodeIn(VERTEXC::knot_s, ki); ki:=ki+1;
Knot.CodeIn(v1,ki); ki:=ki+1; v1:=v1+dy;
Knot.CodeIn(v2,ki); ki:=ki+1; v2:=v2+drl;
Knot.CodeIn(v3,ki); ki:=ki+1; v3:=v3+dru;
Knot.CodeIn(v4,ki); ki:=ki+1; v4:=v4+dlu;
Knot.CodeIn(v5,ki); ki:=ki+1; v5:=v5+dll;
Knot.CodeIn(VERTEXC::knot_e, ki); ki:=ki+1;
end;
else
v1:=v0-dx; v2:=v0; --left side
ki:=0;
loop i::=1.upto!(ch);
Knot.CodeIn(VERTEXC::knot_s, ki); ki:=ki+1;
Knot.CodeIn(v1,ki); ki:=ki+1;
Knot.CodeIn(v2,ki); ki:=ki+1;
Knot.CodeIn(VERTEXC::knot_e, ki); ki:=ki+1;
v1:=v1+dy; v2:=v2+dy;
end;
v1:=v0+dx*cw.max(1); v2:=v1+dx; -- right side
loop i::=1.upto!(ch);
Knot.CodeIn(VERTEXC::knot_s, ki); ki:=ki+1;
Knot.CodeIn(v1,ki); ki:=ki+1;
Knot.CodeIn(v2,ki); ki:=ki+1;
Knot.CodeIn(VERTEXC::knot_e, ki); ki:=ki+1;
v1:=v1+dy; v2:=v2+dy;
end;
return;
end;
end;
setw(cw,ch:CARD) pre ch>1 is
-- set width and origin of braiding
-- d:max interval for closing string.
-- ds:max width of crossing. must be even.
-- dx, dy: width of crossing. (even)
if cw=0 then cw:=1; end;
w, h:INT;
-- width/hight of crossings
dx:=#((width-2.int*d*ch.int)/cw.int,0.int);
dy:=#(0.int,(height-ds-d*(ch.int-1))/(ch.int-1));
if dx.x>ds then dx.x:=ds; end;
if dy.y>ds then dy.y:=ds; end;
dxy:=dx+dy; vc:=dxy/2.int;
-- w,h is width/height of closed braid diagram
w:=d*2.int*ch.int+dx.x*cw.int; h:=(d+dy.y)*(ch.int-1)+ds;
-- left/right, upper/lower width of closing strings
dlu:=#(d,-d); dru:=#(-d,-d);
dll:=dy.plus(d,0.int); drl:=dy.plus(-d,0.int);
-- left/right, upper/lower corner of diagram
vlu:=#(0.int,0.int); vru:=vlu.plus(w,0.int);
vll:=vlu.plus(0.int,-h); vrl:=vll.plus(w,0.int);
-- v0=left lower of braid word
v0:=vll.plus(d*ch, 0.int);
end;
Braid2Knot(word:BRAID, inout Knot:KNOT, pack:BOOL, close:BOOL):BOOL is
-- Get a braid diagram "Knot" from the braid "word".
Knot:=#;
if word.index=0 then return true; end;
if word.check.not then return true; end;
-- if pack and BRAID_REDUCTION::wordReduction(inout word) then ; end; --nothing
if word.index=1 then
if close then Knot:=KNOT_TEST::trivial;
else
ki::=0;
Knot.CodeIn(VERTEXC::knot_s, ki); ki:=ki+1;
Knot.CodeIn(0.int,0.int,ki); ki:=ki+1;
Knot.CodeIn(30.int,0.int,ki); ki:=ki+1;
Knot.CodeIn(VERTEXC::knot_e, ki); ki:=ki+1;
end;
Knot.shiftToInside;
return true;
end;
-- Assume that word.index>1.
-- set position of crossings
tbl:BRAID_TABLE:=#(word);
if pack then tbl.pack; end;
-- set width/height: d ds,dx,dy
d:=2.int; ds:=16.int;
height:=(ds+(tbl.index.int-1)*(d+ds)).max(KNOTXW::GraphHeight-20);
width:=(tbl.length.int*ds+tbl.index.int*d*2).max(KNOTXW::GraphWidth-20);
d:=12.int; ds:=32.int;
setw(tbl.length,tbl.index);
if (dy.y<ds)or(dx.x<ds) then d:=8.int; ds:=24.int; setw(tbl.length,tbl.index); end;
if (dy.y<ds)or(dx.x<ds) then d:=4.int; ds:=16.int; setw(tbl.length,tbl.index); end;
if (dy.y<ds)or(dx.x<ds) then d:=2.int; ds:=16.int; setw(tbl.length,tbl.index); end;
-- set diagram
setString(inout Knot,tbl);
setClosing(inout Knot,tbl.length,tbl.index,close);
Knot.concat; Knot.edge_clean; Knot.shiftToInside;
return true;
end;
end; -- BRAID2KNOT
class BRAIDTC2BRAID
class BRAIDTC2BRAID is
------------- TCode[] --> word[] -----------
shared cTbl:ARRAY{INT};
shared str:INT;
chk_cTbl(TCode:TCODE) is
cod:VERTEXC;
#OUT+"ct:";
loop i::=TCode.k.ind!; #OUT+cTbl[i].str; end;
#OUT+"TC:";
loop i::=TCode.k.ind!; #OUT+TCode[i].companion.str; end;
#OUT+"cd:";
loop i::=TCode.k.ind!;
cod:=TCode[i].sep;
if VERTEXC::crossing.in(cod) then #OUT+" ";
if VERTEXC::over.in(cod) then #OUT+"o"; end;
if VERTEXC::under.in(cod) then #OUT+"u"; end;
if VERTEXC::positive.in(cod) then #OUT+"+"; end;
if VERTEXC::negative.in(cod) then #OUT+"-"; end;
else #OUT+" ";
end;
end;
end;
nextW(word:BRAID,inout wi:INT) is
loop while!((wi<word.size.int-1)and(word.w[wi.card].abs<(str-1))) ;
wi:=wi+1;
end;
if (wi<word.size.int) then wi:=wi+1; end;
-- The condition is the same as: (str>1)and(ABS(word[wi])=(str-1))
end;
TCode2Braid(TCode:TCODE, out word:BRAID):BOOL is
wi:INT;
sBase:INT;
cTbl:=#(TCode.size); cTbl.to_val(0.int);
word:=#; word.index:=0;
loop
tp::=0;
loop while!( (tp<TCode.length) and cTbl[tp].is_pos ); tp:=tp+1; end;
if tp>=TCode.length then break!; end;
word.index:=word.index+1; sBase:=word.index.int; str:=sBase;
loop
loop while!(cTbl[tp].is_zero) ; -- Seifert circle
cTbl[tp]:=str;
if VERTEXC::crossing.in(TCode[tp].sep) then
tp:=TCode[tp].companion.card+1;
elsif VERTEXC::ks.in(TCode[tp].sep) then tp:=tp+1;
elsif VERTEXC::ke.in(TCode[tp].sep) then
tp:=TCode[tp].companion.card;
end;
end;
-- next circle
tp:=0;
loop
tp:=tp+1;
tp1::=tp+1;
if VERTEXC::separator.in(TCode[tp1].sep) then
tp1:=TCode[tp1].companion.card+1;
end;
str:=cTbl[tp1];
until!( TCode.length<=(tp+1)
or
(cTbl[tp].is_zero and
VERTEXC::crossing.in(TCode[tp].sep) and
str.is_pos) );
end;
if TCode.length<=(tp+1) then break!; end;
if (VERTEXC::over.in(TCode[tp].sep)
=VERTEXC::positive.in(TCode[tp].sep)) then str:=str+1;
else str:=str-1;
end;
if word.index.int<str then word.index:=word.index+1;
elsif str<sBase then word.index:=word.index+1; str:=str+1;
loop tp1::=TCode.k.ind! ;
if sBase<=cTbl[tp1] then cTbl[tp1]:=cTbl[tp1]+1; end;
end;
else cTbl:=#; return false;
end;
end;
-- chkCt;
loop str:=sBase.upto!(word.index.int-1) ; -- for each Seifert circle
tp0::=0; loop while!(cTbl[tp0]/=sBase) ; tp0:=tp0+1; end;
loop while!(cTbl[tp0]<str) ;
if VERTEXC::crossing.in(TCode[tp0].sep) then
if cTbl[tp0+1]<cTbl[tp0] then
tp0:=TCode[tp0].companion.card+1;
else tp0:=tp0+1;
end;
elsif VERTEXC::ke.in(TCode[tp0].sep) then
tp0:=TCode[tp0].companion.card;
elsif VERTEXC::ks.in(TCode[tp0].sep) then tp0:=tp0+1;
end;
end;
tp:=tp0; wi:=0.int; nextW(word,inout wi);
loop
if VERTEXC::crossing.in(TCode[tp].sep) then
if cTbl[tp+1]<str then nextW(word,inout wi);
else if VERTEXC::under.in(TCode[tp].sep) then
word.insert(wi.card,str); wi:=wi+1;
else word.insert(wi.card,-str); wi:=wi+1;
end;
end;
tp:=TCode[tp].companion.card+1;
elsif VERTEXC::ke.in(TCode[tp].sep) then
tp:=TCode[tp].companion.card;
elsif VERTEXC::ks.in(TCode[tp].sep) then tp:=tp+1;
end;
until!(tp=tp0); -- around the Seifert circle
end;
end;
-- #OUT+"TCode2Word\n"; chkW;
end;
cTbl:=#;
return true;
end;
end; -- class BRAIDTC2BRAID
class KNOT2BRAIDTC
class KNOT2BRAIDTC is
shared cTbl:ARRAY{INT}; -- [0..BRAIDmaxT]
shared index:INT;
SeifertCircuit(TCode:TCODE) is
cTbl:=#(TCode.size); cTbl.to_val(0.int);
index:=0.int;
loop
tp::=0;
loop while!( (tp<TCode.length)and cTbl[tp].is_pos );tp:=tp+1; end;
if tp>=TCode.length then break!; end;
index:=index+1;
loop while!( cTbl[tp].is_non_pos ); -- Seifert circle
cTbl[tp]:=index;
if VERTEXC::crossing.in(TCode[tp].sep) then
tp:=TCode[tp].companion.card+1;
elsif VERTEXC::ks.in(TCode[tp].sep) then tp:=tp+1;
elsif VERTEXC::ke.in(TCode[tp].sep) then
tp:=TCode[tp].companion.card;
end;
end;
end;
end;
const right:BOOL:=true;
const left:BOOL:=false;
InCode(inout TCode:TCODE,tp:INT):BOOL is
cTbl:=cTbl.resize(cTbl.size+1);
loop i::=(cTbl.size-2).downto!(tp.card);
cTbl[i+1]:=cTbl[i];
end;
TCode.CodeInCmp(tp);
return true;
end;
sideC(TCode:TCODE,side:BOOL,tp:INT):BOOL is
cod:VERTEXC:=TCode[tp].sep;
return ( VERTEXC::crossing.in(cod)
and (side=(
(VERTEXC::cross_po=cod) or (VERTEXC::cross_nu=cod)
)
)
);
end;
nextTp(TCode:TCODE, inout tp:INT) is
tcn:INT;
cod:VERTEXC;
tcn:=TCode[tp].companion; cod:=TCode[tp].sep;
if VERTEXC::crossing.in(cod) then tp:=tcn+1;
elsif VERTEXC::ke.in(cod) then tp:=tcn;
elsif VERTEXC::ks.in(cod) then tp:=tp+1;
end;
end;
nextC(TCode:TCODE, side:BOOL, inout tp, inout str:INT) is
tps:INT:=tp;
loop
if sideC(TCode,side,tp) then break!; end;
nextTp(TCode,inout tp);
if tps=tp then break!; end;
end;
if sideC(TCode,side,tp) then str:=cTbl[tp.card+1]; else str:=-1; end;
end;
Unify(inout TCode:TCODE, side:BOOL):BOOL is
uFlg:BOOL;
tp0, tp1, tp2, str, str0, str1, str2:INT;
cop::=VERTEXC::cross_po;
cup::=VERTEXC::cross_pu;
com::=VERTEXC::cross_no;
cum::=VERTEXC::cross_nu;
str:=1.int;
loop while!(str<=index) ;
-- #OUT+"Unify:2 inde:="+index.str+" str="+str.str+"\n";
tp0:=0.int; loop until!(cTbl[tp0.card]=str); tp0:=tp0+1; end;
nextC(TCode,side, inout tp0, inout str0);
uFlg:=false;
if str0.is_pos then
str1:=str0; tp1:=tp0;
loop
-- #OUT+"Unify:3\n";
-- #OUT+"TCode\n"; TCode.checkD;
tp2:=tp1;
loop
tp1:=tp2; nextTp(TCode,inout tp2);
nextC(TCode,side, inout tp2, inout str2);
until!( (tp2=tp0)or(str1/=str2));
end;
if tp2=tp0 then break!; end;
-- out('tp5: tp1,tp2, s1,s2:');
-- WriteInt(tp1,4); WriteInt(tp2,4);
-- WriteInt(str1,4); WriteInt(str2,4);
-- chkCt;
uFlg:=true; tp2:=TCode[tp2.card].companion;
if ~ (InCode(inout TCode,tp1+1) and InCode(inout TCode,tp1+1)) then
return false;
end;
if tp1<tp2 then tp2:=tp2+2; end;
if tp1<tp0 then tp0:=tp0+2; end;
if ~(InCode(inout TCode,tp2) and InCode(inout TCode,tp2)) then return false; end;
if tp2<tp1 then tp1:=tp1+2; end;
if tp2<tp0 then tp0:=tp0+2; end;
tp2:=tp2+2;
if side=right then
TCode[tp1+1].sep:=cop;
TCode[tp1+2].sep:=com;
TCode[tp2-1].sep:=cup;
TCode[tp2-2].sep:=cum;
else
TCode[tp1+1].sep:=com;
TCode[tp1+2].sep:=cop;
TCode[tp2-1].sep:=cum;
TCode[tp2-2].sep:=cup;
end;
TCode[tp1+1].companion:=tp2-1;
TCode[tp1+2].companion:=tp2-2;
TCode[tp2-1].companion:=tp1+1;
TCode[tp2-2].companion:=tp1+2;
loop i::=TCode.k.ind! ;
if cTbl[i]=str2 then cTbl[i]:=str1; end;
end;
cTbl[tp1.card+1]:=str1;
cTbl[tp1.card+2]:=str2;
cTbl[tp2.card-2]:=str1;
cTbl[tp2.card-1]:=str2;
end;
end;
if uFlg then str:=1; else str:=str+1; end;
end;
return true;
end;
TCode2BraidTC(inout TCode:TCODE):BOOL is
cTbl:=#;
SeifertCircuit(TCode);
reply:BOOL:=Unify(inout TCode,right) and Unify(inout TCode,left);
cTbl:=#;
return reply;
end;
Knot2BraidTC(Knot:KNOT,out TCode:TCODE):BOOL is
-- #OUT+"Knot2BraidTC:\n";
if ~Knot.is_proper then return false; end;
if Knot.has_band then
#OUT+"Band is not supported.\n"; return false;
end;
if Knot.CrossSet then ; end;
TCode:=#;
if ~ Knot.SetTCode(out TCode) then return false; end;
if ~TCode2BraidTC(inout TCode) then return false; end;
return true;
end;
end; -- class KNOT2BRAIDTC
class BRAID_CNV
class BRAID_CNV is
shared error:INT;
TCode2Braid(TCode:TCODE, out braid:BRAID):BOOL is
tcode:TCODE:=TCode.clone;
braid:=#;
if ~KNOT2BRAIDTC::TCode2BraidTC(inout tcode) then return false; end;
if ~BRAIDTC2BRAID::TCode2Braid(tcode,out braid) then return false; end;
braid:=BRAID_REDUCTION::wordReduction(braid, true);
return true;
end;
Knot2BraidWord(Knot:KNOT,out str:STR):BOOL is
-- #OUT+"Knot2BraidWord:\n";
TCode:TCODE:=#;
reply:BOOL:=Knot.CrossSet;
reply:=reply and KNOT2BRAIDTC::Knot2BraidTC(Knot,out TCode);
-- #OUT+"Knot2BraidWord:\n"; TCode.checkD;
Word:BRAID:=#;
reply:=reply and BRAIDTC2BRAID::TCode2Braid(TCode,out Word);
if ~ reply then Word:=#; end;
str:=Word.str;
return reply;
end;
BraidWord2Knot(str:STR, inout Knot:KNOT,packBraid,closeBraid:BOOL):BOOL is
HISTORY::put(Knot);
-- #OUT+"BraidWord2Knot: str="+str+"\n";
word:BRAID:=#(str);
reply:BOOL:= BRAID2KNOT::Braid2Knot(word,inout Knot,packBraid,closeBraid);
if ~ reply then HISTORY::back(inout Knot); end;
return reply;
end;
BraidWordA2Knot(str:STR, inout Knot:KNOT, reduce:BOOL):BOOL is
HISTORY::put(Knot);
reply:BOOL:=true; BRAID_CNV::error:=0.int;
word:BRAID:=#(str);
reply:=reply and (BRAID_CNV::error.is_zero);
word1::=ARTIN_FORM::GArtinNormalForm(word,reduce);
reply:=reply and(BRAID_CNV::error.is_zero) and
BRAID2KNOT::Braid2Knot(word1,inout Knot,false,true) and (BRAID_CNV::error.is_zero);
if ~ reply then HISTORY::back(inout Knot); end;
return reply;
end;
BraidWord2ArtinNormalFormS(inout str:STR, reduce:BOOL):BOOL is
reply:BOOL:=true; BRAID_CNV::error:=0.int;
str0:STR:=""+str;
word:BRAID:=#(str);
--reply:=Str2Word(str, out word)and(BRAID_CNV::error=0);
word1::=ARTIN_FORM::GArtinNormalForm(word,reduce);
str:=word1.str;
if ~reply then
str:=str0;
#OUT+"Fail to convert the word.\n";
end;
return reply;
end;
BraidWord2ArtinNormalForm(inout str:STR):BOOL is
reply:BOOL;
reply:= BraidWord2ArtinNormalFormS(inout str,false);
return reply;
end;
BraidWord2RArtinNormalForm(inout str:STR):BOOL is
reply:BOOL;
reply:= BraidWord2ArtinNormalFormS(inout str,true);
return reply;
end;
BraidWord2RBraidWord(inout str:STR,close:BOOL):BOOL is
-- get reduced word
str0:STR:=""+str;
reply:BOOL:=true;
word:BRAID:=#BRAID(str);
word:=BRAID_REDUCTION::wordReduction(word,close);
str:=word.str;
BRAID_CNV::error:=0.int;
-- reply:=Str2Word(str,out word) and(BRAID_CNV::error=0);
reply:=reply and(BRAID_CNV::error=0.int);
--reply:=reply and Word2Str(word,out str) and (BRAID_CNV::error=0);
if ~ reply then str:=str0;
#OUT+"Fail to convert the word.\n";
end;
return reply;
end;
SetBraid(inout Knot:KNOT) is
wordStr:STR:="";
if Knot2BraidWord(Knot,out wordStr)
and BraidWord2Knot(wordStr,inout Knot,true,true) then
end;
end;
SetBraidArtinNormalForm(inout Knot:KNOT) is
wordStr:STR:="";
if Knot2BraidWord(Knot, out wordStr)
and BraidWordA2Knot(wordStr,inout Knot,false) then; end;
end;
SetBraidRArtinNormalForm(inout Knot:KNOT) is
wordStr:STR:="";
if Knot2BraidWord(Knot,out wordStr)
and BraidWordA2Knot(wordStr,inout Knot,true) then; end;
end;
end; -- class BRAID_CNV