/********************************* * Drawing the Higman-Sims Graph * (C) 2008 Claudio Rocchini * CC-BY 3.0 *********************************/ #include <stdio.h> #include <stdlib.h> #include <math.h> #include <set> #include <vector> #include <map> const double PI = 3.1415926535897932384626433832795; static int Q( int x ) { return x*x; } bool is_strong_regular( const int nv, bool MA[] ){ int i,j,k; std::vector<int> adj(nv); std::fill(adj.begin(),adj.end(),0); for(k=0;k<nv*nv;++k) if(MA[k]) { i = k%nv; j = k/nv; if(i<j) { ++adj[i]; ++adj[j]; } } for(i=1;i<nv;++i) if(adj[0]!=adj[i]) { printf("Error: different rank: %d, %d\n",adj[0],adj[i]); return false; } printf("OK rank: %d\n",adj[0]); int gni = -1; int gno = -1; // lambda mu for(i=0;i<nv-1;++i) for(j=i+1;j<nv;++j) { int n = 0; for(k=0;k<nv;++k) if(k!=i && k!=j) if( MA[i*nv+k] && MA[j*nv+k] ) ++n; if( MA[i*nv+j] ) { if(gni==-1) gni = n; else if(gni!=n ) { printf("Error: different ni\n"); return false; } } else { if(gno==-1) gno = n; else if(gno!=n ) { printf("Error: different no\n"); return false; } } } printf("OK l:%d m:%d\n",gni,gno); return true; } int main( int argc, char * argv[] ) { const int NV = 100; static int tri[100][3]; // Z4*Z5*Z5 static bool MA[NV*NV]; static int CO[NV*NV]; int i,j,k,n; n = 0; for(k=0;k<5;++k) for(j=0;j<5;++j) for(i=0;i<4;++i) { tri[n][0] = i; tri[n][1] = j; tri[n][2] = k; ++n; } printf("%d nodes\n",n); std::fill(MA,MA+NV*NV,false); std::fill(CO,CO+NV*NV,0 ); for(i=0;i<n;++i) for(j=0;j<n;++j) if(i!=j) { int * ti = tri[i]; int * tj = tri[j]; int t = 0; if(ti[0]==0 && tj[0]==0 && ti[1]==tj[1] && ( (ti[2]-tj[2]+5)%5==1 || (ti[2]-tj[2]+5)%5==4 ) ) t |= 0x0001; if(ti[0]==1 && tj[0]==1 && ti[1]==tj[1] && ( (ti[2]-tj[2]+5)%5==2 || (ti[2]-tj[2]+5)%5==3 ) ) t |= 0x0002; if(ti[0]==2 && tj[0]==2 && ti[1]==tj[1] && ( (ti[2]-tj[2]+5)%5==1 || (ti[2]-tj[2]+5)%5==4 ) ) t |= 0x0004; if(ti[0]==3 && tj[0]==3 && ti[1]==tj[1] && ( (ti[2]-tj[2]+5)%5==2 || (ti[2]-tj[2]+5)%5==3 ) ) t |= 0x0008; if(ti[0]==0 && tj[0]==1 &&( ti[1]*tj[1] +tj[2]+5000)%5==ti[2] ) t |= 0x0010; if(ti[0]==1 && tj[0]==2 && (2*Q(ti[1]-tj[1])+tj[2]+5000)%5==ti[2] ) t |= 0x0020; if(ti[0]==3 && tj[0]==0 && ( Q(tj[1]-ti[1])+ti[2]+5000)%5==tj[2] ) t |= 0x0080; if(ti[0]==2 && tj[0]==3 && (2*Q(ti[1])+3*(ti[1]*tj[1])-Q(tj[1])+tj[2]+5000)%5==ti[2] ) t |= 0x0040; if(ti[0]==0 && tj[0]==2 && ( (3*Q(ti[1])+ti[1]*tj[1]+tj[2] +1 +5000)%5==ti[2] || (3*Q(ti[1])+ti[1]*tj[1]+tj[2] -1 +5000)%5==ti[2] ) ) t |= 0x0100; if(ti[0]==1 && tj[0]==3 && ( ( Q(ti[1])-ti[1]*tj[1]+tj[2] +2 +5000)%5==ti[2] || ( Q(ti[1])-ti[1]*tj[1]+tj[2] -2 +5000)%5==ti[2] ) ) t |= 0x0200; if(t) { MA[i+NV*j] = MA[j+NV*i] = true; CO[i+NV*j] |= t; CO[j+NV*i] |= t; } } std::map<int,int> stats; for(i=0;i<NV*NV;++i) if(CO[i]) ++stats[CO[i]]; std::map<int,int>::iterator ii; int ne = 0; for(ii=stats.begin();ii!=stats.end();++ii) { printf("color %04X: %d\n",(*ii).first,(*ii).second/2); ne += (*ii).second/2; } printf("TOTAL: %d arcs\n",ne); is_strong_regular(100,MA); // check! for(int v=0;v<2;++v){ const double SX = 800; const double SY = v==0 ? 800 : 400; const double B = 16; const double R = v==0 ? 3 : 1; char filename[256]; sprintf(filename,"c:\\temp\\higman_Sims%d.svg",v+1); FILE * fp = fopen(filename,"w"); fprintf(fp, "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n" "<svg\n" "xmlns:svg=\"http://www.w3.org/2000/svg\"\n" "xmlns=\"http://www.w3.org/2000/svg\"\n" "version=\"1.0\"\n" "width=\"%g\"\n" "height=\"%g\"\n" "id=\"HigmanSimsGraph\">\n" ,SX,SY ); static double xx[NV]; static double yy[NV]; int i,j; for(i=0;i<NV;++i){ const double a = 2*PI*i/NV; const double r = v==0 ? (SX-2*B)/2: (SX-2*B)/11; xx[i] = r*cos(a); yy[i] = r*sin(a); } const char * colors[10] = { "0d0d80", "80590d", "590d80", "800d0d", "0d5980", "0d8059", "59800d", "0d800d", "800d59", "808080", }; int tote = 0; for(k=10;k>0;--k){ fprintf(fp, "<g id=\"edge_layer%d\" style=\"stroke:#%s;stroke-width:%g;stroke-opacity:1.0;\">\n" ,k ,colors[k-1] ,v==0 ? 0.75 : 0.5 ); double ox = v==0 ? SX/2 : SX/2+(SX/5)*((k-1)%5-2); double oy = v==0 ? SY/2 : SY/4+(SY/2)*((k-1)/5); for(i=0;i<NV-1;++i) for(j=i+1;j<NV;++j) if(MA[i+NV*j] && CO[i+NV*j]==(1<<(k-1))){ fprintf(fp, "<line x1=\"%5.1lf\" y1=\"%5.1lf\" x2=\"%5.1lf\" y2=\"%5.1lf\"/>\n" ,ox+xx[i],oy+yy[i] ,ox+xx[j],oy+yy[j] ); ++tote; } fprintf(fp, "</g>\n"); if(v==1 || k==1){ fprintf(fp, "<g id=\"node_layer\" style=\"fill:#000000;stroke:#000000;stroke-width:1;stroke-opacity:1.0;\">\n" ); for(i=0;i<NV;++i) fprintf(fp,"<circle cx=\"%5.1lf\" cy=\"%5.1lf\" r=\"%5.1lf\" />\n" ,ox+xx[i],oy+yy[i],R ); fprintf(fp, "</g>\n" ); } } if(v==0) printf("tot edges: %d\n",tote); fprintf(fp, "</svg>\n" ); fclose(fp); } return 0; }