/* mod P arithmetic */ #ifndef _MODP_h #define _MODP_h 1 #define P 97 // Guess what this is. #include class MODP { private: short int x; short int normalize(short int i) {short int a; a=i%P; if (a<0) a=P+a; return a;} public: MODP() {x=0;} MODP(short int i) :x(normalize(i)) {} //void operator = (const MODP& r) {x=r.x;} void operator += (const MODP& r) {x=normalize(x+r.x);} void operator *= (const MODP& r) {x=normalize(x*r.x);} int iszero() {return 0 == x;} int isnotzero() {return 0 != x;} int operator == (const MODP& r) {return x == r.x;} int operator != (const MODP& r) {return x != r.x;} int operator < (const MODP& r) {return x < r.x;} MODP operator + (const MODP& r) {return (MODP) (x+r.x);} MODP operator - () {return (MODP) (P-x);} MODP operator * (const MODP& r) {return (MODP) (x*r.x);} MODP operator / (const MODP& r) { short int quo,temp; short int prev=0; short int last=1; short int big=P, small=r.x; while (small!=1) { temp=small; small=big-small*(quo=big/small); big=temp; temp=prev; prev=last; last=temp-quo*last; } return (MODP) (x*last); } short int operator ! () {return (x>P/2 ? x-P : x);} }; #endif #define CPP // MODP.h" #define UNUSED(name) name /* An ugly hack */ #include #include #include #define M 5 /* No. of loops */ #define framed 0 /* framed flag: */ /* 0 - consider only legal diagrams */ /* 1 - consider all diagrams */ #define solveQ 1 /* solve? */ /* 0 - no. */ /* 1 - yes, consider both parities */ /* 2 - yes, even parity */ /* 3 - yes, odd parity */ #define statistics_interval 10 /* Statistics printing interval */ #define treat_vans 0 /* Simplify when a van is found? */ #define treat_eqls 0 /* Simplify when an eql is found? */ #define afs_depth 4 /* Depth of afs array */ #define afs_step 4 /* afs step size in bits */ #define cleanup_ratio 15 /* nfree shrinks to #%: do cleanup */ #define CASE(a1,a2,a3,a4,a5,a6,a7,a8,a9) \ (M==1 ? a1 : (M==2 ? a2 : \ (M==3 ? a3 : (M==4 ? a4 : \ (M==5 ? a5 : (M==6 ? a6 : \ (M==7 ? a7 : (M==8 ? a8 : \ (M==9 ? a9 : 0 ))))))))) #if framed #define ndiags CASE(1,2,5,18,105,902,9749,0,0) #else #define ndiags CASE(0,1,2,7,36,300,3218,42335,644808) #endif #define N 8 /* Maximal number of WSs to */ /* participate in a single product */ #define max_C_bank 32 /* Maximal size of a C bank */ #define max_m 16 /* Maximal m is this program */ /* #define abs(n) (n>0 ? n : -n) The absolute value function */ #define max(a,b) ((a)>(b) ? (a) : (b)) /* Maximum */ #define min(a,b) ((a)<(b) ? (a) : (b)) /* Minimum */ /* Data types */ #ifndef CPP typedef int COEFF; #else typedef MODP COEFF; #endif struct ACCUMULATOR { int len; COEFF *coeff; }; struct EQUATION { int len; int *at; COEFF *coeff; }; /* Procedures */ void generate(int); /* Generate diagrams */ int solve(); /* Solve system */ void print_solution(); /* Final printing of a solution */ void print_diagram(int m,int count); /* Print a diagram */ int cyclic_order(); /* Check if i,j,k are cyclically */ /* ordered */ void make_v(int m,int ae[],int v[]); /* Make v from ae */ int find(); /* Search in a lexicographicaly */ /* oredered array */ void cross(int m,int ae[],int v[],int d,int C[]); /* The m==2 weight system */ void m_is_3(int m,int ae[],int v[],int d,int C[]); /* The m==3 weight system */ void su(int m,int ae[],int v[],int d,int C[]); /* Computation of the su(N) weights */ void su_hat(int m,int ae[],int v[],int d,int C[]); /* Computation of su_hat(N) weights */ void su_general(int m,int ae[],int v[],int d,int C[],int hatQ); /* Computation of the general (hat */ /* and n-hat) su(N) weights */ void so(int m,int ae[],int v[],int d,int C[]); /* Computation of the so(N) weights */ void so_hat(int m,int ae[],int v[],int d,int C[]); /* Computation of so_hat(N) weights */ void sp(int m,int ae[],int v[],int d,int C[]); /* Computation of sp(N) weights */ void sp_hat(int m,int ae[],int v[],int d,int C[]); /* Computation of sp_hat(N) weights */ void product(int m,int ae[],int v[],int n,int m_[], void (*(ws_[]))(int m,int ae[],int v[],int d,int C[]), int d_[],int C[]); /* The WS product computation */ /* routine */ void adjoint(int m,int ae[],int v[],int d, void (*ws)(int m,int ae[],int v[],int d,int C[]),int C[]); /* Computations in the Adjoint */ /* representation */ int hat(); /* `hatting' a representation */ void best_version(int m,int ae[]); /* Find the best version of ae */ int best_versionQ(int m,int ae[]); /* Is this the best version of ae? */ void init_solve(); void generate_ee(); void print_status(); void generate_equation(); void addto(struct ACCUMULATOR *acc, struct EQUATION eq); /* Add eq2 into eq1 with the */ /* correct coefficient */ void new_entry(); void interchange(); struct EQUATION compress(struct ACCUMULATOR acc); void new_equality(int at); void new_van(int at); void print_statistics(); int find_diag(unsigned int aec); /* Find a diagram in diags */ void to_basis(int ebound,int ibound); /* Express acc in terms of basis */ /* but never let len>bound */ void printCD(int v[2*M]); /* print in CD format */ void print_d(int m,int count); /* Print in d format */ int next_ae(int m,int ab[],int ae[]); /* Find next ae */ unsigned int compress_ae(int m,int ae[]); /* Compress ae */ void uncompress_ae(int m,unsigned int aec,int ae[]); /* Uncompress ae */ void do_parity(); /* fill matrix with either odd or */ /* even layout */ void afs_update(int position, int dal); /* update afs by dal at position */ int afs_search(int from); /* Search for the next non-zero */ /* entry in acc, past&incl. from. */ void cleanup(); /* Upward simplify matrix */ int statisticsQ(); /* Time to print statistics? */ /* Large arrays */ unsigned int diags[ndiags]; /* ae of the diagrams */ struct EQUATION matrix[ndiags]; /* The Vassiliev equations */ /* Smaller arrays */ int binomial[M+1][M+1]; /* The binomial coefficients */ extern int M2; /* No. of vertices */ extern int count; /* No. of diagrams */ int rep; /* Current report number */ /* solve.c variables */ struct ACCUMULATOR acc; /* The equation currently in use */ int *(afs[afs_depth]); /* acc fill summary */ int ae[2*M]; /* The other end of the arc */ /* connected to the current vertex */ int v[2*M]; /* The vertices */ int ee[2*M-2]; /* The equation symbol */ int i,j,k,l,q; /* Temporary variables */ int ca; /* Current arc */ int cab,cae; /* Current arc beginning and end */ int sa,side,sab,sae,sa_ends[2]; /* Special arc in eq. generator */ int tof,tofree[M]; /* Which free vertex to connect next */ int after,shift; /* Used in the eq. construction */ int pivot; /* The pivot in the current eqn. */ int max_len,max_length; /* Length of the current eqn. */ int s,t; /* Euclid multipliers */ int deg; /* No. of degrees of freedom */ static int nfree=ndiags; /* No. of free rows in matrix */ int eqs,ads; /* Statistics */ int iteration,no_change,last_new, all_done; /* iteration control */ int intrchngs,failures; /* Insertion statistics */ int tl; /* Total length of `matrix' */ int from,to; /* Searching domain */ int position; /* Position to which a new diagram */ /* should be inserted */ struct EQUATION term; /* The new term while equation */ /* is being generated. */ int eqls; /* Number of equalities encountered */ int vans; /* Number of zeros encountered */ int next_cleanup; /* time (in nfree) of next cleanup */ // ws.h" void init(); /* Initializations */ int M2=2*M; int count; main() { int all_done=0; /* Whether solve() has succeded */ init(); generate(M); if (solveQ) { all_done=solve(); if (!all_done) printf("\n\n(* WARNING: all_done flag is off!!!! *)\n\n"); } print_solution(); } void init() { int i,j; /* Temporary variables */ int ca=0; /* Current arc */ /* Initializations */ printf("(* The degree %d case: solveQ=%d, P=%d. *)\n",M,solveQ,P); rep=0; for (i=0; i<=M; ++i) { binomial[i][0]=1; binomial[i][i]=1; for (j=1; j=0) { foundQ=0; for (i=1+ae[cab=ab[at]]; !foundQ && i=at) foundQ=1; if (foundQ && i-cab < ae[0]) foundQ=0; if (foundQ && !framed && 1==(i-cab)) foundQ=0; if (foundQ && cab!=ae[cab]) arc[ae[cab]]=m; if (foundQ) { if (cab!=ae[cab]) arc[ae[cab]]=m; arc[i]=at; ae[cab]=i; ae[i]=cab; if (at==m-1 && !best_versionQ(m,ae)) foundQ=0; } } at+=foundQ; if (foundQ && m>at) { i=cab+1; while (at>arc[i]) ++i; ab[at]=i; arc[i]=at; ae[i]=i; } else if (!foundQ) { arc[cab]=m; arc[ae[cab]]=m; if (0==(--at) && ae[0]>m) --at; } } if (at==m) return(1); else return(0); } unsigned int compress_ae(int m,int ae[]) { unsigned int aec; /* ae compressed */ int i,j; /* Temporary */ int m2; /* No. of vertices */ m2=2*m; aec=0; j=0; for (i=0; ii) { aec=16*aec+(ae[i]-i-1); ++j; } return(aec); } void uncompress_ae(int m,unsigned int aec,int ae[]) { unsigned int taec; /* temporary ae compressed */ int diff[M]; /* aec in base 16 */ int i,j; /* Temporary */ int m2; /* No. of vertices */ m2=2*m; taec=aec; for (i=m-2; i>=0; --i) { diff[i]=taec%16+1; taec/=16; } for (i=0; i1) do_parity(); next_cleanup=(cleanup_ratio*nfree)/100; if (next_cleanup>0) printf("(*First cleanup will be at nfree=%d.*)\n", next_cleanup); eqs=last_new=0; all_done=no_change=1; for (i=0; i1) { l1=sa_ends[1]-sa_ends[0]; l2=M2-2-sa_ends[1]; l3=1+sa_ends[0]; if (((l1>l2 || l2>l3) && (l10) cleanup(); ++eqs; generate_equation(); while (acc.len>0) { if (acc.len>max_len) max_len=acc.len; pivot=afs_search(pivot); if (!matrix[pivot].len) new_entry(); else { interchange(); ++ads; addto(&acc,matrix[pivot]); } } irrelevant: i=M-3; j=0; while (tofree[i]==(j+=2) && i>=0) tofree[i--]=0; if (i>=0) ++tofree[i]; } while (nfree>0 && i>=0); } return(all_done); } void addto(struct ACCUMULATOR *acc, struct EQUATION eq) { COEFF coeff; /* Temporary variables */ COEFF factor; /* Numerator and denumerator of */ /* factor currently in use. */ int i; /* Temporary variable */ int dal; /* delta acc length */ if (!eq.len) return; factor= -acc->coeff[eq.at[0]]/eq.coeff[0]; for (i=0; icoeff[eq.at[i]]; if (coeff.isnotzero()) dal=-1; else dal=0; coeff+=factor*eq.coeff[i]; if (coeff.isnotzero()) ++dal; acc->len+=dal; if (dal) afs_update(eq.at[i],dal); acc->coeff[eq.at[i]]=coeff; } } void init_solve() { int i,j,k; /* Temporary variables */ max_len=0 ; max_length=0; eqs=ads=0; no_change=last_new=all_done=0; intrchngs=failures=0; eqls=0; vans=0; nfree=ndiags; for (count=0; count>=afs_step; afs[i]=new (int [k+1]); for (j=0; j<=k; ++j) afs[i][j]=0; } } void generate_ee() { for (i=0; i=0; ++cab); cae=cab; for (i=0; i<=tof; ++i) { ++cae; while (ee[cae]>=0) ++cae; } ee[cab]=cae; ee[cae]=cab; if (ca==sa) {sa_ends[0]=cab; sa_ends[1]=cae;} } } void print_status() { int count; /* Temporary variables */ tl=0; for (count=0; countsab); ae[sae+1-side]+=1-after; best_version(M,ae); aec=compress_ae(M,ae); position=find_diag(aec); if (position=0 && matrix[position].len!=1) { if (matrix[position].len==2) { coeff=-matrix[position].coeff[1]/matrix[position].coeff[0]; position=matrix[position].at[1]; } else coeff=1; pivot=min(pivot,position); if (acc.coeff[position].isnotzero()) dal=-1; else dal=0; acc.coeff[position]+=(after ? coeff : -coeff); if (acc.coeff[position].isnotzero()) ++dal; acc.len+=dal; if (dal) afs_update(position,dal); } } } void new_entry() { int i; matrix[pivot]=compress(acc); if (0 != matrix[pivot].coeff) { acc.len=0; for (i=0; i1) { saved=0; mat=matrix[count]; for (i=1; mat.at[i]< at && i(m2+ae[(i+q)%m2]-q)%m2) ret=0; } return(ret); } void best_version(int m,int ae[]) { int temp[2*M]; /* temporary `ae' */ int i,q; /* Temporary */ int bq; /* Best q so far */ int m2; /* No. of vertices */ m2=2*m; bq=0; for (q=1; q(m2+ae[(i+q)%m2]-q)%m2) bq=q; } if (bq!=0) { for (i=0; imax_length) max_length= matrix[i].len; printf("(* Total number of equations considered was:%6d. *)\n",eqs); printf("(* Total number of row operations performed was:%7d. *)\n",ads); printf("(* Maximal equation length is:%4d. *)\n",max_length); printf("(* Maximal equation length considered was:%4d. *)\n",max_len); printf("(* Total length of the equations stored:%8d. *)\n",tl); } int find_diag(unsigned int aec) /* Find a diagram in diags */ { int i; /* Temporary variable */ int from,to,position; /* Search outcome */ from=0; to=ndiags-1; while (to>from) { position=(from+to)/2; if (aec==diags[position]) from=to=position; else if (aec>diags[position]) to=--position; else from=++position; } if (position=0) if (aec!=diags[position]) position=ndiags; return(position); } void to_basis(int ebound, int ibound) { int pivot; int behind; /* Number of non-zero acc entries left behind */ pivot=0; behind=0; while (behind<=ibound && acc.len>0 && acc.len<=ebound && pivot1) { mat=matrix[count]; for (i=1; mat.at[i]< at && i2) { matrix[count].len=1; matrix[count].at=new (int[1]); matrix[count].coeff=new (COEFF[1]); matrix[count].at[0]=count; matrix[count].coeff[0]=1; --nfree; ++vans; } if (position>count) { matrix[count].len=2; matrix[count].at=new (int[2]); matrix[count].coeff=new (COEFF[2]); matrix[count].at[0]=count; matrix[count].coeff[0]=1; matrix[count].at[1]=position; matrix[count].coeff[1]=(solveQ==2 ? -1 : 1); --nfree; ++eqls; } } } void afs_update(int position, int dal) { int i,p; p=(position>>afs_step); for (i=0; i>=afs_step; } } int afs_search(int from) { int ret; /* return value */ int l; /* current level of search */ int i; /* current search position */ ret=from; while (ret>afs_step] && acc.coeff[ret].iszero()) ++ret; if (ret==ndiags || acc.coeff[ret].isnotzero()) return(ret); else { l=0; ret>>=afs_step; while(l>=0 && ret<=(ndiags>>(afs_step*(l+1)))) { if (afs[l][ret]!=0) {--l; ret<<=afs_step;} else if (l>afs_step]==0) {++l; ret>>=afs_step;} else ++ret; } if (l>=0) return(ndiags); else { while (ret=0; --count) { if (statisticsQ()) {printf("count=%d*)\n",count); fflush(stdout);} if (matrix[count].len>1) { acc.len=1; afs_update(count,1); acc.coeff[count]=-1; to_basis((matrix[count].len==2) ? 1 : ndiags, matrix[count].len); if (acc.len-1) { if (ca=0) ++(m_left[cm]); while (!m_left[++cm] && cmi) v_[cm][nv_[cm]]= ++(na_[cm]); else { v_[cm][nv_[cm]]=v_[cm][v_name[ae[i]]]; ae_[cm][v_name[ae[i]]]=v_name[i]; ae_[cm][v_name[i]]=v_name[ae[i]]; } } for (i=0; i=0; --i) j= j*d_[i]+nC_[i]; C[j]+=p; i=0; while (i0 && (!equation.coeff[i]) > 0) printf("+"); if ((abs(!equation.coeff[i]))!=1) printf("%d",!equation.coeff[i]); else if ((!equation.coeff[i])==-1) printf("-"); print_d(M,equation.at[i]); } } } void print_monom(char var, int power, int coeff) { if (power==0) printf("%d",coeff); else { if (coeff==1) ; else if (coeff==-1) printf("-"); else printf("%d",coeff); printf("%c",var); if (power>1) printf("^%d",power); } } void print_polynom(char var, int deg, int *coeffs) { int i; i=deg; while (i>=0 && coeffs[i]==0) --i; if (i>=0) print_monom(var,i,coeffs[i]); else printf("0"); --i; while (i>=0) { while (i>=0 && coeffs[i]==0) --i; if (i>=0) { if (coeffs[i]>0) printf("+"); print_monom(var,i,coeffs[i]); --i; } } } void printCD(int v[2*M]) { int i; printf("CD[%d",v[0]+1); for (i=1; i<2*M; ++i) printf(",%d",v[i]+1); printf("]"); } void print_d(int m,int count) { printf("d"); if (!framed) printf("r"); printf("[%d,%d]",m,count+1); } int statisticsQ() { int c,diff; /* Clock reading */ static int last_c=0; /* internal rep */ c=clock(); diff=c-last_c; if (diff>1000000*statistics_interval) { ++rep; printf("(*t=%d ",rep*statistics_interval); last_c=c; return(rep); } else return(0); }