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