1 #include "defs.h"
2
3 extern char ginrel[];
4 extern int space;
5 extern int mpt,rel[],cosno[],gno[],inv[],gch[],*imcos[];
6 int ng,ngi,nsg,nr,endsg,endr,maxcos,str,len,ad,*fpt,*bpt,
7 ccos,maxd,totd,lastd,cind,nfree,stcr,endcr,fcos,bcos,lcl;
8 char fullsc,clsd,lkah;
9 FILE *op;
10 /* All comments as for tcp.c */
11
inperr(char * s,int n)12 void inperr (char *s, int n)
13 { fprintf(stderr,"Input error in %s no %d\n",s,n); }
14
digit(int j)15 int digit (int j)
16 { if (j>='0' && j<='9') return(1); else return(0); }
17
letter(int j)18 int letter (int j)
19 { if ((j>='a' && j<='z') || (j>='A' && j<='Z')) return(1); else return(0);}
20
seeknln(void)21 void seeknln (void) { while (getchar()!='\n'); }
22
23 int
readrel(int s,int no)24 readrel (int s, int no)
25 { int stbr,endbr,exp,l,m,n; char ch;
26 char gotg,br,clbr,emptybr,name[10];
27 if (s) strcpy(name,"relation"); else strcpy(name,"subgen");
28 gotg=0; br=0; clbr=0; ad=str; len=0;
29 ch=getchar();
30 while (ch!='\n')
31 { if (ch==' ') ch=getchar();
32 else if (ch=='(')
33 { if (br || clbr) { inperr(name,no); return(-1); }
34 emptybr=1; br=1; stbr=ad+1; gotg=0; ch=getchar();
35 }
36 else if (ch==')')
37 { if (br==0 || emptybr) {inperr(name,no); return(-1); }
38 br=0; gotg=0; clbr=1; endbr=ad; ch=getchar();
39 }
40 else if (letter(ch))
41 { if (clbr || gch[ch]==0) {inperr(name,no); return(-1);}
42 emptybr=0; gotg=1; len++; ad++; rel[ad]=gch[ch]; ch=getchar();
43 }
44 else if (ch=='-' || digit(ch))
45 { if (gotg==0 && clbr==0) { inperr(name,no); return(-1); }
46 gotg=0;
47 if (ch=='-')
48 { ch=getchar();
49 if (digit(ch)==0) exp= -1;
50 else
51 { exp=0; while (digit(ch)) {exp*=10; exp-=(ch-'0'); ch=getchar();}}
52 }
53 else
54 { exp=0; while (digit(ch)) {exp*=10; exp+=(ch-'0'); ch=getchar();}}
55 if (exp==0) {inperr(name,no); return(-1);}
56 if (clbr)
57 { if (exp<0) for (m=stbr,n=endbr;m<=n;m++,n--)
58 { if (m==n) rel[m]= -rel[m];
59 else { l= -rel[m]; rel[m]= -rel[n]; rel[n]=l; }
60 }
61 exp=abs(exp); exp--; clbr=0;
62 for (n=1;n<=exp;n++) for (m=stbr;m<=endbr;m++)
63 { len++; ad++; rel[ad]=rel[m]; }
64 }
65 else
66 { n=rel[ad];
67 if (exp<0) { n= -n; rel[ad]=n; exp= -exp; }
68 exp--;
69 for (m=1;m<=exp;m++) { len++; ad++; rel[ad]=n; }
70 }
71 }
72 else {inperr(name,no); return(-1); }
73 }
74 if (br || clbr) {inperr(name,no); return(-1); }
75 rel[str]=len; str=ad+1;
76 return(0);
77 }
78
79 int
tcprog(void)80 tcprog (void)
81 { int i,j,k,ch,*p; char fname[80];
82 printf("Todd-Coxeter Coset Enumeration Algorithm. (HLT + Lookahead).\n\n");
83 printf(" Total space for relations and coset table = %d.\n",space);
84 printf(" Generators should be upper or lower case letters.\n");
85 printf(" Relations and subgroup generators are input as strings in the");
86 printf(" generators.\n");
87 printf(" Generators may be followed by a positive or negative exponent");
88 printf(" ('-' = '-1').\n");
89 printf(" Brackets (but no nested brackets) are allowed, and a bracketed");
90 printf(" expression.\n");
91 printf(" must be followed by an exponent.\n");
92 printf(" Example: ab-3c6(ab)-2(XYZ)-ba-\n\n\n");
93 printf("Input numbers of generators, subgroup generators and relations.\n");
94 scanf("%d%d%d",&ng,&nsg,&nr);
95 for (i=0;i<=127;i++) gch[i]=0;
96 printf("Input names of generators (upper or lower case letters).\n");
97 for (i=1;i<=ng;i++)
98 { ch= ' '; while (ch==' ' || ch=='\n') ch=getchar();
99 if (letter(ch)==0)
100 { fprintf(stderr,"Generators must be letters.\n"); return(-1);}
101 if (gch[ch]!=0)
102 { fprintf(stderr,"Repeated generator.\n"); return(-1); }
103 gch[ch]=i; gno[i]=0; ginrel[i]=0;
104 }
105 seeknln();
106 if (nsg>0)
107 printf("Input subgroup generators (separated by new lines).\n");
108 str=0; ad= -1;
109 for (i=1;i<=nsg;i++) if (readrel(0,i)== -1) return(-1);
110 endsg=ad;
111 if (nr>0) printf("Input relators (separated by new lines).\n");
112 for (i=1;i<=nr;i++)
113 { if (readrel(1,i)== -1) return(-1);
114 if (len==2 && rel[ad]==rel[ad-1])
115 { gno[abs(rel[ad])]=1; str-=3; ad-=3; }
116 else
117 { k=ad-len+1; for (j=k;j<=ad;j++) ginrel[abs(rel[j])]=1; }
118 }
119 for (i=1;i<=ng;i++) if (gno[i]==1 && ginrel[i]==0)
120 { rel[ad+1]=2; rel[ad+2]=i; rel[ad+3]=i; ad+=3; gno[i]=0; }
121 endr=ad;
122
123 ngi= -1;
124 for (i=1;i<=ng;i++) if (gno[i]==1)
125 { ngi++; gno[i]=ngi; gno[i+52]=ngi; inv[ngi]=ngi; }
126 else
127 { ngi+=2; gno[i]=ngi-1; gno[i+52]=ngi; inv[ngi]=ngi-1; inv[ngi-1]=ngi;}
128 i= -1;
129 while (++i<=endr)
130 { j=rel[i]; k=i+j;
131 while (++i<=k) { p=rel+i; *p= (*p<0) ? gno[52- *p] : gno[*p]; }
132 i=k;
133 }
134 maxcos= (space-endr-2)/(ngi+3); fpt=rel+1+endr; bpt=fpt+maxcos;
135 for (i=0;i<=ngi;i++) imcos[i]=fpt+maxcos*(2+i);
136 printf("Maxcos=%d.\n\n",maxcos);
137
138 ccos=1; lastd=1; maxd=1; totd=1; cind=1; nfree=2;
139 for (i=0;i<=ngi;i++) imcos[i][1]=0;
140 for (i=0;i<maxcos;i++) fpt[i]=i+1;
141 fpt[1]=0; fpt[maxcos]=0;
142 lkah=0; bpt[1]=0; endcr= -1;
143 while (endcr!=endsg)
144 { scanrel();
145 if (fullsc==0)
146 { fprintf(stderr,"Space overflow in subgroup generation phase.\n");
147 return(-1);
148 }
149 }
150 while (ccos!=0)
151 { clsd=1; endcr=endsg;
152 while (endcr!=endr)
153 { scanrel();
154 if (fullsc==0)
155 { clsd=0;
156 if (lkah==0)
157 { lcl=bpt[ccos]; printf("Entering lookahead.\n"); lkah=1; }
158 }
159 }
160 if (lkah)
161 { i=fpt[ccos];
162 if (clsd)
163 { j=bpt[ccos];
164 if (j!=lcl)
165 { fpt[j]=i;
166 if (i==0) lastd=j; else bpt[i]=j;
167 j=fpt[lcl]; fpt[lcl]=ccos; bpt[ccos]=lcl; fpt[ccos]=j; bpt[j]=ccos;
168 }
169 lcl=ccos;
170 }
171 ccos=i;
172 if (ccos==0)
173 { if (cind==maxcos)
174 { fprintf(stderr,"Not enough space.\n"); return(-1); }
175 printf("Exiting lookahead. No. of cosets=%d\n",cind);
176 ccos=fpt[lcl]; lkah=0;
177 }
178 }
179 else ccos=fpt[ccos];
180 }
181
182 for (i=1;i<=ng;i++) if (ginrel[i]==0)
183 { k=gno[i]; j=lastd;
184 while (j!=0)
185 { if (imcos[k][j]==0)
186 { fprintf(stderr,"Coset table incomplete at end of scan. Index is infinite.\n");
187 return(-1);
188 }
189 j=bpt[j];
190 }
191 }
192 printf("Algorithm complete. maxdef,totdef=%d,%d.\n\n",maxd,totd);
193 if (nsg==0) printf("The order of the group is %d.\n\n",cind);
194 else printf("The index of the subgroup is %d.\n\n",cind);
195 if (cind<=mpt)
196 { printf("Do you wish to store the permutations? (y/n) ");
197 ch=getchar(); seeknln();
198 if (ch=='y')
199 { printf("Input filename "); scanf("%s",fname);
200 op=fopen(fname,"w"); fprintf(op,"%4d%4d%4d%4d\n",cind,ng,0,0);
201 bpt[1]=1; cosno[1]=1; j=1;
202 for (i=2;i<=cind;i++) { j=fpt[j]; cosno[i]=j; bpt[j]=i; }
203 for (i=1;i<=ng;i++)
204 { k=gno[i];
205 for (j=1;j<=cind;j++) fprintf(op," %3d",bpt[imcos[k][cosno[j]]]);
206 fprintf(op,"\n");
207 }
208 }
209 }
210 return(0);
211 }
212
213 int
scanrel(void)214 scanrel (void)
215 { int i,j,k,l,m; char comp;
216 fullsc=1; stcr=endcr+2; endcr+=(1+rel[stcr-1]);
217 fcos=ccos; bcos=ccos; comp=1;
218 for (i=stcr;i<=endcr;i++)
219 { k=imcos[rel[i]][fcos];
220 if (k==0) { comp=0; break;}
221 fcos=k;
222 }
223 if (comp) { if (fcos!=bcos) coinc(fcos,bcos); return(0); }
224 stcr=i;
225 for (i=endcr;i>=stcr;i--)
226 { l=rel[i]; m=inv[l]; k=imcos[m][bcos];
227 if (k==0)
228 { if (i==stcr)
229 { k=imcos[l][fcos];
230 if (k==0) { imcos[l][fcos]=bcos; imcos[m][bcos]=fcos; }
231 else if (k!=bcos) coinc(k,bcos);
232 return(0);
233 }
234 if (lkah || nfree==0) { fullsc=0; return(0); }
235 for (j=0;j<=ngi;j++) imcos[j][nfree]=0;
236 totd++; cind++;
237 if (maxd<cind) maxd++;
238 imcos[m][bcos]=nfree; imcos[l][nfree]=bcos; bcos=nfree;
239 bpt[nfree]=lastd; fpt[lastd]=nfree; lastd=nfree;
240 nfree=fpt[nfree]; fpt[lastd]=0;
241 }
242 else bcos=k;
243 }
244 if (fcos!=bcos) coinc(fcos,bcos);
245 return(0);
246 }
247
248 int
coinc(int c1,int c2)249 coinc (int c1, int c2)
250 { int lc,hc,qh,qt,i,j,x,fhc,bhc,lim,him;
251 if (c1<c2) { lc=c1; hc=c2; }
252 else { lc=c2; hc=c1; }
253 qh=0; qt=0;
254 fhc=fpt[hc]; bhc=bpt[hc]; fpt[bhc]=fhc;
255 if (fhc==0) lastd=bhc; else bpt[fhc]=bhc;
256 if (ccos==hc) { ccos=bhc; endcr=endr; clsd=0; }
257 if (lkah && lcl==hc) lcl=bhc;
258 while (1)
259 { fpt[hc]=nfree; nfree=hc; cind--;
260 for (i=0;i<=ngi;i++)
261 { him=imcos[i][hc];
262 if (him!=0)
263 { j=inv[i]; lim=imcos[i][lc];
264 if (him==hc) him=lc; else imcos[j][him]=0;
265 if (lim==0) imcos[i][lc]=him;
266 else
267 { if (lim==hc) { imcos[i][lc]=lc; lim=lc; }
268 while (fpt[him]<0) him= -fpt[him];
269 while (fpt[lim]<0) lim= -fpt[lim];
270 if (him!=lim)
271 { if (lim>him) { x=lim; lim=him; him=x; }
272 fhc=fpt[him]; bhc=bpt[him]; fpt[bhc]=fhc;
273 if (fhc==0) lastd=bhc; else bpt[fhc]=bhc;
274 if (ccos==him) { ccos=bhc; endcr=endr; clsd=0; }
275 if (lkah && lcl==him) lcl=bhc;
276 fpt[him]= -lim;
277 if (qh==0) qh=him; else bpt[qt]=him;
278 qt=him; bpt[qt]=0;
279 }
280 }
281 x=imcos[i][lc];
282 if (imcos[j][x]==0) imcos[j][x]=lc;
283 }
284 }
285 if (qh==0) break;
286 hc=qh; qh=bpt[qh]; lc= -fpt[hc]; bpt[hc]=0;
287 }
288 return(0);
289 }
290