oddcycle_shannon_capacity/code/tabu4.c

316 lines
7.3 KiB
C
Raw Normal View History

2017-07-01 09:49:30 +00:00
/* tabu3.c tabu search program for clique finding
by Patric Ostergard, 15.05.2014 */
/* make -f makefile3 */
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#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;i<n;i++) {
wt[i] = 1;
for(j=0;j<n;j++) {
gr[i][j] = d(i,j);
}
}
#endif
FILE *infile = fopen(infilename, "r");
if(fscanf(infile, "%d",&n)==EOF)
err_message(6); /* second integer not used (EOF instead) */
if(n==0) {
printf("0 rows in matrix. exiting\n"); exit(0);
}
for(i=0;i<n;i++) {
if(fscanf(infile, "%d",&wt[i])==EOF)
err_message(7);
for(j=0;j<n;j++)
if(fscanf(infile, "%d",&gr[i][j])==EOF)
err_message(8);
}
/* INITIALIZE */
again: /* start of outer loop */
weight = 0;
srand48(time(0)%100000 + seed++);
/* random vertices until n guesses does not go right */
ant = 0;
for(i=0;;i++) {
temp = 0;
anyo: if(temp>n) break;
value[i] = lrand48()%n;
for(j=0;j<i;j++)
if(gr[value[i]][value[j]]<d1) {
temp++;
goto anyo;
}
weight += wt[value[i]];
ant++;
}
i = 0;
/* complete clique in a greedy manner */
do {
ok = -1;
for(j=0;j<ant;j++)
if(gr[value[j]][i]<d1) {
ok = 0;
break;
}
if(ok) {
value[ant++] = i;
weight += wt[i];
}
i++;
} while(i<n);
if(debug_level > 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;j<ant;j++)
htab[j] = 0;
ant2 = 0;
weight2 = 0;
for(j=0;j<ant;j++) {
if(gr[value[i]][value[j]]>d3) 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;j<n;j++) {
/* if(j==value[i]) continue; */ /* don't include the specified vertex */
ok = -1;
for(k=0;k<ant;k++) {
if(htab[k]) continue;
if(gr[j][value[k]]<d1) {
ok = 0;
break;
}
}
if(ok) {
gtab[gsize++] = j;
}
}
if(gsize==0) continue;
g = graph_new(gsize);
for(j=0;j<gsize;j++) {
g->weights[j] = wt[gtab[j]];
for(k=j+1;k<gsize;k++)
if(gr[gtab[j]][gtab[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;j<ant;j++)
htab[j] = 0;
ant2 = 0;
weight2 = 0;
temp = 0;
for(j=0;j<ant;j++) {
if(gr[value[ii[posit]]][value[j]]>d3) { /* order matters */
v2[temp++] = value[j]; /* save */
continue;
}
htab[j] = -1;
ant2++;
weight2 += wt[value[j]];
}
/* run clique search */
gsize = 0;
for(j=0;j<n;j++) {
if(high==0&&j==value[ii[posit]]) continue; /* don't include specified vertex */
ok = -1;
for(k=0;k<ant;k++) {
if(htab[k]) continue;
if(gr[j][value[k]]<d1) {
ok = 0;
break;
}
}
if(ok) {
gtab[gsize++] = j;
}
}
if(gsize==0) {
timeout++;
continue;
}
g = graph_new(gsize);
for(j=0;j<gsize;j++) {
g->weights[j] = wt[gtab[j]];
for(k=j+1;k<gsize;k++)
if(gr[gtab[j]][gtab[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<ant;i++)
value[i] = v2[i];
/* for(i=0;i<ant;i++)
printf("%d ",value[i]);
printf("\n"); */
/* restart timout counter */
timeout = 1;
if(weight>=threshold) {
/* YES! */
printf("Yess!!! %d %d\n",ant,weight);
for(i=0;i<ant;i++)
printf("%d ",value[i]);
printf("\n");
snprintf(outfilename, sizeof(outfilename), "%s.yes", infilename);
FILE *ofile = fopen(outfilename, "w+");
fclose(ofile);
exit(0);
}
if(++count%10 == 0) {
if(debug_level >0) {
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);
}
}
}
}