diff --git a/README.md b/README.md index 2a9df6a..7538a6a 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,7 @@ # oddcycle_shannon_capacity Code for the shannon capacity of odd cycles paper http://dl.acm.org/citation.cfm?id=3100779 + +paper is also available at https://arxiv.org/abs/1504.01472 + +The code is written by the authors of the paper and is uploaded to GitGub for archival +and for any refernce use by other researchers. diff --git a/code/conj.cpp b/code/conj.cpp new file mode 100644 index 0000000..a7e97e5 --- /dev/null +++ b/code/conj.cpp @@ -0,0 +1,93 @@ +#include "rep.h" +#include +#define MAXC 22450 + + +int is_conj(int e1[5], int e2[5]) { + for (int i1 = 0; i1<18; i1++) { + for(int i2 = 0; i2<18; i2++) { + for (int i3 = 0; i3<18; i3++) { + for(int i4 = 0; i4<18; i4++) { + for(int j1 = 0; j1<24; j1++) { + int g[5]; + g[0] = i1, g[1] = i2, g[2] = i3, g[3] = i4, g[4] = j1; + + int ge1[5]; + perform_groupop(g, e1, ge1); + + int ginv[5]; + inverse(g, ginv); + int ge1ginv[5]; + perform_groupop(ge1, ginv, ge1ginv); + if(is_same(ge1ginv, e2)) { + return 1; + } + } + } + } + } + } + return 0; +} +int main(int argc, char *argv[]) { + if(argc<2) { + printf("usage: %s \n", argv[0]); + exit(-1); + } + + FILE *infile = fopen(argv[1], "r"); + int inputs[MAXC][6]; + int rqinputs[MAXC][5]; + char line[128]; + int linenum = 0; + init_rep(); + while ( fgets ( line, sizeof line, infile ) != NULL ) /* read a line */ + { + linenum++; + char delims[] = ", "; + char *pc = NULL; + pc = strtok(line, delims); + + int incount = 0; + while(pc != NULL) { + int el = atoi(pc); + inputs[linenum-1][incount] = el; + incount++; + pc = strtok( NULL, delims ); + } + if(incount!=6) { + printf("ERROR in input file, incount= %d\n", + incount); + exit(-1); + } + for(int ii = 0; ii<5; ii++) { + rqinputs[linenum-1][ii] = inputs[linenum-1][ii]; + } + //inputs contain the generator of the cyclic group that we need + } + int alreadyconj[MAXC]; + for(int i=0; i18 || candidate[i]<0) { + return 0; + } + } + if(candidate[4] >24 || candidate[4]<0) { + return 0; + } + return 1; +} +void print_groupelem(int el[5]) { + for(int i=0; i<5; i++) { + printf("(%d)", el[i]); + } + printf("\n"); +} + +// the following fn maps n\in{0.. fact(n)-1} to a permutation of {0..n-1} +void itoperm(int p, int arr[4]) { + int pt = p; + int filled[4] = {0,0,0,0}; + arr[0] = pt%4; + filled[arr[0]] = 1; + pt = floor(pt/4); + for(int i=1; i<4; i++) { + int pp1 = pt%(4-i); + pt = floor(pt/(4-i)); + int j = 0, k = 0; + while(k8 && el2[i]>8)) { + resor = 0; + } + else { + resor = 1; + } + //orientation of res[i] is now determined. + int val1 = el1[i]%9; + int val2 = el2[i]%9; + int resval = (val1+val2)%9; + result[i] = (9*resor)+resval; + } + result[4] = perm_prod(el1[4], el2[4]); + if(!is_valid_groupelem(result)) { + printf("CRITICAL ERROR at %S:%d\n", __FILE__, __LINE__); + exit(-1); + } +} + +int PERMINV_TABLE[24]; +//store inverses of permutation group elems in a table +void init_PERMINV_TABLE() { + for(int i=0; i<24; i++) { + for(int j=0; j<24; j++) { + if(perm_prod(i, j)==0) { + PERMINV_TABLE[i] = j; + // PERMINV_TABLE[j] = i; + } + } + } +} + +//inverse of an element in the torus group +void inverse(int el[5], int res[5]) { + for(int i=0; i<4; i++) { + int elor = 0; + if(el[i]>8) { + elor = 1; + } + res[i] = (9*elor) + (9-(el[i])%9)%9; + } + res[4] = PERMINV_TABLE[el[4]]; +} + +int fact(int n) { + if(n==1) return 1; + else return n*fact(n-1); +} + +void init_rep() { + init_PERMARRAY(); + init_PERMINV_TABLE(); + +} + diff --git a/code/rep.h b/code/rep.h new file mode 100644 index 0000000..d4adfb6 --- /dev/null +++ b/code/rep.h @@ -0,0 +1,17 @@ +#include +#include +#include +#include + +int is_valid_groupelem(int candidate[5]); +void print_groupelem(int el[5]); + +void init_PERMARRAY(); +int perm_prod(int p1, int p2) ; +int is_same(int el1[5], int el2[5]); +void perform_groupop(int el1[5], int el2[5], int result[5]); + +void init_PERMINV_TABLE(); +void inverse(int el[5], int res[5]); +int fact(int n); +void init_rep(); diff --git a/code/tabu4.c b/code/tabu4.c new file mode 100644 index 0000000..c00fd11 --- /dev/null +++ b/code/tabu4.c @@ -0,0 +1,315 @@ +/* tabu3.c tabu search program for clique finding + by Patric Ostergard, 15.05.2014 */ + +/* make -f makefile3 */ + +#include +#include +#include +#include "cliquer.h" +char infilename[128], outfilename[128]; +#define MAXN 7000 /* order of graph */ + +int debug_level = 0; + +extern long int lrand48(); + +int gr[MAXN][MAXN]; /* distance matrix */ +int wt[MAXN]; /* orbit size */ +int a60=0; + +int d(int a,int b) +{ + int c,e,i; + + c = a^b; + e = 0; + for(i=0;i<16;i++) + if(((c>>i)&1)==1) + e++; + return e; +} + +int err_message(int i) +{ + printf("Usage: tabu d1 d2 threshold sim rounds seed (error %d)\n",i); + exit(1); +} + +int main(argc,argv) +int argc; +char *argv[]; +/* arguments: d1 d2 lambda sim rd tabu seed */ +{ + int n,k,m,total; + int ii[MAXN],jj[MAXN],nr,posit,sim,rd,rct=0; + int tabu[MAXN],pp,npos; + int absval,count,count2,p,size,temp,temp2; + int timeout; + + int i,j,k2,tabo,seed; + int weight,weight2,ok,ant,ant2,mx,gsize; + int gtab[MAXN],htab[MAXN],value[MAXN],v2[MAXN]; + int d1,d2,d3; + int high,threshold; + int max=0; + graph_t *g; + set_t st; + +/* no timer */ + clique_default_options->time_function = NULL; + + if(argc<8) + err_message(10); + if((d1 = atoi(argv[1]))==0) + err_message(1); + if((d2 = atoi(argv[2]))==0) + err_message(2); + if((threshold = atoi(argv[3]))==0) + err_message(3); + if((sim = atoi(argv[4]))==0) + err_message(4); + if((rd = atoi(argv[5]))==0) + err_message(5); + seed = atoi(argv[6]); + strncpy(infilename, argv[7], sizeof(infilename)); + if(argc>8) debug_level = atoi(argv[8]); + +/* INIT graph (now: testing)*/ + int pidx; + for(pidx = 0; pidx<8; pidx++) { + printf("%s ", argv[pidx]); + } + printf("\n"); +#if 0 + n = 2048; + for(i=0;in) break; + value[i] = lrand48()%n; + for(j=0;j 0) { + printf("Initial weight/size: %d/%d\n",weight,ant); + } + + int ct = 0; + timeout = 1; + for(;;) { + /* if(timeout%5==0) + printf("T: %d\n",timeout); */ + if(timeout>1000) { /* now we are stuck, RESTART */ + count2 = 0; + if(weight>max) + max = weight; + goto again; + } + high = -1; + nr = 0; + if(ct<100) { /* different nbrhood in the beginning, ct rounds */ + d3 = d1; + ct++; + } + else + d3 = d2; + for(;;) { + i = (lrand48()%ant); /* remove vertex */ + /* if(tabu[i]) continue; */ + /* find vertices (indices) that are close to the removed one */ + for(j=0;jd3) continue; /* order matters! */ + htab[j] = -1; + ant2++; + weight2 += wt[value[j]]; + } + /* printf("%d %d\n",ant2,weight2); for testing */ + /* run clique search */ + gsize = 0; + for(j=0;jweights[j] = wt[gtab[j]]; + for(k=j+1;k=d1) + GRAPH_ADD_EDGE(g,j,k); + } + mx = clique_max_weight(g,clique_default_options); + graph_free(g); + total = mx-weight2; + if(total > high) { + nr = 1; + ii[0] = i; + jj[0] = mx; + high = total; + } + else if(total==high) { + ii[nr] = i; + jj[nr++] = mx; + } + break; + } + posit = (lrand48()%nr); + +/* MAKE CHANGE */ + + for(j=0;jd3) { /* order matters */ + v2[temp++] = value[j]; /* save */ + continue; + } + htab[j] = -1; + ant2++; + weight2 += wt[value[j]]; + } + /* run clique search */ + gsize = 0; + for(j=0;jweights[j] = wt[gtab[j]]; + for(k=j+1;k=d1) + GRAPH_ADD_EDGE(g,j,k); + } + st = clique_find_single(g,jj[posit],jj[posit],FALSE,clique_default_options); + graph_free(g); + if(st==NULL) { + timeout++; + continue; + } + i = -1; + while ((i=set_return_next(st,i)) >= 0) { + v2[temp++] = gtab[i]; + } + ant = temp; + weight += high; + for(i=0;i=threshold) { + /* YES! */ + printf("Yess!!! %d %d\n",ant,weight); + for(i=0;i0) { + printf("%d/%d %d %d (max %d) %d/%d\n",count2,sim,ant,weight,max,a60,rct); + } + if(count2++==sim) { + count2 = 0; + if(weight>max) + max = weight; + if(weight>=threshold-1) a60++; + if(++rct < rd) + goto again; + exit(0); + } + } + } +} + diff --git a/shannon_oddcycles.pdf b/shannon_oddcycles.pdf new file mode 100644 index 0000000..057a824 Binary files /dev/null and b/shannon_oddcycles.pdf differ